diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b157b4a63..7ed0af7ce 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -55,11 +55,11 @@ body: validations: required: false - type: input - id: other + id: os_detail attributes: - label: If Other OS, please describe + label: Please describe your specific OS version description: Other details - placeholder: "Windows, Mac OSX version, Debian, Ubuntu, Arch, etc." + placeholder: "Windows 11 Home/Pro/Server/etc, Mac OSX version, Debian 10/11/etc, Ubuntu 18/20/etc, Arch, etc." validations: required: false - type: input @@ -82,7 +82,7 @@ body: id: description attributes: label: A clear and concise description of what the bug is. - description: Describe what happens, what software were you running? _Include screenshot if possible_ + description: Describe what happens, what software were you running? _Include a small mod demonstrating the bug, or a screenshot if possible_ placeholder: "How & When does this occur?" validations: required: true diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 41e8be012..9ed95672c 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -11,56 +11,62 @@ jobs: matrix: config: - { - name: "Visual Studio 64-bit", + name: "Visual Studio 2022", + os: windows-2022, + extra_options: "-A x64", + build_type: "Release" + } + - { + name: "Visual Studio 2019", os: windows-2019, extra_options: "-A x64", build_type: "Release" } - { - name: "Visual Studio 64-bit", + name: "Visual Studio 2019", os: windows-2019, extra_options: "-A x64", build_type: "Debug" } - { name: "macOS", - os: macos-11, + os: macos-12, + deps_cmdline: "brew install libvpx", build_type: "Release" } - { name: "macOS", - os: macos-11, - extra_options: "-DDYN_FLUIDSYNTH=OFF -DDYN_OPENAL=OFF -DDYN_SNDFILE=OFF -DDYN_MPG123=OFF", - deps_cmdline: "brew install fluidsynth mpg123 libsndfile", + os: macos-12, + extra_options: "-G Xcode -DDYN_OPENAL=OFF", + deps_cmdline: "brew install libvpx fluidsynth mpg123 libsndfile", build_type: "Debug" } - { name: "Linux GCC 7", os: ubuntu-20.04, extra_options: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7", - deps_cmdline: "sudo apt update && sudo apt install g++-7 libsdl2-dev libgtk2.0-dev", + deps_cmdline: "sudo apt update && sudo apt install g++-7 libsdl2-dev libvpx-dev libgtk2.0-dev", build_type: "RelWithDebInfo" } - { name: "Linux GCC 11", os: ubuntu-20.04, extra_options: "-DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11", - deps_cmdline: "sudo apt update && sudo apt install g++-11 libsdl2-dev libgtk-3-dev", + deps_cmdline: "sudo apt update && sudo apt install g++-11 libsdl2-dev libvpx-dev libgtk-3-dev", build_type: "MinSizeRel" } - { name: "Linux Clang 6", os: ubuntu-20.04, - extra_options: "-DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 \ - -DDYN_FLUIDSYNTH=OFF -DDYN_OPENAL=OFF -DDYN_SNDFILE=OFF -DDYN_MPG123=OFF", - deps_cmdline: "sudo apt update && sudo apt install clang-6.0 libsdl2-dev libopenal-dev libfluidsynth-dev libmpg123-dev libsndfile1-dev", + extra_options: "-DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DDYN_OPENAL=OFF", + deps_cmdline: "sudo apt update && sudo apt install clang-6.0 libsdl2-dev libvpx-dev libopenal-dev libfluidsynth-dev libmpg123-dev libsndfile1-dev", build_type: "Debug" } - { name: "Linux Clang 12", os: ubuntu-20.04, extra_options: "-DCMAKE_C_COMPILER=clang-12 -DCMAKE_CXX_COMPILER=clang++-12", - deps_cmdline: "sudo apt update && sudo apt install clang-12 libsdl2-dev", + deps_cmdline: "sudo apt update && sudo apt install clang-12 libsdl2-dev libvpx-dev", build_type: "Release" } @@ -75,9 +81,9 @@ jobs: fi mkdir build if [[ "${{ runner.os }}" == 'macOS' ]]; then - export ZMUSIC_PACKAGE=zmusic-1.1.7-macos.tar.bz2 + export ZMUSIC_PACKAGE=zmusic-1.1.9-macos.tar.xz elif [[ "${{ runner.os }}" == 'Linux' ]]; then - export ZMUSIC_PACKAGE=zmusic-1.1.7-linux.tar.bz2 + export ZMUSIC_PACKAGE=zmusic-1.1.9-linux.tar.xz fi if [[ ! -z "${ZMUSIC_PACKAGE}" ]]; then cd build @@ -88,6 +94,10 @@ jobs: - name: Configure shell: bash run: | + if [[ "${{ runner.os }}" == 'Windows' ]]; then + # Remove Strawberry Perl from PATH environment variable to avoid usage of libraries it provides + export PATH=`echo $PATH | tr ":" "\n" | grep -v "Strawberry" | tr "\n" ":"` + fi 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 80e22e733..b52bcb177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,12 +139,12 @@ else() endif() if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) - set( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE TRUE ) + set( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE TRUE ) else() - set( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE FALSE ) + set( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE FALSE ) endif() -if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +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 ) @@ -157,7 +157,7 @@ endif() # Fast math flags, required by some subprojects set( ZD_FASTMATH_FLAG "" ) -if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( ZD_FASTMATH_FLAG "-ffast-math -ffp-contract=fast" ) elseif( MSVC ) set( ZD_FASTMATH_FLAG "/fp:fast" ) @@ -189,13 +189,14 @@ option( NO_OPENAL "Disable OpenAL sound support" OFF ) find_package( BZip2 ) find_package( JPEG ) +find_package( VPX ) find_package( ZLIB ) include( TargetArch ) -target_architecture(ZDOOM_TARGET_ARCH) +target_architecture(TARGET_ARCHITECTURE) -if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" ) +if( ${TARGET_ARCHITECTURE} MATCHES "x86_64" ) set( HAVE_VM_JIT ON ) endif() @@ -217,7 +218,7 @@ if( MSVC ) # String pooling # Function-level linking # Disable run-time type information - set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_SOFTPOLY" ) + set( ALL_C_FLAGS "/GF /Gy /permissive-" ) if ( HAVE_VULKAN ) set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_VULKAN" ) @@ -245,7 +246,7 @@ if( MSVC ) set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" ) # Disable warnings for unsecure CRT functions from VC8+ - set( ALL_C_FLAGS "${ALL_C_FLAGS} /wd4996 /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0600" ) + 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} ) @@ -259,7 +260,7 @@ if( MSVC ) string(REPLACE "/MDd " " " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} ) else() set( REL_LINKER_FLAGS "" ) - set( ALL_C_FLAGS "-ffp-contract=off -DHAVE_SOFTPOLY" ) + set( ALL_C_FLAGS "-ffp-contract=off" ) if ( HAVE_VULKAN ) set( ALL_C_FLAGS "${ALL_C_FLAGS} -DHAVE_VULKAN" ) @@ -323,11 +324,14 @@ option(FORCE_INTERNAL_ASMJIT "Use internal asmjit" ON) mark_as_advanced( FORCE_INTERNAL_ASMJIT ) if (HAVE_VULKAN) - add_subdirectory( libraries/glslang/glslang) - add_subdirectory( libraries/glslang/spirv ) - add_subdirectory( libraries/glslang/OGLCompilersDLL ) + add_subdirectory( libraries/ZVulkan ) endif() +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() @@ -386,7 +390,6 @@ else() set( BZIP2_LIBRARY bz2 ) endif() - set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/lzma/C" ) if( NOT CMAKE_CROSSCOMPILING ) diff --git a/README.md b/README.md index 82b2c3b6f..2792c9f61 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ [![QZDoom Logo](https://forum.drdteam.org/download/file.php?id=3080)](https://zdoom.org/) # Welcome to QZDoom! -[![Build Status](https://ci.appveyor.com/api/projects/status/github/madame-rachelle/qzdoom?branch=master&svg=true)](https://ci.appveyor.com/project/madame-rachelle/qzdoom) [![Build Status](https://travis-ci.org/madame-rachelle/qzdoom.svg?branch=master)](https://travis-ci.org/madame-rachelle/qzdoom) +[![Continuous Integration](https://github.com/ZDoom/qzdoom/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/ZDoom/qzdoom/actions/workflows/continuous_integration.yml) ## QZDoom is a fork of [GZDoom](https://github.com/coelckers/gzdoom) for beta testing new features that have not yet been included in GZDoom's mainline. -Copyright (c) 1998-2021 ZDoom + GZDoom teams, and contributors +Copyright (c) 1998-2022 ZDoom + GZDoom teams, and contributors Doom Source (c) 1997 id Software, Raven Software, and contributors @@ -22,3 +22,9 @@ Special thanks to Coraline of the EDGE team for allowing us to use her [README.m To build QZDoom, please see the [wiki](https://zdoom.org/wiki/) and see the "Programmer's Corner" on the bottom-right corner of the page to build for your platform. Follow the same instructions as with GZDoom, except substituting "coelckers/gzdoom" with "madame-rachelle/qzdoom" in order to link this repository in your build environment. +# Resources +- https://zdoom.org/ - Home Page +- https://forum.zdoom.org/ - Forum +- https://zdoom.org/wiki/ - Wiki +- https://discord.gg/zdoom - Discord Server +- https://docs.google.com/spreadsheets/d/1pvwXEgytkor9SClCiDn4j5AH7FedyXS-ocCbsuQIXDU/edit?usp=sharing - Translation sheet (Google Docs) diff --git a/bin/windows/vpx/include/vpx/vp8.h b/bin/windows/vpx/include/vpx/vp8.h new file mode 100644 index 000000000..8a035f977 --- /dev/null +++ b/bin/windows/vpx/include/vpx/vp8.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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. + */ + +/*!\defgroup vp8 VP8 + * \ingroup codecs + * VP8 is vpx's newest video compression algorithm that uses motion + * compensated prediction, Discrete Cosine Transform (DCT) coding of the + * prediction error signal and context dependent entropy coding techniques + * based on arithmetic principles. It features: + * - YUV 4:2:0 image format + * - Macro-block based coding (16x16 luma plus two 8x8 chroma) + * - 1/4 (1/8) pixel accuracy motion compensated prediction + * - 4x4 DCT transform + * - 128 level linear quantizer + * - In loop deblocking filter + * - Context-based entropy coding + * + * @{ + */ +/*!\file + * \brief Provides controls common to both the VP8 encoder and decoder. + */ +#ifndef VPX_VP8_H_ +#define VPX_VP8_H_ + +#include "./vpx_codec.h" +#include "./vpx_image.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*!\brief Control functions + * + * The set of macros define the control functions of VP8 interface + */ +enum vp8_com_control_id { + VP8_SET_REFERENCE = 1, /**< pass in an external frame into decoder to be used as reference frame */ + VP8_COPY_REFERENCE = 2, /**< get a copy of reference frame from the decoder */ + VP8_SET_POSTPROC = 3, /**< set the decoder's post processing settings */ + VP8_SET_DBG_COLOR_REF_FRAME = 4, /**< set the reference frames to color for each macroblock */ + VP8_SET_DBG_COLOR_MB_MODES = 5, /**< set which macro block modes to color */ + VP8_SET_DBG_COLOR_B_MODES = 6, /**< set which blocks modes to color */ + VP8_SET_DBG_DISPLAY_MV = 7, /**< set which motion vector modes to draw */ + + /* TODO(jkoleszar): The encoder incorrectly reuses some of these values (5+) + * for its control ids. These should be migrated to something like the + * VP8_DECODER_CTRL_ID_START range next time we're ready to break the ABI. + */ + VP9_GET_REFERENCE = 128, /**< get a pointer to a reference frame */ + VP8_COMMON_CTRL_ID_MAX, + VP8_DECODER_CTRL_ID_START = 256 +}; + +/*!\brief post process flags + * + * The set of macros define VP8 decoder post processing flags + */ +enum vp8_postproc_level { + VP8_NOFILTERING = 0, + VP8_DEBLOCK = 1 << 0, + VP8_DEMACROBLOCK = 1 << 1, + VP8_ADDNOISE = 1 << 2, + VP8_DEBUG_TXT_FRAME_INFO = 1 << 3, /**< print frame information */ + VP8_DEBUG_TXT_MBLK_MODES = 1 << 4, /**< print macro block modes over each macro block */ + VP8_DEBUG_TXT_DC_DIFF = 1 << 5, /**< print dc diff for each macro block */ + VP8_DEBUG_TXT_RATE_INFO = 1 << 6, /**< print video rate info (encoder only) */ + VP8_MFQE = 1 << 10 +}; + +/*!\brief post process flags + * + * This define a structure that describe the post processing settings. For + * the best objective measure (using the PSNR metric) set post_proc_flag + * to VP8_DEBLOCK and deblocking_level to 1. + */ + +typedef struct vp8_postproc_cfg { + int post_proc_flag; /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */ + int deblocking_level; /**< the strength of deblocking, valid range [0, 16] */ + int noise_level; /**< the strength of additive noise, valid range [0, 16] */ +} vp8_postproc_cfg_t; + +/*!\brief reference frame type + * + * The set of macros define the type of VP8 reference frames + */ +typedef enum vpx_ref_frame_type { + VP8_LAST_FRAME = 1, + VP8_GOLD_FRAME = 2, + VP8_ALTR_FRAME = 4 +} vpx_ref_frame_type_t; + +/*!\brief reference frame data struct + * + * Define the data struct to access vp8 reference frames. + */ +typedef struct vpx_ref_frame { + vpx_ref_frame_type_t frame_type; /**< which reference frame */ + vpx_image_t img; /**< reference frame data in image format */ +} vpx_ref_frame_t; + +/*!\brief VP9 specific reference frame data struct + * + * Define the data struct to access vp9 reference frames. + */ +typedef struct vp9_ref_frame { + int idx; /**< frame index to get (input) */ + vpx_image_t img; /**< img structure to populate (output) */ +} vp9_ref_frame_t; + +/*!\cond */ +/*!\brief vp8 decoder control function parameter type + * + * defines the data type for each of VP8 decoder control function requires + */ +VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE, vpx_ref_frame_t *) +#define VPX_CTRL_VP8_SET_REFERENCE +VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE, vpx_ref_frame_t *) +#define VPX_CTRL_VP8_COPY_REFERENCE +VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC, vp8_postproc_cfg_t *) +#define VPX_CTRL_VP8_SET_POSTPROC +VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_REF_FRAME, int) +#define VPX_CTRL_VP8_SET_DBG_COLOR_REF_FRAME +VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_MB_MODES, int) +#define VPX_CTRL_VP8_SET_DBG_COLOR_MB_MODES +VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_B_MODES, int) +#define VPX_CTRL_VP8_SET_DBG_COLOR_B_MODES +VPX_CTRL_USE_TYPE(VP8_SET_DBG_DISPLAY_MV, int) +#define VPX_CTRL_VP8_SET_DBG_DISPLAY_MV +VPX_CTRL_USE_TYPE(VP9_GET_REFERENCE, vp9_ref_frame_t *) +#define VPX_CTRL_VP9_GET_REFERENCE + +/*!\endcond */ +/*! @} - end defgroup vp8 */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VP8_H_ diff --git a/bin/windows/vpx/include/vpx/vp8dx.h b/bin/windows/vpx/include/vpx/vp8dx.h new file mode 100644 index 000000000..67c97bb6c --- /dev/null +++ b/bin/windows/vpx/include/vpx/vp8dx.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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. + */ + + +/*!\defgroup vp8_decoder WebM VP8/VP9 Decoder + * \ingroup vp8 + * + * @{ + */ +/*!\file + * \brief Provides definitions for using VP8 or VP9 within the vpx Decoder + * interface. + */ +#ifndef VPX_VP8DX_H_ +#define VPX_VP8DX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include controls common to both the encoder and decoder */ +#include "./vp8.h" + +/*!\name Algorithm interface for VP8 + * + * This interface provides the capability to decode VP8 streams. + * @{ + */ +extern vpx_codec_iface_t vpx_codec_vp8_dx_algo; +extern vpx_codec_iface_t *vpx_codec_vp8_dx(void); +/*!@} - end algorithm interface member group*/ + +/*!\name Algorithm interface for VP9 + * + * This interface provides the capability to decode VP9 streams. + * @{ + */ +extern vpx_codec_iface_t vpx_codec_vp9_dx_algo; +extern vpx_codec_iface_t *vpx_codec_vp9_dx(void); +/*!@} - end algorithm interface member group*/ + +/*!\enum vp8_dec_control_id + * \brief VP8 decoder control functions + * + * This set of macros define the control functions available for the VP8 + * decoder interface. + * + * \sa #vpx_codec_control + */ +enum vp8_dec_control_id { + /** control function to get info on which reference frames were updated + * by the last decode + */ + VP8D_GET_LAST_REF_UPDATES = VP8_DECODER_CTRL_ID_START, + + /** check if the indicated frame is corrupted */ + VP8D_GET_FRAME_CORRUPTED, + + /** control function to get info on which reference frames were used + * by the last decode + */ + VP8D_GET_LAST_REF_USED, + + /** decryption function to decrypt encoded buffer data immediately + * before decoding. Takes a vpx_decrypt_init, which contains + * a callback function and opaque context pointer. + */ + VPXD_SET_DECRYPTOR, + VP8D_SET_DECRYPTOR = VPXD_SET_DECRYPTOR, + + /** control function to get the dimensions that the current frame is decoded + * at. This may be different to the intended display size for the frame as + * specified in the wrapper or frame header (see VP9D_GET_DISPLAY_SIZE). */ + VP9D_GET_FRAME_SIZE, + + /** control function to get the current frame's intended display dimensions + * (as specified in the wrapper or frame header). This may be different to + * the decoded dimensions of this frame (see VP9D_GET_FRAME_SIZE). */ + VP9D_GET_DISPLAY_SIZE, + + /** control function to get the bit depth of the stream. */ + VP9D_GET_BIT_DEPTH, + + /** control function to set the byte alignment of the planes in the reference + * buffers. Valid values are power of 2, from 32 to 1024. A value of 0 sets + * legacy alignment. I.e. Y plane is aligned to 32 bytes, U plane directly + * follows Y plane, and V plane directly follows U plane. Default value is 0. + */ + VP9_SET_BYTE_ALIGNMENT, + + /** control function to invert the decoding order to from right to left. The + * function is used in a test to confirm the decoding independence of tile + * columns. The function may be used in application where this order + * of decoding is desired. + * + * TODO(yaowu): Rework the unit test that uses this control, and in a future + * release, this test-only control shall be removed. + */ + VP9_INVERT_TILE_DECODE_ORDER, + + /** control function to set the skip loop filter flag. Valid values are + * integers. The decoder will skip the loop filter when its value is set to + * nonzero. If the loop filter is skipped the decoder may accumulate decode + * artifacts. The default value is 0. + */ + VP9_SET_SKIP_LOOP_FILTER, + + VP8_DECODER_CTRL_ID_MAX +}; + +/** Decrypt n bytes of data from input -> output, using the decrypt_state + * passed in VPXD_SET_DECRYPTOR. + */ +typedef void (*vpx_decrypt_cb)(void *decrypt_state, const unsigned char *input, + unsigned char *output, int count); + +/*!\brief Structure to hold decryption state + * + * Defines a structure to hold the decryption state and access function. + */ +typedef struct vpx_decrypt_init { + /*! Decrypt callback. */ + vpx_decrypt_cb decrypt_cb; + + /*! Decryption state. */ + void *decrypt_state; +} vpx_decrypt_init; + +/*!\brief A deprecated alias for vpx_decrypt_init. + */ +typedef vpx_decrypt_init vp8_decrypt_init; + + +/*!\cond */ +/*!\brief VP8 decoder control function parameter type + * + * Defines the data types that VP8D control functions take. Note that + * additional common controls are defined in vp8.h + * + */ + + +VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *) +#define VPX_CTRL_VP8D_GET_LAST_REF_UPDATES +VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *) +#define VPX_CTRL_VP8D_GET_FRAME_CORRUPTED +VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *) +#define VPX_CTRL_VP8D_GET_LAST_REF_USED +VPX_CTRL_USE_TYPE(VPXD_SET_DECRYPTOR, vpx_decrypt_init *) +#define VPX_CTRL_VPXD_SET_DECRYPTOR +VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vpx_decrypt_init *) +#define VPX_CTRL_VP8D_SET_DECRYPTOR +VPX_CTRL_USE_TYPE(VP9D_GET_DISPLAY_SIZE, int *) +#define VPX_CTRL_VP9D_GET_DISPLAY_SIZE +VPX_CTRL_USE_TYPE(VP9D_GET_BIT_DEPTH, unsigned int *) +#define VPX_CTRL_VP9D_GET_BIT_DEPTH +VPX_CTRL_USE_TYPE(VP9D_GET_FRAME_SIZE, int *) +#define VPX_CTRL_VP9D_GET_FRAME_SIZE +VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int) +#define VPX_CTRL_VP9_INVERT_TILE_DECODE_ORDER + +/*!\endcond */ +/*! @} - end defgroup vp8_decoder */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VP8DX_H_ diff --git a/bin/windows/vpx/include/vpx/vpx_codec.h b/bin/windows/vpx/include/vpx/vpx_codec.h new file mode 100644 index 000000000..b6037bb4d --- /dev/null +++ b/bin/windows/vpx/include/vpx/vpx_codec.h @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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. + */ + + +/*!\defgroup codec Common Algorithm Interface + * This abstraction allows applications to easily support multiple video + * formats with minimal code duplication. This section describes the interface + * common to all codecs (both encoders and decoders). + * @{ + */ + +/*!\file + * \brief Describes the codec algorithm interface to applications. + * + * This file describes the interface between an application and a + * video codec algorithm. + * + * An application instantiates a specific codec instance by using + * vpx_codec_init() and a pointer to the algorithm's interface structure: + *
+ *     my_app.c:
+ *       extern vpx_codec_iface_t my_codec;
+ *       {
+ *           vpx_codec_ctx_t algo;
+ *           res = vpx_codec_init(&algo, &my_codec);
+ *       }
+ *     
+ * + * Once initialized, the instance is manged using other functions from + * the vpx_codec_* family. + */ +#ifndef VPX_VPX_CODEC_H_ +#define VPX_VPX_CODEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./vpx_integer.h" +#include "./vpx_image.h" + + /*!\brief Decorator indicating a function is deprecated */ +#ifndef DEPRECATED +#if defined(__GNUC__) && __GNUC__ +#define DEPRECATED __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define DEPRECATED +#else +#define DEPRECATED +#endif +#endif /* DEPRECATED */ + +#ifndef DECLSPEC_DEPRECATED +#if defined(__GNUC__) && __GNUC__ +#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */ +#elif defined(_MSC_VER) +#define DECLSPEC_DEPRECATED __declspec(deprecated) /**< \copydoc #DEPRECATED */ +#else +#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */ +#endif +#endif /* DECLSPEC_DEPRECATED */ + + /*!\brief Decorator indicating a function is potentially unused */ +#ifdef UNUSED +#elif defined(__GNUC__) || defined(__clang__) +#define UNUSED __attribute__ ((unused)) +#else +#define UNUSED +#endif + + /*!\brief Current ABI version number + * + * \internal + * If this file is altered in any way that changes the ABI, this value + * must be bumped. Examples include, but are not limited to, changing + * types, removing or reassigning enums, adding/removing/rearranging + * fields to structures + */ +#define VPX_CODEC_ABI_VERSION (3 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/ + + /*!\brief Algorithm return codes */ + typedef enum { + /*!\brief Operation completed without error */ + VPX_CODEC_OK, + + /*!\brief Unspecified error */ + VPX_CODEC_ERROR, + + /*!\brief Memory operation failed */ + VPX_CODEC_MEM_ERROR, + + /*!\brief ABI version mismatch */ + VPX_CODEC_ABI_MISMATCH, + + /*!\brief Algorithm does not have required capability */ + VPX_CODEC_INCAPABLE, + + /*!\brief The given bitstream is not supported. + * + * The bitstream was unable to be parsed at the highest level. The decoder + * is unable to proceed. This error \ref SHOULD be treated as fatal to the + * stream. */ + VPX_CODEC_UNSUP_BITSTREAM, + + /*!\brief Encoded bitstream uses an unsupported feature + * + * The decoder does not implement a feature required by the encoder. This + * return code should only be used for features that prevent future + * pictures from being properly decoded. This error \ref MAY be treated as + * fatal to the stream or \ref MAY be treated as fatal to the current GOP. + */ + VPX_CODEC_UNSUP_FEATURE, + + /*!\brief The coded data for this stream is corrupt or incomplete + * + * There was a problem decoding the current frame. This return code + * should only be used for failures that prevent future pictures from + * being properly decoded. This error \ref MAY be treated as fatal to the + * stream or \ref MAY be treated as fatal to the current GOP. If decoding + * is continued for the current GOP, artifacts may be present. + */ + VPX_CODEC_CORRUPT_FRAME, + + /*!\brief An application-supplied parameter is not valid. + * + */ + VPX_CODEC_INVALID_PARAM, + + /*!\brief An iterator reached the end of list. + * + */ + VPX_CODEC_LIST_END + + } + vpx_codec_err_t; + + + /*! \brief Codec capabilities bitfield + * + * Each codec advertises the capabilities it supports as part of its + * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces + * or functionality, and are not required to be supported. + * + * The available flags are specified by VPX_CODEC_CAP_* defines. + */ + typedef long vpx_codec_caps_t; +#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */ +#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */ + + + /*! \brief Initialization-time Feature Enabling + * + * Certain codec features must be known at initialization time, to allow for + * proper memory allocation. + * + * The available flags are specified by VPX_CODEC_USE_* defines. + */ + typedef long vpx_codec_flags_t; + + + /*!\brief Codec interface structure. + * + * Contains function pointers and other data private to the codec + * implementation. This structure is opaque to the application. + */ + typedef const struct vpx_codec_iface vpx_codec_iface_t; + + + /*!\brief Codec private data structure. + * + * Contains data private to the codec implementation. This structure is opaque + * to the application. + */ + typedef struct vpx_codec_priv vpx_codec_priv_t; + + + /*!\brief Iterator + * + * Opaque storage used for iterating over lists. + */ + typedef const void *vpx_codec_iter_t; + + + /*!\brief Codec context structure + * + * All codecs \ref MUST support this context structure fully. In general, + * this data should be considered private to the codec algorithm, and + * not be manipulated or examined by the calling application. Applications + * may reference the 'name' member to get a printable description of the + * algorithm. + */ + typedef struct vpx_codec_ctx { + const char *name; /**< Printable interface name */ + vpx_codec_iface_t *iface; /**< Interface pointers */ + vpx_codec_err_t err; /**< Last returned error */ + const char *err_detail; /**< Detailed info, if available */ + vpx_codec_flags_t init_flags; /**< Flags passed at init time */ + union { + /**< Decoder Configuration Pointer */ + const struct vpx_codec_dec_cfg *dec; + /**< Encoder Configuration Pointer */ + const struct vpx_codec_enc_cfg *enc; + const void *raw; + } config; /**< Configuration pointer aliasing union */ + vpx_codec_priv_t *priv; /**< Algorithm private storage */ + } vpx_codec_ctx_t; + + /*!\brief Bit depth for codec + * * + * This enumeration determines the bit depth of the codec. + */ + typedef enum vpx_bit_depth { + VPX_BITS_8 = 8, /**< 8 bits */ + VPX_BITS_10 = 10, /**< 10 bits */ + VPX_BITS_12 = 12, /**< 12 bits */ + } vpx_bit_depth_t; + + /* + * Library Version Number Interface + * + * For example, see the following sample return values: + * vpx_codec_version() (1<<16 | 2<<8 | 3) + * vpx_codec_version_str() "v1.2.3-rc1-16-gec6a1ba" + * vpx_codec_version_extra_str() "rc1-16-gec6a1ba" + */ + + /*!\brief Return the version information (as an integer) + * + * Returns a packed encoding of the library version number. This will only include + * the major.minor.patch component of the version number. Note that this encoded + * value should be accessed through the macros provided, as the encoding may change + * in the future. + * + */ + int vpx_codec_version(void); +#define VPX_VERSION_MAJOR(v) ((v>>16)&0xff) /**< extract major from packed version */ +#define VPX_VERSION_MINOR(v) ((v>>8)&0xff) /**< extract minor from packed version */ +#define VPX_VERSION_PATCH(v) ((v>>0)&0xff) /**< extract patch from packed version */ + + /*!\brief Return the version major number */ +#define vpx_codec_version_major() ((vpx_codec_version()>>16)&0xff) + + /*!\brief Return the version minor number */ +#define vpx_codec_version_minor() ((vpx_codec_version()>>8)&0xff) + + /*!\brief Return the version patch number */ +#define vpx_codec_version_patch() ((vpx_codec_version()>>0)&0xff) + + + /*!\brief Return the version information (as a string) + * + * Returns a printable string containing the full library version number. This may + * contain additional text following the three digit version number, as to indicate + * release candidates, prerelease versions, etc. + * + */ + const char *vpx_codec_version_str(void); + + + /*!\brief Return the version information (as a string) + * + * Returns a printable "extra string". This is the component of the string returned + * by vpx_codec_version_str() following the three digit version number. + * + */ + const char *vpx_codec_version_extra_str(void); + + + /*!\brief Return the build configuration + * + * Returns a printable string containing an encoded version of the build + * configuration. This may be useful to vpx support. + * + */ + const char *vpx_codec_build_config(void); + + + /*!\brief Return the name for a given interface + * + * Returns a human readable string for name of the given codec interface. + * + * \param[in] iface Interface pointer + * + */ + const char *vpx_codec_iface_name(vpx_codec_iface_t *iface); + + + /*!\brief Convert error number to printable string + * + * Returns a human readable string for the last error returned by the + * algorithm. The returned error will be one line and will not contain + * any newline characters. + * + * + * \param[in] err Error number. + * + */ + const char *vpx_codec_err_to_string(vpx_codec_err_t err); + + + /*!\brief Retrieve error synopsis for codec context + * + * Returns a human readable string for the last error returned by the + * algorithm. The returned error will be one line and will not contain + * any newline characters. + * + * + * \param[in] ctx Pointer to this instance's context. + * + */ + const char *vpx_codec_error(vpx_codec_ctx_t *ctx); + + + /*!\brief Retrieve detailed error information for codec context + * + * Returns a human readable string providing detailed information about + * the last error. + * + * \param[in] ctx Pointer to this instance's context. + * + * \retval NULL + * No detailed information is available. + */ + const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx); + + + /* REQUIRED FUNCTIONS + * + * The following functions are required to be implemented for all codecs. + * They represent the base case functionality expected of all codecs. + */ + + /*!\brief Destroy a codec instance + * + * Destroys a codec context, freeing any associated memory buffers. + * + * \param[in] ctx Pointer to this instance's context + * + * \retval #VPX_CODEC_OK + * The codec algorithm initialized. + * \retval #VPX_CODEC_MEM_ERROR + * Memory allocation failed. + */ + vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx); + + + /*!\brief Get the capabilities of an algorithm. + * + * Retrieves the capabilities bitfield from the algorithm's interface. + * + * \param[in] iface Pointer to the algorithm interface + * + */ + vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface); + + + /*!\brief Control algorithm + * + * This function is used to exchange algorithm specific data with the codec + * instance. This can be used to implement features specific to a particular + * algorithm. + * + * This wrapper function dispatches the request to the helper function + * associated with the given ctrl_id. It tries to call this function + * transparently, but will return #VPX_CODEC_ERROR if the request could not + * be dispatched. + * + * Note that this function should not be used directly. Call the + * #vpx_codec_control wrapper macro instead. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] ctrl_id Algorithm specific control identifier + * + * \retval #VPX_CODEC_OK + * The control request was processed. + * \retval #VPX_CODEC_ERROR + * The control request was not processed. + * \retval #VPX_CODEC_INVALID_PARAM + * The data was not valid. + */ + vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx, + int ctrl_id, + ...); +#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS +# define vpx_codec_control(ctx,id,data) vpx_codec_control_(ctx,id,data) +# define VPX_CTRL_USE_TYPE(id, typ) +# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) +# define VPX_CTRL_VOID(id, typ) + +#else + /*!\brief vpx_codec_control wrapper macro + * + * This macro allows for type safe conversions across the variadic parameter + * to vpx_codec_control_(). + * + * \internal + * It works by dispatching the call to the control function through a wrapper + * function named with the id parameter. + */ +# define vpx_codec_control(ctx,id,data) vpx_codec_control_##id(ctx,id,data)\ + /**<\hideinitializer*/ + + + /*!\brief vpx_codec_control type definition macro + * + * This macro allows for type safe conversions across the variadic parameter + * to vpx_codec_control_(). It defines the type of the argument for a given + * control identifier. + * + * \internal + * It defines a static function with + * the correctly typed arguments as a wrapper to the type-unsafe internal + * function. + */ +# define VPX_CTRL_USE_TYPE(id, typ) \ + static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) UNUSED;\ + \ + static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\ + return vpx_codec_control_(ctx, ctrl_id, data);\ + } /**<\hideinitializer*/ + + + /*!\brief vpx_codec_control deprecated type definition macro + * + * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is + * deprecated and should not be used. Consult the documentation for your + * codec for more information. + * + * \internal + * It defines a static function with the correctly typed arguments as a + * wrapper to the type-unsafe internal function. + */ +# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \ + DECLSPEC_DEPRECATED static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) DEPRECATED UNUSED;\ + \ + DECLSPEC_DEPRECATED static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\ + return vpx_codec_control_(ctx, ctrl_id, data);\ + } /**<\hideinitializer*/ + + + /*!\brief vpx_codec_control void type definition macro + * + * This macro allows for type safe conversions across the variadic parameter + * to vpx_codec_control_(). It indicates that a given control identifier takes + * no argument. + * + * \internal + * It defines a static function without a data argument as a wrapper to the + * type-unsafe internal function. + */ +# define VPX_CTRL_VOID(id) \ + static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t*, int) UNUSED;\ + \ + static vpx_codec_err_t \ + vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id) {\ + return vpx_codec_control_(ctx, ctrl_id);\ + } /**<\hideinitializer*/ + + +#endif + + /*!@} - end defgroup codec*/ +#ifdef __cplusplus +} +#endif +#endif // VPX_VPX_CODEC_H_ + diff --git a/bin/windows/vpx/include/vpx/vpx_decoder.h b/bin/windows/vpx/include/vpx/vpx_decoder.h new file mode 100644 index 000000000..62fd91975 --- /dev/null +++ b/bin/windows/vpx/include/vpx/vpx_decoder.h @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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 VPX_VPX_DECODER_H_ +#define VPX_VPX_DECODER_H_ + +/*!\defgroup decoder Decoder Algorithm Interface + * \ingroup codec + * This abstraction allows applications using this decoder to easily support + * multiple video formats with minimal code duplication. This section describes + * the interface common to all decoders. + * @{ + */ + +/*!\file + * \brief Describes the decoder algorithm interface to applications. + * + * This file describes the interface between an application and a + * video decoder algorithm. + * + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include "./vpx_codec.h" +#include "./vpx_frame_buffer.h" + + /*!\brief Current ABI version number + * + * \internal + * If this file is altered in any way that changes the ABI, this value + * must be bumped. Examples include, but are not limited to, changing + * types, removing or reassigning enums, adding/removing/rearranging + * fields to structures + */ +#define VPX_DECODER_ABI_VERSION (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/ + + /*! \brief Decoder capabilities bitfield + * + * Each decoder advertises the capabilities it supports as part of its + * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces + * or functionality, and are not required to be supported by a decoder. + * + * The available flags are specified by VPX_CODEC_CAP_* defines. + */ +#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */ +#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */ +#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */ +#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to + packet loss */ +#define VPX_CODEC_CAP_INPUT_FRAGMENTS 0x100000 /**< Can receive encoded frames + one fragment at a time */ + + /*! \brief Initialization-time Feature Enabling + * + * Certain codec features must be known at initialization time, to allow for + * proper memory allocation. + * + * The available flags are specified by VPX_CODEC_USE_* defines. + */ +#define VPX_CODEC_CAP_FRAME_THREADING 0x200000 /**< Can support frame-based + multi-threading */ +#define VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER 0x400000 /**< Can support external + frame buffers */ + +#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */ +#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded + frames */ +#define VPX_CODEC_USE_INPUT_FRAGMENTS 0x40000 /**< The input frame should be + passed to the decoder one + fragment at a time */ +#define VPX_CODEC_USE_FRAME_THREADING 0x80000 /**< Enable frame-based + multi-threading */ + + /*!\brief Stream properties + * + * This structure is used to query or set properties of the decoded + * stream. Algorithms may extend this structure with data specific + * to their bitstream by setting the sz member appropriately. + */ + typedef struct vpx_codec_stream_info { + unsigned int sz; /**< Size of this structure */ + unsigned int w; /**< Width (or 0 for unknown/default) */ + unsigned int h; /**< Height (or 0 for unknown/default) */ + unsigned int is_kf; /**< Current frame is a keyframe */ + } vpx_codec_stream_info_t; + + /* REQUIRED FUNCTIONS + * + * The following functions are required to be implemented for all decoders. + * They represent the base case functionality expected of all decoders. + */ + + + /*!\brief Initialization Configurations + * + * This structure is used to pass init time configuration options to the + * decoder. + */ + typedef struct vpx_codec_dec_cfg { + unsigned int threads; /**< Maximum number of threads to use, default 1 */ + unsigned int w; /**< Width */ + unsigned int h; /**< Height */ + } vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */ + + + /*!\brief Initialize a decoder instance + * + * Initializes a decoder context using the given interface. Applications + * should call the vpx_codec_dec_init convenience macro instead of this + * function directly, to ensure that the ABI version number parameter + * is properly initialized. + * + * If the library was configured with --disable-multithread, this call + * is not thread safe and should be guarded with a lock if being used + * in a multithreaded context. + * + * \param[in] ctx Pointer to this instance's context. + * \param[in] iface Pointer to the algorithm interface to use. + * \param[in] cfg Configuration to use, if known. May be NULL. + * \param[in] flags Bitfield of VPX_CODEC_USE_* flags + * \param[in] ver ABI version number. Must be set to + * VPX_DECODER_ABI_VERSION + * \retval #VPX_CODEC_OK + * The decoder algorithm initialized. + * \retval #VPX_CODEC_MEM_ERROR + * Memory allocation failed. + */ + vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx, + vpx_codec_iface_t *iface, + const vpx_codec_dec_cfg_t *cfg, + vpx_codec_flags_t flags, + int ver); + + /*!\brief Convenience macro for vpx_codec_dec_init_ver() + * + * Ensures the ABI version parameter is properly set. + */ +#define vpx_codec_dec_init(ctx, iface, cfg, flags) \ + vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION) + + + /*!\brief Parse stream info from a buffer + * + * Performs high level parsing of the bitstream. Construction of a decoder + * context is not necessary. Can be used to determine if the bitstream is + * of the proper format, and to extract information from the stream. + * + * \param[in] iface Pointer to the algorithm interface + * \param[in] data Pointer to a block of data to parse + * \param[in] data_sz Size of the data buffer + * \param[in,out] si Pointer to stream info to update. The size member + * \ref MUST be properly initialized, but \ref MAY be + * clobbered by the algorithm. This parameter \ref MAY + * be NULL. + * + * \retval #VPX_CODEC_OK + * Bitstream is parsable and stream information updated + */ + vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, + const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si); + + + /*!\brief Return information about the current stream. + * + * Returns information about the stream that has been parsed during decoding. + * + * \param[in] ctx Pointer to this instance's context + * \param[in,out] si Pointer to stream info to update. The size member + * \ref MUST be properly initialized, but \ref MAY be + * clobbered by the algorithm. This parameter \ref MAY + * be NULL. + * + * \retval #VPX_CODEC_OK + * Bitstream is parsable and stream information updated + */ + vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx, + vpx_codec_stream_info_t *si); + + + /*!\brief Decode data + * + * Processes a buffer of coded data. If the processing results in a new + * decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be + * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode + * time stamp) order. Frames produced will always be in PTS (presentation + * time stamp) order. + * If the decoder is configured with VPX_CODEC_USE_INPUT_FRAGMENTS enabled, + * data and data_sz can contain a fragment of the encoded frame. Fragment + * \#n must contain at least partition \#n, but can also contain subsequent + * partitions (\#n+1 - \#n+i), and if so, fragments \#n+1, .., \#n+i must + * be empty. When no more data is available, this function should be called + * with NULL as data and 0 as data_sz. The memory passed to this function + * must be available until the frame has been decoded. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] data Pointer to this block of new coded data. If + * NULL, a VPX_CODEC_CB_PUT_FRAME event is posted + * for the previously decoded frame. + * \param[in] data_sz Size of the coded data, in bytes. + * \param[in] user_priv Application specific data to associate with + * this frame. + * \param[in] deadline Soft deadline the decoder should attempt to meet, + * in us. Set to zero for unlimited. + * + * \return Returns #VPX_CODEC_OK if the coded data was processed completely + * and future pictures can be decoded without error. Otherwise, + * see the descriptions of the other error codes in ::vpx_codec_err_t + * for recoverability capabilities. + */ + vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, + const uint8_t *data, + unsigned int data_sz, + void *user_priv, + long deadline); + + + /*!\brief Decoded frames iterator + * + * Iterates over a list of the frames available for display. The iterator + * storage should be initialized to NULL to start the iteration. Iteration is + * complete when this function returns NULL. + * + * The list of available frames becomes valid upon completion of the + * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode. + * + * \param[in] ctx Pointer to this instance's context + * \param[in,out] iter Iterator storage, initialized to NULL + * + * \return Returns a pointer to an image, if one is ready for display. Frames + * produced will always be in PTS (presentation time stamp) order. + */ + vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, + vpx_codec_iter_t *iter); + + + /*!\defgroup cap_put_frame Frame-Based Decoding Functions + * + * The following functions are required to be implemented for all decoders + * that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these functions + * for codecs that don't advertise this capability will result in an error + * code being returned, usually VPX_CODEC_ERROR + * @{ + */ + + /*!\brief put frame callback prototype + * + * This callback is invoked by the decoder to notify the application of + * the availability of decoded image data. + */ + typedef void (*vpx_codec_put_frame_cb_fn_t)(void *user_priv, + const vpx_image_t *img); + + + /*!\brief Register for notification of frame completion. + * + * Registers a given function to be called when a decoded frame is + * available. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] cb Pointer to the callback function + * \param[in] user_priv User's private data + * + * \retval #VPX_CODEC_OK + * Callback successfully registered. + * \retval #VPX_CODEC_ERROR + * Decoder context not initialized, or algorithm not capable of + * posting slice completion. + */ + vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, + vpx_codec_put_frame_cb_fn_t cb, + void *user_priv); + + + /*!@} - end defgroup cap_put_frame */ + + /*!\defgroup cap_put_slice Slice-Based Decoding Functions + * + * The following functions are required to be implemented for all decoders + * that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these functions + * for codecs that don't advertise this capability will result in an error + * code being returned, usually VPX_CODEC_ERROR + * @{ + */ + + /*!\brief put slice callback prototype + * + * This callback is invoked by the decoder to notify the application of + * the availability of partially decoded image data. The + */ + typedef void (*vpx_codec_put_slice_cb_fn_t)(void *user_priv, + const vpx_image_t *img, + const vpx_image_rect_t *valid, + const vpx_image_rect_t *update); + + + /*!\brief Register for notification of slice completion. + * + * Registers a given function to be called when a decoded slice is + * available. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] cb Pointer to the callback function + * \param[in] user_priv User's private data + * + * \retval #VPX_CODEC_OK + * Callback successfully registered. + * \retval #VPX_CODEC_ERROR + * Decoder context not initialized, or algorithm not capable of + * posting slice completion. + */ + vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, + vpx_codec_put_slice_cb_fn_t cb, + void *user_priv); + + + /*!@} - end defgroup cap_put_slice*/ + + /*!\defgroup cap_external_frame_buffer External Frame Buffer Functions + * + * The following section is required to be implemented for all decoders + * that advertise the VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER capability. + * Calling this function for codecs that don't advertise this capability + * will result in an error code being returned, usually VPX_CODEC_ERROR. + * + * \note + * Currently this only works with VP9. + * @{ + */ + + /*!\brief Pass in external frame buffers for the decoder to use. + * + * Registers functions to be called when libvpx needs a frame buffer + * to decode the current frame and a function to be called when libvpx does + * not internally reference the frame buffer. This set function must + * be called before the first call to decode or libvpx will assume the + * default behavior of allocating frame buffers internally. + * + * \param[in] ctx Pointer to this instance's context + * \param[in] cb_get Pointer to the get callback function + * \param[in] cb_release Pointer to the release callback function + * \param[in] cb_priv Callback's private data + * + * \retval #VPX_CODEC_OK + * External frame buffers will be used by libvpx. + * \retval #VPX_CODEC_INVALID_PARAM + * One or more of the callbacks were NULL. + * \retval #VPX_CODEC_ERROR + * Decoder context not initialized, or algorithm not capable of + * using external frame buffers. + * + * \note + * When decoding VP9, the application may be required to pass in at least + * #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS external frame + * buffers. + */ + vpx_codec_err_t vpx_codec_set_frame_buffer_functions( + vpx_codec_ctx_t *ctx, + vpx_get_frame_buffer_cb_fn_t cb_get, + vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv); + + /*!@} - end defgroup cap_external_frame_buffer */ + + /*!@} - end defgroup decoder*/ +#ifdef __cplusplus +} +#endif +#endif // VPX_VPX_DECODER_H_ + diff --git a/bin/windows/vpx/include/vpx/vpx_frame_buffer.h b/bin/windows/vpx/include/vpx/vpx_frame_buffer.h new file mode 100644 index 000000000..9036459af --- /dev/null +++ b/bin/windows/vpx/include/vpx/vpx_frame_buffer.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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 VPX_VPX_FRAME_BUFFER_H_ +#define VPX_VPX_FRAME_BUFFER_H_ + +/*!\file + * \brief Describes the decoder external frame buffer interface. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./vpx_integer.h" + +/*!\brief The maximum number of work buffers used by libvpx. + * Support maximum 4 threads to decode video in parallel. + * Each thread will use one work buffer. + * TODO(hkuang): Add support to set number of worker threads dynamically. + */ +#define VPX_MAXIMUM_WORK_BUFFERS 8 + +/*!\brief The maximum number of reference buffers that a VP9 encoder may use. + */ +#define VP9_MAXIMUM_REF_BUFFERS 8 + +/*!\brief External frame buffer + * + * This structure holds allocated frame buffers used by the decoder. + */ +typedef struct vpx_codec_frame_buffer { + uint8_t *data; /**< Pointer to the data buffer */ + size_t size; /**< Size of data in bytes */ + void *priv; /**< Frame's private data */ +} vpx_codec_frame_buffer_t; + +/*!\brief get frame buffer callback prototype + * + * This callback is invoked by the decoder to retrieve data for the frame + * buffer in order for the decode call to complete. The callback must + * allocate at least min_size in bytes and assign it to fb->data. The callback + * must zero out all the data allocated. Then the callback must set fb->size + * to the allocated size. The application does not need to align the allocated + * data. The callback is triggered when the decoder needs a frame buffer to + * decode a compressed image into. This function may be called more than once + * for every call to vpx_codec_decode. The application may set fb->priv to + * some data which will be passed back in the ximage and the release function + * call. |fb| is guaranteed to not be NULL. On success the callback must + * return 0. Any failure the callback must return a value less than 0. + * + * \param[in] priv Callback's private data + * \param[in] new_size Size in bytes needed by the buffer + * \param[in,out] fb Pointer to vpx_codec_frame_buffer_t + */ +typedef int (*vpx_get_frame_buffer_cb_fn_t)( + void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb); + +/*!\brief release frame buffer callback prototype + * + * This callback is invoked by the decoder when the frame buffer is not + * referenced by any other buffers. |fb| is guaranteed to not be NULL. On + * success the callback must return 0. Any failure the callback must return + * a value less than 0. + * + * \param[in] priv Callback's private data + * \param[in] fb Pointer to vpx_codec_frame_buffer_t + */ +typedef int (*vpx_release_frame_buffer_cb_fn_t)( + void *priv, vpx_codec_frame_buffer_t *fb); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VPX_FRAME_BUFFER_H_ diff --git a/bin/windows/vpx/include/vpx/vpx_image.h b/bin/windows/vpx/include/vpx/vpx_image.h new file mode 100644 index 000000000..7958c6980 --- /dev/null +++ b/bin/windows/vpx/include/vpx/vpx_image.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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. + */ + + +/*!\file + * \brief Describes the vpx image descriptor and associated operations + * + */ +#ifndef VPX_VPX_IMAGE_H_ +#define VPX_VPX_IMAGE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + /*!\brief Current ABI version number + * + * \internal + * If this file is altered in any way that changes the ABI, this value + * must be bumped. Examples include, but are not limited to, changing + * types, removing or reassigning enums, adding/removing/rearranging + * fields to structures + */ +#define VPX_IMAGE_ABI_VERSION (4) /**<\hideinitializer*/ + + +#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format. */ +#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U in memory. */ +#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel. */ +#define VPX_IMG_FMT_HIGHBITDEPTH 0x800 /**< Image uses 16bit framebuffer. */ + + /*!\brief List of supported image formats */ + typedef enum vpx_img_fmt { + VPX_IMG_FMT_NONE, + VPX_IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */ + VPX_IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */ + VPX_IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */ + VPX_IMG_FMT_RGB555, /**< 16 bit per pixel, 555 */ + VPX_IMG_FMT_UYVY, /**< UYVY packed YUV */ + VPX_IMG_FMT_YUY2, /**< YUYV packed YUV */ + VPX_IMG_FMT_YVYU, /**< YVYU packed YUV */ + VPX_IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */ + VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */ + VPX_IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */ + VPX_IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */ + VPX_IMG_FMT_RGB565_LE, /**< 16 bit per pixel, gggbbbbb rrrrrggg */ + VPX_IMG_FMT_RGB555_LE, /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */ + VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */ + VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2, + VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */ + VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4, + VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5, + VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6, + VPX_IMG_FMT_I440 = VPX_IMG_FMT_PLANAR | 7, + VPX_IMG_FMT_444A = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_HAS_ALPHA | 6, + VPX_IMG_FMT_I42016 = VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGHBITDEPTH, + VPX_IMG_FMT_I42216 = VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGHBITDEPTH, + VPX_IMG_FMT_I44416 = VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGHBITDEPTH, + VPX_IMG_FMT_I44016 = VPX_IMG_FMT_I440 | VPX_IMG_FMT_HIGHBITDEPTH + } vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */ + + /*!\brief List of supported color spaces */ + typedef enum vpx_color_space { + VPX_CS_UNKNOWN = 0, /**< Unknown */ + VPX_CS_BT_601 = 1, /**< BT.601 */ + VPX_CS_BT_709 = 2, /**< BT.709 */ + VPX_CS_SMPTE_170 = 3, /**< SMPTE.170 */ + VPX_CS_SMPTE_240 = 4, /**< SMPTE.240 */ + VPX_CS_BT_2020 = 5, /**< BT.2020 */ + VPX_CS_RESERVED = 6, /**< Reserved */ + VPX_CS_SRGB = 7 /**< sRGB */ + } vpx_color_space_t; /**< alias for enum vpx_color_space */ + + /*!\brief List of supported color range */ + typedef enum vpx_color_range { + VPX_CR_STUDIO_RANGE = 0, /**< Y [16..235], UV [16..240] */ + VPX_CR_FULL_RANGE = 1 /**< YUV/RGB [0..255] */ + } vpx_color_range_t; /**< alias for enum vpx_color_range */ + + /**\brief Image Descriptor */ + typedef struct vpx_image { + vpx_img_fmt_t fmt; /**< Image Format */ + vpx_color_space_t cs; /**< Color Space */ + vpx_color_range_t range; /**< Color Range */ + + /* Image storage dimensions */ + unsigned int w; /**< Stored image width */ + unsigned int h; /**< Stored image height */ + unsigned int bit_depth; /**< Stored image bit-depth */ + + /* Image display dimensions */ + unsigned int d_w; /**< Displayed image width */ + unsigned int d_h; /**< Displayed image height */ + + /* Image intended rendering dimensions */ + unsigned int r_w; /**< Intended rendering image width */ + unsigned int r_h; /**< Intended rendering image height */ + + /* Chroma subsampling info */ + unsigned int x_chroma_shift; /**< subsampling order, X */ + unsigned int y_chroma_shift; /**< subsampling order, Y */ + + /* Image data pointers. */ +#define VPX_PLANE_PACKED 0 /**< To be used for all packed formats */ +#define VPX_PLANE_Y 0 /**< Y (Luminance) plane */ +#define VPX_PLANE_U 1 /**< U (Chroma) plane */ +#define VPX_PLANE_V 2 /**< V (Chroma) plane */ +#define VPX_PLANE_ALPHA 3 /**< A (Transparency) plane */ + unsigned char *planes[4]; /**< pointer to the top left pixel for each plane */ + int stride[4]; /**< stride between rows for each plane */ + + int bps; /**< bits per sample (for packed formats) */ + + /* The following member may be set by the application to associate data + * with this image. + */ + void *user_priv; /**< may be set by the application to associate data + * with this image. */ + + /* The following members should be treated as private. */ + unsigned char *img_data; /**< private */ + int img_data_owner; /**< private */ + int self_allocd; /**< private */ + + void *fb_priv; /**< Frame buffer data associated with the image. */ + } vpx_image_t; /**< alias for struct vpx_image */ + + /**\brief Representation of a rectangle on a surface */ + typedef struct vpx_image_rect { + unsigned int x; /**< leftmost column */ + unsigned int y; /**< topmost row */ + unsigned int w; /**< width */ + unsigned int h; /**< height */ + } vpx_image_rect_t; /**< alias for struct vpx_image_rect */ + + /*!\brief Open a descriptor, allocating storage for the underlying image + * + * Returns a descriptor for storing an image of the given format. The + * storage for the descriptor is allocated on the heap. + * + * \param[in] img Pointer to storage for descriptor. If this parameter + * is NULL, the storage for the descriptor will be + * allocated on the heap. + * \param[in] fmt Format for the image + * \param[in] d_w Width of the image + * \param[in] d_h Height of the image + * \param[in] align Alignment, in bytes, of the image buffer and + * each row in the image(stride). + * + * \return Returns a pointer to the initialized image descriptor. If the img + * parameter is non-null, the value of the img parameter will be + * returned. + */ + vpx_image_t *vpx_img_alloc(vpx_image_t *img, + vpx_img_fmt_t fmt, + unsigned int d_w, + unsigned int d_h, + unsigned int align); + + /*!\brief Open a descriptor, using existing storage for the underlying image + * + * Returns a descriptor for storing an image of the given format. The + * storage for descriptor has been allocated elsewhere, and a descriptor is + * desired to "wrap" that storage. + * + * \param[in] img Pointer to storage for descriptor. If this parameter + * is NULL, the storage for the descriptor will be + * allocated on the heap. + * \param[in] fmt Format for the image + * \param[in] d_w Width of the image + * \param[in] d_h Height of the image + * \param[in] align Alignment, in bytes, of each row in the image. + * \param[in] img_data Storage to use for the image + * + * \return Returns a pointer to the initialized image descriptor. If the img + * parameter is non-null, the value of the img parameter will be + * returned. + */ + vpx_image_t *vpx_img_wrap(vpx_image_t *img, + vpx_img_fmt_t fmt, + unsigned int d_w, + unsigned int d_h, + unsigned int align, + unsigned char *img_data); + + + /*!\brief Set the rectangle identifying the displayed portion of the image + * + * Updates the displayed rectangle (aka viewport) on the image surface to + * match the specified coordinates and size. + * + * \param[in] img Image descriptor + * \param[in] x leftmost column + * \param[in] y topmost row + * \param[in] w width + * \param[in] h height + * + * \return 0 if the requested rectangle is valid, nonzero otherwise. + */ + int vpx_img_set_rect(vpx_image_t *img, + unsigned int x, + unsigned int y, + unsigned int w, + unsigned int h); + + + /*!\brief Flip the image vertically (top for bottom) + * + * Adjusts the image descriptor's pointers and strides to make the image + * be referenced upside-down. + * + * \param[in] img Image descriptor + */ + void vpx_img_flip(vpx_image_t *img); + + /*!\brief Close an image descriptor + * + * Frees all allocated storage associated with an image descriptor. + * + * \param[in] img Image descriptor + */ + void vpx_img_free(vpx_image_t *img); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VPX_IMAGE_H_ diff --git a/bin/windows/vpx/include/vpx/vpx_integer.h b/bin/windows/vpx/include/vpx/vpx_integer.h new file mode 100644 index 000000000..829c9d132 --- /dev/null +++ b/bin/windows/vpx/include/vpx/vpx_integer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE 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 VPX_VPX_INTEGER_H_ +#define VPX_VPX_INTEGER_H_ + +/* get ptrdiff_t, size_t, wchar_t, NULL */ +#include + +#if defined(_MSC_VER) +#define VPX_FORCE_INLINE __forceinline +#define VPX_INLINE __inline +#else +#define VPX_FORCE_INLINE __inline__ __attribute__(always_inline) +// TODO(jbb): Allow a way to force inline off for older compilers. +#define VPX_INLINE inline +#endif + +#if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES) +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#if (defined(_MSC_VER) && (_MSC_VER < 1600)) +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#define INT64_MAX _I64_MAX +#define INT32_MAX _I32_MAX +#define INT32_MIN _I32_MIN +#define INT16_MAX _I16_MAX +#define INT16_MIN _I16_MIN +#endif + +#ifndef _UINTPTR_T_DEFINED +typedef size_t uintptr_t; +#endif + +#else + +/* Most platforms have the C99 standard integer types. */ + +#if defined(__cplusplus) +# if !defined(__STDC_FORMAT_MACROS) +# define __STDC_FORMAT_MACROS +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS +# endif +#endif // __cplusplus + +#include + +#endif + +/* VS2010 defines stdint.h, but not inttypes.h */ +#if defined(_MSC_VER) && _MSC_VER < 1800 +#define PRId64 "I64d" +#else +#include +#endif + +#endif // VPX_VPX_INTEGER_H_ diff --git a/bin/windows/vpx/lib/32/libcompat-to-msvc.lib b/bin/windows/vpx/lib/32/libcompat-to-msvc.lib new file mode 100644 index 000000000..6ec8b870e Binary files /dev/null and b/bin/windows/vpx/lib/32/libcompat-to-msvc.lib differ diff --git a/bin/windows/vpx/lib/32/libvpx.lib b/bin/windows/vpx/lib/32/libvpx.lib new file mode 100644 index 000000000..1a9753e32 Binary files /dev/null and b/bin/windows/vpx/lib/32/libvpx.lib differ diff --git a/bin/windows/vpx/lib/64/libcompat-to-msvc.lib b/bin/windows/vpx/lib/64/libcompat-to-msvc.lib new file mode 100644 index 000000000..5428547cc Binary files /dev/null and b/bin/windows/vpx/lib/64/libcompat-to-msvc.lib differ diff --git a/bin/windows/vpx/lib/64/libvpx.lib b/bin/windows/vpx/lib/64/libvpx.lib new file mode 100644 index 000000000..3b552c027 Binary files /dev/null and b/bin/windows/vpx/lib/64/libvpx.lib differ diff --git a/bin/windows/vpx/lib/arm64/libvpx.lib b/bin/windows/vpx/lib/arm64/libvpx.lib new file mode 100644 index 000000000..17f7a3294 Binary files /dev/null and b/bin/windows/vpx/lib/arm64/libvpx.lib differ diff --git a/bin/windows/vpx/lib/instructions.txt b/bin/windows/vpx/lib/instructions.txt new file mode 100644 index 000000000..a028c7595 --- /dev/null +++ b/bin/windows/vpx/lib/instructions.txt @@ -0,0 +1,44 @@ +Instructions for Building EDuke32's Library Dependencies Targeting Win32 and Win64 +================================================================================== + +First, follow these instructions: http://wiki.eduke32.com/wiki/Building_EDuke32_on_Windows + +Download the latest sources from the link provided. + +The build output listed as "Desired Results" is what EDuke32 needs to function. + +The desired results for each library in some cases may need to be installed to the compiler. "x depends on the results of y to compile" means that the build output of x must be added to the compiler in this way. Copy files listed in each category to the appropriate destinations. Unless otherwise noted, do NOT copy the ".dll.a" file or else the final product may depend on external DLLs (which you may actually want). + +For MinGW (MinGW32): +from the compiler root (ex. C:/MinGW/) + * headers: include/ + * libraries: lib/ + +For MinGW-w64: +from the compiler root (ex. C:/MinGW-w64/mingw32-dw2/) + * headers: -w64-mingw32/include/ + * libraries: -w64-mingw32/lib/ + +Binaries (if mentioned) need to be present with the finished EDuke32 executables. They are not needed during compilation. + +NB: Text formatted as code blocks are commands to be pasted into the Windows command prompt. +http://wiki.eduke32.com/wiki/Working_with_the_Windows_Command_Prompt + +[//]: # (Plain text readers: This refers to lines beginning with exactly four spaces.) + + +libvpx +------ +### Prerequisites ### +Download the binary of yasm (http://yasm.tortall.net/) for your host system architecture. Both builds target both architectures. +The build environment needs pr.exe (https://mingw-lib.googlecode.com/files/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2). +### Download ### + * Instructions: http://www.webmproject.org/code/ + * Stable: http://downloads.webmproject.org/releases/webm/ + * Git: https://chromium.googlesource.com/webm/libvpx +### Build ### + sh ./configure --disable-vp8-encoder --disable-vp9-encoder --disable-multithread --disable-spatial-resampling --as=yasm && make libvpx.a +### Desired Results ### + * headers: vpx/vp8.h vpx/vp8dx.h vpx/vpx_codec.h vpx/vpx_decoder.h vpx/vpx_frame_buffer.h vpx/vpx_image.h vpx/vpx_integer.h + * libraries: libvpx.a + diff --git a/bin/windows/vpx/src/_dbg_LOAD_IMAGE.h b/bin/windows/vpx/src/_dbg_LOAD_IMAGE.h new file mode 100644 index 000000000..0568f3016 --- /dev/null +++ b/bin/windows/vpx/src/_dbg_LOAD_IMAGE.h @@ -0,0 +1,55 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _dbg_LOAD_IMAGE_h +#define _dbg_LOAD_IMAGE_h + +#ifndef WINAPI +#define WINAPI __stdcall +#endif + +#define IMAGEAPI DECLSPEC_IMPORT WINAPI +#define DBHLP_DEPRECIATED __declspec(deprecated) + +#define DBHLPAPI IMAGEAPI + +#ifndef EBACKTRACE_MINGW32 + +#define IMAGE_SEPARATION (64*1024) + + typedef struct _LOADED_IMAGE { + PSTR ModuleName; + HANDLE hFile; + PUCHAR MappedAddress; +#ifdef _IMAGEHLP64 + PIMAGE_NT_HEADERS64 FileHeader; +#else + PIMAGE_NT_HEADERS32 FileHeader; +#endif + PIMAGE_SECTION_HEADER LastRvaSection; + ULONG NumberOfSections; + PIMAGE_SECTION_HEADER Sections; + ULONG Characteristics; + BOOLEAN fSystemImage; + BOOLEAN fDOSImage; + BOOLEAN fReadOnly; + UCHAR Version; + LIST_ENTRY Links; + ULONG SizeOfImage; + } LOADED_IMAGE,*PLOADED_IMAGE; + +#endif + +#define MAX_SYM_NAME 2000 + + typedef struct _MODLOAD_DATA { + DWORD ssize; + DWORD ssig; + PVOID data; + DWORD size; + DWORD flags; + } MODLOAD_DATA,*PMODLOAD_DATA; + +#endif diff --git a/bin/windows/vpx/src/_dbg_common.h b/bin/windows/vpx/src/_dbg_common.h new file mode 100644 index 000000000..2c412e4cc --- /dev/null +++ b/bin/windows/vpx/src/_dbg_common.h @@ -0,0 +1,2051 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _dbg_common_h +#define _dbg_common_h + +// from _mingw_mac.h +#ifndef __MINGW_EXTENSION +#if defined(__GNUC__) || defined(__GNUG__) +#define __MINGW_EXTENSION __extension__ +#else +#define __MINGW_EXTENSION +#endif +#endif + +/* Special case nameless struct/union. */ +#ifndef __C89_NAMELESS +#define __C89_NAMELESS __MINGW_EXTENSION + +#define __C89_NAMELESSSTRUCTNAME +#define __C89_NAMELESSUNIONNAME +#endif + +#include "_dbg_LOAD_IMAGE.h" + +// from winnt.h +#if defined(UNICODE) + typedef LPWSTR LPTCH,PTCH; + typedef LPWSTR PTSTR,LPTSTR; + typedef LPCWSTR PCTSTR,LPCTSTR; + typedef LPUWSTR PUTSTR,LPUTSTR; + typedef LPCUWSTR PCUTSTR,LPCUTSTR; + typedef LPWSTR LP; +#else + typedef LPSTR LPTCH,PTCH; + typedef LPSTR PTSTR,LPTSTR,PUTSTR,LPUTSTR; + typedef LPCSTR PCTSTR,LPCTSTR,PCUTSTR,LPCUTSTR; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef WINBOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACK)(HANDLE FileHandle,PCSTR FileName,PVOID CallerData); + typedef WINBOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACKW)(HANDLE FileHandle,PCWSTR FileName,PVOID CallerData); + typedef WINBOOL (CALLBACK *PFINDFILEINPATHCALLBACK)(PCSTR filename,PVOID context); + typedef WINBOOL (CALLBACK *PFINDFILEINPATHCALLBACKW)(PCWSTR filename,PVOID context); + typedef WINBOOL (CALLBACK *PFIND_EXE_FILE_CALLBACK)(HANDLE FileHandle,PCSTR FileName,PVOID CallerData); + typedef WINBOOL (CALLBACK *PFIND_EXE_FILE_CALLBACKW)(HANDLE FileHandle,PCWSTR FileName,PVOID CallerData); + + typedef WINBOOL (WINAPI *PSYMBOLSERVERPROC)(LPCSTR,LPCSTR,PVOID,DWORD,DWORD,LPSTR); + typedef WINBOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID); + typedef WINBOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID); + typedef WINBOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR,ULONG64); + typedef WINBOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action,ULONG64 data,ULONG64 context); + typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)(); + typedef WINBOOL (WINAPI *PSYMBOLSERVERPINGPROC)(LPCSTR); + +#ifndef EBACKTRACE_MINGW32 + HANDLE IMAGEAPI FindDebugInfoFile(PCSTR FileName,PCSTR SymbolPath,PSTR DebugFilePath); +#endif + HANDLE IMAGEAPI FindDebugInfoFileEx(PCSTR FileName,PCSTR SymbolPath,PSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACK Callback,PVOID CallerData); + HANDLE IMAGEAPI FindDebugInfoFileExW(PCWSTR FileName,PCWSTR SymbolPath,PWSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACKW Callback,PVOID CallerData); + WINBOOL IMAGEAPI SymFindFileInPath(HANDLE hprocess,PCSTR SearchPath,PCSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACK callback,PVOID context); + WINBOOL IMAGEAPI SymFindFileInPathW(HANDLE hprocess,PCWSTR SearchPath,PCWSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACKW callback,PVOID context); +#ifndef EBACKTRACE_MINGW32 + HANDLE IMAGEAPI FindExecutableImage(PCSTR FileName,PCSTR SymbolPath,PSTR ImageFilePath); +#endif + HANDLE IMAGEAPI FindExecutableImageEx(PCSTR FileName,PCSTR SymbolPath,PSTR ImageFilePath,PFIND_EXE_FILE_CALLBACK Callback,PVOID CallerData); + HANDLE IMAGEAPI FindExecutableImageExW(PCWSTR FileName,PCWSTR SymbolPath,PWSTR ImageFilePath,PFIND_EXE_FILE_CALLBACKW Callback,PVOID CallerData); + PIMAGE_NT_HEADERS IMAGEAPI ImageNtHeader(PVOID Base); + PVOID IMAGEAPI ImageDirectoryEntryToDataEx(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size,PIMAGE_SECTION_HEADER *FoundHeader); + PVOID IMAGEAPI ImageDirectoryEntryToData(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size); + PIMAGE_SECTION_HEADER IMAGEAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva); + PVOID IMAGEAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva,PIMAGE_SECTION_HEADER *LastRvaSection); + +#define SSRVOPT_CALLBACK 0x0001 +#define SSRVOPT_DWORD 0x0002 +#define SSRVOPT_DWORDPTR 0x0004 +#define SSRVOPT_GUIDPTR 0x0008 +#define SSRVOPT_OLDGUIDPTR 0x0010 +#define SSRVOPT_UNATTENDED 0x0020 +#define SSRVOPT_NOCOPY 0x0040 +#define SSRVOPT_PARENTWIN 0x0080 +#define SSRVOPT_PARAMTYPE 0x0100 +#define SSRVOPT_SECURE 0x0200 +#define SSRVOPT_TRACE 0x0400 +#define SSRVOPT_SETCONTEXT 0x0800 +#define SSRVOPT_PROXY 0x1000 +#define SSRVOPT_DOWNSTREAM_STORE 0x2000 +#define SSRVOPT_RESET ((ULONG_PTR)-1) + +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 + +#if !defined _WIN64 && !defined EBACKTRACE_MINGW32 + typedef struct _IMAGE_DEBUG_INFORMATION { + LIST_ENTRY List; + DWORD ReservedSize; + PVOID ReservedMappedBase; + USHORT ReservedMachine; + USHORT ReservedCharacteristics; + DWORD ReservedCheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD ReservedNumberOfSections; + PIMAGE_SECTION_HEADER ReservedSections; + DWORD ReservedExportedNamesSize; + PSTR ReservedExportedNames; + DWORD ReservedNumberOfFunctionTableEntries; + PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries; + DWORD ReservedLowestFunctionStartingAddress; + DWORD ReservedHighestFunctionEndingAddress; + DWORD ReservedNumberOfFpoTableEntries; + PFPO_DATA ReservedFpoTableEntries; + DWORD SizeOfCoffSymbols; + PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols; + DWORD ReservedSizeOfCodeViewSymbols; + PVOID ReservedCodeViewSymbols; + PSTR ImageFilePath; + PSTR ImageFileName; + PSTR ReservedDebugFilePath; + DWORD ReservedTimeDateStamp; + WINBOOL ReservedRomImage; + PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory; + DWORD ReservedNumberOfDebugDirectories; + DWORD ReservedOriginalFunctionTableBaseAddress; + DWORD Reserved[2]; + } IMAGE_DEBUG_INFORMATION,*PIMAGE_DEBUG_INFORMATION; + + PIMAGE_DEBUG_INFORMATION IMAGEAPI MapDebugInformation(HANDLE FileHandle,PSTR FileName,PSTR SymbolPath,DWORD ImageBase); + WINBOOL IMAGEAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo); +#endif + + typedef WINBOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR FilePath,PVOID CallerData); + + WINBOOL IMAGEAPI SearchTreeForFile(PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer); + WINBOOL IMAGEAPI SearchTreeForFileW(PWSTR RootPath,PWSTR InputPathName,PWSTR OutputPathBuffer); + WINBOOL IMAGEAPI EnumDirTree(HANDLE hProcess,PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer,PENUMDIRTREE_CALLBACK Callback,PVOID CallbackData); + WINBOOL IMAGEAPI MakeSureDirectoryPathExists(PCSTR DirPath); + +#ifndef EBACKTRACE_MINGW32 +#define UNDNAME_COMPLETE (0x0000) +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) +#define UNDNAME_NO_MS_KEYWORDS (0x0002) +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) +#define UNDNAME_NO_MS_THISTYPE (0x0020) +#define UNDNAME_NO_CV_THISTYPE (0x0040) +#define UNDNAME_NO_THISTYPE (0x0060) +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) +#define UNDNAME_NO_MEMBER_TYPE (0x0200) +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) +#define UNDNAME_32_BIT_DECODE (0x0800) +#define UNDNAME_NAME_ONLY (0x1000) +#define UNDNAME_NO_ARGUMENTS (0x2000) +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) + +#define UNDNAME_NO_ARGUMENTS (0x2000) +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) +#endif + + DWORD IMAGEAPI WINAPI UnDecorateSymbolName(PCSTR DecoratedName,PSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags); + DWORD IMAGEAPI WINAPI UnDecorateSymbolNameW(PCWSTR DecoratedName,PWSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define UnDecorateSymbolName UnDecorateSymbolNameW +#endif + +#define DBHHEADER_DEBUGDIRS 0x1 +#define DBHHEADER_CVMISC 0x2 + + typedef struct _MODLOAD_CVMISC { + DWORD oCV; + size_t cCV; + DWORD oMisc; + size_t cMisc; + DWORD dtImage; + DWORD cImage; + } MODLOAD_CVMISC, *PMODLOAD_CVMISC; + +#ifndef EBACKTRACE_MINGW32 + typedef enum { + AddrMode1616, + AddrMode1632, + AddrModeReal, + AddrModeFlat + } ADDRESS_MODE; +#endif + + typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS64,*LPADDRESS64; + +#ifdef _IMAGEHLP64 +#define ADDRESS ADDRESS64 +#define LPADDRESS LPADDRESS64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _tagADDRESS { + DWORD Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS,*LPADDRESS; + + static __inline void Address32To64(LPADDRESS a32,LPADDRESS64 a64) { + a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset; + a64->Segment = a32->Segment; + a64->Mode = a32->Mode; + } + + static __inline void Address64To32(LPADDRESS64 a64,LPADDRESS a32) { + a32->Offset = (ULONG)a64->Offset; + a32->Segment = a64->Segment; + a32->Mode = a64->Mode; + } +#endif + + typedef struct _KDHELP64 { + DWORD64 Thread; + DWORD ThCallbackStack; + DWORD ThCallbackBStore; + DWORD NextCallback; + DWORD FramePointer; + DWORD64 KiCallUserMode; + DWORD64 KeUserCallbackDispatcher; + DWORD64 SystemRangeStart; + DWORD64 KiUserExceptionDispatcher; + DWORD64 StackBase; + DWORD64 StackLimit; + DWORD64 Reserved[5]; + } KDHELP64,*PKDHELP64; + +#ifdef _IMAGEHLP64 +#define KDHELP KDHELP64 +#define PKDHELP PKDHELP64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _KDHELP { + DWORD Thread; + DWORD ThCallbackStack; + DWORD NextCallback; + DWORD FramePointer; + DWORD KiCallUserMode; + DWORD KeUserCallbackDispatcher; + DWORD SystemRangeStart; + DWORD ThCallbackBStore; + DWORD KiUserExceptionDispatcher; + DWORD StackBase; + DWORD StackLimit; + DWORD Reserved[5]; + } KDHELP,*PKDHELP; + + static __inline void KdHelp32To64(PKDHELP p32,PKDHELP64 p64) { + p64->Thread = p32->Thread; + p64->ThCallbackStack = p32->ThCallbackStack; + p64->NextCallback = p32->NextCallback; + p64->FramePointer = p32->FramePointer; + p64->KiCallUserMode = p32->KiCallUserMode; + p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher; + p64->SystemRangeStart = p32->SystemRangeStart; + p64->KiUserExceptionDispatcher = p32->KiUserExceptionDispatcher; + p64->StackBase = p32->StackBase; + p64->StackLimit = p32->StackLimit; + } +#endif + + typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; + ADDRESS64 AddrReturn; + ADDRESS64 AddrFrame; + ADDRESS64 AddrStack; + ADDRESS64 AddrBStore; + PVOID FuncTableEntry; + DWORD64 Params[4]; + WINBOOL Far; + WINBOOL Virtual; + DWORD64 Reserved[3]; + KDHELP64 KdHelp; + } STACKFRAME64,*LPSTACKFRAME64; + +#ifdef _IMAGEHLP64 +#define STACKFRAME STACKFRAME64 +#define LPSTACKFRAME LPSTACKFRAME64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _tagSTACKFRAME { + ADDRESS AddrPC; + ADDRESS AddrReturn; + ADDRESS AddrFrame; + ADDRESS AddrStack; + PVOID FuncTableEntry; + DWORD Params[4]; + WINBOOL Far; + WINBOOL Virtual; + DWORD Reserved[3]; + KDHELP KdHelp; + ADDRESS AddrBStore; + } STACKFRAME,*LPSTACKFRAME; +#endif + + typedef WINBOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,DWORD64 qwBaseAddress,PVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess,DWORD64 AddrBase); + typedef DWORD64 (WINAPI *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,DWORD64 Address); + typedef DWORD64 (WINAPI *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,HANDLE hThread,LPADDRESS64 lpaddr); + + WINBOOL IMAGEAPI StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 +GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + +#ifdef _IMAGEHLP64 +#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 +#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 +#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 +#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 +#define StackWalk StackWalk64 +#elif !defined(EBACKTRACE_MINGW32) + typedef WINBOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE)(HANDLE hProcess,DWORD lpBaseAddress,PVOID lpBuffer,DWORD nSize,PDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE)(HANDLE hProcess,DWORD AddrBase); + typedef DWORD (WINAPI *PGET_MODULE_BASE_ROUTINE)(HANDLE hProcess,DWORD Address); + typedef DWORD (WINAPI *PTRANSLATE_ADDRESS_ROUTINE)(HANDLE hProcess,HANDLE hThread,LPADDRESS lpaddr); + + WINBOOL IMAGEAPI StackWalk(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE +GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE TranslateAddress); +#endif + +#ifndef EBACKTRACE_MINGW32 +#define API_VERSION_NUMBER 11 + + typedef struct API_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; + USHORT Revision; + USHORT Reserved; + } API_VERSION,*LPAPI_VERSION; +#endif + + LPAPI_VERSION IMAGEAPI ImagehlpApiVersion(VOID); + LPAPI_VERSION IMAGEAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion); + DWORD IMAGEAPI GetTimestampForLoadedLibrary(HMODULE Module); + + typedef WINBOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK64)(PCSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACKW64)(PCWSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)(PCSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)(PCWSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK64)(PCSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)(PCWSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)(HANDLE hProcess,DWORD AddrBase,PVOID UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)(HANDLE hProcess,ULONG64 AddrBase,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W +#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64 +#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64 +#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64 +#elif !defined(EBACKTRACE_MINGW32) + typedef WINBOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK)(PCSTR ModuleName,ULONG BaseOfDll,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)(PCSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)(PCWSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK)(PCSTR ModuleName,ULONG ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess,ULONG ActionCode,PVOID CallbackData,PVOID UserContext); +#endif + +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_VIRTUAL 0x00001000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 + +#ifndef EBACKTRACE_MINGW32 + typedef enum { + SymNone = 0, + SymCoff, + SymCv, + SymPdb, + SymExport, + SymDeferred, + SymSym, + SymDia, + SymVirtual, + NumSymTypes + } SYM_TYPE; +#endif + + typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; + DWORD64 Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL64,*PIMAGEHLP_SYMBOL64; + + typedef struct _IMAGEHLP_SYMBOL64_PACKAGE { + IMAGEHLP_SYMBOL64 sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL64_PACKAGE,*PIMAGEHLP_SYMBOL64_PACKAGE; + +#ifdef _IMAGEHLP64 + +#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 +#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 +#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE +#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE +#elif !defined(EBACKTRACE_MINGW32) + + typedef struct _IMAGEHLP_SYMBOL { + DWORD SizeOfStruct; + DWORD Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL,*PIMAGEHLP_SYMBOL; + + typedef struct _IMAGEHLP_SYMBOL_PACKAGE { + IMAGEHLP_SYMBOL sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL_PACKAGE,*PIMAGEHLP_SYMBOL_PACKAGE; +#endif + + typedef struct _IMAGEHLP_MODULE64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + CHAR LoadedPdbName[256]; + DWORD CVSig; + CHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + WINBOOL PdbUnmatched; + WINBOOL DbgUnmatched; + WINBOOL LineNumbers; + WINBOOL GlobalSymbols; + WINBOOL TypeInfo; + WINBOOL SourceIndexed; + WINBOOL Publics; + } IMAGEHLP_MODULE64,*PIMAGEHLP_MODULE64; + + typedef struct _IMAGEHLP_MODULE64W { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + WCHAR LoadedPdbName[256]; + DWORD CVSig; + WCHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + WINBOOL PdbUnmatched; + WINBOOL DbgUnmatched; + WINBOOL LineNumbers; + WINBOOL GlobalSymbols; + WINBOOL TypeInfo; + WINBOOL SourceIndexed; + WINBOOL Publics; + } IMAGEHLP_MODULEW64,*PIMAGEHLP_MODULEW64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_MODULE IMAGEHLP_MODULE64 +#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 +#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _IMAGEHLP_MODULE { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + } IMAGEHLP_MODULE,*PIMAGEHLP_MODULE; + + typedef struct _IMAGEHLP_MODULEW { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + } IMAGEHLP_MODULEW,*PIMAGEHLP_MODULEW; +#endif + + typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD64 Address; + } IMAGEHLP_LINE64,*PIMAGEHLP_LINE64; + + typedef struct _IMAGEHLP_LINEW64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PWSTR FileName; + DWORD64 Address; + } IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_LINE IMAGEHLP_LINE64 +#define PIMAGEHLP_LINE PIMAGEHLP_LINE64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _IMAGEHLP_LINE { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD Address; + } IMAGEHLP_LINE,*PIMAGEHLP_LINE; +#endif + + typedef struct _SOURCEFILE { + DWORD64 ModBase; + PCHAR FileName; + } SOURCEFILE,*PSOURCEFILE; + + typedef struct _SOURCEFILEW { + DWORD64 ModBase; + PWCHAR FileName; + } SOURCEFILEW,*PSOURCEFILEW; + +#ifndef EBACKTRACE_MINGW32 +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_DEBUG_INFO 0x10000000 +#define CBA_SRCSRV_INFO 0x20000000 +#define CBA_SRCSRV_EVENT 0x40000000 +#endif + + typedef struct _IMAGEHLP_CBA_READ_MEMORY { + DWORD64 addr; + PVOID buf; + DWORD bytes; + DWORD *bytesread; + } IMAGEHLP_CBA_READ_MEMORY,*PIMAGEHLP_CBA_READ_MEMORY; + + enum { + sevInfo = 0, + sevProblem, + sevAttn, + sevFatal, + sevMax + }; + + typedef struct _IMAGEHLP_CBA_EVENT { + DWORD severity; + DWORD code; + PCHAR desc; + PVOID object; + } IMAGEHLP_CBA_EVENT,*PIMAGEHLP_CBA_EVENT; + + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + DWORD Flags; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD64,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD64; + +#define DSLFLAG_MISMATCHED_PDB 0x1 +#define DSLFLAG_MISMATCHED_DBG 0x2 + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD; +#endif + + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL64 Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL64,*PIMAGEHLP_DUPLICATE_SYMBOL64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64 +#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64 +#elif !defined(EBACKTRACE_MINGW32) + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL,*PIMAGEHLP_DUPLICATE_SYMBOL; +#endif + +typedef struct _SYMSRV_INDEX_INFO { + DWORD sizeofstruct; + CHAR file[MAX_PATH +1]; + WINBOOL stripped; + DWORD timestamp; + DWORD size; + CHAR dbgfile[MAX_PATH +1]; + CHAR pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFO, *PSYMSRV_INDEX_INFO; + +typedef struct _SYMSRV_INDEX_INFOW { + DWORD sizeofstruct; + WCHAR file[MAX_PATH +1]; + WINBOOL stripped; + DWORD timestamp; + DWORD size; + WCHAR dbgfile[MAX_PATH +1]; + WCHAR pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFOW, *PSYMSRV_INDEX_INFOW; + + WINBOOL IMAGEAPI SymSetParentWindow(HWND hwnd); + PCHAR IMAGEAPI SymSetHomeDirectory(HANDLE hProcess,PCSTR dir); + PCHAR IMAGEAPI SymSetHomeDirectoryW(HANDLE hProcess,PCWSTR dir); + PCHAR IMAGEAPI SymGetHomeDirectory(DWORD type,PSTR dir,size_t size); + PWCHAR IMAGEAPI SymGetHomeDirectoryW(DWORD type,PWSTR dir,size_t size); + +#define hdBase 0 +#define hdSym 1 +#define hdSrc 2 +#define hdMax 3 + +#ifndef EBACKTRACE_MINGW32 +#define SYMOPT_CASE_INSENSITIVE 0x00000001 +#define SYMOPT_UNDNAME 0x00000002 +#define SYMOPT_DEFERRED_LOADS 0x00000004 +#define SYMOPT_NO_CPP 0x00000008 +#define SYMOPT_LOAD_LINES 0x00000010 +#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 +#define SYMOPT_LOAD_ANYTHING 0x00000040 +#define SYMOPT_IGNORE_CVREC 0x00000080 +#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 +#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 +#define SYMOPT_EXACT_SYMBOLS 0x00000400 +#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 +#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 +#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 +#define SYMOPT_PUBLICS_ONLY 0x00004000 +#define SYMOPT_NO_PUBLICS 0x00008000 +#define SYMOPT_AUTO_PUBLICS 0x00010000 +#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 +#define SYMOPT_SECURE 0x00040000 +#define SYMOPT_NO_PROMPTS 0x00080000 +#define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000 +#define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000 +#define SYMOPT_FAVOR_COMPRESSED 0x00800000 +#define SYMOPT_FLAT_DIRECTORY 0x00400000 +#define SYMOPT_IGNORE_IMAGEDIR 0x00200000 +#define SYMOPT_OVERWRITE 0x00100000 + +#define SYMOPT_DEBUG 0x80000000 +#endif + + DWORD IMAGEAPI SymSetOptions(DWORD SymOptions); + DWORD IMAGEAPI SymGetOptions(VOID); + WINBOOL IMAGEAPI SymCleanup(HANDLE hProcess); + WINBOOL IMAGEAPI SymMatchString(PCSTR string,PCSTR expression,WINBOOL fCase); + WINBOOL IMAGEAPI SymMatchStringW(PCWSTR string,PCWSTR expression,WINBOOL fCase); + + typedef WINBOOL (CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACK)(PSOURCEFILE pSourceFile,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACKW)(PSOURCEFILEW pSourceFile,PVOID UserContext); +#define PSYM_ENUMSOURCFILES_CALLBACK PSYM_ENUMSOURCEFILES_CALLBACK + + WINBOOL IMAGEAPI SymEnumSourceFiles(HANDLE hProcess,ULONG64 ModBase,PCSTR Mask,PSYM_ENUMSOURCEFILES_CALLBACK cbSrcFiles,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumSourceFilesW(HANDLE hProcess,ULONG64 ModBase,PCWSTR Mask,PSYM_ENUMSOURCEFILES_CALLBACKW cbSrcFiles,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumerateModules64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumerateModulesW64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateModules SymEnumerateModules64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymEnumerateModules(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,PVOID UserContext); +#endif + + WINBOOL IMAGEAPI SymEnumerateSymbols64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumerateSymbolsW64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateSymbols SymEnumerateSymbols64 +#define SymEnumerateSymbolsW SymEnumerateSymbolsW64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymEnumerateSymbols(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumerateSymbolsW(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); +#endif + + WINBOOL IMAGEAPI EnumerateLoadedModules64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,PVOID UserContext); + WINBOOL IMAGEAPI EnumerateLoadedModulesW64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,PVOID UserContext); + +#ifdef DBGHELP_TRANSLATE_TCHAR + #define EnumerateLoadedModules64 EnumerateLoadedModulesW64 +#endif + +#ifdef _IMAGEHLP64 +#define EnumerateLoadedModules EnumerateLoadedModules64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI EnumerateLoadedModules(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,PVOID UserContext); +#endif + + PVOID IMAGEAPI SymFunctionTableAccess64(HANDLE hProcess,DWORD64 AddrBase); + +#ifdef _IMAGEHLP64 +#define SymFunctionTableAccess SymFunctionTableAccess64 +#elif !defined(EBACKTRACE_MINGW32) + PVOID IMAGEAPI SymFunctionTableAccess(HANDLE hProcess,DWORD AddrBase); +#endif + + WINBOOL IMAGEAPI SymGetModuleInfo64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULE64 ModuleInfo); + WINBOOL IMAGEAPI SymGetModuleInfoW64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULEW64 ModuleInfo); + +#ifdef _IMAGEHLP64 +#define SymGetModuleInfo SymGetModuleInfo64 +#define SymGetModuleInfoW SymGetModuleInfoW64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetModuleInfo(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULE ModuleInfo); + WINBOOL IMAGEAPI SymGetModuleInfoW(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULEW ModuleInfo); +#endif + + DWORD64 IMAGEAPI SymGetModuleBase64(HANDLE hProcess,DWORD64 qwAddr); + +#ifdef _IMAGEHLP64 +#define SymGetModuleBase SymGetModuleBase64 +#elif !defined(EBACKTRACE_MINGW32) + DWORD IMAGEAPI SymGetModuleBase(HANDLE hProcess,DWORD dwAddr); +#endif + + WINBOOL IMAGEAPI SymGetSymNext64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymNext SymGetSymNext64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetSymNext(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + WINBOOL IMAGEAPI SymGetSymPrev64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymPrev SymGetSymPrev64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetSymPrev(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + typedef struct _SRCCODEINFO { + DWORD SizeOfStruct; + PVOID Key; + DWORD64 ModBase; + CHAR Obj[MAX_PATH + 1]; + CHAR FileName[MAX_PATH + 1]; + DWORD LineNumber; + DWORD64 Address; + } SRCCODEINFO,*PSRCCODEINFO; + + typedef struct _SRCCODEINFOW { + DWORD SizeOfStruct; + PVOID Key; + DWORD64 ModBase; + WCHAR Obj[MAX_PATH + 1]; + WCHAR FileName[MAX_PATH + 1]; + DWORD LineNumber; + DWORD64 Address; + } SRCCODEINFOW,*PSRCCODEINFOW; + + typedef WINBOOL (CALLBACK *PSYM_ENUMLINES_CALLBACK)(PSRCCODEINFO LineInfo,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMLINES_CALLBACKW)(PSRCCODEINFOW LineInfo,PVOID UserContext); + + WINBOOL IMAGEAPI SymEnumLines(HANDLE hProcess,ULONG64 Base,PCSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACK EnumLinesCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumLinesW(HANDLE hProcess,ULONG64 Base,PCWSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACKW EnumLinesCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymGetLineFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE64 Line64); + WINBOOL IMAGEAPI SymGetLineFromAddrW64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINEW64 Line64); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromAddr SymGetLineFromAddr64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetLineFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE Line); +#endif + + WINBOOL IMAGEAPI SymGetLineFromName64(HANDLE hProcess,PCSTR ModuleName,PCSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE64 Line); + WINBOOL IMAGEAPI SymGetLineFromNameW64(HANDLE hProcess,PCWSTR ModuleName,PCWSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINEW64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromName SymGetLineFromName64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetLineFromName(HANDLE hProcess,PCSTR ModuleName,PCSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE Line); +#endif + + WINBOOL IMAGEAPI SymGetLineNext64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + WINBOOL IMAGEAPI SymGetLineNextW64(HANDLE hProcess,PIMAGEHLP_LINEW64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineNext SymGetLineNext64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetLineNext(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + + WINBOOL IMAGEAPI SymGetLinePrev64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + WINBOOL IMAGEAPI SymGetLinePrevW64(HANDLE hProcess,PIMAGEHLP_LINEW64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLinePrev SymGetLinePrev64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetLinePrev(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + +#ifndef EBACKTRACE_MINGW32 + WINBOOL IMAGEAPI SymMatchFileName(PCSTR FileName,PCSTR Match,PSTR *FileNameStop,PSTR *MatchStop); +#endif + WINBOOL IMAGEAPI SymMatchFileNameW(PCWSTR FileName,PCWSTR Match,PWSTR *FileNameStop,PWSTR *MatchStop); +#ifndef EBACKTRACE_MINGW32 + WINBOOL IMAGEAPI SymInitialize(HANDLE hProcess,PCSTR UserSearchPath,WINBOOL fInvadeProcess); +#endif + WINBOOL IMAGEAPI SymInitializeW(HANDLE hProcess,PCWSTR UserSearchPath,WINBOOL fInvadeProcess); +#ifndef EBACKTRACE_MINGW32 + WINBOOL IMAGEAPI SymGetSearchPath(HANDLE hProcess,PSTR SearchPath,DWORD SearchPathLength); +#endif + WINBOOL IMAGEAPI SymGetSearchPathW(HANDLE hProcess,PWSTR SearchPath,DWORD SearchPathLength); +#ifndef EBACKTRACE_MINGW32 + WINBOOL IMAGEAPI SymSetSearchPath(HANDLE hProcess,PCSTR SearchPath); +#endif + WINBOOL IMAGEAPI SymSetSearchPathW(HANDLE hProcess,PCWSTR SearchPath); + DWORD64 IMAGEAPI SymLoadModule64(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD SizeOfDll); + +#define SLMFLAG_VIRTUAL 0x1 + + DWORD64 IMAGEAPI SymLoadModuleEx(HANDLE hProcess,HANDLE hFile,PCSTR ImageName,PCSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags); + DWORD64 IMAGEAPI SymLoadModuleExW(HANDLE hProcess,HANDLE hFile,PCWSTR ImageName,PCWSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags); + +#ifdef _IMAGEHLP64 +#define SymLoadModule SymLoadModule64 +#elif !defined(EBACKTRACE_MINGW32) + DWORD IMAGEAPI SymLoadModule(HANDLE hProcess,HANDLE hFile,PCSTR ImageName,PCSTR ModuleName,DWORD BaseOfDll,DWORD SizeOfDll); +#endif + + WINBOOL IMAGEAPI SymUnloadModule64(HANDLE hProcess,DWORD64 BaseOfDll); + +#ifdef _IMAGEHLP64 +#define SymUnloadModule SymUnloadModule64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymUnloadModule(HANDLE hProcess,DWORD BaseOfDll); +#endif + + WINBOOL IMAGEAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym,PSTR UnDecName,DWORD UnDecNameLength); + +#ifdef _IMAGEHLP64 +#define SymUnDName SymUnDName64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymUnDName(PIMAGEHLP_SYMBOL sym,PSTR UnDecName,DWORD UnDecNameLength); +#endif + + WINBOOL IMAGEAPI SymRegisterCallback64(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext); + WINBOOL IMAGEAPI SymRegisterCallback64W(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext); + + WINBOOL IMAGEAPI SymRegisterFunctionEntryCallback64(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define SymRegisterCallback SymRegisterCallback64 +#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymRegisterCallback(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK CallbackFunction,PVOID UserContext); + WINBOOL IMAGEAPI SymRegisterFunctionEntryCallback(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,PVOID UserContext); +#endif + + typedef struct _IMAGEHLP_SYMBOL_SRC { + DWORD sizeofstruct; + DWORD type; + char file[MAX_PATH]; + } IMAGEHLP_SYMBOL_SRC,*PIMAGEHLP_SYMBOL_SRC; + + typedef struct _MODULE_TYPE_INFO { + USHORT dataLength; + USHORT leaf; + BYTE data[1]; + } MODULE_TYPE_INFO,*PMODULE_TYPE_INFO; + + typedef struct _SYMBOL_INFO { + ULONG SizeOfStruct; + ULONG TypeIndex; + ULONG64 Reserved[2]; + ULONG info; + ULONG Size; + ULONG64 ModBase; + ULONG Flags; + ULONG64 Value; + ULONG64 Address; + ULONG Register; + ULONG Scope; + ULONG Tag; + ULONG NameLen; + ULONG MaxNameLen; + CHAR Name[1]; + } SYMBOL_INFO,*PSYMBOL_INFO; + + typedef struct _SYMBOL_INFOW { + ULONG SizeOfStruct; + ULONG TypeIndex; + ULONG64 Reserved[2]; + ULONG info; + ULONG Size; + ULONG64 ModBase; + ULONG Flags; + ULONG64 Value; + ULONG64 Address; + ULONG Register; + ULONG Scope; + ULONG Tag; + ULONG NameLen; + ULONG MaxNameLen; + WCHAR Name[1]; + } SYMBOL_INFOW,*PSYMBOL_INFOW; + +#define SYMFLAG_CLR_TOKEN 0x00040000 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_ILREL 0x00010000 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_METADATA 0x00020000 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_SLOT 0x00008000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_VIRTUAL 0x00001000 + + typedef struct _SYMBOL_INFO_PACKAGE { + SYMBOL_INFO si; + CHAR name[MAX_SYM_NAME + 1]; + } SYMBOL_INFO_PACKAGE,*PSYMBOL_INFO_PACKAGE; + + typedef struct _IMAGEHLP_STACK_FRAME { + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + WINBOOL Virtual; + ULONG Reserved2; + } IMAGEHLP_STACK_FRAME,*PIMAGEHLP_STACK_FRAME; + + typedef VOID IMAGEHLP_CONTEXT,*PIMAGEHLP_CONTEXT; + + WINBOOL IMAGEAPI SymSetContext(HANDLE hProcess,PIMAGEHLP_STACK_FRAME StackFrame,PIMAGEHLP_CONTEXT Context); + WINBOOL IMAGEAPI SymFromAddr(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFO Symbol); + WINBOOL IMAGEAPI SymFromAddrW(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFOW Symbol); + WINBOOL IMAGEAPI SymFromToken(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFO Symbol); + WINBOOL IMAGEAPI SymFromTokenW(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFOW Symbol); + WINBOOL IMAGEAPI SymFromName(HANDLE hProcess,PCSTR Name,PSYMBOL_INFO Symbol); + WINBOOL IMAGEAPI SymFromNameW(HANDLE hProcess,PCWSTR Name,PSYMBOL_INFOW Symbol); + + typedef WINBOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext); + typedef WINBOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)(PSYMBOL_INFOW pSymInfo,ULONG SymbolSize,PVOID UserContext); + + WINBOOL IMAGEAPI SymEnumSymbols(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumSymbolsW(HANDLE hProcess,ULONG64 BaseOfDll,PCWSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumSymbolsForAddr(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumSymbolsForAddrW(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); + +#define SYMENUMFLAG_FULLSRCH 1 +#define SYMENUMFLAG_SPEEDSRCH 2 + + typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO { + TI_GET_SYMTAG, + TI_GET_SYMNAME, + TI_GET_LENGTH, + TI_GET_TYPE, + TI_GET_TYPEID, + TI_GET_BASETYPE, + TI_GET_ARRAYINDEXTYPEID, + TI_FINDCHILDREN, + TI_GET_DATAKIND, + TI_GET_ADDRESSOFFSET, + TI_GET_OFFSET, + TI_GET_VALUE, + TI_GET_COUNT, + TI_GET_CHILDRENCOUNT, + TI_GET_BITPOSITION, + TI_GET_VIRTUALBASECLASS, + TI_GET_VIRTUALTABLESHAPEID, + TI_GET_VIRTUALBASEPOINTEROFFSET, + TI_GET_CLASSPARENTID, + TI_GET_NESTED, + TI_GET_SYMINDEX, + TI_GET_LEXICALPARENT, + TI_GET_ADDRESS, + TI_GET_THISADJUST, + TI_GET_UDTKIND, + TI_IS_EQUIV_TO, + TI_GET_CALLING_CONVENTION + } IMAGEHLP_SYMBOL_TYPE_INFO; + + typedef struct _TI_FINDCHILDREN_PARAMS { + ULONG Count; + ULONG Start; + ULONG ChildId[1]; + } TI_FINDCHILDREN_PARAMS; + + WINBOOL IMAGEAPI SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo); + WINBOOL IMAGEAPI SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymEnumTypesW(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); + WINBOOL IMAGEAPI SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,PSYMBOL_INFO Symbol); + WINBOOL IMAGEAPI SymGetTypeFromNameW(HANDLE hProcess,ULONG64 BaseOfDll,PCWSTR Name,PSYMBOL_INFOW Symbol); + WINBOOL IMAGEAPI SymAddSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Size,DWORD Flags); + WINBOOL IMAGEAPI SymAddSymbolW(HANDLE hProcess,ULONG64 BaseOfDll,PCWSTR Name,DWORD64 Address,DWORD Size,DWORD Flags); + WINBOOL IMAGEAPI SymDeleteSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Flags); + WINBOOL IMAGEAPI SymDeleteSymbolW(HANDLE hProcess,ULONG64 BaseOfDll,PCWSTR Name,DWORD64 Address,DWORD Flags); + + typedef WINBOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)(DWORD DataType,PVOID *Data,LPDWORD DataLength,PVOID UserData); + + WINBOOL WINAPI DbgHelpCreateUserDump(LPCSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + WINBOOL WINAPI DbgHelpCreateUserDumpW(LPCWSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + WINBOOL IMAGEAPI SymGetSymFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD64 pdwDisplacement,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromAddr SymGetSymFromAddr64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetSymFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_SYMBOL Symbol); +#endif + + WINBOOL IMAGEAPI SymGetSymFromName64(HANDLE hProcess,PCSTR Name,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromName SymGetSymFromName64 +#elif !defined(EBACKTRACE_MINGW32) + WINBOOL IMAGEAPI SymGetSymFromName(HANDLE hProcess,PCSTR Name,PIMAGEHLP_SYMBOL Symbol); +#endif + + DBHLP_DEPRECIATED WINBOOL IMAGEAPI FindFileInPath(HANDLE hprocess,PCSTR SearchPath,PCSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,PSTR FilePath); + DBHLP_DEPRECIATED WINBOOL IMAGEAPI FindFileInSearchPath(HANDLE hprocess,PCSTR SearchPath,PCSTR FileName,DWORD one,DWORD two,DWORD three,PSTR FilePath); + DBHLP_DEPRECIATED WINBOOL IMAGEAPI SymEnumSym(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + +#ifdef __cplusplus +} +#endif + +#ifndef EBACKTRACE_MINGW32 +#define SYMF_OMAP_GENERATED 0x00000001 +#define SYMF_OMAP_MODIFIED 0x00000002 +#define SYMF_REGISTER 0x00000008 +#define SYMF_REGREL 0x00000010 +#define SYMF_FRAMEREL 0x00000020 +#define SYMF_PARAMETER 0x00000040 +#define SYMF_LOCAL 0x00000080 +#define SYMF_CONSTANT 0x00000100 +#define SYMF_EXPORT 0x00000200 +#define SYMF_FORWARDER 0x00000400 +#define SYMF_FUNCTION 0x00000800 +#define SYMF_VIRTUAL 0x00001000 +#define SYMF_THUNK 0x00002000 +#define SYMF_TLSREL 0x00004000 +#endif + +#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1 +#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER +#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL +#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL +#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER +#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL +#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT +#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION +#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL +#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK +#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL + +#include + +#define MINIDUMP_SIGNATURE ('PMDM') +#define MINIDUMP_VERSION (42899) + typedef DWORD RVA; + typedef ULONG64 RVA64; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR { + ULONG32 DataSize; + RVA Rva; + } MINIDUMP_LOCATION_DESCRIPTOR; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 { + ULONG64 DataSize; + RVA64 Rva; + } MINIDUMP_LOCATION_DESCRIPTOR64; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR { + ULONG64 StartOfMemoryRange; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_MEMORY_DESCRIPTOR,*PMINIDUMP_MEMORY_DESCRIPTOR; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 { + ULONG64 StartOfMemoryRange; + ULONG64 DataSize; + } MINIDUMP_MEMORY_DESCRIPTOR64,*PMINIDUMP_MEMORY_DESCRIPTOR64; + + typedef struct _MINIDUMP_HEADER { + ULONG32 Signature; + ULONG32 Version; + ULONG32 NumberOfStreams; + RVA StreamDirectoryRva; + ULONG32 CheckSum; + __C89_NAMELESS union { + ULONG32 Reserved; + ULONG32 TimeDateStamp; + }; + ULONG64 Flags; + } MINIDUMP_HEADER,*PMINIDUMP_HEADER; + + typedef struct _MINIDUMP_DIRECTORY { + ULONG32 StreamType; + MINIDUMP_LOCATION_DESCRIPTOR Location; + } MINIDUMP_DIRECTORY,*PMINIDUMP_DIRECTORY; + + typedef struct _MINIDUMP_STRING { + ULONG32 Length; + WCHAR Buffer[0]; + } MINIDUMP_STRING,*PMINIDUMP_STRING; + + typedef enum _MINIDUMP_STREAM_TYPE { + UnusedStream = 0, + ReservedStream0 = 1, + ReservedStream1 = 2, + ThreadListStream = 3, + ModuleListStream = 4, + MemoryListStream = 5, + ExceptionStream = 6, + SystemInfoStream = 7, + ThreadExListStream = 8, + Memory64ListStream = 9, + CommentStreamA = 10, + CommentStreamW = 11, + HandleDataStream = 12, + FunctionTableStream = 13, + UnloadedModuleListStream = 14, + MiscInfoStream = 15, + LastReservedStream = 0xffff + } MINIDUMP_STREAM_TYPE; + + typedef union _CPU_INFORMATION { + struct { + ULONG32 VendorId[3]; + ULONG32 VersionInformation; + ULONG32 FeatureInformation; + ULONG32 AMDExtendedCpuFeatures; + } X86CpuInfo; + struct { + ULONG64 ProcessorFeatures[2]; + } OtherCpuInfo; + } CPU_INFORMATION,*PCPU_INFORMATION; + + typedef struct _MINIDUMP_SYSTEM_INFO { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + __C89_NAMELESS union { + USHORT Reserved0; + __C89_NAMELESS struct { + UCHAR NumberOfProcessors; + UCHAR ProductType; + }; + }; + ULONG32 MajorVersion; + ULONG32 MinorVersion; + ULONG32 BuildNumber; + ULONG32 PlatformId; + RVA CSDVersionRva; + __C89_NAMELESS union { + ULONG32 Reserved1; + __C89_NAMELESS struct { + USHORT SuiteMask; + USHORT Reserved2; + }; + }; + CPU_INFORMATION Cpu; + } MINIDUMP_SYSTEM_INFO,*PMINIDUMP_SYSTEM_INFO; + + C_ASSERT(sizeof(((PPROCESS_INFORMATION)0)->dwThreadId)==4); + + typedef struct _MINIDUMP_THREAD { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_THREAD,*PMINIDUMP_THREAD; + + typedef struct _MINIDUMP_THREAD_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD Threads[0]; + } MINIDUMP_THREAD_LIST,*PMINIDUMP_THREAD_LIST; + + typedef struct _MINIDUMP_THREAD_EX { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + MINIDUMP_MEMORY_DESCRIPTOR BackingStore; + } MINIDUMP_THREAD_EX,*PMINIDUMP_THREAD_EX; + + typedef struct _MINIDUMP_THREAD_EX_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD_EX Threads[0]; + } MINIDUMP_THREAD_EX_LIST,*PMINIDUMP_THREAD_EX_LIST; + + typedef struct _MINIDUMP_EXCEPTION { + ULONG32 ExceptionCode; + ULONG32 ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG32 NumberParameters; + ULONG32 __unusedAlignment; + ULONG64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; + } MINIDUMP_EXCEPTION,*PMINIDUMP_EXCEPTION; + + typedef struct MINIDUMP_EXCEPTION_STREAM { + ULONG32 ThreadId; + ULONG32 __alignment; + MINIDUMP_EXCEPTION ExceptionRecord; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM; + + typedef struct _MINIDUMP_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + VS_FIXEDFILEINFO VersionInfo; + MINIDUMP_LOCATION_DESCRIPTOR CvRecord; + MINIDUMP_LOCATION_DESCRIPTOR MiscRecord; + ULONG64 Reserved0; + ULONG64 Reserved1; + } MINIDUMP_MODULE,*PMINIDUMP_MODULE; + + typedef struct _MINIDUMP_MODULE_LIST { + ULONG32 NumberOfModules; + MINIDUMP_MODULE Modules[0]; + } MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST; + + typedef struct _MINIDUMP_MEMORY_LIST { + ULONG32 NumberOfMemoryRanges; + MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[0]; + } MINIDUMP_MEMORY_LIST,*PMINIDUMP_MEMORY_LIST; + + typedef struct _MINIDUMP_MEMORY64_LIST { + ULONG64 NumberOfMemoryRanges; + RVA64 BaseRva; + MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges[0]; + } MINIDUMP_MEMORY64_LIST,*PMINIDUMP_MEMORY64_LIST; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION { + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + WINBOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION,*PMINIDUMP_EXCEPTION_INFORMATION; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 { + DWORD ThreadId; + ULONG64 ExceptionRecord; + ULONG64 ContextRecord; + WINBOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION64,*PMINIDUMP_EXCEPTION_INFORMATION64; + + typedef struct _MINIDUMP_HANDLE_DESCRIPTOR { + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; + } MINIDUMP_HANDLE_DESCRIPTOR,*PMINIDUMP_HANDLE_DESCRIPTOR; + + typedef struct _MINIDUMP_HANDLE_DATA_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 NumberOfDescriptors; + ULONG32 Reserved; + } MINIDUMP_HANDLE_DATA_STREAM,*PMINIDUMP_HANDLE_DATA_STREAM; + + typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR { + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; + ULONG32 EntryCount; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_DESCRIPTOR,*PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR; + + typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 SizeOfNativeDescriptor; + ULONG32 SizeOfFunctionEntry; + ULONG32 NumberOfDescriptors; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_STREAM,*PMINIDUMP_FUNCTION_TABLE_STREAM; + + typedef struct _MINIDUMP_UNLOADED_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + } MINIDUMP_UNLOADED_MODULE,*PMINIDUMP_UNLOADED_MODULE; + + typedef struct _MINIDUMP_UNLOADED_MODULE_LIST { + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; + } MINIDUMP_UNLOADED_MODULE_LIST,*PMINIDUMP_UNLOADED_MODULE_LIST; + +#define MINIDUMP_MISC1_PROCESS_ID 0x00000001 +#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002 +#define MINIDUMP_MISC1_PROCESSOR_POWER_INFO 0x00000004 + + typedef struct _MINIDUMP_MISC_INFO { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + } MINIDUMP_MISC_INFO,*PMINIDUMP_MISC_INFO; + + typedef struct _MINIDUMP_USER_RECORD { + ULONG32 Type; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_USER_RECORD,*PMINIDUMP_USER_RECORD; + + typedef struct _MINIDUMP_USER_STREAM { + ULONG32 Type; + ULONG BufferSize; + PVOID Buffer; + } MINIDUMP_USER_STREAM,*PMINIDUMP_USER_STREAM; + + typedef struct _MINIDUMP_USER_STREAM_INFORMATION { + ULONG UserStreamCount; + PMINIDUMP_USER_STREAM UserStreamArray; + } MINIDUMP_USER_STREAM_INFORMATION,*PMINIDUMP_USER_STREAM_INFORMATION; + + typedef enum _MINIDUMP_CALLBACK_TYPE { + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback + } MINIDUMP_CALLBACK_TYPE; + + typedef struct _MINIDUMP_THREAD_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + } MINIDUMP_THREAD_CALLBACK,*PMINIDUMP_THREAD_CALLBACK; + + typedef struct _MINIDUMP_THREAD_EX_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + ULONG64 BackingStoreBase; + ULONG64 BackingStoreEnd; + } MINIDUMP_THREAD_EX_CALLBACK,*PMINIDUMP_THREAD_EX_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK { + ULONG ThreadId; + } MINIDUMP_INCLUDE_THREAD_CALLBACK,*PMINIDUMP_INCLUDE_THREAD_CALLBACK; + + typedef enum _THREAD_WRITE_FLAGS { + ThreadWriteThread = 0x0001, + ThreadWriteStack = 0x0002, + ThreadWriteContext = 0x0004, + ThreadWriteBackingStore = 0x0008, + ThreadWriteInstructionWindow = 0x0010, + ThreadWriteThreadData = 0x0020, + ThreadWriteThreadInfo = 0x0040 + } THREAD_WRITE_FLAGS; + + typedef struct _MINIDUMP_MODULE_CALLBACK { + PWCHAR FullPath; + ULONG64 BaseOfImage; + ULONG SizeOfImage; + ULONG CheckSum; + ULONG TimeDateStamp; + VS_FIXEDFILEINFO VersionInfo; + PVOID CvRecord; + ULONG SizeOfCvRecord; + PVOID MiscRecord; + ULONG SizeOfMiscRecord; + } MINIDUMP_MODULE_CALLBACK,*PMINIDUMP_MODULE_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK { + ULONG64 BaseOfImage; + } MINIDUMP_INCLUDE_MODULE_CALLBACK,*PMINIDUMP_INCLUDE_MODULE_CALLBACK; + + typedef enum _MODULE_WRITE_FLAGS { + ModuleWriteModule = 0x0001, + ModuleWriteDataSeg = 0x0002, + ModuleWriteMiscRecord = 0x0004, + ModuleWriteCvRecord = 0x0008, + ModuleReferencedByMemory = 0x0010, + ModuleWriteTlsData = 0x0020, + ModuleWriteCodeSegs = 0x0040 + } MODULE_WRITE_FLAGS; + + typedef enum _MINIDUMP_SECONDARY_FLAGS { + MiniSecondaryWithoutPowerInfo = 0x00000001 + } MINIDUMP_SECONDARY_FLAGS; + + typedef struct _MINIDUMP_CALLBACK_INPUT { + ULONG ProcessId; + HANDLE ProcessHandle; + ULONG CallbackType; + __C89_NAMELESS union { + MINIDUMP_THREAD_CALLBACK Thread; + MINIDUMP_THREAD_EX_CALLBACK ThreadEx; + MINIDUMP_MODULE_CALLBACK Module; + MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; + MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; + }; + } MINIDUMP_CALLBACK_INPUT,*PMINIDUMP_CALLBACK_INPUT; + +typedef struct _MINIDUMP_MEMORY_INFO { + ULONG64 BaseAddress; + ULONG64 AllocationBase; + ULONG32 AllocationProtect; + ULONG32 __alignment1; + ULONG64 RegionSize; + ULONG32 State; + ULONG32 Protect; + ULONG32 Type; + ULONG32 __alignment2; +} MINIDUMP_MEMORY_INFO, *PMINIDUMP_MEMORY_INFO; + +typedef struct _MINIDUMP_MISC_INFO_2 { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + ULONG32 ProcessorMaxMhz; + ULONG32 ProcessorCurrentMhz; + ULONG32 ProcessorMhzLimit; + ULONG32 ProcessorMaxIdleState; + ULONG32 ProcessorCurrentIdleState; +} MINIDUMP_MISC_INFO_2, *PMINIDUMP_MISC_INFO_2; + +typedef struct _MINIDUMP_MEMORY_INFO_LIST { + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG64 NumberOfEntries; +} MINIDUMP_MEMORY_INFO_LIST, *PMINIDUMP_MEMORY_INFO_LIST; + + typedef struct _MINIDUMP_CALLBACK_OUTPUT { + __C89_NAMELESS union { + ULONG ModuleWriteFlags; + ULONG ThreadWriteFlags; + ULONG SecondaryFlags; + __C89_NAMELESS struct { + ULONG64 MemoryBase; + ULONG MemorySize; + }; + __C89_NAMELESS struct { + WINBOOL CheckCancel; + WINBOOL Cancel; + }; + HANDLE Handle; + }; + __C89_NAMELESS struct { + MINIDUMP_MEMORY_INFO VmRegion; + WINBOOL Continue; + }; + HRESULT Status; + } MINIDUMP_CALLBACK_OUTPUT, *PMINIDUMP_CALLBACK_OUTPUT; + + typedef enum _MINIDUMP_TYPE { + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000, + MiniDumpWithoutAuxiliaryState = 0x00004000, + MiniDumpWithFullAuxiliaryState = 0x00008000, + MiniDumpWithPrivateWriteCopyMemory = 0x00010000, + MiniDumpIgnoreInaccessibleMemory = 0x00020000, + MiniDumpWithTokenInformation = 0x00040000 + } MINIDUMP_TYPE; + +#define MINIDUMP_THREAD_INFO_ERROR_THREAD 0x00000001 +#define MINIDUMP_THREAD_INFO_WRITING_THREAD 0x00000002 +#define MINIDUMP_THREAD_INFO_EXITED_THREAD 0x00000004 +#define MINIDUMP_THREAD_INFO_INVALID_INFO 0x00000008 +#define MINIDUMP_THREAD_INFO_INVALID_CONTEXT 0x00000010 +#define MINIDUMP_THREAD_INFO_INVALID_TEB 0x00000020 + +typedef struct _MINIDUMP_THREAD_INFO { + ULONG32 ThreadId; + ULONG32 DumpFlags; + ULONG32 DumpError; + ULONG32 ExitStatus; + ULONG64 CreateTime; + ULONG64 ExitTime; + ULONG64 KernelTime; + ULONG64 UserTime; + ULONG64 StartAddress; + ULONG64 Affinity; +} MINIDUMP_THREAD_INFO, *PMINIDUMP_THREAD_INFO; + +typedef struct _MINIDUMP_THREAD_INFO_LIST { + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG NumberOfEntries; +} MINIDUMP_THREAD_INFO_LIST, *PMINIDUMP_THREAD_INFO_LIST; + +#ifdef __cplusplus +extern "C" { +#endif + + typedef WINBOOL (WINAPI *MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,PMINIDUMP_CALLBACK_OUTPUT CallbackOutput); + + typedef struct _MINIDUMP_CALLBACK_INFORMATION { + MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + PVOID CallbackParam; + } MINIDUMP_CALLBACK_INFORMATION,*PMINIDUMP_CALLBACK_INFORMATION; + +#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva))) + + WINBOOL WINAPI MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + WINBOOL WINAPI MiniDumpReadDumpStream(PVOID BaseOfDump,ULONG StreamNumber,PMINIDUMP_DIRECTORY *Dir,PVOID *StreamPointer,ULONG *StreamSize); + +WINBOOL WINAPI EnumerateLoadedModulesEx( + HANDLE hProcess, + PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, + PVOID UserContext +); + +WINBOOL WINAPI EnumerateLoadedModulesExW( + HANDLE hProcess, + PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, + PVOID UserContext +); + +WINBOOL WINAPI SymAddSourceStream( + HANDLE hProcess, + ULONG64 Base, + PCSTR StreamFile, + PBYTE Buffer, + size_t Size +); + +WINBOOL WINAPI SymAddSourceStreamW( + HANDLE hProcess, + ULONG64 Base, + PCWSTR StreamFile, + PBYTE Buffer, + size_t Size +); + +WINBOOL WINAPI SymEnumSourceLines( + HANDLE hProcess, + ULONG64 Base, + PCSTR Obj, + PCSTR File, + DWORD Line, + DWORD Flags, + PSYM_ENUMLINES_CALLBACK EnumLinesCallback, + PVOID UserContext +); + +WINBOOL WINAPI SymEnumSourceLinesW( + HANDLE hProcess, + ULONG64 Base, + PCWSTR Obj, + PCWSTR File, + DWORD Line, + DWORD Flags, + PSYM_ENUMLINES_CALLBACKW EnumLinesCallback, + PVOID UserContext +); + +WINBOOL WINAPI SymEnumTypesByName( + HANDLE hProcess, + ULONG64 BaseOfDll, + PCSTR mask, + PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + PVOID UserContext +); + +WINBOOL WINAPI SymEnumTypesByNameW( + HANDLE hProcess, + ULONG64 BaseOfDll, + PCSTR mask, + PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + PVOID UserContext +); + +HANDLE WINAPI SymFindDebugInfoFile( + HANDLE hProcess, + PCSTR FileName, + PSTR DebugFilePath, + PFIND_DEBUG_FILE_CALLBACK Callback, + PVOID CallerData +); + +HANDLE WINAPI SymFindDebugInfoFileW( + HANDLE hProcess, + PCWSTR FileName, + PWSTR DebugFilePath, + PFIND_DEBUG_FILE_CALLBACKW Callback, + PVOID CallerData +); + +HANDLE WINAPI SymFindExecutableImage( + HANDLE hProcess, + PCSTR FileName, + PSTR ImageFilePath, + PFIND_EXE_FILE_CALLBACK Callback, + PVOID CallerData +); + +HANDLE WINAPI SymFindExecutableImageW( + HANDLE hProcess, + PCWSTR FileName, + PWSTR ImageFilePath, + PFIND_EXE_FILE_CALLBACKW Callback, + PVOID CallerData +); + +WINBOOL WINAPI SymFromIndex( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + PSYMBOL_INFO Symbol +); + +WINBOOL WINAPI SymFromIndexW( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + PSYMBOL_INFOW Symbol +); + +WINBOOL WINAPI SymGetScope( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + PSYMBOL_INFO Symbol +); + +WINBOOL WINAPI SymGetScopeW( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + PSYMBOL_INFOW Symbol +); + +WINBOOL WINAPI SymGetSourceFileFromToken( + HANDLE hProcess, + PVOID Token, + PCSTR Params, + PSTR FilePath, + DWORD Size +); + +WINBOOL WINAPI SymGetSourceFileFromTokenW( + HANDLE hProcess, + PVOID Token, + PCWSTR Params, + PWSTR FilePath, + DWORD Size +); + +WINBOOL WINAPI SymGetSourceFileToken( + HANDLE hProcess, + ULONG64 Base, + PCSTR FileSpec, + PVOID *Token, + DWORD *Size +); + +WINBOOL WINAPI SymGetSourceFileTokenW( + HANDLE hProcess, + ULONG64 Base, + PCWSTR FileSpec, + PVOID *Token, + DWORD *Size +); + +WINBOOL WINAPI SymGetSourceFile( + HANDLE hProcess, + ULONG64 Base, + PCSTR Params, + PCSTR FileSpec, + PSTR FilePath, + DWORD Size +); + +WINBOOL WINAPI SymGetSourceFileW( + HANDLE hProcess, + ULONG64 Base, + PCWSTR Params, + PCWSTR FileSpec, + PWSTR FilePath, + DWORD Size +); + +WINBOOL WINAPI SymGetSourceVarFromToken( + HANDLE hProcess, + PVOID Token, + PCSTR Params, + PCSTR VarName, + PSTR Value, + DWORD Size +); + +WINBOOL WINAPI SymGetSourceVarFromTokenW( + HANDLE hProcess, + PVOID Token, + PCWSTR Params, + PCWSTR VarName, + PWSTR Value, + DWORD Size +); + +WINBOOL WINAPI SymGetSymbolFile( + HANDLE hProcess, + PCSTR SymPath, + PCSTR ImageFile, + DWORD Type, + PSTR SymbolFile, + size_t cSymbolFile, + PSTR DbgFile, + size_t cDbgFile +); + +WINBOOL WINAPI SymGetSymbolFileW( + HANDLE hProcess, + PCWSTR SymPath, + PCWSTR ImageFile, + DWORD Type, + PWSTR SymbolFile, + size_t cSymbolFile, + PWSTR DbgFile, + size_t cDbgFile +); + +WINBOOL WINAPI SymNext( + HANDLE hProcess, + PSYMBOL_INFO Symbol +); + +WINBOOL WINAPI SymNextW( + HANDLE hProcess, + PSYMBOL_INFOW Symbol +); + +WINBOOL WINAPI SymPrev( + HANDLE hProcess, + PSYMBOL_INFO Symbol +); + +WINBOOL WINAPI SymPrevW( + HANDLE hProcess, + PSYMBOL_INFOW Symbol +); + +WINBOOL WINAPI SymRefreshModuleList( + HANDLE hProcess +); + +#define SYMSEARCH_MASKOBJS 0x01 +#define SYMSEARCH_RECURSE 0x02 +#define SYMSEARCH_GLOBALSONLY 0x04 +#define SYMSEARCH_ALLITEMS 0x08 + +WINBOOL WINAPI SymSearch( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + DWORD SymTag, + PCSTR Mask, + DWORD64 Address, + PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + PVOID UserContext, + DWORD Options +); + +WINBOOL WINAPI SymSearchW( + HANDLE hProcess, + ULONG64 BaseOfDll, + DWORD Index, + DWORD SymTag, + PCWSTR Mask, + DWORD64 Address, + PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + PVOID UserContext, + DWORD Options +); + +WINBOOL WINAPI SymSrvGetFileIndexString( + HANDLE hProcess, + PCSTR SrvPath, + PCSTR File, + PSTR Index, + size_t Size, + DWORD Flags +); + +WINBOOL WINAPI SymSrvGetFileIndexStringW( + HANDLE hProcess, + PCWSTR SrvPath, + PCWSTR File, + PWSTR Index, + size_t Size, + DWORD Flags +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvGetFileIndexString SymSrvGetFileIndexStringW +#endif + +WINBOOL WINAPI SymSrvGetFileIndexInfo( + PCSTR File, + PSYMSRV_INDEX_INFO Info, + DWORD Flags +); + +WINBOOL WINAPI SymSrvGetFileIndexInfoW( + PCWSTR File, + PSYMSRV_INDEX_INFOW Info, + DWORD Flags +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvGetFileIndexInfo SymSrvGetFileIndexInfoW +#endif + +WINBOOL WINAPI SymSrvGetFileIndexes( + PCTSTR File, + GUID *Id, + DWORD *Val1, + DWORD *Val2, + DWORD Flags +); + +WINBOOL WINAPI SymSrvGetFileIndexesW( + PCWSTR File, + GUID *Id, + DWORD *Val1, + DWORD *Val2, + DWORD Flags +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvGetFileIndexes SymSrvGetFileIndexesW +#endif + +PCSTR WINAPI SymSrvGetSupplement( + HANDLE hProcess, + PCSTR SymPath, + PCSTR Node, + PCSTR File +); + +PCWSTR WINAPI SymSrvGetSupplementW( + HANDLE hProcess, + PCWSTR SymPath, + PCWSTR Node, + PCWSTR File +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvGetSupplement SymSrvGetSupplementW +#endif + +WINBOOL WINAPI SymSrvIsStore( + HANDLE hProcess, + PCSTR path +); + +WINBOOL WINAPI SymSrvIsStoreW( + HANDLE hProcess, + PCWSTR path +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvIsStore SymSrvIsStoreW +#endif + +PCSTR WINAPI SymSrvStoreFile( + HANDLE hProcess, + PCSTR SrvPath, + PCSTR File, + DWORD Flags +); + +PCWSTR WINAPI SymSrvStoreFileW( + HANDLE hProcess, + PCWSTR SrvPath, + PCWSTR File, + DWORD Flags +); + +#define SYMSTOREOPT_COMPRESS 0x01 +#define SYMSTOREOPT_OVERWRITE 0x02 +#define SYMSTOREOPT_RETURNINDEX 0x04 +#define SYMSTOREOPT_POINTER 0x08 +#define SYMSTOREOPT_PASS_IF_EXISTS 0x40 + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvStoreFile SymSrvStoreFileW +#endif + +PCSTR WINAPI SymSrvStoreSupplement( + HANDLE hProcess, + const PCTSTR SymPath, + PCSTR Node, + PCSTR File, + DWORD Flags +); + +PCWSTR WINAPI SymSrvStoreSupplementW( + HANDLE hProcess, + const PCWSTR SymPath, + PCWSTR Node, + PCWSTR File, + DWORD Flags +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvStoreSupplement SymSrvStoreSupplementW +#endif + +PCSTR WINAPI SymSrvDeltaName( + HANDLE hProcess, + PCSTR SymPath, + PCSTR Type, + PCSTR File1, + PCSTR File2 +); + +PCWSTR WINAPI SymSrvDeltaNameW( + HANDLE hProcess, + PCWSTR SymPath, + PCWSTR Type, + PCWSTR File1, + PCWSTR File2 +); + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymSrvDeltaName SymSrvDeltaNameW +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bin/windows/vpx/src/backtrace.c b/bin/windows/vpx/src/backtrace.c new file mode 100644 index 000000000..4bbe88bbe --- /dev/null +++ b/bin/windows/vpx/src/backtrace.c @@ -0,0 +1,702 @@ +/* + Copyright (c) 2010 , + Cloud Wu . All rights reserved. + + http://www.codingnow.com + + Use, modification and distribution are subject to the "New BSD License" + as listed at . + + filename: backtrace.c + + build command: gcc -O2 -shared -Wall -o backtrace.dll backtrace.c -lbfd -liberty -limagehlp + + how to use: Call LoadLibraryA("backtrace.dll"); at beginning of your program . + + */ + +/* modified from original for EDuke32 */ + +// warnings cleaned up, ported to 64-bit, and heavily extended by Hendricks266 + +#include +#include +#include + +// Tenuous: MinGW provides _IMAGEHLP_H while MinGW-w64 defines _IMAGEHLP_. +#ifdef _IMAGEHLP_H +# define EBACKTRACE_MINGW32 +#endif +#ifdef _IMAGEHLP_ +# define EBACKTRACE_MINGW_W64 +#endif +#if defined(EBACKTRACE_MINGW32) && !defined(EBACKTRACE_MINGW_W64) +# include "_dbg_common.h" +#endif + +#ifndef PACKAGE +# define PACKAGE EBACKTRACE1 +#endif +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION 1 +#endif + +#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(_WIN64) +# define EBACKTRACE64 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#ifndef DBG_PRINTEXCEPTION_C +# define DBG_PRINTEXCEPTION_C (0x40010006) +#endif +#ifndef MS_VC_EXCEPTION +# define MS_VC_EXCEPTION 1080890248 +#endif + +#if defined __GNUC__ || defined __clang__ +# define ATTRIBUTE(attrlist) __attribute__(attrlist) +#else +# define ATTRIBUTE(attrlist) +#endif + +#define BUFFER_MAX (16*1024) + +struct bfd_ctx { + bfd * handle; + asymbol ** symbol; +}; + +struct bfd_set { + char * name; + struct bfd_ctx * bc; + struct bfd_set *next; +}; + +struct find_info { + asymbol **symbol; + bfd_vma counter; + const char *file; + const char *func; + unsigned line; +}; + +struct output_buffer { + char * buf; + size_t sz; + size_t ptr; +}; + +static void +output_init(struct output_buffer *ob, char * buf, size_t sz) +{ + ob->buf = buf; + ob->sz = sz; + ob->ptr = 0; + ob->buf[0] = '\0'; +} + +static void +output_print(struct output_buffer *ob, const char * format, ...) +{ + va_list ap; + + if (ob->sz == ob->ptr) + return; + ob->buf[ob->ptr] = '\0'; + va_start(ap,format); + vsnprintf(ob->buf + ob->ptr , ob->sz - ob->ptr , format, ap); + va_end(ap); + + ob->ptr = strlen(ob->buf + ob->ptr) + ob->ptr; +} + +static void +lookup_section(bfd *abfd, asection *sec, void *opaque_data) +{ + struct find_info *data = opaque_data; + bfd_vma vma; + + if (data->func) + return; + + if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) + return; + + vma = bfd_get_section_vma(abfd, sec); + if (data->counter < vma || vma + bfd_get_section_size(sec) <= data->counter) + return; + + bfd_find_nearest_line(abfd, sec, data->symbol, data->counter - vma, &(data->file), &(data->func), &(data->line)); +} + +static void +find(struct bfd_ctx * b, DWORD offset, const char **file, const char **func, unsigned *line) +{ + struct find_info data; + data.func = NULL; + data.symbol = b->symbol; + data.counter = offset; + data.file = NULL; + data.func = NULL; + data.line = 0; + + bfd_map_over_sections(b->handle, &lookup_section, &data); + if (file) { + *file = data.file; + } + if (func) { + *func = data.func; + } + if (line) { + *line = data.line; + } +} + +static int +init_bfd_ctx(struct bfd_ctx *bc, const char * procname, struct output_buffer *ob) +{ + int r1, r2, r3; + bfd *b; + void *symbol_table; + unsigned dummy = 0; + bc->handle = NULL; + bc->symbol = NULL; + + b = bfd_openr(procname, 0); + if (!b) { + output_print(ob,"Failed to open bfd from (%s)\n" , procname); + return 1; + } + + r1 = bfd_check_format(b, bfd_object); + r2 = bfd_check_format_matches(b, bfd_object, NULL); + r3 = bfd_get_file_flags(b) & HAS_SYMS; + + if (!(r1 && r2 && r3)) { + bfd_close(b); + if (!(r1 && r2)) + output_print(ob,"Failed to init bfd from (%s): %d %d %d\n", procname, r1, r2, r3); + return 1; + } + + if (bfd_read_minisymbols(b, FALSE, &symbol_table, &dummy) == 0) { + if (bfd_read_minisymbols(b, TRUE, &symbol_table, &dummy) < 0) { + free(symbol_table); + bfd_close(b); + output_print(ob,"Failed to read symbols from (%s)\n", procname); + return 1; + } + } + + bc->handle = b; + bc->symbol = symbol_table; + + return 0; +} + +static void +close_bfd_ctx(struct bfd_ctx *bc) +{ + if (bc) { + if (bc->symbol) { + free(bc->symbol); + } + if (bc->handle) { + bfd_close(bc->handle); + } + } +} + +static struct bfd_ctx * +get_bc(struct output_buffer *ob , struct bfd_set *set , const char *procname) +{ + struct bfd_ctx bc; + while(set->name) { + if (strcmp(set->name , procname) == 0) { + return set->bc; + } + set = set->next; + } + if (init_bfd_ctx(&bc, procname , ob)) { + return NULL; + } + set->next = calloc(1, sizeof(*set)); + set->bc = malloc(sizeof(struct bfd_ctx)); + memcpy(set->bc, &bc, sizeof(bc)); + set->name = strdup(procname); + + return set->bc; +} + +static void +release_set(struct bfd_set *set) +{ + while(set) { + struct bfd_set * temp = set->next; + if (set->name) + free(set->name); + close_bfd_ctx(set->bc); + free(set); + set = temp; + } +} + +static char procname[MAX_PATH]; + +#ifdef EBACKTRACE64 +# define MachineType IMAGE_FILE_MACHINE_AMD64 +# define MAYBE64(x) x ## 64 +#else +# define MachineType IMAGE_FILE_MACHINE_I386 +# define MAYBE64(x) x +#endif + +static void +_backtrace(struct output_buffer *ob, struct bfd_set *set, int depth , LPCONTEXT context) +{ + MAYBE64(STACKFRAME) frame; + HANDLE process, thread; + char symbol_buffer[sizeof(MAYBE64(IMAGEHLP_SYMBOL)) + 255]; + char module_name_raw[MAX_PATH]; + struct bfd_ctx *bc = NULL; + + GetModuleFileNameA(NULL, procname, sizeof procname); + + memset(&frame,0,sizeof(frame)); + +#ifdef EBACKTRACE64 + frame.AddrPC.Offset = context->Rip; + frame.AddrStack.Offset = context->Rsp; + frame.AddrFrame.Offset = context->Rbp; +#else + frame.AddrPC.Offset = context->Eip; + frame.AddrStack.Offset = context->Esp; + frame.AddrFrame.Offset = context->Ebp; +#endif + + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Mode = AddrModeFlat; + + process = GetCurrentProcess(); + thread = GetCurrentThread(); + + while(MAYBE64(StackWalk)(MachineType, + process, + thread, + &frame, + context, + NULL, + MAYBE64(SymFunctionTableAccess), + MAYBE64(SymGetModuleBase), NULL)) { + MAYBE64(IMAGEHLP_SYMBOL) *symbol; + MAYBE64(DWORD) module_base; + const char * module_name = "[unknown module]"; + + const char * file = NULL; + const char * func = NULL; + unsigned line = 0; + + --depth; + if (depth < 0) + break; + + symbol = (MAYBE64(IMAGEHLP_SYMBOL) *)symbol_buffer; + symbol->SizeOfStruct = (sizeof *symbol) + 255; + symbol->MaxNameLength = 254; + + module_base = MAYBE64(SymGetModuleBase)(process, frame.AddrPC.Offset); + + if (module_base && + GetModuleFileNameA((HINSTANCE)(intptr_t)module_base, module_name_raw, MAX_PATH)) { + module_name = module_name_raw; + bc = get_bc(ob, set, module_name); + } + + if (bc) { + find(bc,frame.AddrPC.Offset,&file,&func,&line); + } + + if (file == NULL) { + MAYBE64(DWORD) dummy = 0; + if (MAYBE64(SymGetSymFromAddr)(process, frame.AddrPC.Offset, &dummy, symbol)) { + file = symbol->Name; + } + else { + file = "[unknown file]"; + } + } + + output_print(ob,"0x%p : %s : %s", frame.AddrPC.Offset, module_name, file); + if (func != NULL) + output_print(ob, " (%d) : in function (%s)", line, func); + output_print(ob, "\n"); + } +} + +static LPTSTR FormatErrorMessage(DWORD dwMessageId) +{ + LPTSTR lpBuffer = NULL; + + // adapted from http://stackoverflow.com/a/455533 + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwMessageId, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) + (LPTSTR)&lpBuffer, + 0, + NULL); + + return lpBuffer; // must be LocalFree()'d by caller +} + +static LPTSTR FormatExceptionCodeMessage(DWORD dwMessageId) +{ + LPTSTR lpBuffer = NULL; + + FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE + |FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS, + GetModuleHandleA("ntdll.dll"), + dwMessageId, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) + (LPTSTR)&lpBuffer, + 0, + NULL); + + return lpBuffer; // must be LocalFree()'d by caller +} + + +// adapted from http://www.catch22.net/tuts/custom-messagebox +static HHOOK hMsgBoxHook; + +LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode < 0) + return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam); + + switch (nCode) + { + case HCBT_ACTIVATE: + { + // Get handle to the message box! + HWND hwnd = (HWND)wParam; + + // Do customization! + SetWindowTextA(GetDlgItem(hwnd, IDYES), "Quit"); + SetWindowTextA(GetDlgItem(hwnd, IDNO), "Continue"); + SetWindowTextA(GetDlgItem(hwnd, IDCANCEL), "Ignore"); + return 0; + } + break; + } + + // Call the next hook, if there is one + return CallNextHookEx(hMsgBoxHook, nCode, wParam, lParam); +} + +int ExceptionMessage(TCHAR *szText, TCHAR *szCaption) +{ + int retval; + + // Install a window hook, so we can intercept the message-box + // creation, and customize it + hMsgBoxHook = SetWindowsHookEx( + WH_CBT, + CBTProc, + NULL, + GetCurrentThreadId() // Only install for THIS thread!!! + ); + + // Display a standard message box + retval = MessageBoxA(NULL, szText, szCaption, MB_YESNOCANCEL|MB_ICONERROR|MB_TASKMODAL); + + // remove the window hook + UnhookWindowsHookEx(hMsgBoxHook); + + return retval; +} + +static char crashlogfilename[MAX_PATH] = "crash.log"; +static char propername[MAX_PATH] = "this application"; + +__declspec(dllexport) void SetTechnicalName(const char* input) +{ + snprintf(crashlogfilename, MAX_PATH, "%s.crash.log", input); +} +__declspec(dllexport) void SetProperName(const char* input) +{ + strncpy(propername, input, MAX_PATH); +} + +static char * g_output = NULL; +static PVOID g_prev = NULL; + +static LONG WINAPI +exception_filter(LPEXCEPTION_POINTERS info) +{ + struct output_buffer ob; + int logfd, written, msgboxID; + PEXCEPTION_RECORD exception; + BOOL initialized = FALSE; + char *ExceptionPrinted; + + for (exception = info->ExceptionRecord; exception != NULL; exception = exception->ExceptionRecord) + { +#if 0 + if (exception->ExceptionFlags & EXCEPTION_NONCONTINUABLE) + continuable = FALSE; +#endif + + switch (exception->ExceptionCode) + { + case EXCEPTION_BREAKPOINT: + case EXCEPTION_SINGLE_STEP: + case DBG_CONTROL_C: + case DBG_PRINTEXCEPTION_C: + case MS_VC_EXCEPTION: + break; + default: + { + LPTSTR ExceptionCodeMsg = FormatExceptionCodeMessage(exception->ExceptionCode); + // The message for this exception code is broken. + LPTSTR ExceptionText = exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ? "Access violation." : ExceptionCodeMsg; + + if (!initialized) + { + output_init(&ob, g_output, BUFFER_MAX); + initialized = TRUE; + } + + output_print(&ob, "Caught exception 0x%08X at 0x%p: %s\n", exception->ExceptionCode, exception->ExceptionAddress, ExceptionText); + + LocalFree(ExceptionCodeMsg); + } + break; + } + } + + if (!initialized) + return EXCEPTION_CONTINUE_SEARCH; // EXCEPTION_CONTINUE_EXECUTION + + ExceptionPrinted = (char*)calloc(strlen(g_output) + 37 + 2*MAX_PATH, sizeof(char)); + strcpy(ExceptionPrinted, g_output); + strcat(ExceptionPrinted, "\nPlease send "); + strcat(ExceptionPrinted, crashlogfilename); + strcat(ExceptionPrinted, " to the maintainers of "); + strcat(ExceptionPrinted, propername); + strcat(ExceptionPrinted, "."); + + { + DWORD error = 0; + BOOL SymInitialized = SymInitialize(GetCurrentProcess(), NULL, TRUE); + + if (!SymInitialized) + { + LPTSTR errorText; + + error = GetLastError(); + errorText = FormatErrorMessage(error); + output_print(&ob, "SymInitialize() failed with error %d: %s\n", error, errorText); + LocalFree(errorText); + } + + if (SymInitialized || error == 87) + { + struct bfd_set *set = calloc(1,sizeof(*set)); + bfd_init(); + _backtrace(&ob , set , 128 , info->ContextRecord); + release_set(set); + + SymCleanup(GetCurrentProcess()); + } + } + + logfd = open(crashlogfilename, O_APPEND | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + + if (logfd) { + time_t curtime; + struct tm *curltime; + const char *theasctime; + const char *finistr = "---------------\n"; + + while ((written = write(logfd, g_output, strlen(g_output)))) { + g_output += written; + } + + curtime = time(NULL); + curltime = localtime(&curtime); + theasctime = curltime ? asctime(curltime) : NULL; + + if (theasctime) + write(logfd, theasctime, strlen(theasctime)); + write(logfd, finistr, strlen(finistr)); + close(logfd); + } + + //fputs(g_output, stderr); + + msgboxID = ExceptionMessage(ExceptionPrinted, propername); + + free(ExceptionPrinted); + + switch (msgboxID) + { + case IDYES: + exit(0xBAC); + break; + case IDNO: + break; + case IDCANCEL: + return EXCEPTION_CONTINUE_EXECUTION; + break; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +static void +backtrace_register(void) +{ + if (g_output == NULL) { + g_output = malloc(BUFFER_MAX); + g_prev = AddVectoredExceptionHandler(1, exception_filter); + } +} + +static void +backtrace_unregister(void) +{ + if (g_output) { + free(g_output); + RemoveVectoredExceptionHandler(g_prev); + g_prev = NULL; + g_output = NULL; + } +} + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL ATTRIBUTE((unused)), DWORD dwReason, LPVOID lpvReserved ATTRIBUTE((unused))) +{ + switch (dwReason) { + case DLL_PROCESS_ATTACH: + backtrace_register(); + break; + case DLL_PROCESS_DETACH: + backtrace_unregister(); + break; + } + return TRUE; +} + + +/* cut dependence on libintl... libbfd needs this */ +char *libintl_dgettext (const char *domain_name ATTRIBUTE((unused)), const char *msgid ATTRIBUTE((unused))) +{ + static char buf[1024] = "XXX placeholder XXX"; + return buf; +} + +int __printf__ ( const char * format, ... ); +int libintl_fprintf ( FILE * stream, const char * format, ... ); +int libintl_sprintf ( char * str, const char * format, ... ); +int libintl_snprintf ( char *buffer, int buf_size, const char *format, ... ); +int libintl_vprintf ( const char * format, va_list arg ); +int libintl_vfprintf ( FILE * stream, const char * format, va_list arg ); +int libintl_vsprintf ( char * str, const char * format, va_list arg ); + +int __printf__ ( const char * format, ... ) +{ + int value; + va_list arg; + va_start(arg, format); + value = vprintf ( format, arg ); + va_end(arg); + return value; +} + +int libintl_fprintf ( FILE * stream, const char * format, ... ) +{ + int value; + va_list arg; + va_start(arg, format); + value = vfprintf ( stream, format, arg ); + va_end(arg); + return value; +} +int libintl_sprintf ( char * str, const char * format, ... ) +{ + int value; + va_list arg; + va_start(arg, format); + value = vsprintf ( str, format, arg ); + va_end(arg); + return value; +} +int libintl_snprintf ( char *buffer, int buf_size, const char *format, ... ) +{ + int value; + va_list arg; + va_start(arg, format); + value = vsnprintf ( buffer, buf_size, format, arg ); + va_end(arg); + return value; +} +int libintl_vprintf ( const char * format, va_list arg ) +{ + return vprintf ( format, arg ); +} +int libintl_vfprintf ( FILE * stream, const char * format, va_list arg ) +{ + return vfprintf ( stream, format, arg ); +} +int libintl_vsprintf ( char * str, const char * format, va_list arg ) +{ + return vsprintf ( str, format, arg ); +} + +/* cut dependence on zlib... libbfd needs this */ + +int compress (unsigned char *dest ATTRIBUTE((unused)), unsigned long destLen ATTRIBUTE((unused)), const unsigned char source ATTRIBUTE((unused)), unsigned long sourceLen ATTRIBUTE((unused))) +{ + return 0; +} +unsigned long compressBound (unsigned long sourceLen) +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; +} +int inflateEnd(void *strm ATTRIBUTE((unused))) +{ + return 0; +} +int inflateInit_(void *strm ATTRIBUTE((unused)), const char *version ATTRIBUTE((unused)), int stream_size ATTRIBUTE((unused))) +{ + return 0; +} +int inflateReset(void *strm ATTRIBUTE((unused))) +{ + return 0; +} +int inflate(void *strm ATTRIBUTE((unused)), int flush ATTRIBUTE((unused))) +{ + return 0; +} diff --git a/bin/windows/vpx/src/compat-to-msvc/Makefile b/bin/windows/vpx/src/compat-to-msvc/Makefile new file mode 100644 index 000000000..7c5f3760d --- /dev/null +++ b/bin/windows/vpx/src/compat-to-msvc/Makefile @@ -0,0 +1,22 @@ + +o=o + +NAME:=libcompat-to-msvc + + +%.$o: %.c + gcc -Wall -Wextra -O3 -c $< -o $@ + +%.$o: %.S + gcc -c $< -o $@ + +OBJS=dll_math.$o io_math.$o dll_dependency.$o vsnprintf.$o + +.INTERMEDIATE: $(OBJS) + +$(NAME).a: $(OBJS) + ar rc $@ $^ + ranlib $@ + +clean: + -rm -f *.a *.o diff --git a/bin/windows/vpx/src/compat-to-msvc/dll_dependency.S b/bin/windows/vpx/src/compat-to-msvc/dll_dependency.S new file mode 100644 index 000000000..31fd95c82 --- /dev/null +++ b/bin/windows/vpx/src/compat-to-msvc/dll_dependency.S @@ -0,0 +1,88 @@ +/* Implementation for gcc's internal stack-allocation routines. */ +.global ___chkstk +.global __alloca + +.global ___chkstk_ms +___chkstk_ms: +#ifdef _WIN64 + pushq %rax + pushq %rcx + cmpq $0x1000, %rax + leaq 24(%rsp), %rcx + jb .Lchkstk_ms_end +.Lchkstk_ms_loop: + subq $0x1000, %rcx + subq $0x1000, %rax + orq $0x0, (%rcx) + cmpq $0x1000, %rax + ja .Lchkstk_ms_loop +.Lchkstk_ms_end: + subq %rax, %rcx + orq $0x0, (%rcx) + popq %rcx + popq %rax + ret +#else + pushl %eax + pushl %ecx + cmpl $0x1000, %eax + leal 12(%esp), %ecx + jb chkstk_ms_end +chkstk_ms_loop: + subl $0x1000, %ecx + subl $0x1000, %eax + orl $0x0, (%ecx) + cmpl $0x1000, %eax + ja chkstk_ms_loop +chkstk_ms_end: + subl %eax, %ecx + orl $0x0, (%ecx) + popl %ecx + popl %eax + ret +#endif + +#ifdef _WIN64 +__alloca: + movq %rcx, %rax +.align 4 +___chkstk: + popq %r11 + movq %rsp, %r10 + cmpq $0x1000, %rax + jb .Lchkstk_end +.Lchkstk_loop: + subq $0x1000, %r10 + subq $0x1000, %rax + orl $0x0, (%r10) + cmpq $0x1000, %rax + ja .Lchkstk_loop +.Lchkstk_end: + subq %rax, %r10 + movq %rsp, %rax + orl $0x0, (%r10) + movq %r10, %rsp + pushq %r11 + ret +#else +___chkstk: +__alloca: + pushl %ecx + leal 8(%esp), %ecx + cmpl $0x1000, %eax /* > 4k ?*/ + jb chkstk_end +chkstk_loop: + subl $0x1000, %ecx + subl $0x1000, %eax + orl $0x0, (%ecx) + cmpl $0x1000, %eax + ja chkstk_loop +chkstk_end: + subl %eax, %ecx + orl $0x0, (%ecx) + movl %esp, %eax + movl %ecx, %esp + movl (%eax), %ecx + pushl 4(%eax) + ret +#endif diff --git a/bin/windows/vpx/src/compat-to-msvc/dll_math.c b/bin/windows/vpx/src/compat-to-msvc/dll_math.c new file mode 100644 index 000000000..966fb99d7 --- /dev/null +++ b/bin/windows/vpx/src/compat-to-msvc/dll_math.c @@ -0,0 +1,572 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + */ + +#ifndef _LIBKERN_QUAD_H_ +#define _LIBKERN_QUAD_H_ + +/* + * Quad arithmetic. + * + * This library makes the following assumptions: + * + * - The type long long (aka quad_t) exists. + * + * - A quad variable is exactly twice as long as `long'. + * + * - The machine's arithmetic is two's complement. + * + * This library can provide 128-bit arithmetic on a machine with 128-bit + * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines + * with 48-bit longs. + */ +/* +#include +#include +#include +#include +*/ + +#include +typedef long long quad_t; +typedef unsigned long long u_quad_t; +typedef unsigned long u_long; +#ifndef CHAR_BIT +# define CHAR_BIT __CHAR_BIT__ +#endif + +/* + * Define the order of 32-bit words in 64-bit words. + * For little endian only. + */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + quad_t q; /* as a (signed) quad */ + quad_t uq; /* as an unsigned quad */ + long sl[2]; /* as two signed longs */ + u_long ul[2]; /* as two unsigned longs */ +}; + +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +/* + * Extract high and low shortwords from longword, and move low shortword of + * longword to upper half of long, i.e., produce the upper longword of + * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) + * + * These are used in the multiply code, to split a longword into upper + * and lower halves, and to reassemble a product as a quad_t, shifted left + * (sizeof(long)*CHAR_BIT/2). + */ +#define HHALF(x) ((x) >> HALF_BITS) +#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1)) +#define LHUP(x) ((x) << HALF_BITS) + +typedef unsigned int qshift_t; + +quad_t __ashldi3(quad_t, qshift_t); +quad_t __ashrdi3(quad_t, qshift_t); +int __cmpdi2(quad_t a, quad_t b); +quad_t __divdi3(quad_t a, quad_t b); +quad_t __lshrdi3(quad_t, qshift_t); +quad_t __moddi3(quad_t a, quad_t b); +u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem); +u_quad_t __udivdi3(u_quad_t a, u_quad_t b); +u_quad_t __umoddi3(u_quad_t a, u_quad_t b); +int __ucmpdi2(u_quad_t a, u_quad_t b); + +#endif /* !_LIBKERN_QUAD_H_ */ + +#if defined (_X86_) && !defined (__x86_64__) +/* + * Shift a (signed) quad value left (arithmetic shift left). + * This is the same as logical shift left! + */ +quad_t +__ashldi3(a, shift) + quad_t a; + qshift_t shift; +{ + union uu aa; + + aa.q = a; + if (shift >= LONG_BITS) { + aa.ul[H] = shift >= QUAD_BITS ? 0 : + aa.ul[L] << (shift - LONG_BITS); + aa.ul[L] = 0; + } else if (shift > 0) { + aa.ul[H] = (aa.ul[H] << shift) | + (aa.ul[L] >> (LONG_BITS - shift)); + aa.ul[L] <<= shift; + } + return (aa.q); +} + +/* + * Shift a (signed) quad value right (arithmetic shift right). + */ +quad_t +__ashrdi3(a, shift) + quad_t a; + qshift_t shift; +{ + union uu aa; + + aa.q = a; + if (shift >= LONG_BITS) { + long s; + + /* + * Smear bits rightward using the machine's right-shift + * method, whether that is sign extension or zero fill, + * to get the `sign word' s. Note that shifting by + * LONG_BITS is undefined, so we shift (LONG_BITS-1), + * then 1 more, to get our answer. + */ + s = (aa.sl[H] >> (LONG_BITS - 1)) >> 1; + aa.ul[L] = shift >= QUAD_BITS ? s : + aa.sl[H] >> (shift - LONG_BITS); + aa.ul[H] = s; + } else if (shift > 0) { + aa.ul[L] = (aa.ul[L] >> shift) | + (aa.ul[H] << (LONG_BITS - shift)); + aa.sl[H] >>= shift; + } + return (aa.q); +} + +/* + * Return 0, 1, or 2 as a <, =, > b respectively. + * Both a and b are considered signed---which means only the high word is + * signed. + */ +int +__cmpdi2(a, b) + quad_t a, b; +{ + union uu aa, bb; + + aa.q = a; + bb.q = b; + return (aa.sl[H] < bb.sl[H] ? 0 : aa.sl[H] > bb.sl[H] ? 2 : + aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1); +} + +/* + * Divide two signed quads. + * ??? if -1/2 should produce -1 on this machine, this code is wrong + */ +quad_t +__divdi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, uq; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + uq = __qdivrem(ua, ub, (u_quad_t *)0); + return (neg ? -uq : uq); +} + +/* + * Shift an (unsigned) quad value right (logical shift right). + */ +quad_t +__lshrdi3(a, shift) + quad_t a; + qshift_t shift; +{ + union uu aa; + + aa.q = a; + if (shift >= LONG_BITS) { + aa.ul[L] = shift >= QUAD_BITS ? 0 : + aa.ul[H] >> (shift - LONG_BITS); + aa.ul[H] = 0; + } else if (shift > 0) { + aa.ul[L] = (aa.ul[L] >> shift) | + (aa.ul[H] << (LONG_BITS - shift)); + aa.ul[H] >>= shift; + } + return (aa.q); +} + +/* + * Return remainder after dividing two signed quads. + * + * XXX + * If -1/2 should produce -1 on this machine, this code is wrong. + */ +quad_t +__moddi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, ur; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b; + else + ub = b; + (void)__qdivrem(ua, ub, &ur); + return (neg ? -ur : ur); +} + + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ + +#define B (1 << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff +typedef unsigned short digit; +#else +typedef u_long digit; +#endif + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void +__shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +u_quad_t +__qdivrem(uq, vq, arq) + u_quad_t uq, vq, *arq; +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + __shl(&u[0], m + n, d); /* u <<= d */ + __shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long nn = COMBINE(uj0, uj1); + qhat = nn / v1; + rhat = nn % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} + +/* + * Return 0, 1, or 2 as a <, =, > b respectively. + * Neither a nor b are considered signed. + */ +int +__ucmpdi2(a, b) + u_quad_t a, b; +{ + union uu aa, bb; + + aa.uq = a; + bb.uq = b; + return (aa.ul[H] < bb.ul[H] ? 0 : aa.ul[H] > bb.ul[H] ? 2 : + aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1); +} + +/* + * Divide two unsigned quads. + */ +u_quad_t +__udivdi3(a, b) + u_quad_t a, b; +{ + + return (__qdivrem(a, b, (u_quad_t *)0)); +} + +/* + * Return remainder after dividing two unsigned quads. + */ +u_quad_t +__umoddi3(a, b) + u_quad_t a, b; +{ + u_quad_t r; + + (void)__qdivrem(a, b, &r); + return (r); +} + +/* + * Divide two unsigned quads. + * This function is new in GCC 7. + */ +u_quad_t +__udivmoddi4(a, b, rem) + u_quad_t a, b, *rem; +{ + u_quad_t ua, ub, uq, ur; + + ua = a; + ub = b; + uq = __qdivrem(ua, ub, &ur); + if (rem) + *rem = ur; + return uq; +} +#else +static int __attribute__((unused)) dummy; +#endif /* defined (_X86_) && !defined (__x86_64__) */ + diff --git a/bin/windows/vpx/src/compat-to-msvc/io_math.c b/bin/windows/vpx/src/compat-to-msvc/io_math.c new file mode 100644 index 000000000..39d5a8e39 --- /dev/null +++ b/bin/windows/vpx/src/compat-to-msvc/io_math.c @@ -0,0 +1,39 @@ +// Some libraries expect these functions, for which Visual Studio (pre-2013) falls down on the job. + +#include +#include + +#ifndef _MSC_VER +# include +int64_t _ftelli64( + FILE *stream +); +int _fseeki64( + FILE *stream, + int64_t offset, + int origin +); +#endif + +int fseeko(FILE *fp, off_t offset, int whence) +{ + return _fseeki64(fp, (int64_t)offset, whence); +} +int fseeko64(FILE *fp, off64_t offset, int whence) +{ + return _fseeki64(fp, (int64_t)offset, whence); +} + +off_t ftello(FILE *stream) +{ + return (off_t)_ftelli64(stream); +} +off64_t ftello64(FILE *stream) +{ + return (off64_t)_ftelli64(stream); +} + +long lround(double d) +{ + return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5)); +} diff --git a/bin/windows/vpx/src/compat-to-msvc/vsnprintf.c b/bin/windows/vpx/src/compat-to-msvc/vsnprintf.c new file mode 100644 index 000000000..15de014c4 --- /dev/null +++ b/bin/windows/vpx/src/compat-to-msvc/vsnprintf.c @@ -0,0 +1,19 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include +#include + +extern int __cdecl _vsnprintf(char * __restrict__, size_t, const char * __restrict__, va_list); + +int __cdecl __ms_vsnprintf (char * __restrict__ s, size_t n, const char * __restrict__ format, va_list arg) +{ + return _vsnprintf(s, n, format, arg); +} +int __cdecl __mingw_vsnprintf (char * __restrict__ s, size_t n, const char * __restrict__ format, va_list arg) +{ + return _vsnprintf(s, n, format, arg); +} diff --git a/bin/windows/zmusic/arm64/zmusic.dll b/bin/windows/zmusic/arm64/zmusic.dll deleted file mode 100644 index 9417d1e41..000000000 Binary files a/bin/windows/zmusic/arm64/zmusic.dll and /dev/null differ diff --git a/bin/windows/zmusic/include/zmusic.h b/bin/windows/zmusic/include/zmusic.h index 7de05c5fa..7422b58da 100644 --- a/bin/windows/zmusic/include/zmusic.h +++ b/bin/windows/zmusic/include/zmusic.h @@ -67,7 +67,8 @@ typedef struct SoundStreamInfo_ typedef enum SampleType_ { SampleType_UInt8, - SampleType_Int16 + SampleType_Int16, + SampleType_Float32 } SampleType; typedef enum ChannelConfig_ @@ -76,6 +77,15 @@ typedef enum ChannelConfig_ ChannelConfig_Stereo } ChannelConfig; +typedef struct SoundStreamInfoEx_ +{ + int mBufferSize; // If mBufferSize is 0, the song doesn't use streaming but plays through a different interface. + int mSampleRate; + SampleType mSampleType; + ChannelConfig mChannelConfig; +} SoundStreamInfoEx; + + typedef enum EIntConfigKey_ { zmusic_adl_chips_count, @@ -264,14 +274,14 @@ typedef struct ZMusicConfigurationSetting_ #ifndef ZMUSIC_INTERNAL -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(ZMUSIC_STATIC) #define DLL_IMPORT _declspec(dllimport) -#else // !_MSC_VER +#else #define DLL_IMPORT -#endif // _MSC_VER +#endif // Note that the internal 'class' definitions are not C compatible! -typedef struct { int zm1; } *ZMusic_MidiSource; -typedef struct { int zm2; } *ZMusic_MusicStream; +typedef struct _ZMusic_MidiSource_Struct { int zm1; } *ZMusic_MidiSource; +typedef struct _ZMusic_MusicStream_Struct { int zm2; } *ZMusic_MusicStream; struct SoundDecoder; #endif @@ -319,6 +329,7 @@ extern "C" DLL_IMPORT void ZMusic_VolumeChanged(ZMusic_MusicStream song); DLL_IMPORT zmusic_bool ZMusic_WriteSMF(ZMusic_MidiSource source, const char* fn, int looplimit); DLL_IMPORT void ZMusic_GetStreamInfo(ZMusic_MusicStream song, SoundStreamInfo *info); + DLL_IMPORT void ZMusic_GetStreamInfoEx(ZMusic_MusicStream song, SoundStreamInfoEx *info); // Configuration interface. The return value specifies if a music restart is needed. // RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state. DLL_IMPORT zmusic_bool ChangeMusicSettingInt(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue); @@ -406,6 +417,7 @@ typedef zmusic_bool (*pfn_ZMusic_IsMIDI)(ZMusic_MusicStream song); typedef void (*pfn_ZMusic_VolumeChanged)(ZMusic_MusicStream song); typedef zmusic_bool (*pfn_ZMusic_WriteSMF)(ZMusic_MidiSource source, const char* fn, int looplimit); typedef void (*pfn_ZMusic_GetStreamInfo)(ZMusic_MusicStream song, SoundStreamInfo *info); +typedef void (*pfn_ZMusic_GetStreamInfoEx)(ZMusic_MusicStream song, SoundStreamInfoEx *info); typedef zmusic_bool (*pfn_ChangeMusicSettingInt)(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue); typedef zmusic_bool (*pfn_ChangeMusicSettingFloat)(EFloatConfigKey key, ZMusic_MusicStream song, float value, float* pRealValue); typedef zmusic_bool (*pfn_ChangeMusicSettingString)(EStringConfigKey key, ZMusic_MusicStream song, const char* value); @@ -419,4 +431,4 @@ typedef const ZMusicMidiOutDevice *(*pfn_ZMusic_GetMidiDevices)(int *pAmount); -#endif \ No newline at end of file +#endif diff --git a/cmake/FindVPX.cmake b/cmake/FindVPX.cmake new file mode 100644 index 000000000..160ff0618 --- /dev/null +++ b/cmake/FindVPX.cmake @@ -0,0 +1,8 @@ + +find_path(VPX_INCLUDE_DIR NAMES vpx/vp8dx.h vpx/vpx_decoder.h) +find_library(VPX_LIBRARIES NAMES vpx) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(VPX DEFAULT_MSG VPX_LIBRARIES VPX_INCLUDE_DIR) + +mark_as_advanced(VPX_INCLUDE_DIR VPX_LIBRARIES) diff --git a/docs/licenses/README.TXT b/docs/licenses/README.TXT index 53d939b06..46d84c26b 100644 --- a/docs/licenses/README.TXT +++ b/docs/licenses/README.TXT @@ -9,7 +9,7 @@ GPL v3 with permission. The majority of original code uses a BSD-like lincese. See bsd.txt. The OpenGL renderer is released under the LGPL v3, except some bits -of code that were inherited fro ZDoomGL. +of code that were inherited from ZDoomGL. Some code was taken from the Eternity Engine. Copyright (c) James Haley, Stephen McGranahan, et al. @@ -31,4 +31,4 @@ version used by the foobar2000 component foo_dumb as of mid-2008, found at http://kode54.foobar2000.org/. All script code in gzdoom.pk3 is licensed under the GPL v3 unless noted -otherwise. \ No newline at end of file +otherwise. diff --git a/fm_banks/LINKS.txt b/fm_banks/LINKS.txt new file mode 100644 index 000000000..4a5f592a3 --- /dev/null +++ b/fm_banks/LINKS.txt @@ -0,0 +1 @@ +https://github.com/Wohlstand/OPN2BankEditor diff --git a/fm_banks/Tomsoft-readme.txt b/fm_banks/Tomsoft-readme.txt new file mode 100644 index 000000000..13746830a --- /dev/null +++ b/fm_banks/Tomsoft-readme.txt @@ -0,0 +1,15 @@ +Bank was imported by a hacky way from the Tomsoft's SegaMusic program +by TommyXie (Xie Rong Chun): +- the dummy MIDI file was created that contains all 128 instruments in GM order +- the Sega emulator playable BIN file was generated +- the GYM dump was generated from the playback of that dummy instrument +- OPN2 Bank Editor was used to scan GYM file for instruments and import all of +them. + +The work woth done by Jean-Pierre Cimalando: +https://github.com/Wohlstand/OPN2BankEditor/issues/44 + +Then, the bank was tuned by Wohlstand: +- Corrected note offsets to align octaves of all instruments +- Merged with xg.wopn to provide the set of percussions. + diff --git a/fm_banks/Tomsoft.wopn b/fm_banks/Tomsoft.wopn new file mode 100644 index 000000000..92ccabfb0 Binary files /dev/null and b/fm_banks/Tomsoft.wopn differ diff --git a/fm_banks/gs-by-papiezak-and-sneakernets.wopn b/fm_banks/gs-by-papiezak-and-sneakernets.wopn index f3757d5b0..ecd87a53e 100644 Binary files a/fm_banks/gs-by-papiezak-and-sneakernets.wopn and b/fm_banks/gs-by-papiezak-and-sneakernets.wopn differ diff --git a/fm_banks/readme.txt b/fm_banks/readme.txt new file mode 100644 index 000000000..4d7994a22 --- /dev/null +++ b/fm_banks/readme.txt @@ -0,0 +1,14 @@ +This bank (gm.wopn and xg.wopn) is made by me. I have imported some instruments from various +VGM files, ported from OPL3 banks, or remixed them. + +This bank can be freely used, modified, shared with any purposes. + +License for this bank - MIT + +To edit this bank and other banks in WOPN format, you can use this editor +which I created for that: https://github.com/Wohlstand/OPN2BankEditor + +============================================================================== + +Vitaliy Novichkov "Wohlstand", 2017-2018 + diff --git a/fm_banks/xg.wopn b/fm_banks/xg.wopn new file mode 100644 index 000000000..38208b255 Binary files /dev/null and b/fm_banks/xg.wopn differ diff --git a/libraries/ZVulkan/CMakeLists.txt b/libraries/ZVulkan/CMakeLists.txt new file mode 100644 index 000000000..8a99d6a91 --- /dev/null +++ b/libraries/ZVulkan/CMakeLists.txt @@ -0,0 +1,199 @@ +cmake_minimum_required(VERSION 3.15) +project(zvulkan) + +set(ZVULKAN_SOURCES + src/vulkanbuilders.cpp + src/vulkandevice.cpp + src/vulkaninstance.cpp + src/vulkansurface.cpp + src/vulkanswapchain.cpp + src/vk_mem_alloc/vk_mem_alloc.cpp + src/vk_mem_alloc/vk_mem_alloc.natvis + src/volk/volk.c + src/glslang/glslang/MachineIndependent/SymbolTable.h + src/glslang/glslang/MachineIndependent/propagateNoContraction.cpp + src/glslang/glslang/MachineIndependent/PoolAlloc.cpp + src/glslang/glslang/MachineIndependent/Intermediate.cpp + src/glslang/glslang/MachineIndependent/gl_types.h + src/glslang/glslang/MachineIndependent/parseVersions.h + src/glslang/glslang/MachineIndependent/attribute.cpp + src/glslang/glslang/MachineIndependent/Scan.cpp + src/glslang/glslang/MachineIndependent/iomapper.h + src/glslang/glslang/MachineIndependent/ParseHelper.h + src/glslang/glslang/MachineIndependent/glslang_tab.cpp.h + src/glslang/glslang/MachineIndependent/SymbolTable.cpp + src/glslang/glslang/MachineIndependent/RemoveTree.cpp + src/glslang/glslang/MachineIndependent/Versions.h + src/glslang/glslang/MachineIndependent/reflection.cpp + src/glslang/glslang/MachineIndependent/LiveTraverser.h + src/glslang/glslang/MachineIndependent/iomapper.cpp + src/glslang/glslang/MachineIndependent/intermOut.cpp + src/glslang/glslang/MachineIndependent/Versions.cpp + src/glslang/glslang/MachineIndependent/Initialize.h + src/glslang/glslang/MachineIndependent/linkValidate.cpp + src/glslang/glslang/MachineIndependent/InfoSink.cpp + src/glslang/glslang/MachineIndependent/Constant.cpp + src/glslang/glslang/MachineIndependent/IntermTraverse.cpp + src/glslang/glslang/MachineIndependent/propagateNoContraction.h + src/glslang/glslang/MachineIndependent/glslang_tab.cpp + src/glslang/glslang/MachineIndependent/ShaderLang.cpp + src/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp + src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h + src/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp + src/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp + src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp + src/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp + src/glslang/glslang/MachineIndependent/preprocessor/PpContext.h + src/glslang/glslang/MachineIndependent/attribute.h + src/glslang/glslang/MachineIndependent/localintermediate.h + src/glslang/glslang/MachineIndependent/parseConst.cpp + src/glslang/glslang/MachineIndependent/Initialize.cpp + src/glslang/glslang/MachineIndependent/limits.cpp + src/glslang/glslang/MachineIndependent/ParseContextBase.cpp + src/glslang/glslang/MachineIndependent/RemoveTree.h + src/glslang/glslang/MachineIndependent/ParseHelper.cpp + src/glslang/glslang/MachineIndependent/Scan.h + src/glslang/glslang/MachineIndependent/reflection.h + src/glslang/glslang/MachineIndependent/ScanContext.h + src/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp + src/glslang/glslang/OSDependent/osinclude.h + src/glslang/glslang/GenericCodeGen/Link.cpp + src/glslang/glslang/GenericCodeGen/CodeGen.cpp + src/glslang/glslang/Public/ShaderLang.h + src/glslang/glslang/Include/ConstantUnion.h + src/glslang/glslang/Include/InitializeGlobals.h + src/glslang/glslang/Include/Common.h + src/glslang/glslang/Include/PoolAlloc.h + src/glslang/glslang/Include/arrays.h + src/glslang/glslang/Include/ShHandle.h + src/glslang/glslang/Include/InfoSink.h + src/glslang/glslang/Include/ResourceLimits.h + src/glslang/glslang/Include/Types.h + src/glslang/glslang/Include/BaseTypes.h + src/glslang/glslang/Include/intermediate.h + src/glslang/glslang/Include/SpirvIntrinsics.h + src/glslang/glslang/Include/build_info.h + src/glslang/glslang/OSDependent/osinclude.h + src/glslang/spirv/Logger.h + src/glslang/spirv/GlslangToSpv.cpp + src/glslang/spirv/SPVRemapper.h + src/glslang/spirv/GLSL.ext.EXT.h + src/glslang/spirv/hex_float.h + src/glslang/spirv/doc.cpp + src/glslang/spirv/disassemble.cpp + src/glslang/spirv/SpvPostProcess.cpp + src/glslang/spirv/bitutils.h + src/glslang/spirv/InReadableOrder.cpp + src/glslang/spirv/GLSL.ext.AMD.h + src/glslang/spirv/GLSL.ext.NV.h + src/glslang/spirv/SPVRemapper.cpp + src/glslang/spirv/SpvBuilder.h + src/glslang/spirv/GLSL.ext.KHR.h + src/glslang/spirv/disassemble.h + src/glslang/spirv/SpvBuilder.cpp + src/glslang/spirv/GlslangToSpv.h + src/glslang/spirv/doc.h + src/glslang/spirv/SpvTools.cpp + src/glslang/spirv/spvIR.h + src/glslang/spirv/Logger.cpp + src/glslang/spirv/SpvTools.h + src/glslang/spirv/GLSL.std.450.h + src/glslang/spirv/NonSemanticDebugPrintf.h + src/glslang/OGLCompilersDLL/InitializeDll.cpp + src/glslang/OGLCompilersDLL/InitializeDll.h +) + +set(ZVULKAN_INCLUDES + include/zvulkan/vulkanbuilders.h + include/zvulkan/vulkancompatibledevice.h + include/zvulkan/vulkandevice.h + include/zvulkan/vulkaninstance.h + include/zvulkan/vulkanobjects.h + include/zvulkan/vulkansurface.h + include/zvulkan/vulkanswapchain.h + include/zvulkan/volk/volk.h + include/zvulkan/vk_mem_alloc/vk_mem_alloc.h +) + +set(ZVULKAN_WIN32_SOURCES + src/glslang/glslang/OSDependent/Windows/ossource.cpp +) + +set(ZVULKAN_UNIX_SOURCES + src/glslang/glslang/OSDependent/Unix/ossource.cpp +) + +set(VULKAN_INCLUDES + include/vulkan/vk_enum_string_helper.h + include/vulkan/vk_icd.h + include/vulkan/vk_layer.h + include/vulkan/vk_layer_dispatch_table.h + include/vulkan/vk_platform.h + include/vulkan/vk_sdk_platform.h + include/vulkan/vulkan.h + include/vulkan/vulkan_android.h + include/vulkan/vulkan_beta.h + include/vulkan/vulkan_core.h + include/vulkan/vulkan_directfb.h + include/vulkan/vulkan_fuchsia.h + include/vulkan/vulkan_ggp.h + include/vulkan/vulkan_ios.h + include/vulkan/vulkan_macos.h + include/vulkan/vulkan_metal.h + include/vulkan/vulkan_mir.h + include/vulkan/vulkan_screen.h + include/vulkan/vulkan_vi.h + include/vulkan/vulkan_wayland.h + include/vulkan/vulkan_win32.h + include/vulkan/vulkan_xcb.h + include/vulkan/vulkan_xlib.h + include/vulkan/vulkan_xlib_xrandr.h +) + +source_group("src" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/.+") +source_group("src\\glslang" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/.+") +source_group("src\\glslang\\glslang" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/.+") +source_group("src\\glslang\\glslang\\GenericCodeGen" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/GenericCodeGen/.+") +source_group("src\\glslang\\glslang\\Include" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/Include/.+") +source_group("src\\glslang\\glslang\\MachineIndependent" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/MachineIndependent/.+") +source_group("src\\glslang\\glslang\\MachineIndependent\\preprocessor" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/MachineIndependent/preprocessor/.+") +source_group("src\\glslang\\glslang\\OSDependent" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/OSDependent/.+") +source_group("src\\glslang\\glslang\\OSDependent\\Unix" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/OSDependent/Unix/.+") +source_group("src\\glslang\\glslang\\OSDependent\\Web" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/OSDependent/Web/.+") +source_group("src\\glslang\\glslang\\OSDependent\\Windows" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/OSDependent/Windows/.+") +source_group("src\\glslang\\glslang\\Public" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/glslang/Public/.+") +source_group("src\\glslang\\OGLCompilersDLL" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/OGLCompilersDLL/.+") +source_group("src\\glslang\\spirv" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/glslang/spirv/.+") +source_group("src\\vk_mem_alloc" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/vk_mem_alloc/.+") +source_group("src\\volk" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/volk/.+") +source_group("include" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zvulkan/.+") +source_group("include\\vk_mem_alloc" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zvulkan/vk_mem_alloc/.+") +source_group("include\\volk" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/include/zvulkan/volk/.+") + +include_directories(include include/zvulkan src) + +if(WIN32) + set(ZVULKAN_SOURCES ${ZVULKAN_SOURCES} ${ZVULKAN_WIN32_SOURCES}) + add_definitions(-DUNICODE -D_UNICODE) +else() + set(ZVULKAN_SOURCES ${ZVULKAN_SOURCES} ${ZVULKAN_UNIX_SOURCES}) + set(ZVULKAN_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(${ZVULKAN_SOURCES} PROPERTIES COMPILE_FLAGS "/wd4244 /wd4267 /wd4005 /wd4018 -D_CRT_SECURE_NO_WARNINGS") +endif() + +add_library(zvulkan STATIC ${ZVULKAN_SOURCES} ${ZVULKAN_INCLUDES} ${VULKAN_INCLUDES}) +target_link_libraries(zvulkan ${ZVULKAN_LIBS}) +set_target_properties(zvulkan PROPERTIES CXX_STANDARD 17) + +if(MSVC) + set_property(TARGET zvulkan PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() diff --git a/libraries/ZVulkan/LICENSE.md b/libraries/ZVulkan/LICENSE.md new file mode 100644 index 000000000..6685241c0 --- /dev/null +++ b/libraries/ZVulkan/LICENSE.md @@ -0,0 +1,90 @@ +# License information + +## License for ZVulkan itself + + // Copyright (c) 2016-2022 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. + +## License for src/vk_mem_alloc + + // Copyright (c) 2017-2018 Advanced Micro Devices, Inc. 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. + // + +## License for src/volk + + /** + * Copyright (c) 2018-2019 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 + * 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. + */ + +## License for include/zvulkan/vulkan + + /* + ** Copyright (c) 2015-2019 The Khronos Group 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. + */ + +## License for src/glslang + + See src/glslang/LICENSE.txt diff --git a/libraries/ZVulkan/README.md b/libraries/ZVulkan/README.md new file mode 100644 index 000000000..391082b5c --- /dev/null +++ b/libraries/ZVulkan/README.md @@ -0,0 +1,2 @@ +# ZVulkan +A framework for building vulkan applications diff --git a/libraries/ZVulkan/include/vulkan/vk_enum_string_helper.h b/libraries/ZVulkan/include/vulkan/vk_enum_string_helper.h new file mode 100644 index 000000000..e82bb6ce4 --- /dev/null +++ b/libraries/ZVulkan/include/vulkan/vk_enum_string_helper.h @@ -0,0 +1,8448 @@ +// *** THIS FILE IS GENERATED - DO NOT EDIT *** +// See helper_file_generator.py for modifications + + +/*************************************************************************** + * + * Copyright (c) 2015-2021 The Khronos Group Inc. + * Copyright (c) 2015-2021 Valve Corporation + * Copyright (c) 2015-2021 LunarG, Inc. + * Copyright (c) 2015-2021 Google 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. + * + * Author: Mark Lobodzinski + * Author: Courtney Goeltzenleuchter + * Author: Tobin Ehlis + * Author: Chris Forbes + * Author: John Zulauf + * + ****************************************************************************/ + + +#pragma once +#ifdef _MSC_VER +#pragma warning( disable : 4065 ) +#endif + +#include +#include + + +static inline const char* string_VkResult(VkResult input_value) +{ + switch (input_value) + { + case VK_ERROR_DEVICE_LOST: + return "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_EXTENSION_NOT_PRESENT: + return "VK_ERROR_EXTENSION_NOT_PRESENT"; + case VK_ERROR_FEATURE_NOT_PRESENT: + return "VK_ERROR_FEATURE_NOT_PRESENT"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: + return "VK_ERROR_FORMAT_NOT_SUPPORTED"; + case VK_ERROR_FRAGMENTATION: + return "VK_ERROR_FRAGMENTATION"; + case VK_ERROR_FRAGMENTED_POOL: + return "VK_ERROR_FRAGMENTED_POOL"; + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: + return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; + case VK_ERROR_INCOMPATIBLE_DRIVER: + return "VK_ERROR_INCOMPATIBLE_DRIVER"; + case VK_ERROR_INITIALIZATION_FAILED: + return "VK_ERROR_INITIALIZATION_FAILED"; + case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: + return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: + return "VK_ERROR_INVALID_EXTERNAL_HANDLE"; + case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: + return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS"; + case VK_ERROR_INVALID_SHADER_NV: + return "VK_ERROR_INVALID_SHADER_NV"; + case VK_ERROR_LAYER_NOT_PRESENT: + return "VK_ERROR_LAYER_NOT_PRESENT"; + case VK_ERROR_MEMORY_MAP_FAILED: + return "VK_ERROR_MEMORY_MAP_FAILED"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: + return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; + case VK_ERROR_NOT_PERMITTED_EXT: + return "VK_ERROR_NOT_PERMITTED_EXT"; + case VK_ERROR_OUT_OF_DATE_KHR: + return "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: + return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_OUT_OF_HOST_MEMORY: + return "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_POOL_MEMORY: + return "VK_ERROR_OUT_OF_POOL_MEMORY"; + case VK_ERROR_SURFACE_LOST_KHR: + return "VK_ERROR_SURFACE_LOST_KHR"; + case VK_ERROR_TOO_MANY_OBJECTS: + return "VK_ERROR_TOO_MANY_OBJECTS"; + case VK_ERROR_UNKNOWN: + return "VK_ERROR_UNKNOWN"; + case VK_ERROR_VALIDATION_FAILED_EXT: + return "VK_ERROR_VALIDATION_FAILED_EXT"; + case VK_EVENT_RESET: + return "VK_EVENT_RESET"; + case VK_EVENT_SET: + return "VK_EVENT_SET"; + case VK_INCOMPLETE: + return "VK_INCOMPLETE"; + case VK_NOT_READY: + return "VK_NOT_READY"; + case VK_OPERATION_DEFERRED_KHR: + return "VK_OPERATION_DEFERRED_KHR"; + case VK_OPERATION_NOT_DEFERRED_KHR: + return "VK_OPERATION_NOT_DEFERRED_KHR"; + case VK_PIPELINE_COMPILE_REQUIRED_EXT: + return "VK_PIPELINE_COMPILE_REQUIRED_EXT"; + case VK_SUBOPTIMAL_KHR: + return "VK_SUBOPTIMAL_KHR"; + case VK_SUCCESS: + return "VK_SUCCESS"; + case VK_THREAD_DONE_KHR: + return "VK_THREAD_DONE_KHR"; + case VK_THREAD_IDLE_KHR: + return "VK_THREAD_IDLE_KHR"; + case VK_TIMEOUT: + return "VK_TIMEOUT"; + default: + return "Unhandled VkResult"; + } +} + +static inline const char* string_VkStructureType(VkStructureType input_value) +{ + switch (input_value) + { + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV"; + case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR"; + case VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR: + return "VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID: + return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID"; + case VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_APPLICATION_INFO: + return "VK_STRUCTURE_TYPE_APPLICATION_INFO"; + case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2: + return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2"; + case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT: + return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT"; + case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2: + return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2"; + case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT: + return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT"; + case VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV: + return "VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV"; + case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO: + return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO"; + case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR"; + case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: + return "VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO"; + case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: + return "VK_STRUCTURE_TYPE_BIND_SPARSE_INFO"; + case VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR: + return "VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR"; + case VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR: + return "VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR"; + case VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT: + return "VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT"; + case VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV: + return "VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV"; + case VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV: + return "VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV"; + case VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT: + return "VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT"; + case VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR"; + case VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM: + return "VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM"; + case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET: + return "VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET"; + case VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR: + return "VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR"; + case VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX"; + case VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX"; + case VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX: + return "VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX"; + case VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT"; + case VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2: + return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2"; + case VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT: + return "VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT"; + case VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD: + return "VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT: + return "VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT"; + case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR"; + case VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: + return "VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"; + case VK_STRUCTURE_TYPE_EVENT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EVENT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID: + return "VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID"; + case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES: + return "VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES"; + case VK_STRUCTURE_TYPE_FENCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FENCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV: + return "VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV"; + case VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV: + return "VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV"; + case VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV: + return "VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_NV"; + case VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV: + return "VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV"; + case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_HDR_METADATA_EXT: + return "VK_STRUCTURE_TYPE_HDR_METADATA_EXT"; + case VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2: + return "VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2"; + case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX"; + case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: + return "VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID"; + case VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV"; + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV: + return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV"; + case VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL: + return "VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL"; + case VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK: + return "VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK"; + case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK: + return "VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK"; + case VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE: + return "VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE"; + case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_BARRIER: + return "VK_STRUCTURE_TYPE_MEMORY_BARRIER"; + case VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: + return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS"; + case VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID: + return "VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID"; + case VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV: + return "VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV"; + case VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO: + return "VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO"; + case VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2: + return "VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2"; + case VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA: + return "VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA"; + case VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE: + return "VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE"; + case VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL: + return "VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR: + return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD"; + case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP: + return "VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP"; + case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_ID_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: + return "VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR"; + case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: + return "VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE"; + case VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO: + return "VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO"; + case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL: + return "VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT"; + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV: + return "VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV"; + case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2: + return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2"; + case VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO: + return "VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO"; + case VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT: + return "VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT"; + case VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM: + return "VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM"; + case VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES"; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: + return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO"; + case VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT: + return "VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT"; + case VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX: + return "VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX"; + case VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR"; + case VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA: + return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA"; + case VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR: + return "VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR"; + case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO: + return "VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO"; + case VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO: + return "VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO"; + case VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2: + return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2"; + case VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2: + return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2"; + case VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP: + return "VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP"; + case VK_STRUCTURE_TYPE_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR: + return "VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR"; + case VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO: + return "VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO"; + case VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2: + return "VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2"; + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2: + return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2"; + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE: + return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE"; + case VK_STRUCTURE_TYPE_SUBPASS_END_INFO: + return "VK_STRUCTURE_TYPE_SUBPASS_END_INFO"; + case VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI: + return "VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR"; + case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR"; + case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT: + return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT"; + case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD: + return "VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD"; + case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD: + return "VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD"; + case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO: + return "VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO"; + case VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT"; + case VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT"; + case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT: + return "VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT"; + case VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT: + return "VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT"; + case VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT: + return "VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN: + return "VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN"; + case VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV: + return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV"; + case VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV"; + case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: + return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT"; + case VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR"; + case VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR: + return "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR"; + default: + return "Unhandled VkStructureType"; + } +} + +static inline const char* string_VkAccessFlagBits(VkAccessFlagBits input_value) +{ + switch (input_value) + { + case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: + return "VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: + return "VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: + return "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT"; + case VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: + return "VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV: + return "VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV"; + case VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV: + return "VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV"; + case VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT: + return "VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT"; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: + return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT"; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: + return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"; + case VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: + return "VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + case VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_HOST_READ_BIT: + return "VK_ACCESS_HOST_READ_BIT"; + case VK_ACCESS_HOST_WRITE_BIT: + return "VK_ACCESS_HOST_WRITE_BIT"; + case VK_ACCESS_INDEX_READ_BIT: + return "VK_ACCESS_INDEX_READ_BIT"; + case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: + return "VK_ACCESS_INDIRECT_COMMAND_READ_BIT"; + case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: + return "VK_ACCESS_INPUT_ATTACHMENT_READ_BIT"; + case VK_ACCESS_MEMORY_READ_BIT: + return "VK_ACCESS_MEMORY_READ_BIT"; + case VK_ACCESS_MEMORY_WRITE_BIT: + return "VK_ACCESS_MEMORY_WRITE_BIT"; + case VK_ACCESS_NONE_KHR: + return "VK_ACCESS_NONE_KHR"; + case VK_ACCESS_SHADER_READ_BIT: + return "VK_ACCESS_SHADER_READ_BIT"; + case VK_ACCESS_SHADER_WRITE_BIT: + return "VK_ACCESS_SHADER_WRITE_BIT"; + case VK_ACCESS_TRANSFER_READ_BIT: + return "VK_ACCESS_TRANSFER_READ_BIT"; + case VK_ACCESS_TRANSFER_WRITE_BIT: + return "VK_ACCESS_TRANSFER_WRITE_BIT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + case VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: + return "VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + case VK_ACCESS_UNIFORM_READ_BIT: + return "VK_ACCESS_UNIFORM_READ_BIT"; + case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: + return "VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT"; + default: + return "Unhandled VkAccessFlagBits"; + } +} + +static inline std::string string_VkAccessFlags(VkAccessFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccessFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccessFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageLayout(VkImageLayout input_value) +{ + switch (input_value) + { + case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR: + return "VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR"; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: + return "VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT"; + case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR: + return "VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR"; + case VK_IMAGE_LAYOUT_GENERAL: + return "VK_IMAGE_LAYOUT_GENERAL"; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return "VK_IMAGE_LAYOUT_PREINITIALIZED"; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR"; + case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR: + return "VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR"; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: + return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR"; + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL"; + case VK_IMAGE_LAYOUT_UNDEFINED: + return "VK_IMAGE_LAYOUT_UNDEFINED"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR: + return "VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkImageLayout"; + } +} + +static inline const char* string_VkImageAspectFlagBits(VkImageAspectFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_ASPECT_COLOR_BIT: + return "VK_IMAGE_ASPECT_COLOR_BIT"; + case VK_IMAGE_ASPECT_DEPTH_BIT: + return "VK_IMAGE_ASPECT_DEPTH_BIT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT"; + case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT: + return "VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT"; + case VK_IMAGE_ASPECT_METADATA_BIT: + return "VK_IMAGE_ASPECT_METADATA_BIT"; + case VK_IMAGE_ASPECT_PLANE_0_BIT: + return "VK_IMAGE_ASPECT_PLANE_0_BIT"; + case VK_IMAGE_ASPECT_PLANE_1_BIT: + return "VK_IMAGE_ASPECT_PLANE_1_BIT"; + case VK_IMAGE_ASPECT_PLANE_2_BIT: + return "VK_IMAGE_ASPECT_PLANE_2_BIT"; + case VK_IMAGE_ASPECT_STENCIL_BIT: + return "VK_IMAGE_ASPECT_STENCIL_BIT"; + default: + return "Unhandled VkImageAspectFlagBits"; + } +} + +static inline std::string string_VkImageAspectFlags(VkImageAspectFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageAspectFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageAspectFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkObjectType(VkObjectType input_value) +{ + switch (input_value) + { + case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR: + return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR"; + case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: + return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV"; + case VK_OBJECT_TYPE_BUFFER: + return "VK_OBJECT_TYPE_BUFFER"; + case VK_OBJECT_TYPE_BUFFER_VIEW: + return "VK_OBJECT_TYPE_BUFFER_VIEW"; + case VK_OBJECT_TYPE_COMMAND_BUFFER: + return "VK_OBJECT_TYPE_COMMAND_BUFFER"; + case VK_OBJECT_TYPE_COMMAND_POOL: + return "VK_OBJECT_TYPE_COMMAND_POOL"; + case VK_OBJECT_TYPE_CU_FUNCTION_NVX: + return "VK_OBJECT_TYPE_CU_FUNCTION_NVX"; + case VK_OBJECT_TYPE_CU_MODULE_NVX: + return "VK_OBJECT_TYPE_CU_MODULE_NVX"; + case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: + return "VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT"; + case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: + return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT"; + case VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR: + return "VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR"; + case VK_OBJECT_TYPE_DESCRIPTOR_POOL: + return "VK_OBJECT_TYPE_DESCRIPTOR_POOL"; + case VK_OBJECT_TYPE_DESCRIPTOR_SET: + return "VK_OBJECT_TYPE_DESCRIPTOR_SET"; + case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: + return "VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT"; + case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: + return "VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE"; + case VK_OBJECT_TYPE_DEVICE: + return "VK_OBJECT_TYPE_DEVICE"; + case VK_OBJECT_TYPE_DEVICE_MEMORY: + return "VK_OBJECT_TYPE_DEVICE_MEMORY"; + case VK_OBJECT_TYPE_DISPLAY_KHR: + return "VK_OBJECT_TYPE_DISPLAY_KHR"; + case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: + return "VK_OBJECT_TYPE_DISPLAY_MODE_KHR"; + case VK_OBJECT_TYPE_EVENT: + return "VK_OBJECT_TYPE_EVENT"; + case VK_OBJECT_TYPE_FENCE: + return "VK_OBJECT_TYPE_FENCE"; + case VK_OBJECT_TYPE_FRAMEBUFFER: + return "VK_OBJECT_TYPE_FRAMEBUFFER"; + case VK_OBJECT_TYPE_IMAGE: + return "VK_OBJECT_TYPE_IMAGE"; + case VK_OBJECT_TYPE_IMAGE_VIEW: + return "VK_OBJECT_TYPE_IMAGE_VIEW"; + case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV: + return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV"; + case VK_OBJECT_TYPE_INSTANCE: + return "VK_OBJECT_TYPE_INSTANCE"; + case VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL: + return "VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL"; + case VK_OBJECT_TYPE_PHYSICAL_DEVICE: + return "VK_OBJECT_TYPE_PHYSICAL_DEVICE"; + case VK_OBJECT_TYPE_PIPELINE: + return "VK_OBJECT_TYPE_PIPELINE"; + case VK_OBJECT_TYPE_PIPELINE_CACHE: + return "VK_OBJECT_TYPE_PIPELINE_CACHE"; + case VK_OBJECT_TYPE_PIPELINE_LAYOUT: + return "VK_OBJECT_TYPE_PIPELINE_LAYOUT"; + case VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT: + return "VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT"; + case VK_OBJECT_TYPE_QUERY_POOL: + return "VK_OBJECT_TYPE_QUERY_POOL"; + case VK_OBJECT_TYPE_QUEUE: + return "VK_OBJECT_TYPE_QUEUE"; + case VK_OBJECT_TYPE_RENDER_PASS: + return "VK_OBJECT_TYPE_RENDER_PASS"; + case VK_OBJECT_TYPE_SAMPLER: + return "VK_OBJECT_TYPE_SAMPLER"; + case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: + return "VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION"; + case VK_OBJECT_TYPE_SEMAPHORE: + return "VK_OBJECT_TYPE_SEMAPHORE"; + case VK_OBJECT_TYPE_SHADER_MODULE: + return "VK_OBJECT_TYPE_SHADER_MODULE"; + case VK_OBJECT_TYPE_SURFACE_KHR: + return "VK_OBJECT_TYPE_SURFACE_KHR"; + case VK_OBJECT_TYPE_SWAPCHAIN_KHR: + return "VK_OBJECT_TYPE_SWAPCHAIN_KHR"; + case VK_OBJECT_TYPE_UNKNOWN: + return "VK_OBJECT_TYPE_UNKNOWN"; + case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: + return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_OBJECT_TYPE_VIDEO_SESSION_KHR: + return "VK_OBJECT_TYPE_VIDEO_SESSION_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR: + return "VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkObjectType"; + } +} + +static inline const char* string_VkPipelineCacheHeaderVersion(VkPipelineCacheHeaderVersion input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CACHE_HEADER_VERSION_ONE: + return "VK_PIPELINE_CACHE_HEADER_VERSION_ONE"; + default: + return "Unhandled VkPipelineCacheHeaderVersion"; + } +} + +static inline const char* string_VkVendorId(VkVendorId input_value) +{ + switch (input_value) + { + case VK_VENDOR_ID_CODEPLAY: + return "VK_VENDOR_ID_CODEPLAY"; + case VK_VENDOR_ID_KAZAN: + return "VK_VENDOR_ID_KAZAN"; + case VK_VENDOR_ID_MESA: + return "VK_VENDOR_ID_MESA"; + case VK_VENDOR_ID_POCL: + return "VK_VENDOR_ID_POCL"; + case VK_VENDOR_ID_VIV: + return "VK_VENDOR_ID_VIV"; + case VK_VENDOR_ID_VSI: + return "VK_VENDOR_ID_VSI"; + default: + return "Unhandled VkVendorId"; + } +} + +static inline const char* string_VkSystemAllocationScope(VkSystemAllocationScope input_value) +{ + switch (input_value) + { + case VK_SYSTEM_ALLOCATION_SCOPE_CACHE: + return "VK_SYSTEM_ALLOCATION_SCOPE_CACHE"; + case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND: + return "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND"; + case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE: + return "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE"; + case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE: + return "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE"; + case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT: + return "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT"; + default: + return "Unhandled VkSystemAllocationScope"; + } +} + +static inline const char* string_VkInternalAllocationType(VkInternalAllocationType input_value) +{ + switch (input_value) + { + case VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE: + return "VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE"; + default: + return "Unhandled VkInternalAllocationType"; + } +} + +static inline const char* string_VkFormat(VkFormat input_value) +{ + switch (input_value) + { + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + return "VK_FORMAT_A1R5G5B5_UNORM_PACK16"; + case VK_FORMAT_A2B10G10R10_SINT_PACK32: + return "VK_FORMAT_A2B10G10R10_SINT_PACK32"; + case VK_FORMAT_A2B10G10R10_SNORM_PACK32: + return "VK_FORMAT_A2B10G10R10_SNORM_PACK32"; + case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: + return "VK_FORMAT_A2B10G10R10_SSCALED_PACK32"; + case VK_FORMAT_A2B10G10R10_UINT_PACK32: + return "VK_FORMAT_A2B10G10R10_UINT_PACK32"; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return "VK_FORMAT_A2B10G10R10_UNORM_PACK32"; + case VK_FORMAT_A2B10G10R10_USCALED_PACK32: + return "VK_FORMAT_A2B10G10R10_USCALED_PACK32"; + case VK_FORMAT_A2R10G10B10_SINT_PACK32: + return "VK_FORMAT_A2R10G10B10_SINT_PACK32"; + case VK_FORMAT_A2R10G10B10_SNORM_PACK32: + return "VK_FORMAT_A2R10G10B10_SNORM_PACK32"; + case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: + return "VK_FORMAT_A2R10G10B10_SSCALED_PACK32"; + case VK_FORMAT_A2R10G10B10_UINT_PACK32: + return "VK_FORMAT_A2R10G10B10_UINT_PACK32"; + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: + return "VK_FORMAT_A2R10G10B10_UNORM_PACK32"; + case VK_FORMAT_A2R10G10B10_USCALED_PACK32: + return "VK_FORMAT_A2R10G10B10_USCALED_PACK32"; + case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: + return "VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT"; + case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: + return "VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT"; + case VK_FORMAT_A8B8G8R8_SINT_PACK32: + return "VK_FORMAT_A8B8G8R8_SINT_PACK32"; + case VK_FORMAT_A8B8G8R8_SNORM_PACK32: + return "VK_FORMAT_A8B8G8R8_SNORM_PACK32"; + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + return "VK_FORMAT_A8B8G8R8_SRGB_PACK32"; + case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: + return "VK_FORMAT_A8B8G8R8_SSCALED_PACK32"; + case VK_FORMAT_A8B8G8R8_UINT_PACK32: + return "VK_FORMAT_A8B8G8R8_UINT_PACK32"; + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: + return "VK_FORMAT_A8B8G8R8_UNORM_PACK32"; + case VK_FORMAT_A8B8G8R8_USCALED_PACK32: + return "VK_FORMAT_A8B8G8R8_USCALED_PACK32"; + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x10_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x10_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + return "VK_FORMAT_ASTC_10x8_SRGB_BLOCK"; + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + return "VK_FORMAT_ASTC_10x8_UNORM_BLOCK"; + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + return "VK_FORMAT_ASTC_12x10_SRGB_BLOCK"; + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + return "VK_FORMAT_ASTC_12x10_UNORM_BLOCK"; + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + return "VK_FORMAT_ASTC_12x12_SRGB_BLOCK"; + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + return "VK_FORMAT_ASTC_12x12_UNORM_BLOCK"; + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + return "VK_FORMAT_ASTC_4x4_SRGB_BLOCK"; + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + return "VK_FORMAT_ASTC_4x4_UNORM_BLOCK"; + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + return "VK_FORMAT_ASTC_5x4_SRGB_BLOCK"; + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + return "VK_FORMAT_ASTC_5x4_UNORM_BLOCK"; + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_5x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_5x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_6x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_6x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_6x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_6x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x5_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x5_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x6_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x6_UNORM_BLOCK"; + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: + return "VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT"; + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + return "VK_FORMAT_ASTC_8x8_SRGB_BLOCK"; + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + return "VK_FORMAT_ASTC_8x8_UNORM_BLOCK"; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: + return "VK_FORMAT_B10G11R11_UFLOAT_PACK32"; + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + return "VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16"; + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + return "VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16"; + case VK_FORMAT_B16G16R16G16_422_UNORM: + return "VK_FORMAT_B16G16R16G16_422_UNORM"; + case VK_FORMAT_B4G4R4A4_UNORM_PACK16: + return "VK_FORMAT_B4G4R4A4_UNORM_PACK16"; + case VK_FORMAT_B5G5R5A1_UNORM_PACK16: + return "VK_FORMAT_B5G5R5A1_UNORM_PACK16"; + case VK_FORMAT_B5G6R5_UNORM_PACK16: + return "VK_FORMAT_B5G6R5_UNORM_PACK16"; + case VK_FORMAT_B8G8R8A8_SINT: + return "VK_FORMAT_B8G8R8A8_SINT"; + case VK_FORMAT_B8G8R8A8_SNORM: + return "VK_FORMAT_B8G8R8A8_SNORM"; + case VK_FORMAT_B8G8R8A8_SRGB: + return "VK_FORMAT_B8G8R8A8_SRGB"; + case VK_FORMAT_B8G8R8A8_SSCALED: + return "VK_FORMAT_B8G8R8A8_SSCALED"; + case VK_FORMAT_B8G8R8A8_UINT: + return "VK_FORMAT_B8G8R8A8_UINT"; + case VK_FORMAT_B8G8R8A8_UNORM: + return "VK_FORMAT_B8G8R8A8_UNORM"; + case VK_FORMAT_B8G8R8A8_USCALED: + return "VK_FORMAT_B8G8R8A8_USCALED"; + case VK_FORMAT_B8G8R8G8_422_UNORM: + return "VK_FORMAT_B8G8R8G8_422_UNORM"; + case VK_FORMAT_B8G8R8_SINT: + return "VK_FORMAT_B8G8R8_SINT"; + case VK_FORMAT_B8G8R8_SNORM: + return "VK_FORMAT_B8G8R8_SNORM"; + case VK_FORMAT_B8G8R8_SRGB: + return "VK_FORMAT_B8G8R8_SRGB"; + case VK_FORMAT_B8G8R8_SSCALED: + return "VK_FORMAT_B8G8R8_SSCALED"; + case VK_FORMAT_B8G8R8_UINT: + return "VK_FORMAT_B8G8R8_UINT"; + case VK_FORMAT_B8G8R8_UNORM: + return "VK_FORMAT_B8G8R8_UNORM"; + case VK_FORMAT_B8G8R8_USCALED: + return "VK_FORMAT_B8G8R8_USCALED"; + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + return "VK_FORMAT_BC1_RGBA_SRGB_BLOCK"; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return "VK_FORMAT_BC1_RGBA_UNORM_BLOCK"; + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + return "VK_FORMAT_BC1_RGB_SRGB_BLOCK"; + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + return "VK_FORMAT_BC1_RGB_UNORM_BLOCK"; + case VK_FORMAT_BC2_SRGB_BLOCK: + return "VK_FORMAT_BC2_SRGB_BLOCK"; + case VK_FORMAT_BC2_UNORM_BLOCK: + return "VK_FORMAT_BC2_UNORM_BLOCK"; + case VK_FORMAT_BC3_SRGB_BLOCK: + return "VK_FORMAT_BC3_SRGB_BLOCK"; + case VK_FORMAT_BC3_UNORM_BLOCK: + return "VK_FORMAT_BC3_UNORM_BLOCK"; + case VK_FORMAT_BC4_SNORM_BLOCK: + return "VK_FORMAT_BC4_SNORM_BLOCK"; + case VK_FORMAT_BC4_UNORM_BLOCK: + return "VK_FORMAT_BC4_UNORM_BLOCK"; + case VK_FORMAT_BC5_SNORM_BLOCK: + return "VK_FORMAT_BC5_SNORM_BLOCK"; + case VK_FORMAT_BC5_UNORM_BLOCK: + return "VK_FORMAT_BC5_UNORM_BLOCK"; + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + return "VK_FORMAT_BC6H_SFLOAT_BLOCK"; + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return "VK_FORMAT_BC6H_UFLOAT_BLOCK"; + case VK_FORMAT_BC7_SRGB_BLOCK: + return "VK_FORMAT_BC7_SRGB_BLOCK"; + case VK_FORMAT_BC7_UNORM_BLOCK: + return "VK_FORMAT_BC7_UNORM_BLOCK"; + case VK_FORMAT_D16_UNORM: + return "VK_FORMAT_D16_UNORM"; + case VK_FORMAT_D16_UNORM_S8_UINT: + return "VK_FORMAT_D16_UNORM_S8_UINT"; + case VK_FORMAT_D24_UNORM_S8_UINT: + return "VK_FORMAT_D24_UNORM_S8_UINT"; + case VK_FORMAT_D32_SFLOAT: + return "VK_FORMAT_D32_SFLOAT"; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return "VK_FORMAT_D32_SFLOAT_S8_UINT"; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: + return "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32"; + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + return "VK_FORMAT_EAC_R11G11_SNORM_BLOCK"; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + return "VK_FORMAT_EAC_R11G11_UNORM_BLOCK"; + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + return "VK_FORMAT_EAC_R11_SNORM_BLOCK"; + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return "VK_FORMAT_EAC_R11_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK"; + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK"; + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + return "VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT: + return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + return "VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT: + return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16"; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16"; + case VK_FORMAT_G16B16G16R16_422_UNORM: + return "VK_FORMAT_G16B16G16R16_422_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + return "VK_FORMAT_G16_B16R16_2PLANE_420_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + return "VK_FORMAT_G16_B16R16_2PLANE_422_UNORM"; + case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT: + return "VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT"; + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM"; + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM"; + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + return "VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM"; + case VK_FORMAT_G8B8G8R8_422_UNORM: + return "VK_FORMAT_G8B8G8R8_422_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + return "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + return "VK_FORMAT_G8_B8R8_2PLANE_422_UNORM"; + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT: + return "VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT"; + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM"; + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM"; + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + return "VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM"; + case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG"; + case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: + return "VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG"; + case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + return "VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16"; + case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: + return "VK_FORMAT_R10X6G10X6_UNORM_2PACK16"; + case VK_FORMAT_R10X6_UNORM_PACK16: + return "VK_FORMAT_R10X6_UNORM_PACK16"; + case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: + return "VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16"; + case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: + return "VK_FORMAT_R12X4G12X4_UNORM_2PACK16"; + case VK_FORMAT_R12X4_UNORM_PACK16: + return "VK_FORMAT_R12X4_UNORM_PACK16"; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return "VK_FORMAT_R16G16B16A16_SFLOAT"; + case VK_FORMAT_R16G16B16A16_SINT: + return "VK_FORMAT_R16G16B16A16_SINT"; + case VK_FORMAT_R16G16B16A16_SNORM: + return "VK_FORMAT_R16G16B16A16_SNORM"; + case VK_FORMAT_R16G16B16A16_SSCALED: + return "VK_FORMAT_R16G16B16A16_SSCALED"; + case VK_FORMAT_R16G16B16A16_UINT: + return "VK_FORMAT_R16G16B16A16_UINT"; + case VK_FORMAT_R16G16B16A16_UNORM: + return "VK_FORMAT_R16G16B16A16_UNORM"; + case VK_FORMAT_R16G16B16A16_USCALED: + return "VK_FORMAT_R16G16B16A16_USCALED"; + case VK_FORMAT_R16G16B16_SFLOAT: + return "VK_FORMAT_R16G16B16_SFLOAT"; + case VK_FORMAT_R16G16B16_SINT: + return "VK_FORMAT_R16G16B16_SINT"; + case VK_FORMAT_R16G16B16_SNORM: + return "VK_FORMAT_R16G16B16_SNORM"; + case VK_FORMAT_R16G16B16_SSCALED: + return "VK_FORMAT_R16G16B16_SSCALED"; + case VK_FORMAT_R16G16B16_UINT: + return "VK_FORMAT_R16G16B16_UINT"; + case VK_FORMAT_R16G16B16_UNORM: + return "VK_FORMAT_R16G16B16_UNORM"; + case VK_FORMAT_R16G16B16_USCALED: + return "VK_FORMAT_R16G16B16_USCALED"; + case VK_FORMAT_R16G16_SFLOAT: + return "VK_FORMAT_R16G16_SFLOAT"; + case VK_FORMAT_R16G16_SINT: + return "VK_FORMAT_R16G16_SINT"; + case VK_FORMAT_R16G16_SNORM: + return "VK_FORMAT_R16G16_SNORM"; + case VK_FORMAT_R16G16_SSCALED: + return "VK_FORMAT_R16G16_SSCALED"; + case VK_FORMAT_R16G16_UINT: + return "VK_FORMAT_R16G16_UINT"; + case VK_FORMAT_R16G16_UNORM: + return "VK_FORMAT_R16G16_UNORM"; + case VK_FORMAT_R16G16_USCALED: + return "VK_FORMAT_R16G16_USCALED"; + case VK_FORMAT_R16_SFLOAT: + return "VK_FORMAT_R16_SFLOAT"; + case VK_FORMAT_R16_SINT: + return "VK_FORMAT_R16_SINT"; + case VK_FORMAT_R16_SNORM: + return "VK_FORMAT_R16_SNORM"; + case VK_FORMAT_R16_SSCALED: + return "VK_FORMAT_R16_SSCALED"; + case VK_FORMAT_R16_UINT: + return "VK_FORMAT_R16_UINT"; + case VK_FORMAT_R16_UNORM: + return "VK_FORMAT_R16_UNORM"; + case VK_FORMAT_R16_USCALED: + return "VK_FORMAT_R16_USCALED"; + case VK_FORMAT_R32G32B32A32_SFLOAT: + return "VK_FORMAT_R32G32B32A32_SFLOAT"; + case VK_FORMAT_R32G32B32A32_SINT: + return "VK_FORMAT_R32G32B32A32_SINT"; + case VK_FORMAT_R32G32B32A32_UINT: + return "VK_FORMAT_R32G32B32A32_UINT"; + case VK_FORMAT_R32G32B32_SFLOAT: + return "VK_FORMAT_R32G32B32_SFLOAT"; + case VK_FORMAT_R32G32B32_SINT: + return "VK_FORMAT_R32G32B32_SINT"; + case VK_FORMAT_R32G32B32_UINT: + return "VK_FORMAT_R32G32B32_UINT"; + case VK_FORMAT_R32G32_SFLOAT: + return "VK_FORMAT_R32G32_SFLOAT"; + case VK_FORMAT_R32G32_SINT: + return "VK_FORMAT_R32G32_SINT"; + case VK_FORMAT_R32G32_UINT: + return "VK_FORMAT_R32G32_UINT"; + case VK_FORMAT_R32_SFLOAT: + return "VK_FORMAT_R32_SFLOAT"; + case VK_FORMAT_R32_SINT: + return "VK_FORMAT_R32_SINT"; + case VK_FORMAT_R32_UINT: + return "VK_FORMAT_R32_UINT"; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + return "VK_FORMAT_R4G4B4A4_UNORM_PACK16"; + case VK_FORMAT_R4G4_UNORM_PACK8: + return "VK_FORMAT_R4G4_UNORM_PACK8"; + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + return "VK_FORMAT_R5G5B5A1_UNORM_PACK16"; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + return "VK_FORMAT_R5G6B5_UNORM_PACK16"; + case VK_FORMAT_R64G64B64A64_SFLOAT: + return "VK_FORMAT_R64G64B64A64_SFLOAT"; + case VK_FORMAT_R64G64B64A64_SINT: + return "VK_FORMAT_R64G64B64A64_SINT"; + case VK_FORMAT_R64G64B64A64_UINT: + return "VK_FORMAT_R64G64B64A64_UINT"; + case VK_FORMAT_R64G64B64_SFLOAT: + return "VK_FORMAT_R64G64B64_SFLOAT"; + case VK_FORMAT_R64G64B64_SINT: + return "VK_FORMAT_R64G64B64_SINT"; + case VK_FORMAT_R64G64B64_UINT: + return "VK_FORMAT_R64G64B64_UINT"; + case VK_FORMAT_R64G64_SFLOAT: + return "VK_FORMAT_R64G64_SFLOAT"; + case VK_FORMAT_R64G64_SINT: + return "VK_FORMAT_R64G64_SINT"; + case VK_FORMAT_R64G64_UINT: + return "VK_FORMAT_R64G64_UINT"; + case VK_FORMAT_R64_SFLOAT: + return "VK_FORMAT_R64_SFLOAT"; + case VK_FORMAT_R64_SINT: + return "VK_FORMAT_R64_SINT"; + case VK_FORMAT_R64_UINT: + return "VK_FORMAT_R64_UINT"; + case VK_FORMAT_R8G8B8A8_SINT: + return "VK_FORMAT_R8G8B8A8_SINT"; + case VK_FORMAT_R8G8B8A8_SNORM: + return "VK_FORMAT_R8G8B8A8_SNORM"; + case VK_FORMAT_R8G8B8A8_SRGB: + return "VK_FORMAT_R8G8B8A8_SRGB"; + case VK_FORMAT_R8G8B8A8_SSCALED: + return "VK_FORMAT_R8G8B8A8_SSCALED"; + case VK_FORMAT_R8G8B8A8_UINT: + return "VK_FORMAT_R8G8B8A8_UINT"; + case VK_FORMAT_R8G8B8A8_UNORM: + return "VK_FORMAT_R8G8B8A8_UNORM"; + case VK_FORMAT_R8G8B8A8_USCALED: + return "VK_FORMAT_R8G8B8A8_USCALED"; + case VK_FORMAT_R8G8B8_SINT: + return "VK_FORMAT_R8G8B8_SINT"; + case VK_FORMAT_R8G8B8_SNORM: + return "VK_FORMAT_R8G8B8_SNORM"; + case VK_FORMAT_R8G8B8_SRGB: + return "VK_FORMAT_R8G8B8_SRGB"; + case VK_FORMAT_R8G8B8_SSCALED: + return "VK_FORMAT_R8G8B8_SSCALED"; + case VK_FORMAT_R8G8B8_UINT: + return "VK_FORMAT_R8G8B8_UINT"; + case VK_FORMAT_R8G8B8_UNORM: + return "VK_FORMAT_R8G8B8_UNORM"; + case VK_FORMAT_R8G8B8_USCALED: + return "VK_FORMAT_R8G8B8_USCALED"; + case VK_FORMAT_R8G8_SINT: + return "VK_FORMAT_R8G8_SINT"; + case VK_FORMAT_R8G8_SNORM: + return "VK_FORMAT_R8G8_SNORM"; + case VK_FORMAT_R8G8_SRGB: + return "VK_FORMAT_R8G8_SRGB"; + case VK_FORMAT_R8G8_SSCALED: + return "VK_FORMAT_R8G8_SSCALED"; + case VK_FORMAT_R8G8_UINT: + return "VK_FORMAT_R8G8_UINT"; + case VK_FORMAT_R8G8_UNORM: + return "VK_FORMAT_R8G8_UNORM"; + case VK_FORMAT_R8G8_USCALED: + return "VK_FORMAT_R8G8_USCALED"; + case VK_FORMAT_R8_SINT: + return "VK_FORMAT_R8_SINT"; + case VK_FORMAT_R8_SNORM: + return "VK_FORMAT_R8_SNORM"; + case VK_FORMAT_R8_SRGB: + return "VK_FORMAT_R8_SRGB"; + case VK_FORMAT_R8_SSCALED: + return "VK_FORMAT_R8_SSCALED"; + case VK_FORMAT_R8_UINT: + return "VK_FORMAT_R8_UINT"; + case VK_FORMAT_R8_UNORM: + return "VK_FORMAT_R8_UNORM"; + case VK_FORMAT_R8_USCALED: + return "VK_FORMAT_R8_USCALED"; + case VK_FORMAT_S8_UINT: + return "VK_FORMAT_S8_UINT"; + case VK_FORMAT_UNDEFINED: + return "VK_FORMAT_UNDEFINED"; + case VK_FORMAT_X8_D24_UNORM_PACK32: + return "VK_FORMAT_X8_D24_UNORM_PACK32"; + default: + return "Unhandled VkFormat"; + } +} + +static inline const char* string_VkFormatFeatureFlagBits(VkFormatFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR: + return "VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"; + case VK_FORMAT_FEATURE_BLIT_DST_BIT: + return "VK_FORMAT_FEATURE_BLIT_DST_BIT"; + case VK_FORMAT_FEATURE_BLIT_SRC_BIT: + return "VK_FORMAT_FEATURE_BLIT_SRC_BIT"; + case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT: + return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT"; + case VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_FORMAT_FEATURE_DISJOINT_BIT: + return "VK_FORMAT_FEATURE_DISJOINT_BIT"; + case VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT: + return "VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"; + case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT: + return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"; + case VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT: + return "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT"; + case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT: + return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"; + case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_TRANSFER_DST_BIT: + return "VK_FORMAT_FEATURE_TRANSFER_DST_BIT"; + case VK_FORMAT_FEATURE_TRANSFER_SRC_BIT: + return "VK_FORMAT_FEATURE_TRANSFER_SRC_BIT"; + case VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT: + return "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR: + return "VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkFormatFeatureFlagBits"; + } +} + +static inline std::string string_VkFormatFeatureFlags(VkFormatFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFormatFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFormatFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageCreateFlagBits(VkImageCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_ALIAS_BIT: + return "VK_IMAGE_CREATE_ALIAS_BIT"; + case VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV: + return "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV"; + case VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT: + return "VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT"; + case VK_IMAGE_CREATE_DISJOINT_BIT: + return "VK_IMAGE_CREATE_DISJOINT_BIT"; + case VK_IMAGE_CREATE_EXTENDED_USAGE_BIT: + return "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT"; + case VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT: + return "VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT"; + case VK_IMAGE_CREATE_PROTECTED_BIT: + return "VK_IMAGE_CREATE_PROTECTED_BIT"; + case VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT: + return "VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT"; + case VK_IMAGE_CREATE_SPARSE_ALIASED_BIT: + return "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT"; + case VK_IMAGE_CREATE_SPARSE_BINDING_BIT: + return "VK_IMAGE_CREATE_SPARSE_BINDING_BIT"; + case VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT: + return "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"; + case VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT: + return "VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT"; + case VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT: + return "VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT"; + default: + return "Unhandled VkImageCreateFlagBits"; + } +} + +static inline std::string string_VkImageCreateFlags(VkImageCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSampleCountFlagBits(VkSampleCountFlagBits input_value) +{ + switch (input_value) + { + case VK_SAMPLE_COUNT_16_BIT: + return "VK_SAMPLE_COUNT_16_BIT"; + case VK_SAMPLE_COUNT_1_BIT: + return "VK_SAMPLE_COUNT_1_BIT"; + case VK_SAMPLE_COUNT_2_BIT: + return "VK_SAMPLE_COUNT_2_BIT"; + case VK_SAMPLE_COUNT_32_BIT: + return "VK_SAMPLE_COUNT_32_BIT"; + case VK_SAMPLE_COUNT_4_BIT: + return "VK_SAMPLE_COUNT_4_BIT"; + case VK_SAMPLE_COUNT_64_BIT: + return "VK_SAMPLE_COUNT_64_BIT"; + case VK_SAMPLE_COUNT_8_BIT: + return "VK_SAMPLE_COUNT_8_BIT"; + default: + return "Unhandled VkSampleCountFlagBits"; + } +} + +static inline std::string string_VkSampleCountFlags(VkSampleCountFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSampleCountFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSampleCountFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageTiling(VkImageTiling input_value) +{ + switch (input_value) + { + case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: + return "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT"; + case VK_IMAGE_TILING_LINEAR: + return "VK_IMAGE_TILING_LINEAR"; + case VK_IMAGE_TILING_OPTIMAL: + return "VK_IMAGE_TILING_OPTIMAL"; + default: + return "Unhandled VkImageTiling"; + } +} + +static inline const char* string_VkImageType(VkImageType input_value) +{ + switch (input_value) + { + case VK_IMAGE_TYPE_1D: + return "VK_IMAGE_TYPE_1D"; + case VK_IMAGE_TYPE_2D: + return "VK_IMAGE_TYPE_2D"; + case VK_IMAGE_TYPE_3D: + return "VK_IMAGE_TYPE_3D"; + default: + return "Unhandled VkImageType"; + } +} + +static inline const char* string_VkImageUsageFlagBits(VkImageUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT: + return "VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT"; + case VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; + case VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI: + return "VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI"; + case VK_IMAGE_USAGE_SAMPLED_BIT: + return "VK_IMAGE_USAGE_SAMPLED_BIT"; + case VK_IMAGE_USAGE_STORAGE_BIT: + return "VK_IMAGE_USAGE_STORAGE_BIT"; + case VK_IMAGE_USAGE_TRANSFER_DST_BIT: + return "VK_IMAGE_USAGE_TRANSFER_DST_BIT"; + case VK_IMAGE_USAGE_TRANSFER_SRC_BIT: + return "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"; + case VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: + return "VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR: + return "VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkImageUsageFlagBits"; + } +} + +static inline std::string string_VkImageUsageFlags(VkImageUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryHeapFlagBits(VkMemoryHeapFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_HEAP_DEVICE_LOCAL_BIT: + return "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT"; + case VK_MEMORY_HEAP_MULTI_INSTANCE_BIT: + return "VK_MEMORY_HEAP_MULTI_INSTANCE_BIT"; + default: + return "Unhandled VkMemoryHeapFlagBits"; + } +} + +static inline std::string string_VkMemoryHeapFlags(VkMemoryHeapFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryHeapFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryHeapFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryPropertyFlagBits(VkMemoryPropertyFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD: + return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD"; + case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT: + return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT"; + case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD: + return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD"; + case VK_MEMORY_PROPERTY_HOST_CACHED_BIT: + return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT"; + case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT: + return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT"; + case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT: + return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT"; + case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT: + return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT"; + case VK_MEMORY_PROPERTY_PROTECTED_BIT: + return "VK_MEMORY_PROPERTY_PROTECTED_BIT"; + case VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV: + return "VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV"; + default: + return "Unhandled VkMemoryPropertyFlagBits"; + } +} + +static inline std::string string_VkMemoryPropertyFlags(VkMemoryPropertyFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryPropertyFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryPropertyFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPhysicalDeviceType(VkPhysicalDeviceType input_value) +{ + switch (input_value) + { + case VK_PHYSICAL_DEVICE_TYPE_CPU: + return "VK_PHYSICAL_DEVICE_TYPE_CPU"; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU"; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU"; + case VK_PHYSICAL_DEVICE_TYPE_OTHER: + return "VK_PHYSICAL_DEVICE_TYPE_OTHER"; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: + return "VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU"; + default: + return "Unhandled VkPhysicalDeviceType"; + } +} + +static inline const char* string_VkQueueFlagBits(VkQueueFlagBits input_value) +{ + switch (input_value) + { + case VK_QUEUE_COMPUTE_BIT: + return "VK_QUEUE_COMPUTE_BIT"; + case VK_QUEUE_GRAPHICS_BIT: + return "VK_QUEUE_GRAPHICS_BIT"; + case VK_QUEUE_PROTECTED_BIT: + return "VK_QUEUE_PROTECTED_BIT"; + case VK_QUEUE_SPARSE_BINDING_BIT: + return "VK_QUEUE_SPARSE_BINDING_BIT"; + case VK_QUEUE_TRANSFER_BIT: + return "VK_QUEUE_TRANSFER_BIT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUEUE_VIDEO_DECODE_BIT_KHR: + return "VK_QUEUE_VIDEO_DECODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: + return "VK_QUEUE_VIDEO_ENCODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkQueueFlagBits"; + } +} + +static inline std::string string_VkQueueFlags(VkQueueFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueueFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueueFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceQueueCreateFlagBits(VkDeviceQueueCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT: + return "VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT"; + default: + return "Unhandled VkDeviceQueueCreateFlagBits"; + } +} + +static inline std::string string_VkDeviceQueueCreateFlags(VkDeviceQueueCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceQueueCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceQueueCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineStageFlagBits(VkPipelineStageFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: + return "VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + case VK_PIPELINE_STAGE_ALL_COMMANDS_BIT: + return "VK_PIPELINE_STAGE_ALL_COMMANDS_BIT"; + case VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT: + return "VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT"; + case VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: + return "VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT"; + case VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV: + return "VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV"; + case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: + return "VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT"; + case VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: + return "VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT"; + case VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT: + return "VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: + return "VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT"; + case VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: + return "VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT"; + case VK_PIPELINE_STAGE_HOST_BIT: + return "VK_PIPELINE_STAGE_HOST_BIT"; + case VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT: + return "VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT"; + case VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV: + return "VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV"; + case VK_PIPELINE_STAGE_NONE_KHR: + return "VK_PIPELINE_STAGE_NONE_KHR"; + case VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV: + return "VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV"; + case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: + return "VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT"; + case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: + return "VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT"; + case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: + return "VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT"; + case VK_PIPELINE_STAGE_TRANSFER_BIT: + return "VK_PIPELINE_STAGE_TRANSFER_BIT"; + case VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT: + return "VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT"; + case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: + return "VK_PIPELINE_STAGE_VERTEX_INPUT_BIT"; + case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: + return "VK_PIPELINE_STAGE_VERTEX_SHADER_BIT"; + default: + return "Unhandled VkPipelineStageFlagBits"; + } +} + +static inline std::string string_VkPipelineStageFlags(VkPipelineStageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineStageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineStageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSparseMemoryBindFlagBits(VkSparseMemoryBindFlagBits input_value) +{ + switch (input_value) + { + case VK_SPARSE_MEMORY_BIND_METADATA_BIT: + return "VK_SPARSE_MEMORY_BIND_METADATA_BIT"; + default: + return "Unhandled VkSparseMemoryBindFlagBits"; + } +} + +static inline std::string string_VkSparseMemoryBindFlags(VkSparseMemoryBindFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSparseMemoryBindFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSparseMemoryBindFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSparseImageFormatFlagBits(VkSparseImageFormatFlagBits input_value) +{ + switch (input_value) + { + case VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT: + return "VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT"; + case VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT: + return "VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT"; + case VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT: + return "VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT"; + default: + return "Unhandled VkSparseImageFormatFlagBits"; + } +} + +static inline std::string string_VkSparseImageFormatFlags(VkSparseImageFormatFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSparseImageFormatFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSparseImageFormatFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceCreateFlagBits(VkFenceCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_FENCE_CREATE_SIGNALED_BIT: + return "VK_FENCE_CREATE_SIGNALED_BIT"; + default: + return "Unhandled VkFenceCreateFlagBits"; + } +} + +static inline std::string string_VkFenceCreateFlags(VkFenceCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkEventCreateFlagBits(VkEventCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR: + return "VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR"; + default: + return "Unhandled VkEventCreateFlagBits"; + } +} + +static inline std::string string_VkEventCreateFlags(VkEventCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkEventCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkEventCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryPipelineStatisticFlagBits(VkQueryPipelineStatisticFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT"; + case VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT: + return "VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT"; + default: + return "Unhandled VkQueryPipelineStatisticFlagBits"; + } +} + +static inline std::string string_VkQueryPipelineStatisticFlags(VkQueryPipelineStatisticFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryType(VkQueryType input_value) +{ + switch (input_value) + { + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV"; + case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR: + return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR"; + case VK_QUERY_TYPE_OCCLUSION: + return "VK_QUERY_TYPE_OCCLUSION"; + case VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL: + return "VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL"; + case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: + return "VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR"; + case VK_QUERY_TYPE_PIPELINE_STATISTICS: + return "VK_QUERY_TYPE_PIPELINE_STATISTICS"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR: + return "VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_QUERY_TYPE_TIMESTAMP: + return "VK_QUERY_TYPE_TIMESTAMP"; + case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: + return "VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR: + return "VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkQueryType"; + } +} + +static inline const char* string_VkQueryResultFlagBits(VkQueryResultFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_RESULT_64_BIT: + return "VK_QUERY_RESULT_64_BIT"; + case VK_QUERY_RESULT_PARTIAL_BIT: + return "VK_QUERY_RESULT_PARTIAL_BIT"; + case VK_QUERY_RESULT_WAIT_BIT: + return "VK_QUERY_RESULT_WAIT_BIT"; + case VK_QUERY_RESULT_WITH_AVAILABILITY_BIT: + return "VK_QUERY_RESULT_WITH_AVAILABILITY_BIT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_QUERY_RESULT_WITH_STATUS_BIT_KHR: + return "VK_QUERY_RESULT_WITH_STATUS_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkQueryResultFlagBits"; + } +} + +static inline std::string string_VkQueryResultFlags(VkQueryResultFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryResultFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryResultFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBufferCreateFlagBits(VkBufferCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_BUFFER_CREATE_PROTECTED_BIT: + return "VK_BUFFER_CREATE_PROTECTED_BIT"; + case VK_BUFFER_CREATE_SPARSE_ALIASED_BIT: + return "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT"; + case VK_BUFFER_CREATE_SPARSE_BINDING_BIT: + return "VK_BUFFER_CREATE_SPARSE_BINDING_BIT"; + case VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT: + return "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT"; + default: + return "Unhandled VkBufferCreateFlagBits"; + } +} + +static inline std::string string_VkBufferCreateFlags(VkBufferCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBufferCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBufferCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBufferUsageFlagBits(VkBufferUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR: + return "VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR"; + case VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR: + return "VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR"; + case VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_BUFFER_USAGE_INDEX_BUFFER_BIT: + return "VK_BUFFER_USAGE_INDEX_BUFFER_BIT"; + case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT: + return "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT"; + case VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR: + return "VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR"; + case VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT: + return "VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT"; + case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT: + return "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT"; + case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT: + return "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT"; + case VK_BUFFER_USAGE_TRANSFER_DST_BIT: + return "VK_BUFFER_USAGE_TRANSFER_DST_BIT"; + case VK_BUFFER_USAGE_TRANSFER_SRC_BIT: + return "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"; + case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT: + return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"; + case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT: + return "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT"; + case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT: + return "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT"; + case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT: + return "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR: + return "VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkBufferUsageFlagBits"; + } +} + +static inline std::string string_VkBufferUsageFlags(VkBufferUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBufferUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBufferUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSharingMode(VkSharingMode input_value) +{ + switch (input_value) + { + case VK_SHARING_MODE_CONCURRENT: + return "VK_SHARING_MODE_CONCURRENT"; + case VK_SHARING_MODE_EXCLUSIVE: + return "VK_SHARING_MODE_EXCLUSIVE"; + default: + return "Unhandled VkSharingMode"; + } +} + +static inline const char* string_VkComponentSwizzle(VkComponentSwizzle input_value) +{ + switch (input_value) + { + case VK_COMPONENT_SWIZZLE_A: + return "VK_COMPONENT_SWIZZLE_A"; + case VK_COMPONENT_SWIZZLE_B: + return "VK_COMPONENT_SWIZZLE_B"; + case VK_COMPONENT_SWIZZLE_G: + return "VK_COMPONENT_SWIZZLE_G"; + case VK_COMPONENT_SWIZZLE_IDENTITY: + return "VK_COMPONENT_SWIZZLE_IDENTITY"; + case VK_COMPONENT_SWIZZLE_ONE: + return "VK_COMPONENT_SWIZZLE_ONE"; + case VK_COMPONENT_SWIZZLE_R: + return "VK_COMPONENT_SWIZZLE_R"; + case VK_COMPONENT_SWIZZLE_ZERO: + return "VK_COMPONENT_SWIZZLE_ZERO"; + default: + return "Unhandled VkComponentSwizzle"; + } +} + +static inline const char* string_VkImageViewCreateFlagBits(VkImageViewCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT: + return "VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT"; + case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT: + return "VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT"; + default: + return "Unhandled VkImageViewCreateFlagBits"; + } +} + +static inline std::string string_VkImageViewCreateFlags(VkImageViewCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkImageViewCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkImageViewCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkImageViewType(VkImageViewType input_value) +{ + switch (input_value) + { + case VK_IMAGE_VIEW_TYPE_1D: + return "VK_IMAGE_VIEW_TYPE_1D"; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + return "VK_IMAGE_VIEW_TYPE_1D_ARRAY"; + case VK_IMAGE_VIEW_TYPE_2D: + return "VK_IMAGE_VIEW_TYPE_2D"; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + return "VK_IMAGE_VIEW_TYPE_2D_ARRAY"; + case VK_IMAGE_VIEW_TYPE_3D: + return "VK_IMAGE_VIEW_TYPE_3D"; + case VK_IMAGE_VIEW_TYPE_CUBE: + return "VK_IMAGE_VIEW_TYPE_CUBE"; + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + return "VK_IMAGE_VIEW_TYPE_CUBE_ARRAY"; + default: + return "Unhandled VkImageViewType"; + } +} + +static inline const char* string_VkPipelineCacheCreateFlagBits(VkPipelineCacheCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT: + return "VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT"; + default: + return "Unhandled VkPipelineCacheCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineCacheCreateFlags(VkPipelineCacheCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCacheCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCacheCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkBlendFactor(VkBlendFactor input_value) +{ + switch (input_value) + { + case VK_BLEND_FACTOR_CONSTANT_ALPHA: + return "VK_BLEND_FACTOR_CONSTANT_ALPHA"; + case VK_BLEND_FACTOR_CONSTANT_COLOR: + return "VK_BLEND_FACTOR_CONSTANT_COLOR"; + case VK_BLEND_FACTOR_DST_ALPHA: + return "VK_BLEND_FACTOR_DST_ALPHA"; + case VK_BLEND_FACTOR_DST_COLOR: + return "VK_BLEND_FACTOR_DST_COLOR"; + case VK_BLEND_FACTOR_ONE: + return "VK_BLEND_FACTOR_ONE"; + case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA"; + case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: + return "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR"; + case VK_BLEND_FACTOR_SRC1_ALPHA: + return "VK_BLEND_FACTOR_SRC1_ALPHA"; + case VK_BLEND_FACTOR_SRC1_COLOR: + return "VK_BLEND_FACTOR_SRC1_COLOR"; + case VK_BLEND_FACTOR_SRC_ALPHA: + return "VK_BLEND_FACTOR_SRC_ALPHA"; + case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: + return "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE"; + case VK_BLEND_FACTOR_SRC_COLOR: + return "VK_BLEND_FACTOR_SRC_COLOR"; + case VK_BLEND_FACTOR_ZERO: + return "VK_BLEND_FACTOR_ZERO"; + default: + return "Unhandled VkBlendFactor"; + } +} + +static inline const char* string_VkBlendOp(VkBlendOp input_value) +{ + switch (input_value) + { + case VK_BLEND_OP_ADD: + return "VK_BLEND_OP_ADD"; + case VK_BLEND_OP_BLUE_EXT: + return "VK_BLEND_OP_BLUE_EXT"; + case VK_BLEND_OP_COLORBURN_EXT: + return "VK_BLEND_OP_COLORBURN_EXT"; + case VK_BLEND_OP_COLORDODGE_EXT: + return "VK_BLEND_OP_COLORDODGE_EXT"; + case VK_BLEND_OP_CONTRAST_EXT: + return "VK_BLEND_OP_CONTRAST_EXT"; + case VK_BLEND_OP_DARKEN_EXT: + return "VK_BLEND_OP_DARKEN_EXT"; + case VK_BLEND_OP_DIFFERENCE_EXT: + return "VK_BLEND_OP_DIFFERENCE_EXT"; + case VK_BLEND_OP_DST_ATOP_EXT: + return "VK_BLEND_OP_DST_ATOP_EXT"; + case VK_BLEND_OP_DST_EXT: + return "VK_BLEND_OP_DST_EXT"; + case VK_BLEND_OP_DST_IN_EXT: + return "VK_BLEND_OP_DST_IN_EXT"; + case VK_BLEND_OP_DST_OUT_EXT: + return "VK_BLEND_OP_DST_OUT_EXT"; + case VK_BLEND_OP_DST_OVER_EXT: + return "VK_BLEND_OP_DST_OVER_EXT"; + case VK_BLEND_OP_EXCLUSION_EXT: + return "VK_BLEND_OP_EXCLUSION_EXT"; + case VK_BLEND_OP_GREEN_EXT: + return "VK_BLEND_OP_GREEN_EXT"; + case VK_BLEND_OP_HARDLIGHT_EXT: + return "VK_BLEND_OP_HARDLIGHT_EXT"; + case VK_BLEND_OP_HARDMIX_EXT: + return "VK_BLEND_OP_HARDMIX_EXT"; + case VK_BLEND_OP_HSL_COLOR_EXT: + return "VK_BLEND_OP_HSL_COLOR_EXT"; + case VK_BLEND_OP_HSL_HUE_EXT: + return "VK_BLEND_OP_HSL_HUE_EXT"; + case VK_BLEND_OP_HSL_LUMINOSITY_EXT: + return "VK_BLEND_OP_HSL_LUMINOSITY_EXT"; + case VK_BLEND_OP_HSL_SATURATION_EXT: + return "VK_BLEND_OP_HSL_SATURATION_EXT"; + case VK_BLEND_OP_INVERT_EXT: + return "VK_BLEND_OP_INVERT_EXT"; + case VK_BLEND_OP_INVERT_OVG_EXT: + return "VK_BLEND_OP_INVERT_OVG_EXT"; + case VK_BLEND_OP_INVERT_RGB_EXT: + return "VK_BLEND_OP_INVERT_RGB_EXT"; + case VK_BLEND_OP_LIGHTEN_EXT: + return "VK_BLEND_OP_LIGHTEN_EXT"; + case VK_BLEND_OP_LINEARBURN_EXT: + return "VK_BLEND_OP_LINEARBURN_EXT"; + case VK_BLEND_OP_LINEARDODGE_EXT: + return "VK_BLEND_OP_LINEARDODGE_EXT"; + case VK_BLEND_OP_LINEARLIGHT_EXT: + return "VK_BLEND_OP_LINEARLIGHT_EXT"; + case VK_BLEND_OP_MAX: + return "VK_BLEND_OP_MAX"; + case VK_BLEND_OP_MIN: + return "VK_BLEND_OP_MIN"; + case VK_BLEND_OP_MINUS_CLAMPED_EXT: + return "VK_BLEND_OP_MINUS_CLAMPED_EXT"; + case VK_BLEND_OP_MINUS_EXT: + return "VK_BLEND_OP_MINUS_EXT"; + case VK_BLEND_OP_MULTIPLY_EXT: + return "VK_BLEND_OP_MULTIPLY_EXT"; + case VK_BLEND_OP_OVERLAY_EXT: + return "VK_BLEND_OP_OVERLAY_EXT"; + case VK_BLEND_OP_PINLIGHT_EXT: + return "VK_BLEND_OP_PINLIGHT_EXT"; + case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT: + return "VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT"; + case VK_BLEND_OP_PLUS_CLAMPED_EXT: + return "VK_BLEND_OP_PLUS_CLAMPED_EXT"; + case VK_BLEND_OP_PLUS_DARKER_EXT: + return "VK_BLEND_OP_PLUS_DARKER_EXT"; + case VK_BLEND_OP_PLUS_EXT: + return "VK_BLEND_OP_PLUS_EXT"; + case VK_BLEND_OP_RED_EXT: + return "VK_BLEND_OP_RED_EXT"; + case VK_BLEND_OP_REVERSE_SUBTRACT: + return "VK_BLEND_OP_REVERSE_SUBTRACT"; + case VK_BLEND_OP_SCREEN_EXT: + return "VK_BLEND_OP_SCREEN_EXT"; + case VK_BLEND_OP_SOFTLIGHT_EXT: + return "VK_BLEND_OP_SOFTLIGHT_EXT"; + case VK_BLEND_OP_SRC_ATOP_EXT: + return "VK_BLEND_OP_SRC_ATOP_EXT"; + case VK_BLEND_OP_SRC_EXT: + return "VK_BLEND_OP_SRC_EXT"; + case VK_BLEND_OP_SRC_IN_EXT: + return "VK_BLEND_OP_SRC_IN_EXT"; + case VK_BLEND_OP_SRC_OUT_EXT: + return "VK_BLEND_OP_SRC_OUT_EXT"; + case VK_BLEND_OP_SRC_OVER_EXT: + return "VK_BLEND_OP_SRC_OVER_EXT"; + case VK_BLEND_OP_SUBTRACT: + return "VK_BLEND_OP_SUBTRACT"; + case VK_BLEND_OP_VIVIDLIGHT_EXT: + return "VK_BLEND_OP_VIVIDLIGHT_EXT"; + case VK_BLEND_OP_XOR_EXT: + return "VK_BLEND_OP_XOR_EXT"; + case VK_BLEND_OP_ZERO_EXT: + return "VK_BLEND_OP_ZERO_EXT"; + default: + return "Unhandled VkBlendOp"; + } +} + +static inline const char* string_VkColorComponentFlagBits(VkColorComponentFlagBits input_value) +{ + switch (input_value) + { + case VK_COLOR_COMPONENT_A_BIT: + return "VK_COLOR_COMPONENT_A_BIT"; + case VK_COLOR_COMPONENT_B_BIT: + return "VK_COLOR_COMPONENT_B_BIT"; + case VK_COLOR_COMPONENT_G_BIT: + return "VK_COLOR_COMPONENT_G_BIT"; + case VK_COLOR_COMPONENT_R_BIT: + return "VK_COLOR_COMPONENT_R_BIT"; + default: + return "Unhandled VkColorComponentFlagBits"; + } +} + +static inline std::string string_VkColorComponentFlags(VkColorComponentFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkColorComponentFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkColorComponentFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCompareOp(VkCompareOp input_value) +{ + switch (input_value) + { + case VK_COMPARE_OP_ALWAYS: + return "VK_COMPARE_OP_ALWAYS"; + case VK_COMPARE_OP_EQUAL: + return "VK_COMPARE_OP_EQUAL"; + case VK_COMPARE_OP_GREATER: + return "VK_COMPARE_OP_GREATER"; + case VK_COMPARE_OP_GREATER_OR_EQUAL: + return "VK_COMPARE_OP_GREATER_OR_EQUAL"; + case VK_COMPARE_OP_LESS: + return "VK_COMPARE_OP_LESS"; + case VK_COMPARE_OP_LESS_OR_EQUAL: + return "VK_COMPARE_OP_LESS_OR_EQUAL"; + case VK_COMPARE_OP_NEVER: + return "VK_COMPARE_OP_NEVER"; + case VK_COMPARE_OP_NOT_EQUAL: + return "VK_COMPARE_OP_NOT_EQUAL"; + default: + return "Unhandled VkCompareOp"; + } +} + +static inline const char* string_VkPipelineCreateFlagBits(VkPipelineCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT: + return "VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT"; + case VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR: + return "VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR"; + case VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR: + return "VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR"; + case VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV: + return "VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV"; + case VK_PIPELINE_CREATE_DERIVATIVE_BIT: + return "VK_PIPELINE_CREATE_DERIVATIVE_BIT"; + case VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT: + return "VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT"; + case VK_PIPELINE_CREATE_DISPATCH_BASE_BIT: + return "VK_PIPELINE_CREATE_DISPATCH_BASE_BIT"; + case VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT: + return "VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT"; + case VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT: + return "VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT"; + case VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV: + return "VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV"; + case VK_PIPELINE_CREATE_LIBRARY_BIT_KHR: + return "VK_PIPELINE_CREATE_LIBRARY_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV: + return "VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR"; + case VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR: + return "VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR"; + case VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT: + return "VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT"; + default: + return "Unhandled VkPipelineCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineCreateFlags(VkPipelineCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineShaderStageCreateFlagBits(VkPipelineShaderStageCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT: + return "VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT"; + case VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT: + return "VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT"; + default: + return "Unhandled VkPipelineShaderStageCreateFlagBits"; + } +} + +static inline std::string string_VkPipelineShaderStageCreateFlags(VkPipelineShaderStageCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkShaderStageFlagBits(VkShaderStageFlagBits input_value) +{ + switch (input_value) + { + case VK_SHADER_STAGE_ALL: + return "VK_SHADER_STAGE_ALL"; + case VK_SHADER_STAGE_ALL_GRAPHICS: + return "VK_SHADER_STAGE_ALL_GRAPHICS"; + case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: + return "VK_SHADER_STAGE_ANY_HIT_BIT_KHR"; + case VK_SHADER_STAGE_CALLABLE_BIT_KHR: + return "VK_SHADER_STAGE_CALLABLE_BIT_KHR"; + case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + return "VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR"; + case VK_SHADER_STAGE_COMPUTE_BIT: + return "VK_SHADER_STAGE_COMPUTE_BIT"; + case VK_SHADER_STAGE_FRAGMENT_BIT: + return "VK_SHADER_STAGE_FRAGMENT_BIT"; + case VK_SHADER_STAGE_GEOMETRY_BIT: + return "VK_SHADER_STAGE_GEOMETRY_BIT"; + case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: + return "VK_SHADER_STAGE_INTERSECTION_BIT_KHR"; + case VK_SHADER_STAGE_MESH_BIT_NV: + return "VK_SHADER_STAGE_MESH_BIT_NV"; + case VK_SHADER_STAGE_MISS_BIT_KHR: + return "VK_SHADER_STAGE_MISS_BIT_KHR"; + case VK_SHADER_STAGE_RAYGEN_BIT_KHR: + return "VK_SHADER_STAGE_RAYGEN_BIT_KHR"; + case VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI: + return "VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI"; + case VK_SHADER_STAGE_TASK_BIT_NV: + return "VK_SHADER_STAGE_TASK_BIT_NV"; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT"; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT"; + case VK_SHADER_STAGE_VERTEX_BIT: + return "VK_SHADER_STAGE_VERTEX_BIT"; + default: + return "Unhandled VkShaderStageFlagBits"; + } +} + +static inline std::string string_VkShaderStageFlags(VkShaderStageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkShaderStageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkShaderStageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCullModeFlagBits(VkCullModeFlagBits input_value) +{ + switch (input_value) + { + case VK_CULL_MODE_BACK_BIT: + return "VK_CULL_MODE_BACK_BIT"; + case VK_CULL_MODE_FRONT_AND_BACK: + return "VK_CULL_MODE_FRONT_AND_BACK"; + case VK_CULL_MODE_FRONT_BIT: + return "VK_CULL_MODE_FRONT_BIT"; + case VK_CULL_MODE_NONE: + return "VK_CULL_MODE_NONE"; + default: + return "Unhandled VkCullModeFlagBits"; + } +} + +static inline std::string string_VkCullModeFlags(VkCullModeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCullModeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCullModeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDynamicState(VkDynamicState input_value) +{ + switch (input_value) + { + case VK_DYNAMIC_STATE_BLEND_CONSTANTS: + return "VK_DYNAMIC_STATE_BLEND_CONSTANTS"; + case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_CULL_MODE_EXT: + return "VK_DYNAMIC_STATE_CULL_MODE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_BIAS: + return "VK_DYNAMIC_STATE_DEPTH_BIAS"; + case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_BOUNDS: + return "VK_DYNAMIC_STATE_DEPTH_BOUNDS"; + case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT: + return "VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT"; + case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT: + return "VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT"; + case VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT: + return "VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT"; + case VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV: + return "VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV"; + case VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR: + return "VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR"; + case VK_DYNAMIC_STATE_FRONT_FACE_EXT: + return "VK_DYNAMIC_STATE_FRONT_FACE_EXT"; + case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT: + return "VK_DYNAMIC_STATE_LINE_STIPPLE_EXT"; + case VK_DYNAMIC_STATE_LINE_WIDTH: + return "VK_DYNAMIC_STATE_LINE_WIDTH"; + case VK_DYNAMIC_STATE_LOGIC_OP_EXT: + return "VK_DYNAMIC_STATE_LOGIC_OP_EXT"; + case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT: + return "VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT"; + case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT: + return "VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT"; + case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT: + return "VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT"; + case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT: + return "VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT"; + case VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR: + return "VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR"; + case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT: + return "VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT"; + case VK_DYNAMIC_STATE_SCISSOR: + return "VK_DYNAMIC_STATE_SCISSOR"; + case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT: + return "VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT"; + case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: + return "VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK"; + case VK_DYNAMIC_STATE_STENCIL_OP_EXT: + return "VK_DYNAMIC_STATE_STENCIL_OP_EXT"; + case VK_DYNAMIC_STATE_STENCIL_REFERENCE: + return "VK_DYNAMIC_STATE_STENCIL_REFERENCE"; + case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT: + return "VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT"; + case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: + return "VK_DYNAMIC_STATE_STENCIL_WRITE_MASK"; + case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT: + return "VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT"; + case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT: + return "VK_DYNAMIC_STATE_VERTEX_INPUT_EXT"; + case VK_DYNAMIC_STATE_VIEWPORT: + return "VK_DYNAMIC_STATE_VIEWPORT"; + case VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV"; + case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT: + return "VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT"; + case VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV: + return "VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV"; + default: + return "Unhandled VkDynamicState"; + } +} + +static inline const char* string_VkFrontFace(VkFrontFace input_value) +{ + switch (input_value) + { + case VK_FRONT_FACE_CLOCKWISE: + return "VK_FRONT_FACE_CLOCKWISE"; + case VK_FRONT_FACE_COUNTER_CLOCKWISE: + return "VK_FRONT_FACE_COUNTER_CLOCKWISE"; + default: + return "Unhandled VkFrontFace"; + } +} + +static inline const char* string_VkVertexInputRate(VkVertexInputRate input_value) +{ + switch (input_value) + { + case VK_VERTEX_INPUT_RATE_INSTANCE: + return "VK_VERTEX_INPUT_RATE_INSTANCE"; + case VK_VERTEX_INPUT_RATE_VERTEX: + return "VK_VERTEX_INPUT_RATE_VERTEX"; + default: + return "Unhandled VkVertexInputRate"; + } +} + +static inline const char* string_VkPrimitiveTopology(VkPrimitiveTopology input_value) +{ + switch (input_value) + { + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST"; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP"; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + return "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST"; + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return "VK_PRIMITIVE_TOPOLOGY_POINT_LIST"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY"; + default: + return "Unhandled VkPrimitiveTopology"; + } +} + +static inline const char* string_VkPolygonMode(VkPolygonMode input_value) +{ + switch (input_value) + { + case VK_POLYGON_MODE_FILL: + return "VK_POLYGON_MODE_FILL"; + case VK_POLYGON_MODE_FILL_RECTANGLE_NV: + return "VK_POLYGON_MODE_FILL_RECTANGLE_NV"; + case VK_POLYGON_MODE_LINE: + return "VK_POLYGON_MODE_LINE"; + case VK_POLYGON_MODE_POINT: + return "VK_POLYGON_MODE_POINT"; + default: + return "Unhandled VkPolygonMode"; + } +} + +static inline const char* string_VkStencilOp(VkStencilOp input_value) +{ + switch (input_value) + { + case VK_STENCIL_OP_DECREMENT_AND_CLAMP: + return "VK_STENCIL_OP_DECREMENT_AND_CLAMP"; + case VK_STENCIL_OP_DECREMENT_AND_WRAP: + return "VK_STENCIL_OP_DECREMENT_AND_WRAP"; + case VK_STENCIL_OP_INCREMENT_AND_CLAMP: + return "VK_STENCIL_OP_INCREMENT_AND_CLAMP"; + case VK_STENCIL_OP_INCREMENT_AND_WRAP: + return "VK_STENCIL_OP_INCREMENT_AND_WRAP"; + case VK_STENCIL_OP_INVERT: + return "VK_STENCIL_OP_INVERT"; + case VK_STENCIL_OP_KEEP: + return "VK_STENCIL_OP_KEEP"; + case VK_STENCIL_OP_REPLACE: + return "VK_STENCIL_OP_REPLACE"; + case VK_STENCIL_OP_ZERO: + return "VK_STENCIL_OP_ZERO"; + default: + return "Unhandled VkStencilOp"; + } +} + +static inline const char* string_VkLogicOp(VkLogicOp input_value) +{ + switch (input_value) + { + case VK_LOGIC_OP_AND: + return "VK_LOGIC_OP_AND"; + case VK_LOGIC_OP_AND_INVERTED: + return "VK_LOGIC_OP_AND_INVERTED"; + case VK_LOGIC_OP_AND_REVERSE: + return "VK_LOGIC_OP_AND_REVERSE"; + case VK_LOGIC_OP_CLEAR: + return "VK_LOGIC_OP_CLEAR"; + case VK_LOGIC_OP_COPY: + return "VK_LOGIC_OP_COPY"; + case VK_LOGIC_OP_COPY_INVERTED: + return "VK_LOGIC_OP_COPY_INVERTED"; + case VK_LOGIC_OP_EQUIVALENT: + return "VK_LOGIC_OP_EQUIVALENT"; + case VK_LOGIC_OP_INVERT: + return "VK_LOGIC_OP_INVERT"; + case VK_LOGIC_OP_NAND: + return "VK_LOGIC_OP_NAND"; + case VK_LOGIC_OP_NOR: + return "VK_LOGIC_OP_NOR"; + case VK_LOGIC_OP_NO_OP: + return "VK_LOGIC_OP_NO_OP"; + case VK_LOGIC_OP_OR: + return "VK_LOGIC_OP_OR"; + case VK_LOGIC_OP_OR_INVERTED: + return "VK_LOGIC_OP_OR_INVERTED"; + case VK_LOGIC_OP_OR_REVERSE: + return "VK_LOGIC_OP_OR_REVERSE"; + case VK_LOGIC_OP_SET: + return "VK_LOGIC_OP_SET"; + case VK_LOGIC_OP_XOR: + return "VK_LOGIC_OP_XOR"; + default: + return "Unhandled VkLogicOp"; + } +} + +static inline const char* string_VkBorderColor(VkBorderColor input_value) +{ + switch (input_value) + { + case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: + return "VK_BORDER_COLOR_FLOAT_CUSTOM_EXT"; + case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: + return "VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK"; + case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: + return "VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE"; + case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: + return "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK"; + case VK_BORDER_COLOR_INT_CUSTOM_EXT: + return "VK_BORDER_COLOR_INT_CUSTOM_EXT"; + case VK_BORDER_COLOR_INT_OPAQUE_BLACK: + return "VK_BORDER_COLOR_INT_OPAQUE_BLACK"; + case VK_BORDER_COLOR_INT_OPAQUE_WHITE: + return "VK_BORDER_COLOR_INT_OPAQUE_WHITE"; + case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: + return "VK_BORDER_COLOR_INT_TRANSPARENT_BLACK"; + default: + return "Unhandled VkBorderColor"; + } +} + +static inline const char* string_VkFilter(VkFilter input_value) +{ + switch (input_value) + { + case VK_FILTER_CUBIC_IMG: + return "VK_FILTER_CUBIC_IMG"; + case VK_FILTER_LINEAR: + return "VK_FILTER_LINEAR"; + case VK_FILTER_NEAREST: + return "VK_FILTER_NEAREST"; + default: + return "Unhandled VkFilter"; + } +} + +static inline const char* string_VkSamplerAddressMode(VkSamplerAddressMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: + return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER"; + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: + return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE"; + case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: + return "VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT"; + case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: + return "VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE"; + case VK_SAMPLER_ADDRESS_MODE_REPEAT: + return "VK_SAMPLER_ADDRESS_MODE_REPEAT"; + default: + return "Unhandled VkSamplerAddressMode"; + } +} + +static inline const char* string_VkSamplerCreateFlagBits(VkSamplerCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT: + return "VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT"; + case VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT: + return "VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT"; + default: + return "Unhandled VkSamplerCreateFlagBits"; + } +} + +static inline std::string string_VkSamplerCreateFlags(VkSamplerCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSamplerCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSamplerCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerMipmapMode(VkSamplerMipmapMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_MIPMAP_MODE_LINEAR: + return "VK_SAMPLER_MIPMAP_MODE_LINEAR"; + case VK_SAMPLER_MIPMAP_MODE_NEAREST: + return "VK_SAMPLER_MIPMAP_MODE_NEAREST"; + default: + return "Unhandled VkSamplerMipmapMode"; + } +} + +static inline const char* string_VkDescriptorPoolCreateFlagBits(VkDescriptorPoolCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT: + return "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT"; + case VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE: + return "VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE"; + case VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT"; + default: + return "Unhandled VkDescriptorPoolCreateFlagBits"; + } +} + +static inline std::string string_VkDescriptorPoolCreateFlags(VkDescriptorPoolCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorType(VkDescriptorType input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR"; + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: + return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV"; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER"; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: + return "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT"; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT"; + case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE: + return "VK_DESCRIPTOR_TYPE_MUTABLE_VALVE"; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE"; + case VK_DESCRIPTOR_TYPE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_SAMPLER"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER"; + default: + return "Unhandled VkDescriptorType"; + } +} + +static inline const char* string_VkDescriptorSetLayoutCreateFlagBits(VkDescriptorSetLayoutCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR"; + case VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT: + return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT"; + default: + return "Unhandled VkDescriptorSetLayoutCreateFlagBits"; + } +} + +static inline std::string string_VkDescriptorSetLayoutCreateFlags(VkDescriptorSetLayoutCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkAttachmentDescriptionFlagBits(VkAttachmentDescriptionFlagBits input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT: + return "VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT"; + default: + return "Unhandled VkAttachmentDescriptionFlagBits"; + } +} + +static inline std::string string_VkAttachmentDescriptionFlags(VkAttachmentDescriptionFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAttachmentDescriptionFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAttachmentDescriptionFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkAttachmentLoadOp(VkAttachmentLoadOp input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_LOAD_OP_CLEAR: + return "VK_ATTACHMENT_LOAD_OP_CLEAR"; + case VK_ATTACHMENT_LOAD_OP_DONT_CARE: + return "VK_ATTACHMENT_LOAD_OP_DONT_CARE"; + case VK_ATTACHMENT_LOAD_OP_LOAD: + return "VK_ATTACHMENT_LOAD_OP_LOAD"; + case VK_ATTACHMENT_LOAD_OP_NONE_EXT: + return "VK_ATTACHMENT_LOAD_OP_NONE_EXT"; + default: + return "Unhandled VkAttachmentLoadOp"; + } +} + +static inline const char* string_VkAttachmentStoreOp(VkAttachmentStoreOp input_value) +{ + switch (input_value) + { + case VK_ATTACHMENT_STORE_OP_DONT_CARE: + return "VK_ATTACHMENT_STORE_OP_DONT_CARE"; + case VK_ATTACHMENT_STORE_OP_NONE_EXT: + return "VK_ATTACHMENT_STORE_OP_NONE_EXT"; + case VK_ATTACHMENT_STORE_OP_STORE: + return "VK_ATTACHMENT_STORE_OP_STORE"; + default: + return "Unhandled VkAttachmentStoreOp"; + } +} + +static inline const char* string_VkDependencyFlagBits(VkDependencyFlagBits input_value) +{ + switch (input_value) + { + case VK_DEPENDENCY_BY_REGION_BIT: + return "VK_DEPENDENCY_BY_REGION_BIT"; + case VK_DEPENDENCY_DEVICE_GROUP_BIT: + return "VK_DEPENDENCY_DEVICE_GROUP_BIT"; + case VK_DEPENDENCY_VIEW_LOCAL_BIT: + return "VK_DEPENDENCY_VIEW_LOCAL_BIT"; + default: + return "Unhandled VkDependencyFlagBits"; + } +} + +static inline std::string string_VkDependencyFlags(VkDependencyFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDependencyFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDependencyFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFramebufferCreateFlagBits(VkFramebufferCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT: + return "VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT"; + default: + return "Unhandled VkFramebufferCreateFlagBits"; + } +} + +static inline std::string string_VkFramebufferCreateFlags(VkFramebufferCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFramebufferCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFramebufferCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPipelineBindPoint(VkPipelineBindPoint input_value) +{ + switch (input_value) + { + case VK_PIPELINE_BIND_POINT_COMPUTE: + return "VK_PIPELINE_BIND_POINT_COMPUTE"; + case VK_PIPELINE_BIND_POINT_GRAPHICS: + return "VK_PIPELINE_BIND_POINT_GRAPHICS"; + case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: + return "VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR"; + case VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI: + return "VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI"; + default: + return "Unhandled VkPipelineBindPoint"; + } +} + +static inline const char* string_VkRenderPassCreateFlagBits(VkRenderPassCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM: + return "VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM"; + default: + return "Unhandled VkRenderPassCreateFlagBits"; + } +} + +static inline std::string string_VkRenderPassCreateFlags(VkRenderPassCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkRenderPassCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkRenderPassCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubpassDescriptionFlagBits(VkSubpassDescriptionFlagBits input_value) +{ + switch (input_value) + { + case VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM: + return "VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM"; + case VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX: + return "VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX"; + case VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX: + return "VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX"; + case VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM: + return "VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM"; + default: + return "Unhandled VkSubpassDescriptionFlagBits"; + } +} + +static inline std::string string_VkSubpassDescriptionFlags(VkSubpassDescriptionFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubpassDescriptionFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubpassDescriptionFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandPoolCreateFlagBits(VkCommandPoolCreateFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_POOL_CREATE_PROTECTED_BIT: + return "VK_COMMAND_POOL_CREATE_PROTECTED_BIT"; + case VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT: + return "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT"; + case VK_COMMAND_POOL_CREATE_TRANSIENT_BIT: + return "VK_COMMAND_POOL_CREATE_TRANSIENT_BIT"; + default: + return "Unhandled VkCommandPoolCreateFlagBits"; + } +} + +static inline std::string string_VkCommandPoolCreateFlags(VkCommandPoolCreateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandPoolCreateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandPoolCreateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandPoolResetFlagBits(VkCommandPoolResetFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT: + return "VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT"; + default: + return "Unhandled VkCommandPoolResetFlagBits"; + } +} + +static inline std::string string_VkCommandPoolResetFlags(VkCommandPoolResetFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandPoolResetFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandPoolResetFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandBufferLevel(VkCommandBufferLevel input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_LEVEL_PRIMARY: + return "VK_COMMAND_BUFFER_LEVEL_PRIMARY"; + case VK_COMMAND_BUFFER_LEVEL_SECONDARY: + return "VK_COMMAND_BUFFER_LEVEL_SECONDARY"; + default: + return "Unhandled VkCommandBufferLevel"; + } +} + +static inline const char* string_VkCommandBufferUsageFlagBits(VkCommandBufferUsageFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT: + return "VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT"; + case VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT: + return "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT"; + case VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT: + return "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT"; + default: + return "Unhandled VkCommandBufferUsageFlagBits"; + } +} + +static inline std::string string_VkCommandBufferUsageFlags(VkCommandBufferUsageFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandBufferUsageFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandBufferUsageFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkQueryControlFlagBits(VkQueryControlFlagBits input_value) +{ + switch (input_value) + { + case VK_QUERY_CONTROL_PRECISE_BIT: + return "VK_QUERY_CONTROL_PRECISE_BIT"; + default: + return "Unhandled VkQueryControlFlagBits"; + } +} + +static inline std::string string_VkQueryControlFlags(VkQueryControlFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkQueryControlFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkQueryControlFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkCommandBufferResetFlagBits(VkCommandBufferResetFlagBits input_value) +{ + switch (input_value) + { + case VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT: + return "VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT"; + default: + return "Unhandled VkCommandBufferResetFlagBits"; + } +} + +static inline std::string string_VkCommandBufferResetFlags(VkCommandBufferResetFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCommandBufferResetFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCommandBufferResetFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkIndexType(VkIndexType input_value) +{ + switch (input_value) + { + case VK_INDEX_TYPE_NONE_KHR: + return "VK_INDEX_TYPE_NONE_KHR"; + case VK_INDEX_TYPE_UINT16: + return "VK_INDEX_TYPE_UINT16"; + case VK_INDEX_TYPE_UINT32: + return "VK_INDEX_TYPE_UINT32"; + case VK_INDEX_TYPE_UINT8_EXT: + return "VK_INDEX_TYPE_UINT8_EXT"; + default: + return "Unhandled VkIndexType"; + } +} + +static inline const char* string_VkStencilFaceFlagBits(VkStencilFaceFlagBits input_value) +{ + switch (input_value) + { + case VK_STENCIL_FACE_BACK_BIT: + return "VK_STENCIL_FACE_BACK_BIT"; + case VK_STENCIL_FACE_FRONT_AND_BACK: + return "VK_STENCIL_FACE_FRONT_AND_BACK"; + case VK_STENCIL_FACE_FRONT_BIT: + return "VK_STENCIL_FACE_FRONT_BIT"; + default: + return "Unhandled VkStencilFaceFlagBits"; + } +} + +static inline std::string string_VkStencilFaceFlags(VkStencilFaceFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkStencilFaceFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkStencilFaceFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubpassContents(VkSubpassContents input_value) +{ + switch (input_value) + { + case VK_SUBPASS_CONTENTS_INLINE: + return "VK_SUBPASS_CONTENTS_INLINE"; + case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS: + return "VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS"; + default: + return "Unhandled VkSubpassContents"; + } +} + +static inline const char* string_VkSubgroupFeatureFlagBits(VkSubgroupFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_SUBGROUP_FEATURE_ARITHMETIC_BIT: + return "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT"; + case VK_SUBGROUP_FEATURE_BALLOT_BIT: + return "VK_SUBGROUP_FEATURE_BALLOT_BIT"; + case VK_SUBGROUP_FEATURE_BASIC_BIT: + return "VK_SUBGROUP_FEATURE_BASIC_BIT"; + case VK_SUBGROUP_FEATURE_CLUSTERED_BIT: + return "VK_SUBGROUP_FEATURE_CLUSTERED_BIT"; + case VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV: + return "VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV"; + case VK_SUBGROUP_FEATURE_QUAD_BIT: + return "VK_SUBGROUP_FEATURE_QUAD_BIT"; + case VK_SUBGROUP_FEATURE_SHUFFLE_BIT: + return "VK_SUBGROUP_FEATURE_SHUFFLE_BIT"; + case VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT: + return "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT"; + case VK_SUBGROUP_FEATURE_VOTE_BIT: + return "VK_SUBGROUP_FEATURE_VOTE_BIT"; + default: + return "Unhandled VkSubgroupFeatureFlagBits"; + } +} + +static inline std::string string_VkSubgroupFeatureFlags(VkSubgroupFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubgroupFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubgroupFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPeerMemoryFeatureFlagBits(VkPeerMemoryFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT"; + default: + return "Unhandled VkPeerMemoryFeatureFlagBits"; + } +} + +static inline std::string string_VkPeerMemoryFeatureFlags(VkPeerMemoryFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryAllocateFlagBits(VkMemoryAllocateFlagBits input_value) +{ + switch (input_value) + { + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT"; + default: + return "Unhandled VkMemoryAllocateFlagBits"; + } +} + +static inline std::string string_VkMemoryAllocateFlags(VkMemoryAllocateFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryAllocateFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkPointClippingBehavior(VkPointClippingBehavior input_value) +{ + switch (input_value) + { + case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES: + return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES"; + case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY: + return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY"; + default: + return "Unhandled VkPointClippingBehavior"; + } +} + +static inline const char* string_VkTessellationDomainOrigin(VkTessellationDomainOrigin input_value) +{ + switch (input_value) + { + case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT"; + case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT"; + default: + return "Unhandled VkTessellationDomainOrigin"; + } +} + +static inline const char* string_VkSamplerYcbcrModelConversion(VkSamplerYcbcrModelConversion input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY"; + default: + return "Unhandled VkSamplerYcbcrModelConversion"; + } +} + +static inline const char* string_VkSamplerYcbcrRange(VkSamplerYcbcrRange input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: + return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL"; + case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: + return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW"; + default: + return "Unhandled VkSamplerYcbcrRange"; + } +} + +static inline const char* string_VkChromaLocation(VkChromaLocation input_value) +{ + switch (input_value) + { + case VK_CHROMA_LOCATION_COSITED_EVEN: + return "VK_CHROMA_LOCATION_COSITED_EVEN"; + case VK_CHROMA_LOCATION_MIDPOINT: + return "VK_CHROMA_LOCATION_MIDPOINT"; + default: + return "Unhandled VkChromaLocation"; + } +} + +static inline const char* string_VkDescriptorUpdateTemplateType(VkDescriptorUpdateTemplateType input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET"; + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR"; + default: + return "Unhandled VkDescriptorUpdateTemplateType"; + } +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBits(VkExternalMemoryHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlags(VkExternalMemoryHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBits(VkExternalMemoryFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlags(VkExternalMemoryFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceHandleTypeFlagBits(VkExternalFenceHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT"; + default: + return "Unhandled VkExternalFenceHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalFenceHandleTypeFlags(VkExternalFenceHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceFeatureFlagBits(VkExternalFenceFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalFenceFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalFenceFeatureFlags(VkExternalFenceFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceImportFlagBits(VkFenceImportFlagBits input_value) +{ + switch (input_value) + { + case VK_FENCE_IMPORT_TEMPORARY_BIT: + return "VK_FENCE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkFenceImportFlagBits"; + } +} + +static inline std::string string_VkFenceImportFlags(VkFenceImportFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceImportFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceImportFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreImportFlagBits(VkSemaphoreImportFlagBits input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT: + return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkSemaphoreImportFlagBits"; + } +} + +static inline std::string string_VkSemaphoreImportFlags(VkSemaphoreImportFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreImportFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreHandleTypeFlagBits(VkExternalSemaphoreHandleTypeFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalSemaphoreHandleTypeFlagBits"; + } +} + +static inline std::string string_VkExternalSemaphoreHandleTypeFlags(VkExternalSemaphoreHandleTypeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreFeatureFlagBits(VkExternalSemaphoreFeatureFlagBits input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalSemaphoreFeatureFlagBits"; + } +} + +static inline std::string string_VkExternalSemaphoreFeatureFlags(VkExternalSemaphoreFeatureFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDriverId(VkDriverId input_value) +{ + switch (input_value) + { + case VK_DRIVER_ID_AMD_OPEN_SOURCE: + return "VK_DRIVER_ID_AMD_OPEN_SOURCE"; + case VK_DRIVER_ID_AMD_PROPRIETARY: + return "VK_DRIVER_ID_AMD_PROPRIETARY"; + case VK_DRIVER_ID_ARM_PROPRIETARY: + return "VK_DRIVER_ID_ARM_PROPRIETARY"; + case VK_DRIVER_ID_BROADCOM_PROPRIETARY: + return "VK_DRIVER_ID_BROADCOM_PROPRIETARY"; + case VK_DRIVER_ID_COREAVI_PROPRIETARY: + return "VK_DRIVER_ID_COREAVI_PROPRIETARY"; + case VK_DRIVER_ID_GGP_PROPRIETARY: + return "VK_DRIVER_ID_GGP_PROPRIETARY"; + case VK_DRIVER_ID_GOOGLE_SWIFTSHADER: + return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER"; + case VK_DRIVER_ID_IMAGINATION_PROPRIETARY: + return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS"; + case VK_DRIVER_ID_JUICE_PROPRIETARY: + return "VK_DRIVER_ID_JUICE_PROPRIETARY"; + case VK_DRIVER_ID_MESA_LLVMPIPE: + return "VK_DRIVER_ID_MESA_LLVMPIPE"; + case VK_DRIVER_ID_MESA_RADV: + return "VK_DRIVER_ID_MESA_RADV"; + case VK_DRIVER_ID_MOLTENVK: + return "VK_DRIVER_ID_MOLTENVK"; + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + return "VK_DRIVER_ID_NVIDIA_PROPRIETARY"; + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY"; + case VK_DRIVER_ID_VERISILICON_PROPRIETARY: + return "VK_DRIVER_ID_VERISILICON_PROPRIETARY"; + default: + return "Unhandled VkDriverId"; + } +} + +static inline const char* string_VkShaderFloatControlsIndependence(VkShaderFloatControlsIndependence input_value) +{ + switch (input_value) + { + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE"; + default: + return "Unhandled VkShaderFloatControlsIndependence"; + } +} + +static inline const char* string_VkResolveModeFlagBits(VkResolveModeFlagBits input_value) +{ + switch (input_value) + { + case VK_RESOLVE_MODE_AVERAGE_BIT: + return "VK_RESOLVE_MODE_AVERAGE_BIT"; + case VK_RESOLVE_MODE_MAX_BIT: + return "VK_RESOLVE_MODE_MAX_BIT"; + case VK_RESOLVE_MODE_MIN_BIT: + return "VK_RESOLVE_MODE_MIN_BIT"; + case VK_RESOLVE_MODE_NONE: + return "VK_RESOLVE_MODE_NONE"; + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: + return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT"; + default: + return "Unhandled VkResolveModeFlagBits"; + } +} + +static inline std::string string_VkResolveModeFlags(VkResolveModeFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkResolveModeFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkResolveModeFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorBindingFlagBits(VkDescriptorBindingFlagBits input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT: + return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT"; + case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT: + return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT"; + default: + return "Unhandled VkDescriptorBindingFlagBits"; + } +} + +static inline std::string string_VkDescriptorBindingFlags(VkDescriptorBindingFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorBindingFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerReductionMode(VkSamplerReductionMode input_value) +{ + switch (input_value) + { + case VK_SAMPLER_REDUCTION_MODE_MAX: + return "VK_SAMPLER_REDUCTION_MODE_MAX"; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return "VK_SAMPLER_REDUCTION_MODE_MIN"; + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE"; + default: + return "Unhandled VkSamplerReductionMode"; + } +} + +static inline const char* string_VkSemaphoreType(VkSemaphoreType input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_TYPE_BINARY: + return "VK_SEMAPHORE_TYPE_BINARY"; + case VK_SEMAPHORE_TYPE_TIMELINE: + return "VK_SEMAPHORE_TYPE_TIMELINE"; + default: + return "Unhandled VkSemaphoreType"; + } +} + +static inline const char* string_VkSemaphoreWaitFlagBits(VkSemaphoreWaitFlagBits input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_WAIT_ANY_BIT: + return "VK_SEMAPHORE_WAIT_ANY_BIT"; + default: + return "Unhandled VkSemaphoreWaitFlagBits"; + } +} + +static inline std::string string_VkSemaphoreWaitFlags(VkSemaphoreWaitFlags input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreWaitFlagBits(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBits(static_cast(0))); + return ret; +} + +static inline const char* string_VkSurfaceTransformFlagBitsKHR(VkSurfaceTransformFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR"; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR"; + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + return "VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR"; + case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: + return "VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR"; + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + return "VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR"; + default: + return "Unhandled VkSurfaceTransformFlagBitsKHR"; + } +} + +static inline std::string string_VkSurfaceTransformFlagsKHR(VkSurfaceTransformFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPresentModeKHR(VkPresentModeKHR input_value) +{ + switch (input_value) + { + case VK_PRESENT_MODE_FIFO_KHR: + return "VK_PRESENT_MODE_FIFO_KHR"; + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + return "VK_PRESENT_MODE_FIFO_RELAXED_KHR"; + case VK_PRESENT_MODE_IMMEDIATE_KHR: + return "VK_PRESENT_MODE_IMMEDIATE_KHR"; + case VK_PRESENT_MODE_MAILBOX_KHR: + return "VK_PRESENT_MODE_MAILBOX_KHR"; + case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: + return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR"; + case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: + return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR"; + default: + return "Unhandled VkPresentModeKHR"; + } +} + +static inline const char* string_VkColorSpaceKHR(VkColorSpaceKHR input_value) +{ + switch (input_value) + { + case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: + return "VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT"; + case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: + return "VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT"; + case VK_COLOR_SPACE_BT2020_LINEAR_EXT: + return "VK_COLOR_SPACE_BT2020_LINEAR_EXT"; + case VK_COLOR_SPACE_BT709_LINEAR_EXT: + return "VK_COLOR_SPACE_BT709_LINEAR_EXT"; + case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: + return "VK_COLOR_SPACE_BT709_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: + return "VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DISPLAY_NATIVE_AMD: + return "VK_COLOR_SPACE_DISPLAY_NATIVE_AMD"; + case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: + return "VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT"; + case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: + return "VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT"; + case VK_COLOR_SPACE_DOLBYVISION_EXT: + return "VK_COLOR_SPACE_DOLBYVISION_EXT"; + case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: + return "VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT"; + case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: + return "VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT"; + case VK_COLOR_SPACE_HDR10_HLG_EXT: + return "VK_COLOR_SPACE_HDR10_HLG_EXT"; + case VK_COLOR_SPACE_HDR10_ST2084_EXT: + return "VK_COLOR_SPACE_HDR10_ST2084_EXT"; + case VK_COLOR_SPACE_PASS_THROUGH_EXT: + return "VK_COLOR_SPACE_PASS_THROUGH_EXT"; + case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: + return "VK_COLOR_SPACE_SRGB_NONLINEAR_KHR"; + default: + return "Unhandled VkColorSpaceKHR"; + } +} + +static inline const char* string_VkCompositeAlphaFlagBitsKHR(VkCompositeAlphaFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR: + return "VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR"; + case VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR: + return "VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR"; + case VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR: + return "VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR"; + case VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR: + return "VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR"; + default: + return "Unhandled VkCompositeAlphaFlagBitsKHR"; + } +} + +static inline std::string string_VkCompositeAlphaFlagsKHR(VkCompositeAlphaFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSwapchainCreateFlagBitsKHR(VkSwapchainCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR"; + case VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR"; + case VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR: + return "VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR"; + default: + return "Unhandled VkSwapchainCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkSwapchainCreateFlagsKHR(VkSwapchainCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceGroupPresentModeFlagBitsKHR(VkDeviceGroupPresentModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR"; + case VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR: + return "VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR"; + default: + return "Unhandled VkDeviceGroupPresentModeFlagBitsKHR"; + } +} + +static inline std::string string_VkDeviceGroupPresentModeFlagsKHR(VkDeviceGroupPresentModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDisplayPlaneAlphaFlagBitsKHR(VkDisplayPlaneAlphaFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR"; + case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR: + return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR"; + default: + return "Unhandled VkDisplayPlaneAlphaFlagBitsKHR"; + } +} + +static inline std::string string_VkDisplayPlaneAlphaFlagsKHR(VkDisplayPlaneAlphaFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast(0))); + return ret; +} + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoCodecOperationFlagBitsKHR(VkVideoCodecOperationFlagBitsKHR input_value) +{ + switch (input_value) + { +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT: + return "VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT: + return "VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT: + return "VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT"; +#endif // VK_ENABLE_BETA_EXTENSIONS + case VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR: + return "VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR"; + default: + return "Unhandled VkVideoCodecOperationFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCodecOperationFlagsKHR(VkVideoCodecOperationFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCodecOperationFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCodecOperationFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoChromaSubsamplingFlagBitsKHR(VkVideoChromaSubsamplingFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR"; + case VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR: + return "VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR"; + default: + return "Unhandled VkVideoChromaSubsamplingFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoChromaSubsamplingFlagsKHR(VkVideoChromaSubsamplingFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoChromaSubsamplingFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoChromaSubsamplingFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoComponentBitDepthFlagBitsKHR(VkVideoComponentBitDepthFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR"; + case VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR: + return "VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR"; + default: + return "Unhandled VkVideoComponentBitDepthFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoComponentBitDepthFlagsKHR(VkVideoComponentBitDepthFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoComponentBitDepthFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoComponentBitDepthFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoCapabilityFlagBitsKHR(VkVideoCapabilityFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR: + return "VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR"; + case VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR: + return "VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR"; + default: + return "Unhandled VkVideoCapabilityFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCapabilityFlagsKHR(VkVideoCapabilityFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCapabilityFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCapabilityFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoSessionCreateFlagBitsKHR(VkVideoSessionCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_SESSION_CREATE_DEFAULT_KHR: + return "VK_VIDEO_SESSION_CREATE_DEFAULT_KHR"; + case VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR: + return "VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR"; + default: + return "Unhandled VkVideoSessionCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoSessionCreateFlagsKHR(VkVideoSessionCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoSessionCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoSessionCreateFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoCodingControlFlagBitsKHR(VkVideoCodingControlFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CODING_CONTROL_DEFAULT_KHR: + return "VK_VIDEO_CODING_CONTROL_DEFAULT_KHR"; + case VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR: + return "VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR"; + default: + return "Unhandled VkVideoCodingControlFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCodingControlFlagsKHR(VkVideoCodingControlFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCodingControlFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCodingControlFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoCodingQualityPresetFlagBitsKHR(VkVideoCodingQualityPresetFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_CODING_QUALITY_PRESET_DEFAULT_BIT_KHR: + return "VK_VIDEO_CODING_QUALITY_PRESET_DEFAULT_BIT_KHR"; + case VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR: + return "VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR"; + case VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR: + return "VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR"; + case VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR: + return "VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR"; + default: + return "Unhandled VkVideoCodingQualityPresetFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoCodingQualityPresetFlagsKHR(VkVideoCodingQualityPresetFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoCodingQualityPresetFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoCodingQualityPresetFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkQueryResultStatusKHR(VkQueryResultStatusKHR input_value) +{ + switch (input_value) + { + case VK_QUERY_RESULT_STATUS_COMPLETE_KHR: + return "VK_QUERY_RESULT_STATUS_COMPLETE_KHR"; + case VK_QUERY_RESULT_STATUS_ERROR_KHR: + return "VK_QUERY_RESULT_STATUS_ERROR_KHR"; + case VK_QUERY_RESULT_STATUS_NOT_READY_KHR: + return "VK_QUERY_RESULT_STATUS_NOT_READY_KHR"; + default: + return "Unhandled VkQueryResultStatusKHR"; + } +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoDecodeFlagBitsKHR(VkVideoDecodeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_DECODE_DEFAULT_KHR: + return "VK_VIDEO_DECODE_DEFAULT_KHR"; + case VK_VIDEO_DECODE_RESERVED_0_BIT_KHR: + return "VK_VIDEO_DECODE_RESERVED_0_BIT_KHR"; + default: + return "Unhandled VkVideoDecodeFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoDecodeFlagsKHR(VkVideoDecodeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoDecodeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoDecodeFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkPeerMemoryFeatureFlagBitsKHR(VkPeerMemoryFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT"; + case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT: + return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT"; + default: + return "Unhandled VkPeerMemoryFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkPeerMemoryFeatureFlagsKHR(VkPeerMemoryFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkMemoryAllocateFlagBitsKHR(VkMemoryAllocateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT"; + case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT: + return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT"; + default: + return "Unhandled VkMemoryAllocateFlagBitsKHR"; + } +} + +static inline std::string string_VkMemoryAllocateFlagsKHR(VkMemoryAllocateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBitsKHR(VkExternalMemoryHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlagsKHR(VkExternalMemoryHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBitsKHR(VkExternalMemoryFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlagsKHR(VkExternalMemoryFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreHandleTypeFlagBitsKHR(VkExternalSemaphoreHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA: + return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA"; + default: + return "Unhandled VkExternalSemaphoreHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalSemaphoreHandleTypeFlagsKHR(VkExternalSemaphoreHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalSemaphoreFeatureFlagBitsKHR(VkExternalSemaphoreFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalSemaphoreFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalSemaphoreFeatureFlagsKHR(VkExternalSemaphoreFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreImportFlagBitsKHR(VkSemaphoreImportFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT: + return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkSemaphoreImportFlagBitsKHR"; + } +} + +static inline std::string string_VkSemaphoreImportFlagsKHR(VkSemaphoreImportFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDescriptorUpdateTemplateTypeKHR(VkDescriptorUpdateTemplateTypeKHR input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET"; + case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR: + return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR"; + default: + return "Unhandled VkDescriptorUpdateTemplateTypeKHR"; + } +} + +static inline const char* string_VkExternalFenceHandleTypeFlagBitsKHR(VkExternalFenceHandleTypeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT"; + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: + return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT"; + default: + return "Unhandled VkExternalFenceHandleTypeFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalFenceHandleTypeFlagsKHR(VkExternalFenceHandleTypeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalFenceFeatureFlagBitsKHR(VkExternalFenceFeatureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT"; + case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT: + return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT"; + default: + return "Unhandled VkExternalFenceFeatureFlagBitsKHR"; + } +} + +static inline std::string string_VkExternalFenceFeatureFlagsKHR(VkExternalFenceFeatureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkFenceImportFlagBitsKHR(VkFenceImportFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_FENCE_IMPORT_TEMPORARY_BIT: + return "VK_FENCE_IMPORT_TEMPORARY_BIT"; + default: + return "Unhandled VkFenceImportFlagBitsKHR"; + } +} + +static inline std::string string_VkFenceImportFlagsKHR(VkFenceImportFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkFenceImportFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkFenceImportFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPerformanceCounterUnitKHR(VkPerformanceCounterUnitKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR"; + case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR: + return "VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR"; + default: + return "Unhandled VkPerformanceCounterUnitKHR"; + } +} + +static inline const char* string_VkPerformanceCounterScopeKHR(VkPerformanceCounterScopeKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR"; + case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR"; + case VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR: + return "VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR"; + default: + return "Unhandled VkPerformanceCounterScopeKHR"; + } +} + +static inline const char* string_VkPerformanceCounterStorageKHR(VkPerformanceCounterStorageKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR"; + case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR: + return "VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR"; + default: + return "Unhandled VkPerformanceCounterStorageKHR"; + } +} + +static inline const char* string_VkPerformanceCounterDescriptionFlagBitsKHR(VkPerformanceCounterDescriptionFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR: + return "VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR"; + case VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR: + return "VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR"; + default: + return "Unhandled VkPerformanceCounterDescriptionFlagBitsKHR"; + } +} + +static inline std::string string_VkPerformanceCounterDescriptionFlagsKHR(VkPerformanceCounterDescriptionFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkPointClippingBehaviorKHR(VkPointClippingBehaviorKHR input_value) +{ + switch (input_value) + { + case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES: + return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES"; + case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY: + return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY"; + default: + return "Unhandled VkPointClippingBehaviorKHR"; + } +} + +static inline const char* string_VkTessellationDomainOriginKHR(VkTessellationDomainOriginKHR input_value) +{ + switch (input_value) + { + case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT"; + case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT: + return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT"; + default: + return "Unhandled VkTessellationDomainOriginKHR"; + } +} + +static inline const char* string_VkSamplerYcbcrModelConversionKHR(VkSamplerYcbcrModelConversionKHR input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709"; + case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY: + return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY"; + default: + return "Unhandled VkSamplerYcbcrModelConversionKHR"; + } +} + +static inline const char* string_VkSamplerYcbcrRangeKHR(VkSamplerYcbcrRangeKHR input_value) +{ + switch (input_value) + { + case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: + return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL"; + case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: + return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW"; + default: + return "Unhandled VkSamplerYcbcrRangeKHR"; + } +} + +static inline const char* string_VkChromaLocationKHR(VkChromaLocationKHR input_value) +{ + switch (input_value) + { + case VK_CHROMA_LOCATION_COSITED_EVEN: + return "VK_CHROMA_LOCATION_COSITED_EVEN"; + case VK_CHROMA_LOCATION_MIDPOINT: + return "VK_CHROMA_LOCATION_MIDPOINT"; + default: + return "Unhandled VkChromaLocationKHR"; + } +} + +static inline const char* string_VkDriverIdKHR(VkDriverIdKHR input_value) +{ + switch (input_value) + { + case VK_DRIVER_ID_AMD_OPEN_SOURCE: + return "VK_DRIVER_ID_AMD_OPEN_SOURCE"; + case VK_DRIVER_ID_AMD_PROPRIETARY: + return "VK_DRIVER_ID_AMD_PROPRIETARY"; + case VK_DRIVER_ID_ARM_PROPRIETARY: + return "VK_DRIVER_ID_ARM_PROPRIETARY"; + case VK_DRIVER_ID_BROADCOM_PROPRIETARY: + return "VK_DRIVER_ID_BROADCOM_PROPRIETARY"; + case VK_DRIVER_ID_COREAVI_PROPRIETARY: + return "VK_DRIVER_ID_COREAVI_PROPRIETARY"; + case VK_DRIVER_ID_GGP_PROPRIETARY: + return "VK_DRIVER_ID_GGP_PROPRIETARY"; + case VK_DRIVER_ID_GOOGLE_SWIFTSHADER: + return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER"; + case VK_DRIVER_ID_IMAGINATION_PROPRIETARY: + return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY"; + case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA: + return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA"; + case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS: + return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS"; + case VK_DRIVER_ID_JUICE_PROPRIETARY: + return "VK_DRIVER_ID_JUICE_PROPRIETARY"; + case VK_DRIVER_ID_MESA_LLVMPIPE: + return "VK_DRIVER_ID_MESA_LLVMPIPE"; + case VK_DRIVER_ID_MESA_RADV: + return "VK_DRIVER_ID_MESA_RADV"; + case VK_DRIVER_ID_MOLTENVK: + return "VK_DRIVER_ID_MOLTENVK"; + case VK_DRIVER_ID_NVIDIA_PROPRIETARY: + return "VK_DRIVER_ID_NVIDIA_PROPRIETARY"; + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY"; + case VK_DRIVER_ID_VERISILICON_PROPRIETARY: + return "VK_DRIVER_ID_VERISILICON_PROPRIETARY"; + default: + return "Unhandled VkDriverIdKHR"; + } +} + +static inline const char* string_VkShaderFloatControlsIndependenceKHR(VkShaderFloatControlsIndependenceKHR input_value) +{ + switch (input_value) + { + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL"; + case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE: + return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE"; + default: + return "Unhandled VkShaderFloatControlsIndependenceKHR"; + } +} + +static inline const char* string_VkResolveModeFlagBitsKHR(VkResolveModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_RESOLVE_MODE_AVERAGE_BIT: + return "VK_RESOLVE_MODE_AVERAGE_BIT"; + case VK_RESOLVE_MODE_MAX_BIT: + return "VK_RESOLVE_MODE_MAX_BIT"; + case VK_RESOLVE_MODE_MIN_BIT: + return "VK_RESOLVE_MODE_MIN_BIT"; + case VK_RESOLVE_MODE_NONE: + return "VK_RESOLVE_MODE_NONE"; + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: + return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT"; + default: + return "Unhandled VkResolveModeFlagBitsKHR"; + } +} + +static inline std::string string_VkResolveModeFlagsKHR(VkResolveModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkResolveModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkResolveModeFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSemaphoreTypeKHR(VkSemaphoreTypeKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_TYPE_BINARY: + return "VK_SEMAPHORE_TYPE_BINARY"; + case VK_SEMAPHORE_TYPE_TIMELINE: + return "VK_SEMAPHORE_TYPE_TIMELINE"; + default: + return "Unhandled VkSemaphoreTypeKHR"; + } +} + +static inline const char* string_VkSemaphoreWaitFlagBitsKHR(VkSemaphoreWaitFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SEMAPHORE_WAIT_ANY_BIT: + return "VK_SEMAPHORE_WAIT_ANY_BIT"; + default: + return "Unhandled VkSemaphoreWaitFlagBitsKHR"; + } +} + +static inline std::string string_VkSemaphoreWaitFlagsKHR(VkSemaphoreWaitFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkFragmentShadingRateCombinerOpKHR(VkFragmentShadingRateCombinerOpKHR input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR"; + case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR: + return "VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR"; + default: + return "Unhandled VkFragmentShadingRateCombinerOpKHR"; + } +} + +static inline const char* string_VkPipelineExecutableStatisticFormatKHR(VkPipelineExecutableStatisticFormatKHR input_value) +{ + switch (input_value) + { + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR"; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: + return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR"; + default: + return "Unhandled VkPipelineExecutableStatisticFormatKHR"; + } +} + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeFlagBitsKHR(VkVideoEncodeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_DEFAULT_KHR: + return "VK_VIDEO_ENCODE_DEFAULT_KHR"; + case VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR: + return "VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeFlagsKHR(VkVideoEncodeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeRateControlFlagBitsKHR(VkVideoEncodeRateControlFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR"; + case VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeRateControlFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeRateControlFlagsKHR(VkVideoEncodeRateControlFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeRateControlFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeRateControlFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeRateControlModeFlagBitsKHR(VkVideoEncodeRateControlModeFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR"; + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR"; + case VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR: + return "VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR"; + default: + return "Unhandled VkVideoEncodeRateControlModeFlagBitsKHR"; + } +} + +static inline std::string string_VkVideoEncodeRateControlModeFlagsKHR(VkVideoEncodeRateControlModeFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeRateControlModeFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeRateControlModeFlagBitsKHR(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkPipelineStageFlagBits2KHR(uint64_t input_value) +{ + switch (input_value) + { + case VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR"; + case VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_BLIT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_BLIT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR"; + case VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR: + return "VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR"; + case VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV: + return "VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"; + case VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT: + return "VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT"; + case VK_PIPELINE_STAGE_2_COPY_BIT_KHR: + return "VK_PIPELINE_STAGE_2_COPY_BIT_KHR"; + case VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR: + return "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR"; + case VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT: + return "VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_HOST_BIT_KHR: + return "VK_PIPELINE_STAGE_2_HOST_BIT_KHR"; + case VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR: + return "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR"; + case VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV: + return "VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV"; + case VK_PIPELINE_STAGE_2_NONE_KHR: + return "VK_PIPELINE_STAGE_2_NONE_KHR"; + case VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR: + return "VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR"; + case VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR"; + case VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI: + return "VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI"; + case VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV: + return "VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV"; + case VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR"; + case VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR"; + case VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT: + return "VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"; + case VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR"; + case VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR: + return "VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkPipelineStageFlagBits2KHR"; + } +} + +static inline std::string string_VkPipelineStageFlags2KHR(VkPipelineStageFlags2KHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineStageFlagBits2KHR(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineStageFlagBits2KHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkAccessFlagBits2KHR(uint64_t input_value) +{ + switch (input_value) + { + case VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"; + case VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: + return "VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: + return "VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"; + case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR: + return "VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR"; + case VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"; + case VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV: + return "VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"; + case VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT: + return "VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR: + return "VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR"; + case VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT: + return "VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"; + case VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_HOST_READ_BIT_KHR: + return "VK_ACCESS_2_HOST_READ_BIT_KHR"; + case VK_ACCESS_2_HOST_WRITE_BIT_KHR: + return "VK_ACCESS_2_HOST_WRITE_BIT_KHR"; + case VK_ACCESS_2_INDEX_READ_BIT_KHR: + return "VK_ACCESS_2_INDEX_READ_BIT_KHR"; + case VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR: + return "VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR"; + case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR: + return "VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR"; + case VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI: + return "VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"; + case VK_ACCESS_2_MEMORY_READ_BIT_KHR: + return "VK_ACCESS_2_MEMORY_READ_BIT_KHR"; + case VK_ACCESS_2_MEMORY_WRITE_BIT_KHR: + return "VK_ACCESS_2_MEMORY_WRITE_BIT_KHR"; + case VK_ACCESS_2_NONE_KHR: + return "VK_ACCESS_2_NONE_KHR"; + case VK_ACCESS_2_SHADER_READ_BIT_KHR: + return "VK_ACCESS_2_SHADER_READ_BIT_KHR"; + case VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR: + return "VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR"; + case VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR: + return "VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR"; + case VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR: + return "VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR"; + case VK_ACCESS_2_SHADER_WRITE_BIT_KHR: + return "VK_ACCESS_2_SHADER_WRITE_BIT_KHR"; + case VK_ACCESS_2_TRANSFER_READ_BIT_KHR: + return "VK_ACCESS_2_TRANSFER_READ_BIT_KHR"; + case VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR: + return "VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"; + case VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT: + return "VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"; + case VK_ACCESS_2_UNIFORM_READ_BIT_KHR: + return "VK_ACCESS_2_UNIFORM_READ_BIT_KHR"; + case VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR: + return "VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR"; +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS +#ifdef VK_ENABLE_BETA_EXTENSIONS + case VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR: + return "VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR"; +#endif // VK_ENABLE_BETA_EXTENSIONS + default: + return "Unhandled VkAccessFlagBits2KHR"; + } +} + +static inline std::string string_VkAccessFlags2KHR(VkAccessFlags2KHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccessFlagBits2KHR(static_cast(1ULL << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccessFlagBits2KHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkSubmitFlagBitsKHR(VkSubmitFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_SUBMIT_PROTECTED_BIT_KHR: + return "VK_SUBMIT_PROTECTED_BIT_KHR"; + default: + return "Unhandled VkSubmitFlagBitsKHR"; + } +} + +static inline std::string string_VkSubmitFlagsKHR(VkSubmitFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSubmitFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSubmitFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugReportFlagBitsEXT(VkDebugReportFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_REPORT_DEBUG_BIT_EXT: + return "VK_DEBUG_REPORT_DEBUG_BIT_EXT"; + case VK_DEBUG_REPORT_ERROR_BIT_EXT: + return "VK_DEBUG_REPORT_ERROR_BIT_EXT"; + case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: + return "VK_DEBUG_REPORT_INFORMATION_BIT_EXT"; + case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT: + return "VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT"; + case VK_DEBUG_REPORT_WARNING_BIT_EXT: + return "VK_DEBUG_REPORT_WARNING_BIT_EXT"; + default: + return "Unhandled VkDebugReportFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugReportFlagsEXT(VkDebugReportFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugReportFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugReportFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugReportObjectTypeEXT(VkDebugReportObjectTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT"; + case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT: + return "VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT"; + default: + return "Unhandled VkDebugReportObjectTypeEXT"; + } +} + +static inline const char* string_VkRasterizationOrderAMD(VkRasterizationOrderAMD input_value) +{ + switch (input_value) + { + case VK_RASTERIZATION_ORDER_RELAXED_AMD: + return "VK_RASTERIZATION_ORDER_RELAXED_AMD"; + case VK_RASTERIZATION_ORDER_STRICT_AMD: + return "VK_RASTERIZATION_ORDER_STRICT_AMD"; + default: + return "Unhandled VkRasterizationOrderAMD"; + } +} + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264CapabilityFlagBitsEXT(VkVideoEncodeH264CapabilityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264CapabilityFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264CapabilityFlagsEXT(VkVideoEncodeH264CapabilityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264CapabilityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264CapabilityFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264InputModeFlagBitsEXT(VkVideoEncodeH264InputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264InputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264InputModeFlagsEXT(VkVideoEncodeH264InputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264InputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264InputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264OutputModeFlagBitsEXT(VkVideoEncodeH264OutputModeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT"; + case VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264OutputModeFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264OutputModeFlagsEXT(VkVideoEncodeH264OutputModeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264OutputModeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264OutputModeFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoEncodeH264CreateFlagBitsEXT(VkVideoEncodeH264CreateFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT: + return "VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT"; + case VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT: + return "VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT"; + default: + return "Unhandled VkVideoEncodeH264CreateFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoEncodeH264CreateFlagsEXT(VkVideoEncodeH264CreateFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoEncodeH264CreateFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoEncodeH264CreateFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + + +#ifdef VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkVideoDecodeH264PictureLayoutFlagBitsEXT(VkVideoDecodeH264PictureLayoutFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT"; + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT"; + case VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT: + return "VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT"; + default: + return "Unhandled VkVideoDecodeH264PictureLayoutFlagBitsEXT"; + } +} + +static inline std::string string_VkVideoDecodeH264PictureLayoutFlagsEXT(VkVideoDecodeH264PictureLayoutFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkVideoDecodeH264PictureLayoutFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkVideoDecodeH264PictureLayoutFlagBitsEXT(static_cast(0))); + return ret; +} +#endif // VK_ENABLE_BETA_EXTENSIONS + +static inline const char* string_VkShaderInfoTypeAMD(VkShaderInfoTypeAMD input_value) +{ + switch (input_value) + { + case VK_SHADER_INFO_TYPE_BINARY_AMD: + return "VK_SHADER_INFO_TYPE_BINARY_AMD"; + case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: + return "VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD"; + case VK_SHADER_INFO_TYPE_STATISTICS_AMD: + return "VK_SHADER_INFO_TYPE_STATISTICS_AMD"; + default: + return "Unhandled VkShaderInfoTypeAMD"; + } +} + +static inline const char* string_VkExternalMemoryHandleTypeFlagBitsNV(VkExternalMemoryHandleTypeFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV"; + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV: + return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV"; + default: + return "Unhandled VkExternalMemoryHandleTypeFlagBitsNV"; + } +} + +static inline std::string string_VkExternalMemoryHandleTypeFlagsNV(VkExternalMemoryHandleTypeFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkExternalMemoryFeatureFlagBitsNV(VkExternalMemoryFeatureFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV"; + case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV"; + case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV: + return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV"; + default: + return "Unhandled VkExternalMemoryFeatureFlagBitsNV"; + } +} + +static inline std::string string_VkExternalMemoryFeatureFlagsNV(VkExternalMemoryFeatureFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkValidationCheckEXT(VkValidationCheckEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_CHECK_ALL_EXT: + return "VK_VALIDATION_CHECK_ALL_EXT"; + case VK_VALIDATION_CHECK_SHADERS_EXT: + return "VK_VALIDATION_CHECK_SHADERS_EXT"; + default: + return "Unhandled VkValidationCheckEXT"; + } +} + +static inline const char* string_VkConditionalRenderingFlagBitsEXT(VkConditionalRenderingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT: + return "VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT"; + default: + return "Unhandled VkConditionalRenderingFlagBitsEXT"; + } +} + +static inline std::string string_VkConditionalRenderingFlagsEXT(VkConditionalRenderingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkSurfaceCounterFlagBitsEXT(VkSurfaceCounterFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_SURFACE_COUNTER_VBLANK_BIT_EXT: + return "VK_SURFACE_COUNTER_VBLANK_BIT_EXT"; + default: + return "Unhandled VkSurfaceCounterFlagBitsEXT"; + } +} + +static inline std::string string_VkSurfaceCounterFlagsEXT(VkSurfaceCounterFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDisplayPowerStateEXT(VkDisplayPowerStateEXT input_value) +{ + switch (input_value) + { + case VK_DISPLAY_POWER_STATE_OFF_EXT: + return "VK_DISPLAY_POWER_STATE_OFF_EXT"; + case VK_DISPLAY_POWER_STATE_ON_EXT: + return "VK_DISPLAY_POWER_STATE_ON_EXT"; + case VK_DISPLAY_POWER_STATE_SUSPEND_EXT: + return "VK_DISPLAY_POWER_STATE_SUSPEND_EXT"; + default: + return "Unhandled VkDisplayPowerStateEXT"; + } +} + +static inline const char* string_VkDeviceEventTypeEXT(VkDeviceEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT: + return "VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT"; + default: + return "Unhandled VkDeviceEventTypeEXT"; + } +} + +static inline const char* string_VkDisplayEventTypeEXT(VkDisplayEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT: + return "VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT"; + default: + return "Unhandled VkDisplayEventTypeEXT"; + } +} + +static inline const char* string_VkViewportCoordinateSwizzleNV(VkViewportCoordinateSwizzleNV input_value) +{ + switch (input_value) + { + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV"; + case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV: + return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV"; + default: + return "Unhandled VkViewportCoordinateSwizzleNV"; + } +} + +static inline const char* string_VkDiscardRectangleModeEXT(VkDiscardRectangleModeEXT input_value) +{ + switch (input_value) + { + case VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT: + return "VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT"; + case VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT: + return "VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT"; + default: + return "Unhandled VkDiscardRectangleModeEXT"; + } +} + +static inline const char* string_VkConservativeRasterizationModeEXT(VkConservativeRasterizationModeEXT input_value) +{ + switch (input_value) + { + case VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT"; + case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT"; + case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT: + return "VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT"; + default: + return "Unhandled VkConservativeRasterizationModeEXT"; + } +} + +static inline const char* string_VkDebugUtilsMessageSeverityFlagBitsEXT(VkDebugUtilsMessageSeverityFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT"; + default: + return "Unhandled VkDebugUtilsMessageSeverityFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugUtilsMessageSeverityFlagsEXT(VkDebugUtilsMessageSeverityFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkDebugUtilsMessageTypeFlagBitsEXT(VkDebugUtilsMessageTypeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT"; + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + return "VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT"; + default: + return "Unhandled VkDebugUtilsMessageTypeFlagBitsEXT"; + } +} + +static inline std::string string_VkDebugUtilsMessageTypeFlagsEXT(VkDebugUtilsMessageTypeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkSamplerReductionModeEXT(VkSamplerReductionModeEXT input_value) +{ + switch (input_value) + { + case VK_SAMPLER_REDUCTION_MODE_MAX: + return "VK_SAMPLER_REDUCTION_MODE_MAX"; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return "VK_SAMPLER_REDUCTION_MODE_MIN"; + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE"; + default: + return "Unhandled VkSamplerReductionModeEXT"; + } +} + +static inline const char* string_VkBlendOverlapEXT(VkBlendOverlapEXT input_value) +{ + switch (input_value) + { + case VK_BLEND_OVERLAP_CONJOINT_EXT: + return "VK_BLEND_OVERLAP_CONJOINT_EXT"; + case VK_BLEND_OVERLAP_DISJOINT_EXT: + return "VK_BLEND_OVERLAP_DISJOINT_EXT"; + case VK_BLEND_OVERLAP_UNCORRELATED_EXT: + return "VK_BLEND_OVERLAP_UNCORRELATED_EXT"; + default: + return "Unhandled VkBlendOverlapEXT"; + } +} + +static inline const char* string_VkCoverageModulationModeNV(VkCoverageModulationModeNV input_value) +{ + switch (input_value) + { + case VK_COVERAGE_MODULATION_MODE_ALPHA_NV: + return "VK_COVERAGE_MODULATION_MODE_ALPHA_NV"; + case VK_COVERAGE_MODULATION_MODE_NONE_NV: + return "VK_COVERAGE_MODULATION_MODE_NONE_NV"; + case VK_COVERAGE_MODULATION_MODE_RGBA_NV: + return "VK_COVERAGE_MODULATION_MODE_RGBA_NV"; + case VK_COVERAGE_MODULATION_MODE_RGB_NV: + return "VK_COVERAGE_MODULATION_MODE_RGB_NV"; + default: + return "Unhandled VkCoverageModulationModeNV"; + } +} + +static inline const char* string_VkValidationCacheHeaderVersionEXT(VkValidationCacheHeaderVersionEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT: + return "VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT"; + default: + return "Unhandled VkValidationCacheHeaderVersionEXT"; + } +} + +static inline const char* string_VkDescriptorBindingFlagBitsEXT(VkDescriptorBindingFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT: + return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT"; + case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT: + return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT"; + case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT: + return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT"; + default: + return "Unhandled VkDescriptorBindingFlagBitsEXT"; + } +} + +static inline std::string string_VkDescriptorBindingFlagsEXT(VkDescriptorBindingFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkShadingRatePaletteEntryNV(VkShadingRatePaletteEntryNV input_value) +{ + switch (input_value) + { + case VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV"; + case VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV: + return "VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV"; + default: + return "Unhandled VkShadingRatePaletteEntryNV"; + } +} + +static inline const char* string_VkCoarseSampleOrderTypeNV(VkCoarseSampleOrderTypeNV input_value) +{ + switch (input_value) + { + case VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV"; + case VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV: + return "VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV"; + default: + return "Unhandled VkCoarseSampleOrderTypeNV"; + } +} + +static inline const char* string_VkRayTracingShaderGroupTypeKHR(VkRayTracingShaderGroupTypeKHR input_value) +{ + switch (input_value) + { + case VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"; + default: + return "Unhandled VkRayTracingShaderGroupTypeKHR"; + } +} + +static inline const char* string_VkRayTracingShaderGroupTypeNV(VkRayTracingShaderGroupTypeNV input_value) +{ + switch (input_value) + { + case VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"; + case VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR: + return "VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"; + default: + return "Unhandled VkRayTracingShaderGroupTypeNV"; + } +} + +static inline const char* string_VkGeometryTypeKHR(VkGeometryTypeKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_TYPE_AABBS_KHR: + return "VK_GEOMETRY_TYPE_AABBS_KHR"; + case VK_GEOMETRY_TYPE_INSTANCES_KHR: + return "VK_GEOMETRY_TYPE_INSTANCES_KHR"; + case VK_GEOMETRY_TYPE_TRIANGLES_KHR: + return "VK_GEOMETRY_TYPE_TRIANGLES_KHR"; + default: + return "Unhandled VkGeometryTypeKHR"; + } +} + +static inline const char* string_VkGeometryTypeNV(VkGeometryTypeNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_TYPE_AABBS_KHR: + return "VK_GEOMETRY_TYPE_AABBS_KHR"; + case VK_GEOMETRY_TYPE_INSTANCES_KHR: + return "VK_GEOMETRY_TYPE_INSTANCES_KHR"; + case VK_GEOMETRY_TYPE_TRIANGLES_KHR: + return "VK_GEOMETRY_TYPE_TRIANGLES_KHR"; + default: + return "Unhandled VkGeometryTypeNV"; + } +} + +static inline const char* string_VkAccelerationStructureTypeKHR(VkAccelerationStructureTypeKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"; + default: + return "Unhandled VkAccelerationStructureTypeKHR"; + } +} + +static inline const char* string_VkAccelerationStructureTypeNV(VkAccelerationStructureTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR"; + case VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR: + return "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"; + default: + return "Unhandled VkAccelerationStructureTypeNV"; + } +} + +static inline const char* string_VkGeometryFlagBitsKHR(VkGeometryFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR: + return "VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"; + case VK_GEOMETRY_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_OPAQUE_BIT_KHR"; + default: + return "Unhandled VkGeometryFlagBitsKHR"; + } +} + +static inline std::string string_VkGeometryFlagsKHR(VkGeometryFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryFlagBitsNV(VkGeometryFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR: + return "VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"; + case VK_GEOMETRY_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_OPAQUE_BIT_KHR"; + default: + return "Unhandled VkGeometryFlagBitsNV"; + } +} + +static inline std::string string_VkGeometryFlagsNV(VkGeometryFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryInstanceFlagBitsKHR(VkGeometryInstanceFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"; + default: + return "Unhandled VkGeometryInstanceFlagBitsKHR"; + } +} + +static inline std::string string_VkGeometryInstanceFlagsKHR(VkGeometryInstanceFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryInstanceFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryInstanceFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkGeometryInstanceFlagBitsNV(VkGeometryInstanceFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"; + case VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR: + return "VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"; + default: + return "Unhandled VkGeometryInstanceFlagBitsNV"; + } +} + +static inline std::string string_VkGeometryInstanceFlagsNV(VkGeometryInstanceFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkBuildAccelerationStructureFlagBitsKHR(VkBuildAccelerationStructureFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV: + return "VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureFlagBitsKHR"; + } +} + +static inline std::string string_VkBuildAccelerationStructureFlagsKHR(VkBuildAccelerationStructureFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBuildAccelerationStructureFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBuildAccelerationStructureFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkBuildAccelerationStructureFlagBitsNV(VkBuildAccelerationStructureFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV: + return "VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureFlagBitsNV"; + } +} + +static inline std::string string_VkBuildAccelerationStructureFlagsNV(VkBuildAccelerationStructureFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkCopyAccelerationStructureModeKHR(VkCopyAccelerationStructureModeKHR input_value) +{ + switch (input_value) + { + case VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR"; + default: + return "Unhandled VkCopyAccelerationStructureModeKHR"; + } +} + +static inline const char* string_VkCopyAccelerationStructureModeNV(VkCopyAccelerationStructureModeNV input_value) +{ + switch (input_value) + { + case VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR"; + case VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR: + return "VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR"; + default: + return "Unhandled VkCopyAccelerationStructureModeNV"; + } +} + +static inline const char* string_VkAccelerationStructureMemoryRequirementsTypeNV(VkAccelerationStructureMemoryRequirementsTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV"; + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV"; + case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV: + return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV"; + default: + return "Unhandled VkAccelerationStructureMemoryRequirementsTypeNV"; + } +} + +static inline const char* string_VkQueueGlobalPriorityEXT(VkQueueGlobalPriorityEXT input_value) +{ + switch (input_value) + { + case VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT: + return "VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT"; + case VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT: + return "VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT"; + case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT: + return "VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT"; + case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT: + return "VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT"; + default: + return "Unhandled VkQueueGlobalPriorityEXT"; + } +} + +static inline const char* string_VkTimeDomainEXT(VkTimeDomainEXT input_value) +{ + switch (input_value) + { + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT: + return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT"; + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT: + return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT"; + case VK_TIME_DOMAIN_DEVICE_EXT: + return "VK_TIME_DOMAIN_DEVICE_EXT"; + case VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT: + return "VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT"; + default: + return "Unhandled VkTimeDomainEXT"; + } +} + +static inline const char* string_VkMemoryOverallocationBehaviorAMD(VkMemoryOverallocationBehaviorAMD input_value) +{ + switch (input_value) + { + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD"; + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD"; + case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD: + return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD"; + default: + return "Unhandled VkMemoryOverallocationBehaviorAMD"; + } +} + +static inline const char* string_VkPipelineCreationFeedbackFlagBitsEXT(VkPipelineCreationFeedbackFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT: + return "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT"; + case VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT: + return "VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT"; + case VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT: + return "VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT"; + default: + return "Unhandled VkPipelineCreationFeedbackFlagBitsEXT"; + } +} + +static inline std::string string_VkPipelineCreationFeedbackFlagsEXT(VkPipelineCreationFeedbackFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkPerformanceConfigurationTypeINTEL(VkPerformanceConfigurationTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL: + return "VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL"; + default: + return "Unhandled VkPerformanceConfigurationTypeINTEL"; + } +} + +static inline const char* string_VkQueryPoolSamplingModeINTEL(VkQueryPoolSamplingModeINTEL input_value) +{ + switch (input_value) + { + case VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL: + return "VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL"; + default: + return "Unhandled VkQueryPoolSamplingModeINTEL"; + } +} + +static inline const char* string_VkPerformanceOverrideTypeINTEL(VkPerformanceOverrideTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL: + return "VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL"; + case VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL: + return "VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL"; + default: + return "Unhandled VkPerformanceOverrideTypeINTEL"; + } +} + +static inline const char* string_VkPerformanceParameterTypeINTEL(VkPerformanceParameterTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL: + return "VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL"; + case VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL: + return "VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL"; + default: + return "Unhandled VkPerformanceParameterTypeINTEL"; + } +} + +static inline const char* string_VkPerformanceValueTypeINTEL(VkPerformanceValueTypeINTEL input_value) +{ + switch (input_value) + { + case VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL"; + case VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL: + return "VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL"; + default: + return "Unhandled VkPerformanceValueTypeINTEL"; + } +} + +static inline const char* string_VkToolPurposeFlagBitsEXT(VkToolPurposeFlagBitsEXT input_value) +{ + switch (input_value) + { + case VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT: + return "VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT"; + case VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"; + case VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT: + return "VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"; + case VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT: + return "VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT"; + case VK_TOOL_PURPOSE_PROFILING_BIT_EXT: + return "VK_TOOL_PURPOSE_PROFILING_BIT_EXT"; + case VK_TOOL_PURPOSE_TRACING_BIT_EXT: + return "VK_TOOL_PURPOSE_TRACING_BIT_EXT"; + case VK_TOOL_PURPOSE_VALIDATION_BIT_EXT: + return "VK_TOOL_PURPOSE_VALIDATION_BIT_EXT"; + default: + return "Unhandled VkToolPurposeFlagBitsEXT"; + } +} + +static inline std::string string_VkToolPurposeFlagsEXT(VkToolPurposeFlagsEXT input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkToolPurposeFlagBitsEXT(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkToolPurposeFlagBitsEXT(static_cast(0))); + return ret; +} + +static inline const char* string_VkValidationFeatureEnableEXT(VkValidationFeatureEnableEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT"; + case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT: + return "VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT"; + default: + return "Unhandled VkValidationFeatureEnableEXT"; + } +} + +static inline const char* string_VkValidationFeatureDisableEXT(VkValidationFeatureDisableEXT input_value) +{ + switch (input_value) + { + case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_ALL_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT"; + case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT: + return "VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT"; + default: + return "Unhandled VkValidationFeatureDisableEXT"; + } +} + +static inline const char* string_VkComponentTypeNV(VkComponentTypeNV input_value) +{ + switch (input_value) + { + case VK_COMPONENT_TYPE_FLOAT16_NV: + return "VK_COMPONENT_TYPE_FLOAT16_NV"; + case VK_COMPONENT_TYPE_FLOAT32_NV: + return "VK_COMPONENT_TYPE_FLOAT32_NV"; + case VK_COMPONENT_TYPE_FLOAT64_NV: + return "VK_COMPONENT_TYPE_FLOAT64_NV"; + case VK_COMPONENT_TYPE_SINT16_NV: + return "VK_COMPONENT_TYPE_SINT16_NV"; + case VK_COMPONENT_TYPE_SINT32_NV: + return "VK_COMPONENT_TYPE_SINT32_NV"; + case VK_COMPONENT_TYPE_SINT64_NV: + return "VK_COMPONENT_TYPE_SINT64_NV"; + case VK_COMPONENT_TYPE_SINT8_NV: + return "VK_COMPONENT_TYPE_SINT8_NV"; + case VK_COMPONENT_TYPE_UINT16_NV: + return "VK_COMPONENT_TYPE_UINT16_NV"; + case VK_COMPONENT_TYPE_UINT32_NV: + return "VK_COMPONENT_TYPE_UINT32_NV"; + case VK_COMPONENT_TYPE_UINT64_NV: + return "VK_COMPONENT_TYPE_UINT64_NV"; + case VK_COMPONENT_TYPE_UINT8_NV: + return "VK_COMPONENT_TYPE_UINT8_NV"; + default: + return "Unhandled VkComponentTypeNV"; + } +} + +static inline const char* string_VkScopeNV(VkScopeNV input_value) +{ + switch (input_value) + { + case VK_SCOPE_DEVICE_NV: + return "VK_SCOPE_DEVICE_NV"; + case VK_SCOPE_QUEUE_FAMILY_NV: + return "VK_SCOPE_QUEUE_FAMILY_NV"; + case VK_SCOPE_SUBGROUP_NV: + return "VK_SCOPE_SUBGROUP_NV"; + case VK_SCOPE_WORKGROUP_NV: + return "VK_SCOPE_WORKGROUP_NV"; + default: + return "Unhandled VkScopeNV"; + } +} + +static inline const char* string_VkCoverageReductionModeNV(VkCoverageReductionModeNV input_value) +{ + switch (input_value) + { + case VK_COVERAGE_REDUCTION_MODE_MERGE_NV: + return "VK_COVERAGE_REDUCTION_MODE_MERGE_NV"; + case VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV: + return "VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV"; + default: + return "Unhandled VkCoverageReductionModeNV"; + } +} + +static inline const char* string_VkProvokingVertexModeEXT(VkProvokingVertexModeEXT input_value) +{ + switch (input_value) + { + case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT: + return "VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT"; + case VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT: + return "VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT"; + default: + return "Unhandled VkProvokingVertexModeEXT"; + } +} + + +#ifdef VK_USE_PLATFORM_WIN32_KHR + +static inline const char* string_VkFullScreenExclusiveEXT(VkFullScreenExclusiveEXT input_value) +{ + switch (input_value) + { + case VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT"; + case VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT: + return "VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT"; + default: + return "Unhandled VkFullScreenExclusiveEXT"; + } +} +#endif // VK_USE_PLATFORM_WIN32_KHR + +static inline const char* string_VkLineRasterizationModeEXT(VkLineRasterizationModeEXT input_value) +{ + switch (input_value) + { + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + return "VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT"; + case VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT: + return "VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT"; + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT"; + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT"; + default: + return "Unhandled VkLineRasterizationModeEXT"; + } +} + +static inline const char* string_VkIndirectStateFlagBitsNV(VkIndirectStateFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV: + return "VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV"; + default: + return "Unhandled VkIndirectStateFlagBitsNV"; + } +} + +static inline std::string string_VkIndirectStateFlagsNV(VkIndirectStateFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkIndirectStateFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkIndirectStateFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkIndirectCommandsTokenTypeNV(VkIndirectCommandsTokenTypeNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV"; + case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV: + return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV"; + default: + return "Unhandled VkIndirectCommandsTokenTypeNV"; + } +} + +static inline const char* string_VkIndirectCommandsLayoutUsageFlagBitsNV(VkIndirectCommandsLayoutUsageFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV"; + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV"; + case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV: + return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV"; + default: + return "Unhandled VkIndirectCommandsLayoutUsageFlagBitsNV"; + } +} + +static inline std::string string_VkIndirectCommandsLayoutUsageFlagsNV(VkIndirectCommandsLayoutUsageFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkDeviceMemoryReportEventTypeEXT(VkDeviceMemoryReportEventTypeEXT input_value) +{ + switch (input_value) + { + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT"; + case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT: + return "VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT"; + default: + return "Unhandled VkDeviceMemoryReportEventTypeEXT"; + } +} + +static inline const char* string_VkDeviceDiagnosticsConfigFlagBitsNV(VkDeviceDiagnosticsConfigFlagBitsNV input_value) +{ + switch (input_value) + { + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV"; + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV"; + case VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV: + return "VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV"; + default: + return "Unhandled VkDeviceDiagnosticsConfigFlagBitsNV"; + } +} + +static inline std::string string_VkDeviceDiagnosticsConfigFlagsNV(VkDeviceDiagnosticsConfigFlagsNV input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkDeviceDiagnosticsConfigFlagBitsNV(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkDeviceDiagnosticsConfigFlagBitsNV(static_cast(0))); + return ret; +} + +static inline const char* string_VkFragmentShadingRateTypeNV(VkFragmentShadingRateTypeNV input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV: + return "VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV"; + case VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV: + return "VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV"; + default: + return "Unhandled VkFragmentShadingRateTypeNV"; + } +} + +static inline const char* string_VkFragmentShadingRateNV(VkFragmentShadingRateNV input_value) +{ + switch (input_value) + { + case VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV"; + case VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV: + return "VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV"; + case VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV: + return "VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV"; + default: + return "Unhandled VkFragmentShadingRateNV"; + } +} + +static inline const char* string_VkAccelerationStructureMotionInstanceTypeNV(VkAccelerationStructureMotionInstanceTypeNV input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV"; + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV"; + case VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV: + return "VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV"; + default: + return "Unhandled VkAccelerationStructureMotionInstanceTypeNV"; + } +} + +static inline const char* string_VkBuildAccelerationStructureModeKHR(VkBuildAccelerationStructureModeKHR input_value) +{ + switch (input_value) + { + case VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR"; + case VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR: + return "VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR"; + default: + return "Unhandled VkBuildAccelerationStructureModeKHR"; + } +} + +static inline const char* string_VkAccelerationStructureBuildTypeKHR(VkAccelerationStructureBuildTypeKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR"; + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR"; + case VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR: + return "VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR"; + default: + return "Unhandled VkAccelerationStructureBuildTypeKHR"; + } +} + +static inline const char* string_VkAccelerationStructureCreateFlagBitsKHR(VkAccelerationStructureCreateFlagBitsKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR: + return "VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR"; + case VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV: + return "VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV"; + default: + return "Unhandled VkAccelerationStructureCreateFlagBitsKHR"; + } +} + +static inline std::string string_VkAccelerationStructureCreateFlagsKHR(VkAccelerationStructureCreateFlagsKHR input_value) +{ + std::string ret; + int index = 0; + while(input_value) { + if (input_value & 1) { + if( !ret.empty()) ret.append("|"); + ret.append(string_VkAccelerationStructureCreateFlagBitsKHR(static_cast(1U << index))); + } + ++index; + input_value >>= 1; + } + if( ret.empty()) ret.append(string_VkAccelerationStructureCreateFlagBitsKHR(static_cast(0))); + return ret; +} + +static inline const char* string_VkAccelerationStructureCompatibilityKHR(VkAccelerationStructureCompatibilityKHR input_value) +{ + switch (input_value) + { + case VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR: + return "VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR"; + case VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR: + return "VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR"; + default: + return "Unhandled VkAccelerationStructureCompatibilityKHR"; + } +} + +static inline const char* string_VkShaderGroupShaderKHR(VkShaderGroupShaderKHR input_value) +{ + switch (input_value) + { + case VK_SHADER_GROUP_SHADER_ANY_HIT_KHR: + return "VK_SHADER_GROUP_SHADER_ANY_HIT_KHR"; + case VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR: + return "VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR"; + case VK_SHADER_GROUP_SHADER_GENERAL_KHR: + return "VK_SHADER_GROUP_SHADER_GENERAL_KHR"; + case VK_SHADER_GROUP_SHADER_INTERSECTION_KHR: + return "VK_SHADER_GROUP_SHADER_INTERSECTION_KHR"; + default: + return "Unhandled VkShaderGroupShaderKHR"; + } +} + +static inline const char * GetPhysDevFeatureString(uint32_t index) { + const char * IndexToPhysDevFeatureString[] = { + "robustBufferAccess", + "fullDrawIndexUint32", + "imageCubeArray", + "independentBlend", + "geometryShader", + "tessellationShader", + "sampleRateShading", + "dualSrcBlend", + "logicOp", + "multiDrawIndirect", + "drawIndirectFirstInstance", + "depthClamp", + "depthBiasClamp", + "fillModeNonSolid", + "depthBounds", + "wideLines", + "largePoints", + "alphaToOne", + "multiViewport", + "samplerAnisotropy", + "textureCompressionETC2", + "textureCompressionASTC_LDR", + "textureCompressionBC", + "occlusionQueryPrecise", + "pipelineStatisticsQuery", + "vertexPipelineStoresAndAtomics", + "fragmentStoresAndAtomics", + "shaderTessellationAndGeometryPointSize", + "shaderImageGatherExtended", + "shaderStorageImageExtendedFormats", + "shaderStorageImageMultisample", + "shaderStorageImageReadWithoutFormat", + "shaderStorageImageWriteWithoutFormat", + "shaderUniformBufferArrayDynamicIndexing", + "shaderSampledImageArrayDynamicIndexing", + "shaderStorageBufferArrayDynamicIndexing", + "shaderStorageImageArrayDynamicIndexing", + "shaderClipDistance", + "shaderCullDistance", + "shaderFloat64", + "shaderInt64", + "shaderInt16", + "shaderResourceResidency", + "shaderResourceMinLod", + "sparseBinding", + "sparseResidencyBuffer", + "sparseResidencyImage2D", + "sparseResidencyImage3D", + "sparseResidency2Samples", + "sparseResidency4Samples", + "sparseResidency8Samples", + "sparseResidency16Samples", + "sparseResidencyAliased", + "variableMultisampleRate", + "inheritedQueries", + }; + + return IndexToPhysDevFeatureString[index]; +} + +static inline bool IsDuplicatePnext(VkStructureType input_value) +{ + switch (input_value) + { + case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT: + case VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT: + case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT: + return true; + default: + return false; + } +} diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vk_icd.h b/libraries/ZVulkan/include/vulkan/vk_icd.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vk_icd.h rename to libraries/ZVulkan/include/vulkan/vk_icd.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vk_layer.h b/libraries/ZVulkan/include/vulkan/vk_layer.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vk_layer.h rename to libraries/ZVulkan/include/vulkan/vk_layer.h diff --git a/libraries/ZVulkan/include/vulkan/vk_layer_dispatch_table.h b/libraries/ZVulkan/include/vulkan/vk_layer_dispatch_table.h new file mode 100644 index 000000000..63d06b6c9 --- /dev/null +++ b/libraries/ZVulkan/include/vulkan/vk_layer_dispatch_table.h @@ -0,0 +1,525 @@ +// *** THIS FILE IS GENERATED - DO NOT EDIT *** +// See loader_extension_generator.py for modifications + +/* + * 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. + * + * Author: Mark Lobodzinski + * Author: Mark Young + */ + +#pragma once + +typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); + +// Instance function pointer dispatch table +typedef struct VkLayerInstanceDispatchTable_ { + // Manually add in GetPhysicalDeviceProcAddr entry + PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr; + + // ---- Core 1_0 commands + PFN_vkCreateInstance CreateInstance; + PFN_vkDestroyInstance DestroyInstance; + PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices; + PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures; + PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties; + PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties; + PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties; + PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties; + PFN_vkGetInstanceProcAddr GetInstanceProcAddr; + PFN_vkCreateDevice CreateDevice; + PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; + PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties; + PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties; + PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties; + + // ---- Core 1_1 commands + PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion; + PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups; + PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2; + PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2; + PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2; + PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2; + PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2; + PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties; + PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties; + PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties; + + // ---- VK_KHR_surface extension commands + PFN_vkDestroySurfaceKHR DestroySurfaceKHR; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR; + + // ---- VK_KHR_swapchain extension commands + PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR; + + // ---- VK_KHR_display extension commands + PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR; + PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR; + PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR; + PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR; + PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR; + PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR; + PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR; + + // ---- VK_KHR_xlib_surface extension commands +#ifdef VK_USE_PLATFORM_XLIB_KHR + PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR; +#endif // VK_USE_PLATFORM_XLIB_KHR +#ifdef VK_USE_PLATFORM_XLIB_KHR + PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR; +#endif // VK_USE_PLATFORM_XLIB_KHR + + // ---- VK_KHR_xcb_surface extension commands +#ifdef VK_USE_PLATFORM_XCB_KHR + PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR; +#endif // VK_USE_PLATFORM_XCB_KHR +#ifdef VK_USE_PLATFORM_XCB_KHR + PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR; +#endif // VK_USE_PLATFORM_XCB_KHR + + // ---- VK_KHR_wayland_surface extension commands +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR; +#endif // VK_USE_PLATFORM_WAYLAND_KHR +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR; +#endif // VK_USE_PLATFORM_WAYLAND_KHR + + // ---- VK_KHR_mir_surface extension commands +#ifdef VK_USE_PLATFORM_MIR_KHR + PFN_vkCreateMirSurfaceKHR CreateMirSurfaceKHR; +#endif // VK_USE_PLATFORM_MIR_KHR +#ifdef VK_USE_PLATFORM_MIR_KHR + PFN_vkGetPhysicalDeviceMirPresentationSupportKHR GetPhysicalDeviceMirPresentationSupportKHR; +#endif // VK_USE_PLATFORM_MIR_KHR + + // ---- VK_KHR_android_surface extension commands +#ifdef VK_USE_PLATFORM_ANDROID_KHR + PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR; +#endif // VK_USE_PLATFORM_ANDROID_KHR + + // ---- VK_KHR_win32_surface extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_get_physical_device_properties2 extension commands + PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR; + PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR; + PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR; + PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysicalDeviceImageFormatProperties2KHR; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysicalDeviceQueueFamilyProperties2KHR; + PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR; + PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysicalDeviceSparseImageFormatProperties2KHR; + + // ---- VK_KHR_device_group_creation extension commands + PFN_vkEnumeratePhysicalDeviceGroupsKHR EnumeratePhysicalDeviceGroupsKHR; + + // ---- VK_KHR_external_memory_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR; + + // ---- VK_KHR_external_semaphore_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR; + + // ---- VK_KHR_external_fence_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR; + + // ---- VK_KHR_get_surface_capabilities2 extension commands + PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR; + PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR; + + // ---- VK_KHR_get_display_properties2 extension commands + PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR; + PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR; + PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR; + PFN_vkGetDisplayPlaneCapabilities2KHR GetDisplayPlaneCapabilities2KHR; + + // ---- VK_EXT_debug_report extension commands + PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT; + PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT; + PFN_vkDebugReportMessageEXT DebugReportMessageEXT; + + // ---- VK_NV_external_memory_capabilities extension commands + PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV; + + // ---- VK_NN_vi_surface extension commands +#ifdef VK_USE_PLATFORM_VI_NN + PFN_vkCreateViSurfaceNN CreateViSurfaceNN; +#endif // VK_USE_PLATFORM_VI_NN + + // ---- VK_NVX_device_generated_commands extension commands + PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX GetPhysicalDeviceGeneratedCommandsPropertiesNVX; + + // ---- VK_EXT_direct_mode_display extension commands + PFN_vkReleaseDisplayEXT ReleaseDisplayEXT; + + // ---- VK_EXT_acquire_xlib_display extension commands +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT + PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT; +#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT +#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT + PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT; +#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT + + // ---- VK_EXT_display_surface_counter extension commands + PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT GetPhysicalDeviceSurfaceCapabilities2EXT; + + // ---- VK_MVK_ios_surface extension commands +#ifdef VK_USE_PLATFORM_IOS_MVK + PFN_vkCreateIOSSurfaceMVK CreateIOSSurfaceMVK; +#endif // VK_USE_PLATFORM_IOS_MVK + + // ---- VK_MVK_macos_surface extension commands +#ifdef VK_USE_PLATFORM_MACOS_MVK + PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK; +#endif // VK_USE_PLATFORM_MACOS_MVK + + // ---- VK_EXT_debug_utils extension commands + PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT; + PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT; + PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT; + + // ---- VK_EXT_sample_locations extension commands + PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT GetPhysicalDeviceMultisamplePropertiesEXT; +} VkLayerInstanceDispatchTable; + +// Device function pointer dispatch table +typedef struct VkLayerDispatchTable_ { + + // ---- Core 1_0 commands + PFN_vkGetDeviceProcAddr GetDeviceProcAddr; + PFN_vkDestroyDevice DestroyDevice; + PFN_vkGetDeviceQueue GetDeviceQueue; + PFN_vkQueueSubmit QueueSubmit; + PFN_vkQueueWaitIdle QueueWaitIdle; + PFN_vkDeviceWaitIdle DeviceWaitIdle; + PFN_vkAllocateMemory AllocateMemory; + PFN_vkFreeMemory FreeMemory; + PFN_vkMapMemory MapMemory; + PFN_vkUnmapMemory UnmapMemory; + PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges; + PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges; + PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment; + PFN_vkBindBufferMemory BindBufferMemory; + PFN_vkBindImageMemory BindImageMemory; + PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements; + PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements; + PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements; + PFN_vkQueueBindSparse QueueBindSparse; + PFN_vkCreateFence CreateFence; + PFN_vkDestroyFence DestroyFence; + PFN_vkResetFences ResetFences; + PFN_vkGetFenceStatus GetFenceStatus; + PFN_vkWaitForFences WaitForFences; + PFN_vkCreateSemaphore CreateSemaphore; + PFN_vkDestroySemaphore DestroySemaphore; + PFN_vkCreateEvent CreateEvent; + PFN_vkDestroyEvent DestroyEvent; + PFN_vkGetEventStatus GetEventStatus; + PFN_vkSetEvent SetEvent; + PFN_vkResetEvent ResetEvent; + PFN_vkCreateQueryPool CreateQueryPool; + PFN_vkDestroyQueryPool DestroyQueryPool; + PFN_vkGetQueryPoolResults GetQueryPoolResults; + PFN_vkCreateBuffer CreateBuffer; + PFN_vkDestroyBuffer DestroyBuffer; + PFN_vkCreateBufferView CreateBufferView; + PFN_vkDestroyBufferView DestroyBufferView; + PFN_vkCreateImage CreateImage; + PFN_vkDestroyImage DestroyImage; + PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout; + PFN_vkCreateImageView CreateImageView; + PFN_vkDestroyImageView DestroyImageView; + PFN_vkCreateShaderModule CreateShaderModule; + PFN_vkDestroyShaderModule DestroyShaderModule; + PFN_vkCreatePipelineCache CreatePipelineCache; + PFN_vkDestroyPipelineCache DestroyPipelineCache; + PFN_vkGetPipelineCacheData GetPipelineCacheData; + PFN_vkMergePipelineCaches MergePipelineCaches; + PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines; + PFN_vkCreateComputePipelines CreateComputePipelines; + PFN_vkDestroyPipeline DestroyPipeline; + PFN_vkCreatePipelineLayout CreatePipelineLayout; + PFN_vkDestroyPipelineLayout DestroyPipelineLayout; + PFN_vkCreateSampler CreateSampler; + PFN_vkDestroySampler DestroySampler; + PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout; + PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout; + PFN_vkCreateDescriptorPool CreateDescriptorPool; + PFN_vkDestroyDescriptorPool DestroyDescriptorPool; + PFN_vkResetDescriptorPool ResetDescriptorPool; + PFN_vkAllocateDescriptorSets AllocateDescriptorSets; + PFN_vkFreeDescriptorSets FreeDescriptorSets; + PFN_vkUpdateDescriptorSets UpdateDescriptorSets; + PFN_vkCreateFramebuffer CreateFramebuffer; + PFN_vkDestroyFramebuffer DestroyFramebuffer; + PFN_vkCreateRenderPass CreateRenderPass; + PFN_vkDestroyRenderPass DestroyRenderPass; + PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity; + PFN_vkCreateCommandPool CreateCommandPool; + PFN_vkDestroyCommandPool DestroyCommandPool; + PFN_vkResetCommandPool ResetCommandPool; + PFN_vkAllocateCommandBuffers AllocateCommandBuffers; + PFN_vkFreeCommandBuffers FreeCommandBuffers; + PFN_vkBeginCommandBuffer BeginCommandBuffer; + PFN_vkEndCommandBuffer EndCommandBuffer; + PFN_vkResetCommandBuffer ResetCommandBuffer; + PFN_vkCmdBindPipeline CmdBindPipeline; + PFN_vkCmdSetViewport CmdSetViewport; + PFN_vkCmdSetScissor CmdSetScissor; + PFN_vkCmdSetLineWidth CmdSetLineWidth; + PFN_vkCmdSetDepthBias CmdSetDepthBias; + PFN_vkCmdSetBlendConstants CmdSetBlendConstants; + PFN_vkCmdSetDepthBounds CmdSetDepthBounds; + PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask; + PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask; + PFN_vkCmdSetStencilReference CmdSetStencilReference; + PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets; + PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer; + PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers; + PFN_vkCmdDraw CmdDraw; + PFN_vkCmdDrawIndexed CmdDrawIndexed; + PFN_vkCmdDrawIndirect CmdDrawIndirect; + PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect; + PFN_vkCmdDispatch CmdDispatch; + PFN_vkCmdDispatchIndirect CmdDispatchIndirect; + PFN_vkCmdCopyBuffer CmdCopyBuffer; + PFN_vkCmdCopyImage CmdCopyImage; + PFN_vkCmdBlitImage CmdBlitImage; + PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage; + PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer; + PFN_vkCmdUpdateBuffer CmdUpdateBuffer; + PFN_vkCmdFillBuffer CmdFillBuffer; + PFN_vkCmdClearColorImage CmdClearColorImage; + PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage; + PFN_vkCmdClearAttachments CmdClearAttachments; + PFN_vkCmdResolveImage CmdResolveImage; + PFN_vkCmdSetEvent CmdSetEvent; + PFN_vkCmdResetEvent CmdResetEvent; + PFN_vkCmdWaitEvents CmdWaitEvents; + PFN_vkCmdPipelineBarrier CmdPipelineBarrier; + PFN_vkCmdBeginQuery CmdBeginQuery; + PFN_vkCmdEndQuery CmdEndQuery; + PFN_vkCmdResetQueryPool CmdResetQueryPool; + PFN_vkCmdWriteTimestamp CmdWriteTimestamp; + PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults; + PFN_vkCmdPushConstants CmdPushConstants; + PFN_vkCmdBeginRenderPass CmdBeginRenderPass; + PFN_vkCmdNextSubpass CmdNextSubpass; + PFN_vkCmdEndRenderPass CmdEndRenderPass; + PFN_vkCmdExecuteCommands CmdExecuteCommands; + + // ---- Core 1_1 commands + PFN_vkBindBufferMemory2 BindBufferMemory2; + PFN_vkBindImageMemory2 BindImageMemory2; + PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures; + PFN_vkCmdSetDeviceMask CmdSetDeviceMask; + PFN_vkCmdDispatchBase CmdDispatchBase; + PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2; + PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2; + PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2; + PFN_vkTrimCommandPool TrimCommandPool; + PFN_vkGetDeviceQueue2 GetDeviceQueue2; + PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion; + PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion; + PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate; + PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate; + PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate; + PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport; + + // ---- VK_KHR_swapchain extension commands + PFN_vkCreateSwapchainKHR CreateSwapchainKHR; + PFN_vkDestroySwapchainKHR DestroySwapchainKHR; + PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR; + PFN_vkAcquireNextImageKHR AcquireNextImageKHR; + PFN_vkQueuePresentKHR QueuePresentKHR; + PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR; + PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR; + PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR; + + // ---- VK_KHR_display_swapchain extension commands + PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR; + + // ---- VK_KHR_device_group extension commands + PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR GetDeviceGroupPeerMemoryFeaturesKHR; + PFN_vkCmdSetDeviceMaskKHR CmdSetDeviceMaskKHR; + PFN_vkCmdDispatchBaseKHR CmdDispatchBaseKHR; + + // ---- VK_KHR_maintenance1 extension commands + PFN_vkTrimCommandPoolKHR TrimCommandPoolKHR; + + // ---- VK_KHR_external_memory_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetMemoryWin32HandleKHR GetMemoryWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetMemoryWin32HandlePropertiesKHR GetMemoryWin32HandlePropertiesKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_memory_fd extension commands + PFN_vkGetMemoryFdKHR GetMemoryFdKHR; + PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR; + + // ---- VK_KHR_external_semaphore_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkImportSemaphoreWin32HandleKHR ImportSemaphoreWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetSemaphoreWin32HandleKHR GetSemaphoreWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_semaphore_fd extension commands + PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR; + PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR; + + // ---- VK_KHR_push_descriptor extension commands + PFN_vkCmdPushDescriptorSetKHR CmdPushDescriptorSetKHR; + PFN_vkCmdPushDescriptorSetWithTemplateKHR CmdPushDescriptorSetWithTemplateKHR; + + // ---- VK_KHR_descriptor_update_template extension commands + PFN_vkCreateDescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplateKHR; + PFN_vkDestroyDescriptorUpdateTemplateKHR DestroyDescriptorUpdateTemplateKHR; + PFN_vkUpdateDescriptorSetWithTemplateKHR UpdateDescriptorSetWithTemplateKHR; + + // ---- VK_KHR_shared_presentable_image extension commands + PFN_vkGetSwapchainStatusKHR GetSwapchainStatusKHR; + + // ---- VK_KHR_external_fence_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkImportFenceWin32HandleKHR ImportFenceWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetFenceWin32HandleKHR GetFenceWin32HandleKHR; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_KHR_external_fence_fd extension commands + PFN_vkImportFenceFdKHR ImportFenceFdKHR; + PFN_vkGetFenceFdKHR GetFenceFdKHR; + + // ---- VK_KHR_get_memory_requirements2 extension commands + PFN_vkGetImageMemoryRequirements2KHR GetImageMemoryRequirements2KHR; + PFN_vkGetBufferMemoryRequirements2KHR GetBufferMemoryRequirements2KHR; + PFN_vkGetImageSparseMemoryRequirements2KHR GetImageSparseMemoryRequirements2KHR; + + // ---- VK_KHR_sampler_ycbcr_conversion extension commands + PFN_vkCreateSamplerYcbcrConversionKHR CreateSamplerYcbcrConversionKHR; + PFN_vkDestroySamplerYcbcrConversionKHR DestroySamplerYcbcrConversionKHR; + + // ---- VK_KHR_bind_memory2 extension commands + PFN_vkBindBufferMemory2KHR BindBufferMemory2KHR; + PFN_vkBindImageMemory2KHR BindImageMemory2KHR; + + // ---- VK_KHR_maintenance3 extension commands + PFN_vkGetDescriptorSetLayoutSupportKHR GetDescriptorSetLayoutSupportKHR; + + // ---- VK_KHR_draw_indirect_count extension commands + PFN_vkCmdDrawIndirectCountKHR CmdDrawIndirectCountKHR; + PFN_vkCmdDrawIndexedIndirectCountKHR CmdDrawIndexedIndirectCountKHR; + + // ---- VK_EXT_debug_marker extension commands + PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT; + PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT; + PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT; + PFN_vkCmdDebugMarkerEndEXT CmdDebugMarkerEndEXT; + PFN_vkCmdDebugMarkerInsertEXT CmdDebugMarkerInsertEXT; + + // ---- VK_AMD_draw_indirect_count extension commands + PFN_vkCmdDrawIndirectCountAMD CmdDrawIndirectCountAMD; + PFN_vkCmdDrawIndexedIndirectCountAMD CmdDrawIndexedIndirectCountAMD; + + // ---- VK_AMD_shader_info extension commands + PFN_vkGetShaderInfoAMD GetShaderInfoAMD; + + // ---- VK_NV_external_memory_win32 extension commands +#ifdef VK_USE_PLATFORM_WIN32_KHR + PFN_vkGetMemoryWin32HandleNV GetMemoryWin32HandleNV; +#endif // VK_USE_PLATFORM_WIN32_KHR + + // ---- VK_NVX_device_generated_commands extension commands + PFN_vkCmdProcessCommandsNVX CmdProcessCommandsNVX; + PFN_vkCmdReserveSpaceForCommandsNVX CmdReserveSpaceForCommandsNVX; + PFN_vkCreateIndirectCommandsLayoutNVX CreateIndirectCommandsLayoutNVX; + PFN_vkDestroyIndirectCommandsLayoutNVX DestroyIndirectCommandsLayoutNVX; + PFN_vkCreateObjectTableNVX CreateObjectTableNVX; + PFN_vkDestroyObjectTableNVX DestroyObjectTableNVX; + PFN_vkRegisterObjectsNVX RegisterObjectsNVX; + PFN_vkUnregisterObjectsNVX UnregisterObjectsNVX; + + // ---- VK_NV_clip_space_w_scaling extension commands + PFN_vkCmdSetViewportWScalingNV CmdSetViewportWScalingNV; + + // ---- VK_EXT_display_control extension commands + PFN_vkDisplayPowerControlEXT DisplayPowerControlEXT; + PFN_vkRegisterDeviceEventEXT RegisterDeviceEventEXT; + PFN_vkRegisterDisplayEventEXT RegisterDisplayEventEXT; + PFN_vkGetSwapchainCounterEXT GetSwapchainCounterEXT; + + // ---- VK_GOOGLE_display_timing extension commands + PFN_vkGetRefreshCycleDurationGOOGLE GetRefreshCycleDurationGOOGLE; + PFN_vkGetPastPresentationTimingGOOGLE GetPastPresentationTimingGOOGLE; + + // ---- VK_EXT_discard_rectangles extension commands + PFN_vkCmdSetDiscardRectangleEXT CmdSetDiscardRectangleEXT; + + // ---- VK_EXT_hdr_metadata extension commands + PFN_vkSetHdrMetadataEXT SetHdrMetadataEXT; + + // ---- VK_EXT_debug_utils extension commands + PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT; + PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT; + PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT; + PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT; + PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT; + PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT; + PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT; + PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT; + + // ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands +#ifdef VK_USE_PLATFORM_ANDROID_KHR + PFN_vkGetAndroidHardwareBufferPropertiesANDROID GetAndroidHardwareBufferPropertiesANDROID; +#endif // VK_USE_PLATFORM_ANDROID_KHR +#ifdef VK_USE_PLATFORM_ANDROID_KHR + PFN_vkGetMemoryAndroidHardwareBufferANDROID GetMemoryAndroidHardwareBufferANDROID; +#endif // VK_USE_PLATFORM_ANDROID_KHR + + // ---- VK_EXT_sample_locations extension commands + PFN_vkCmdSetSampleLocationsEXT CmdSetSampleLocationsEXT; + + // ---- VK_EXT_validation_cache extension commands + PFN_vkCreateValidationCacheEXT CreateValidationCacheEXT; + PFN_vkDestroyValidationCacheEXT DestroyValidationCacheEXT; + PFN_vkMergeValidationCachesEXT MergeValidationCachesEXT; + PFN_vkGetValidationCacheDataEXT GetValidationCacheDataEXT; + + // ---- VK_EXT_external_memory_host extension commands + PFN_vkGetMemoryHostPointerPropertiesEXT GetMemoryHostPointerPropertiesEXT; + + // ---- VK_AMD_buffer_marker extension commands + PFN_vkCmdWriteBufferMarkerAMD CmdWriteBufferMarkerAMD; +} VkLayerDispatchTable; + + diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vk_platform.h b/libraries/ZVulkan/include/vulkan/vk_platform.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vk_platform.h rename to libraries/ZVulkan/include/vulkan/vk_platform.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vk_sdk_platform.h b/libraries/ZVulkan/include/vulkan/vk_sdk_platform.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vk_sdk_platform.h rename to libraries/ZVulkan/include/vulkan/vk_sdk_platform.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan.h b/libraries/ZVulkan/include/vulkan/vulkan.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan.h rename to libraries/ZVulkan/include/vulkan/vulkan.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_android.h b/libraries/ZVulkan/include/vulkan/vulkan_android.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_android.h rename to libraries/ZVulkan/include/vulkan/vulkan_android.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_beta.h b/libraries/ZVulkan/include/vulkan/vulkan_beta.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_beta.h rename to libraries/ZVulkan/include/vulkan/vulkan_beta.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_core.h b/libraries/ZVulkan/include/vulkan/vulkan_core.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_core.h rename to libraries/ZVulkan/include/vulkan/vulkan_core.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_directfb.h b/libraries/ZVulkan/include/vulkan/vulkan_directfb.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_directfb.h rename to libraries/ZVulkan/include/vulkan/vulkan_directfb.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_fuchsia.h b/libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_fuchsia.h rename to libraries/ZVulkan/include/vulkan/vulkan_fuchsia.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_ggp.h b/libraries/ZVulkan/include/vulkan/vulkan_ggp.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_ggp.h rename to libraries/ZVulkan/include/vulkan/vulkan_ggp.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_ios.h b/libraries/ZVulkan/include/vulkan/vulkan_ios.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_ios.h rename to libraries/ZVulkan/include/vulkan/vulkan_ios.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_macos.h b/libraries/ZVulkan/include/vulkan/vulkan_macos.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_macos.h rename to libraries/ZVulkan/include/vulkan/vulkan_macos.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_metal.h b/libraries/ZVulkan/include/vulkan/vulkan_metal.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_metal.h rename to libraries/ZVulkan/include/vulkan/vulkan_metal.h diff --git a/libraries/ZVulkan/include/vulkan/vulkan_mir.h b/libraries/ZVulkan/include/vulkan/vulkan_mir.h new file mode 100644 index 000000000..7d24ed27a --- /dev/null +++ b/libraries/ZVulkan/include/vulkan/vulkan_mir.h @@ -0,0 +1,65 @@ +#ifndef VULKAN_MIR_H_ +#define VULKAN_MIR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2015-2018 The Khronos Group 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. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#define VK_KHR_mir_surface 1 +#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4 +#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface" + +typedef VkFlags VkMirSurfaceCreateFlagsKHR; + +typedef struct VkMirSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkMirSurfaceCreateFlagsKHR flags; + MirConnection* connection; + MirSurface* mirSurface; +} VkMirSurfaceCreateInfoKHR; + + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( + VkInstance instance, + const VkMirSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + MirConnection* connection); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_screen.h b/libraries/ZVulkan/include/vulkan/vulkan_screen.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_screen.h rename to libraries/ZVulkan/include/vulkan/vulkan_screen.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_vi.h b/libraries/ZVulkan/include/vulkan/vulkan_vi.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_vi.h rename to libraries/ZVulkan/include/vulkan/vulkan_vi.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_wayland.h b/libraries/ZVulkan/include/vulkan/vulkan_wayland.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_wayland.h rename to libraries/ZVulkan/include/vulkan/vulkan_wayland.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_win32.h b/libraries/ZVulkan/include/vulkan/vulkan_win32.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_win32.h rename to libraries/ZVulkan/include/vulkan/vulkan_win32.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xcb.h b/libraries/ZVulkan/include/vulkan/vulkan_xcb.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xcb.h rename to libraries/ZVulkan/include/vulkan/vulkan_xcb.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xlib.h b/libraries/ZVulkan/include/vulkan/vulkan_xlib.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xlib.h rename to libraries/ZVulkan/include/vulkan/vulkan_xlib.h diff --git a/src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xlib_xrandr.h b/libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vulkan/vulkan_xlib_xrandr.h rename to libraries/ZVulkan/include/vulkan/vulkan_xlib_xrandr.h diff --git a/src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.h b/libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.h rename to libraries/ZVulkan/include/zvulkan/vk_mem_alloc/vk_mem_alloc.h diff --git a/src/common/rendering/vulkan/thirdparty/volk/volk.h b/libraries/ZVulkan/include/zvulkan/volk/volk.h similarity index 61% rename from src/common/rendering/vulkan/thirdparty/volk/volk.h rename to libraries/ZVulkan/include/zvulkan/volk/volk.h index 143e8f331..2e292ca11 100644 --- a/src/common/rendering/vulkan/thirdparty/volk/volk.h +++ b/libraries/ZVulkan/include/zvulkan/volk/volk.h @@ -6,6 +6,7 @@ * * This library is distributed under the MIT License. See notice at the end of this file. */ +/* clang-format off */ #ifndef VOLK_H_ #define VOLK_H_ @@ -13,16 +14,49 @@ # error To use volk, you need to define VK_NO_PROTOTYPES before including vulkan.h #endif -/* VOLK_GENERATE_VERSION */ -#define VOLK_HEADER_VERSION 102 -/* VOLK_GENERATE_VERSION */ +/* VOLK_GENERATE_VERSION_DEFINE */ +#define VOLK_HEADER_VERSION 190 +/* VOLK_GENERATE_VERSION_DEFINE */ #ifndef VK_NO_PROTOTYPES # define VK_NO_PROTOTYPES #endif #ifndef VULKAN_H_ -# include +# ifdef VOLK_VULKAN_H_PATH +# include VOLK_VULKAN_H_PATH +# elif defined(VK_USE_PLATFORM_WIN32_KHR) +# include +# include + + /* When VK_USE_PLATFORM_WIN32_KHR is defined, instead of including vulkan.h directly, we include individual parts of the SDK + * This is necessary to avoid including which is very heavy - it takes 200ms to parse without WIN32_LEAN_AND_MEAN + * and 100ms to parse with it. vulkan_win32.h only needs a few symbols that are easy to redefine ourselves. + */ + typedef unsigned long DWORD; + typedef const wchar_t* LPCWSTR; + typedef void* HANDLE; + typedef struct HINSTANCE__* HINSTANCE; + typedef struct HWND__* HWND; + typedef struct HMONITOR__* HMONITOR; + typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; + +# include + +# ifdef VK_ENABLE_BETA_EXTENSIONS +# include +# endif +# else +# include +# endif +#endif + +/* Disable several extensions on earlier SDKs because later SDKs introduce a backwards incompatible change to function signatures */ +#if VK_HEADER_VERSION < 140 +# undef VK_NVX_image_view_handle +#endif +#if VK_HEADER_VERSION < 184 +# undef VK_HUAWEI_subpass_shading #endif #ifdef __cplusplus @@ -59,6 +93,12 @@ uint32_t volkGetInstanceVersion(void); */ void volkLoadInstance(VkInstance instance); +/** + * Load global function pointers using application-created VkInstance; call this function after creating the Vulkan instance. + * Skips loading device-based function pointers, requires usage of volkLoadDevice afterwards. + */ +void volkLoadInstanceOnly(VkInstance instance); + /** * Load global function pointers using application-created VkDevice; call this function after creating the Vulkan device. * @@ -66,6 +106,18 @@ void volkLoadInstance(VkInstance instance); */ void volkLoadDevice(VkDevice device); +/** + * Return last VkInstance for which global function pointers have been loaded via volkLoadInstance(), + * or VK_NULL_HANDLE if volkLoadInstance() has not been called. + */ +VkInstance volkGetLoadedInstance(void); + +/** + * Return last VkDevice for which global function pointers have been loaded via volkLoadDevice(), + * or VK_NULL_HANDLE if volkLoadDevice() has not been called. + */ +VkDevice volkGetLoadedDevice(void); + /** * Load function pointers using application-created VkDevice into a table. * Application should use function pointers from that table instead of using global function pointers. @@ -218,9 +270,27 @@ struct VolkDeviceTable PFN_vkTrimCommandPool vkTrimCommandPool; PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; + PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; + PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; + PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; + PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; + PFN_vkCreateRenderPass2 vkCreateRenderPass2; + PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; + PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; + PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; + PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; + PFN_vkResetQueryPool vkResetQueryPool; + PFN_vkSignalSemaphore vkSignalSemaphore; + PFN_vkWaitSemaphores vkWaitSemaphores; +#endif /* defined(VK_VERSION_1_2) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_display_native_hdr) + PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; @@ -238,6 +308,9 @@ struct VolkDeviceTable #if defined(VK_EXT_calibrated_timestamps) PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; #endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; @@ -249,16 +322,6 @@ struct VolkDeviceTable PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT; PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT; #endif /* defined(VK_EXT_debug_marker) */ -#if defined(VK_EXT_debug_utils) - PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT; - PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT; - PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT; - PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT; - PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT; - PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT; - PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT; -#endif /* defined(VK_EXT_debug_utils) */ #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ @@ -268,15 +331,56 @@ struct VolkDeviceTable 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) */ +#if defined(VK_EXT_full_screen_exclusive) + PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; + PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ #if defined(VK_EXT_hdr_metadata) PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_query_reset) + PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; #endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#endif /* defined(VK_EXT_line_rasterization) */ +#if defined(VK_EXT_multi_draw) + PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; + PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_private_data) + PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; + PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; + PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; + PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; #endif /* defined(VK_EXT_sample_locations) */ @@ -294,20 +398,87 @@ 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_external_memory) + PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; + PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; + PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_GOOGLE_display_timing) PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_invocation_mask) + PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) + PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; + PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; + PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; + PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; + PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; + PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; + PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; + PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; + PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; + PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; + PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; + PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; + PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; + PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; + PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; + PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; + PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; + PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; + PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; + PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; + PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; + PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; + PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; + PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; + PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_bind_memory2) PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; #endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; + PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; + PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_copy_commands2) + PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; + PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; + PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; + PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; + PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; + PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#endif /* defined(VK_KHR_copy_commands2) */ #if defined(VK_KHR_create_renderpass2) PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; #endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; + PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; + PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; + PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; + PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; @@ -349,6 +520,9 @@ struct VolkDeviceTable PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; #endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_memory_requirements2) PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; @@ -360,9 +534,30 @@ struct VolkDeviceTable #if defined(VK_KHR_maintenance3) PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_performance_query) + PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; + PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_executable_properties) + PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; + PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; + PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#endif /* defined(VK_KHR_present_wait) */ #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_pipeline) + PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; + PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; + PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; + PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; + PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; + PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; + PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; @@ -377,17 +572,52 @@ struct VolkDeviceTable PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; PFN_vkQueuePresentKHR vkQueuePresentKHR; #endif /* defined(VK_KHR_swapchain) */ -#if defined(VK_NVX_device_generated_commands) - PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX; - PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX; - PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX; - PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX; - PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX; - PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX; - PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX; - PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX; -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_KHR_synchronization2) + PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; + PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; + PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; + PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; + PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; + PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) + PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) + PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_KHR_timeline_semaphore) + PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; + PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; + PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; + PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; + PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; + PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; + PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; + PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; + PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; + PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; + PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; + PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; + PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; + PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; + PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; + PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) + PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; #endif /* defined(VK_NVX_image_view_handle) */ #if defined(VK_NV_clip_space_w_scaling) @@ -397,9 +627,23 @@ struct VolkDeviceTable PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_generated_commands) + PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; + PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; + PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; + PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; + PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; + PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_external_memory_rdma) + PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) + PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ #if defined(VK_NV_mesh_shader) PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; @@ -427,9 +671,12 @@ struct VolkDeviceTable PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) +#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_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)) */ +#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)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; @@ -610,9 +857,27 @@ extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSp extern PFN_vkTrimCommandPool vkTrimCommandPool; extern PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) +extern PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; +extern PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; +extern PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; +extern PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; +extern PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; +extern PFN_vkCreateRenderPass2 vkCreateRenderPass2; +extern PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; +extern PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; +extern PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; +extern PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; +extern PFN_vkResetQueryPool vkResetQueryPool; +extern PFN_vkSignalSemaphore vkSignalSemaphore; +extern PFN_vkWaitSemaphores vkWaitSemaphores; +#endif /* defined(VK_VERSION_1_2) */ #if defined(VK_AMD_buffer_marker) extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_display_native_hdr) +extern PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) extern PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; extern PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; @@ -624,6 +889,10 @@ extern PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_EXT_acquire_drm_display) +extern PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; +extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#endif /* defined(VK_EXT_acquire_drm_display) */ #if defined(VK_EXT_acquire_xlib_display) extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; @@ -635,6 +904,9 @@ extern PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; extern PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; #endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) +extern PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) extern PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; extern PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; @@ -667,6 +939,10 @@ extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; #if defined(VK_EXT_direct_mode_display) extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; #endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) +extern PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; +extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#endif /* defined(VK_EXT_directfb_surface) */ #if defined(VK_EXT_discard_rectangles) extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ @@ -679,22 +955,70 @@ 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) */ +#if defined(VK_EXT_full_screen_exclusive) +extern PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; +extern PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +extern PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ #if defined(VK_EXT_hdr_metadata) extern PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_headless_surface) +extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_host_query_reset) +extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) extern PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; #endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) +extern PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_metal_surface) extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; #endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_multi_draw) +extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; +extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_private_data) +extern PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; +extern PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; +extern PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; +extern PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) extern PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) +extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#endif /* defined(VK_EXT_tooling_info) */ #if defined(VK_EXT_transform_feedback) extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; @@ -709,13 +1033,63 @@ 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_external_memory) +extern PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; +extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) +extern PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; +extern PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_FUCHSIA_imagepipe_surface) extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; #endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) +extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ #if defined(VK_GOOGLE_display_timing) extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_invocation_mask) +extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) +extern PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; +extern PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) +extern PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; +extern PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; +extern PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; +extern PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; +extern PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; +extern PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; +extern PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; +extern PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; +extern PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) +extern PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; +extern PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; +extern PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; +extern PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; +extern PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; +extern PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; +extern PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; +extern PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; +extern PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; +extern PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; +extern PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; +extern PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; +extern PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; +extern PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; +extern PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; +extern PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_android_surface) extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #endif /* defined(VK_KHR_android_surface) */ @@ -723,12 +1097,32 @@ extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; #endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) +extern PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; +extern PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; +extern PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_copy_commands2) +extern PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; +extern PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; +extern PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; +extern PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; +extern PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; +extern PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#endif /* defined(VK_KHR_copy_commands2) */ #if defined(VK_KHR_create_renderpass2) extern PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; extern PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; extern PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; #endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) +extern PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; +extern PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; +extern PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; +extern PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; +extern PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) extern PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; extern PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; @@ -791,6 +1185,10 @@ extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; extern PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; extern PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; #endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) +extern PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_display_properties2) extern PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; extern PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; @@ -821,9 +1219,32 @@ extern PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; #if defined(VK_KHR_maintenance3) extern PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_performance_query) +extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; +extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; +extern PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +extern PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_executable_properties) +extern PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; +extern PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; +extern PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) +extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#endif /* defined(VK_KHR_present_wait) */ #if defined(VK_KHR_push_descriptor) extern PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_pipeline) +extern PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; +extern PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; +extern PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; +extern PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; +extern PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; +extern PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; +extern PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; @@ -845,6 +1266,45 @@ extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; extern PFN_vkQueuePresentKHR vkQueuePresentKHR; #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_synchronization2) +extern PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; +extern PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; +extern PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; +extern PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; +extern PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; +extern PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) +extern PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) +extern PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_KHR_timeline_semaphore) +extern PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; +extern PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; +extern PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) +extern PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) +extern PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +extern PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; +extern PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; +extern PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; +extern PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; +extern PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; +extern PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; +extern PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; +extern PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; +extern PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; +extern PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +extern PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; +extern PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_queue) */ #if defined(VK_KHR_wayland_surface) extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; @@ -870,36 +1330,54 @@ extern PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; #if defined(VK_NN_vi_surface) extern PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; #endif /* defined(VK_NN_vi_surface) */ -#if defined(VK_NVX_device_generated_commands) -extern PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX; -extern PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX; -extern PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX; -extern PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX; -extern PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX; -extern PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX; -extern PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX; -extern PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX; -extern PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX; -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_NVX_binary_import) +extern PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; +extern PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; +extern PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; +extern PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; +extern PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) +extern PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; extern PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NV_acquire_winrt_display) +extern PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; +extern PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#endif /* defined(VK_NV_acquire_winrt_display) */ #if defined(VK_NV_clip_space_w_scaling) extern PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #endif /* defined(VK_NV_clip_space_w_scaling) */ #if defined(VK_NV_cooperative_matrix) extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_coverage_reduction_mode) +extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#endif /* defined(VK_NV_coverage_reduction_mode) */ #if defined(VK_NV_device_diagnostic_checkpoints) extern PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; extern PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_generated_commands) +extern PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; +extern PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; +extern PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; +extern PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; +extern PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; +extern PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands) */ #if defined(VK_NV_external_memory_capabilities) extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; #endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_external_memory_rdma) +extern PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) extern PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) +extern PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ #if defined(VK_NV_mesh_shader) extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; extern PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; @@ -927,9 +1405,16 @@ extern PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; extern PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; extern PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) +#if defined(VK_QNX_screen_surface) +extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; +extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#endif /* defined(VK_QNX_screen_surface) */ +#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_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)) */ +#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)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) extern PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; extern PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; @@ -946,6 +1431,14 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #endif +#ifdef VOLK_IMPLEMENTATION +#undef VOLK_IMPLEMENTATION +// Prevent tools like dependency checkers that don't evaluate +// macros from detecting a cyclic dependency. +#define VOLK_SOURCE "volk.c" +#include VOLK_SOURCE +#endif + /** * Copyright (c) 2018-2019 Arseny Kapoulkine * @@ -967,3 +1460,4 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +/* clang-format on */ diff --git a/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h new file mode 100644 index 000000000..667732a5d --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h @@ -0,0 +1,519 @@ +#pragma once + +#include "vulkanobjects.h" +#include +#include + +class VulkanCompatibleDevice; + +class VulkanInstanceBuilder +{ +public: + VulkanInstanceBuilder(); + + VulkanInstanceBuilder& ApiVersionsToTry(const std::vector& versions); + VulkanInstanceBuilder& RequireExtension(const std::string& extensionName); + VulkanInstanceBuilder& RequireSurfaceExtensions(bool enable = true); + VulkanInstanceBuilder& OptionalExtension(const std::string& extensionName); + VulkanInstanceBuilder& DebugLayer(bool enable = true); + + std::shared_ptr Create(); + +private: + std::vector apiVersionsToTry; + std::set requiredExtensions; + std::set optionalExtensions; + bool debugLayer = false; +}; + +#ifdef VK_USE_PLATFORM_WIN32_KHR + +class VulkanSurfaceBuilder +{ +public: + VulkanSurfaceBuilder(); + + VulkanSurfaceBuilder& Win32Window(HWND handle); + + std::shared_ptr Create(std::shared_ptr instance); + +private: + HWND hwnd = {}; +}; + +#endif + +class VulkanDeviceBuilder +{ +public: + VulkanDeviceBuilder(); + + VulkanDeviceBuilder& RequireExtension(const std::string& extensionName); + VulkanDeviceBuilder& OptionalExtension(const std::string& extensionName); + VulkanDeviceBuilder& OptionalRayQuery(); + VulkanDeviceBuilder& OptionalDescriptorIndexing(); + VulkanDeviceBuilder& Surface(std::shared_ptr surface); + VulkanDeviceBuilder& SelectDevice(int index); + + std::vector FindDevices(const std::shared_ptr& instance); + std::shared_ptr Create(std::shared_ptr instance); + +private: + std::set requiredDeviceExtensions; + std::set optionalDeviceExtensions; + std::shared_ptr surface; + int deviceIndex = 0; +}; + +class VulkanSwapChainBuilder +{ +public: + VulkanSwapChainBuilder(); + + std::shared_ptr Create(VulkanDevice* device); +}; + +class CommandPoolBuilder +{ +public: + CommandPoolBuilder(); + + CommandPoolBuilder& QueueFamily(int index); + CommandPoolBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + const char* debugName = nullptr; + int queueFamilyIndex = -1; +}; + +class SemaphoreBuilder +{ +public: + SemaphoreBuilder(); + + SemaphoreBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + const char* debugName = nullptr; +}; + +class FenceBuilder +{ +public: + FenceBuilder(); + + FenceBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + const char* debugName = nullptr; +}; + +class ImageBuilder +{ +public: + ImageBuilder(); + + ImageBuilder& Size(int width, int height, int miplevels = 1, int arrayLayers = 1); + ImageBuilder& Samples(VkSampleCountFlagBits samples); + ImageBuilder& Format(VkFormat format); + ImageBuilder& Usage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); + ImageBuilder& MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); + ImageBuilder& LinearTiling(); + ImageBuilder& DebugName(const char* name) { debugName = name; return *this; } + + bool IsFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0); + + std::unique_ptr Create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); + std::unique_ptr TryCreate(VulkanDevice *device); + +private: + VkImageCreateInfo imageInfo = {}; + VmaAllocationCreateInfo allocInfo = {}; + const char* debugName = nullptr; +}; + +class ImageViewBuilder +{ +public: + ImageViewBuilder(); + + ImageViewBuilder& Type(VkImageViewType type); + ImageViewBuilder& Image(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + ImageViewBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkImageViewCreateInfo viewInfo = {}; + const char* debugName = nullptr; +}; + +class SamplerBuilder +{ +public: + SamplerBuilder(); + + SamplerBuilder& AddressMode(VkSamplerAddressMode addressMode); + SamplerBuilder& AddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w); + SamplerBuilder& MinFilter(VkFilter minFilter); + SamplerBuilder& MagFilter(VkFilter magFilter); + SamplerBuilder& MipmapMode(VkSamplerMipmapMode mode); + SamplerBuilder& Anisotropy(float maxAnisotropy); + SamplerBuilder& MipLodBias(float bias); + SamplerBuilder& MaxLod(float value); + SamplerBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkSamplerCreateInfo samplerInfo = {}; + const char* debugName = nullptr; +}; + +class BufferBuilder +{ +public: + BufferBuilder(); + + BufferBuilder& Size(size_t size); + BufferBuilder& Usage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); + BufferBuilder& MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); + BufferBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkBufferCreateInfo bufferInfo = {}; + VmaAllocationCreateInfo allocInfo = {}; + const char* debugName = nullptr; +}; + +class ShaderBuilder +{ +public: + ShaderBuilder(); + + static void Init(); + static void Deinit(); + + ShaderBuilder& VertexShader(const std::string &code); + ShaderBuilder& FragmentShader(const std::string&code); + ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(const char *shadername, VulkanDevice *device); + +private: + std::string code; + int stage = 0; + const char* debugName = nullptr; +}; + +class AccelerationStructureBuilder +{ +public: + AccelerationStructureBuilder(); + + AccelerationStructureBuilder& Type(VkAccelerationStructureTypeKHR type); + AccelerationStructureBuilder& Buffer(VulkanBuffer* buffer, VkDeviceSize size); + AccelerationStructureBuilder& Buffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size); + AccelerationStructureBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; + const char* debugName = nullptr; +}; + +class ComputePipelineBuilder +{ +public: + ComputePipelineBuilder(); + + ComputePipelineBuilder& Cache(VulkanPipelineCache* cache); + ComputePipelineBuilder& Layout(VulkanPipelineLayout *layout); + ComputePipelineBuilder& ComputeShader(VulkanShader *shader); + ComputePipelineBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkComputePipelineCreateInfo pipelineInfo = {}; + VkPipelineShaderStageCreateInfo stageInfo = {}; + VulkanPipelineCache* cache = nullptr; + const char* debugName = nullptr; +}; + +class DescriptorSetLayoutBuilder +{ +public: + DescriptorSetLayoutBuilder(); + + DescriptorSetLayoutBuilder& Flags(VkDescriptorSetLayoutCreateFlags flags); + DescriptorSetLayoutBuilder& AddBinding(int binding, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags, VkDescriptorBindingFlags flags = 0); + DescriptorSetLayoutBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkDescriptorSetLayoutCreateInfo layoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingFlagsInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT }; + std::vector bindings; + std::vector bindingFlags; + const char* debugName = nullptr; +}; + +class DescriptorPoolBuilder +{ +public: + DescriptorPoolBuilder(); + + DescriptorPoolBuilder& Flags(VkDescriptorPoolCreateFlags flags); + DescriptorPoolBuilder& MaxSets(int value); + DescriptorPoolBuilder& AddPoolSize(VkDescriptorType type, int count); + DescriptorPoolBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + std::vector poolSizes; + VkDescriptorPoolCreateInfo poolInfo = {}; + const char* debugName = nullptr; +}; + +class QueryPoolBuilder +{ +public: + QueryPoolBuilder(); + + QueryPoolBuilder& QueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics = 0); + QueryPoolBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkQueryPoolCreateInfo poolInfo = {}; + const char* debugName = nullptr; +}; + +class FramebufferBuilder +{ +public: + FramebufferBuilder(); + + FramebufferBuilder& RenderPass(VulkanRenderPass *renderPass); + FramebufferBuilder& AddAttachment(VulkanImageView *view); + FramebufferBuilder& AddAttachment(VkImageView view); + FramebufferBuilder& Size(int width, int height, int layers = 1); + FramebufferBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkFramebufferCreateInfo framebufferInfo = {}; + std::vector attachments; + const char* debugName = nullptr; +}; + +class GraphicsPipelineBuilder +{ +public: + GraphicsPipelineBuilder(); + + GraphicsPipelineBuilder& Cache(VulkanPipelineCache* cache); + GraphicsPipelineBuilder& Subpass(int subpass); + GraphicsPipelineBuilder& Layout(VulkanPipelineLayout *layout); + GraphicsPipelineBuilder& RenderPass(VulkanRenderPass *renderPass); + GraphicsPipelineBuilder& Topology(VkPrimitiveTopology topology); + GraphicsPipelineBuilder& Viewport(float x, float y, float width, float height, float minDepth = 0.0f, float maxDepth = 1.0f); + GraphicsPipelineBuilder& Scissor(int x, int y, int width, int height); + GraphicsPipelineBuilder& RasterizationSamples(VkSampleCountFlagBits samples); + + GraphicsPipelineBuilder& Cull(VkCullModeFlags cullMode, VkFrontFace frontFace); + GraphicsPipelineBuilder& DepthStencilEnable(bool test, bool write, bool stencil); + 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& AddVertexShader(VulkanShader *shader); + GraphicsPipelineBuilder& AddFragmentShader(VulkanShader *shader); + + GraphicsPipelineBuilder& AddVertexBufferBinding(int index, size_t stride); + GraphicsPipelineBuilder& AddVertexAttribute(int location, int binding, VkFormat format, size_t offset); + + GraphicsPipelineBuilder& AddDynamicState(VkDynamicState state); + + GraphicsPipelineBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkGraphicsPipelineCreateInfo pipelineInfo = { }; + VkPipelineVertexInputStateCreateInfo vertexInputInfo = { }; + VkPipelineInputAssemblyStateCreateInfo inputAssembly = { }; + VkViewport viewport = { }; + VkRect2D scissor = { }; + VkPipelineViewportStateCreateInfo viewportState = { }; + VkPipelineRasterizationStateCreateInfo rasterizer = { }; + VkPipelineMultisampleStateCreateInfo multisampling = { }; + VkPipelineColorBlendAttachmentState colorBlendAttachment = { }; + VkPipelineColorBlendStateCreateInfo colorBlending = { }; + VkPipelineDepthStencilStateCreateInfo depthStencil = { }; + VkPipelineDynamicStateCreateInfo dynamicState = {}; + + std::vector shaderStages; + std::vector colorBlendAttachments; + std::vector vertexInputBindings; + std::vector vertexInputAttributes; + std::vector dynamicStates; + + VulkanPipelineCache* cache = nullptr; + const char* debugName = nullptr; +}; + +class PipelineLayoutBuilder +{ +public: + PipelineLayoutBuilder(); + + PipelineLayoutBuilder& AddSetLayout(VulkanDescriptorSetLayout *setLayout); + PipelineLayoutBuilder& AddPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size); + + PipelineLayoutBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; + std::vector setLayouts; + std::vector pushConstantRanges; + const char* debugName = nullptr; +}; + +class PipelineCacheBuilder +{ +public: + PipelineCacheBuilder(); + + PipelineCacheBuilder& InitialData(const void* data, size_t size); + PipelineCacheBuilder& Flags(VkPipelineCacheCreateFlags flags); + + PipelineCacheBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + VkPipelineCacheCreateInfo pipelineCacheInfo = {}; + std::vector initData; + const char* debugName = nullptr; +}; + +class RenderPassBuilder +{ +public: + RenderPassBuilder(); + + RenderPassBuilder& AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout); + RenderPassBuilder& AddDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout); + + RenderPassBuilder& AddExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + + RenderPassBuilder& AddSubpass(); + RenderPassBuilder& AddSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout); + RenderPassBuilder& AddSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout); + + RenderPassBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); + +private: + VkRenderPassCreateInfo renderPassInfo = { }; + + std::vector attachments; + std::vector dependencies; + std::vector subpasses; + + struct SubpassData + { + std::vector colorRefs; + VkAttachmentReference depthRef = { }; + }; + + std::vector> subpassData; + + const char* debugName = nullptr; +}; + +class PipelineBarrier +{ +public: + 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& 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); + + void Execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags = 0); + +private: + std::vector memoryBarriers; + std::vector bufferMemoryBarriers; + std::vector imageMemoryBarriers; +}; + +class QueueSubmit +{ +public: + QueueSubmit(); + + QueueSubmit& AddCommandBuffer(VulkanCommandBuffer *buffer); + QueueSubmit& AddWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore); + QueueSubmit& AddSignal(VulkanSemaphore *semaphore); + void Execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence = nullptr); + +private: + VkSubmitInfo submitInfo = {}; + std::vector waitSemaphores; + std::vector waitStages; + std::vector signalSemaphores; + std::vector commandBuffers; +}; + +class WriteDescriptors +{ +public: + WriteDescriptors& AddBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer); + WriteDescriptors& AddBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range); + WriteDescriptors& AddStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout); + WriteDescriptors& AddCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout); + WriteDescriptors& AddCombinedImageSampler(VulkanDescriptorSet* descriptorSet, int binding, int arrayIndex, VulkanImageView* view, VulkanSampler* sampler, VkImageLayout imageLayout); + WriteDescriptors& AddAccelerationStructure(VulkanDescriptorSet* descriptorSet, int binding, VulkanAccelerationStructure* accelStruct); + void Execute(VulkanDevice *device); + +private: + struct WriteExtra + { + VkDescriptorImageInfo imageInfo; + VkDescriptorBufferInfo bufferInfo; + VkBufferView bufferView; + VkWriteDescriptorSetAccelerationStructureKHR accelStruct; + }; + + std::vector writes; + std::vector> writeExtras; +}; diff --git a/libraries/ZVulkan/include/zvulkan/vulkancompatibledevice.h b/libraries/ZVulkan/include/zvulkan/vulkancompatibledevice.h new file mode 100644 index 000000000..9a2cd5e42 --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkancompatibledevice.h @@ -0,0 +1,19 @@ +#pragma once + +#include "vulkaninstance.h" + +class VulkanSurface; + +class VulkanCompatibleDevice +{ +public: + VulkanPhysicalDevice* Device = nullptr; + + int GraphicsFamily = -1; + int PresentFamily = -1; + + bool GraphicsTimeQueries = false; + + std::set EnabledDeviceExtensions; + VulkanDeviceFeatures EnabledFeatures; +}; diff --git a/libraries/ZVulkan/include/zvulkan/vulkandevice.h b/libraries/ZVulkan/include/zvulkan/vulkandevice.h new file mode 100644 index 000000000..48c1a1f59 --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkandevice.h @@ -0,0 +1,52 @@ +#pragma once + +#include "vulkaninstance.h" + +#include +#include +#include +#include +#include + +class VulkanSwapChain; +class VulkanSemaphore; +class VulkanFence; +class VulkanPhysicalDevice; +class VulkanSurface; +class VulkanCompatibleDevice; + +class VulkanDevice +{ +public: + VulkanDevice(std::shared_ptr instance, std::shared_ptr surface, const VulkanCompatibleDevice& selectedDevice); + ~VulkanDevice(); + + std::set EnabledDeviceExtensions; + VulkanDeviceFeatures EnabledFeatures; + + VulkanPhysicalDevice PhysicalDevice; + + std::shared_ptr Instance; + std::shared_ptr Surface; + + VkDevice device = VK_NULL_HANDLE; + VmaAllocator allocator = VK_NULL_HANDLE; + + VkQueue GraphicsQueue = VK_NULL_HANDLE; + VkQueue PresentQueue = VK_NULL_HANDLE; + + int GraphicsFamily = -1; + int PresentFamily = -1; + bool GraphicsTimeQueries = false; + + bool SupportsDeviceExtension(const char* ext) const; + + 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 new file mode 100644 index 000000000..d30d6aa19 --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkaninstance.h @@ -0,0 +1,94 @@ +#pragma once + +#if defined(_WIN32) +#define VK_USE_PLATFORM_WIN32_KHR +#elif defined(__APPLE__) +#define VK_USE_PLATFORM_MACOS_MVK +#define VK_USE_PLATFORM_METAL_EXT +#endif + +#include "volk/volk.h" +#include "vk_mem_alloc/vk_mem_alloc.h" + +#if defined(_WIN32) +#undef min +#undef max +#endif + +#include +#include +#include +#include +#include + +class VulkanDeviceFeatures +{ +public: + VkPhysicalDeviceFeatures Features = {}; + VkPhysicalDeviceBufferDeviceAddressFeatures BufferDeviceAddress = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES }; + VkPhysicalDeviceAccelerationStructureFeaturesKHR AccelerationStructure = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR }; + VkPhysicalDeviceRayQueryFeaturesKHR RayQuery = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR }; + VkPhysicalDeviceDescriptorIndexingFeatures DescriptorIndexing = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT }; +}; + +class VulkanPhysicalDevice +{ +public: + VkPhysicalDevice Device = VK_NULL_HANDLE; + std::vector Extensions; + std::vector QueueFamilies; + VkPhysicalDeviceProperties Properties = {}; + VkPhysicalDeviceMemoryProperties MemoryProperties = {}; + VulkanDeviceFeatures Features; +}; + +class VulkanInstance +{ +public: + VulkanInstance(std::vector apiVersionsToTry, std::set requiredExtensions, std::set optionalExtensions, bool wantDebugLayer); + ~VulkanInstance(); + + std::vector ApiVersionsToTry; + + std::set RequiredExtensions; + std::set OptionalExtensions; + + std::vector AvailableLayers; + std::vector AvailableExtensions; + + std::set EnabledValidationLayers; + std::set EnabledExtensions; + + std::vector PhysicalDevices; + + uint32_t ApiVersion = {}; + VkInstance Instance = VK_NULL_HANDLE; + + bool DebugLayerActive = false; + +private: + bool WantDebugLayer = false; + VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; + + void CreateInstance(); + void ReleaseResources(); + + static void InitVolk(); + static std::vector GetAvailableLayers(); + static std::vector GetExtensions(); + static std::vector GetPhysicalDevices(VkInstance instance, uint32_t apiVersion); + + static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); + static std::vector SplitString(const std::string& s, const std::string& seperator); +}; + +std::string VkResultToString(VkResult result); + +void VulkanPrintLog(const char* typestr, const std::string& msg); +void VulkanError(const char* text); + +inline void CheckVulkanError(VkResult result, const char* text) +{ + if (result >= VK_SUCCESS) return; + VulkanError((text + std::string(": ") + VkResultToString(result)).c_str()); +} diff --git a/src/common/rendering/vulkan/system/vk_objects.h b/libraries/ZVulkan/include/zvulkan/vulkanobjects.h similarity index 76% rename from src/common/rendering/vulkan/system/vk_objects.h rename to libraries/ZVulkan/include/zvulkan/vulkanobjects.h index dd3204517..c7842f670 100644 --- a/src/common/rendering/vulkan/system/vk_objects.h +++ b/libraries/ZVulkan/include/zvulkan/vulkanobjects.h @@ -1,10 +1,10 @@ #pragma once -#include "vk_device.h" -#include "engineerrors.h" +#include "vulkandevice.h" class VulkanCommandPool; class VulkanDescriptorPool; +class VulkanCommandBuffer; class VulkanSemaphore { @@ -12,7 +12,7 @@ public: VulkanSemaphore(VulkanDevice *device); ~VulkanSemaphore(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)semaphore, VK_OBJECT_TYPE_SEMAPHORE); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)semaphore, VK_OBJECT_TYPE_SEMAPHORE); } VulkanDevice *device = nullptr; VkSemaphore semaphore = VK_NULL_HANDLE; @@ -28,7 +28,7 @@ public: VulkanFence(VulkanDevice *device); ~VulkanFence(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)fence, VK_OBJECT_TYPE_FENCE); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)fence, VK_OBJECT_TYPE_FENCE); } VulkanDevice *device = nullptr; VkFence fence = VK_NULL_HANDLE; @@ -44,7 +44,19 @@ public: VulkanBuffer(VulkanDevice *device, VkBuffer buffer, VmaAllocation allocation, size_t size); ~VulkanBuffer(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); } + VkDeviceAddress GetDeviceAddress() + { + VkBufferDeviceAddressInfo info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; + info.buffer = buffer; + return vkGetBufferDeviceAddress(device->device, &info); + } + +#ifdef _DEBUG + void SetDebugName(const char* name) { debugName = name; device->SetObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); } + std::string debugName; +#else + void SetDebugName(const char* name) { device->SetObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); } +#endif VulkanDevice *device = nullptr; @@ -66,7 +78,7 @@ public: VulkanFramebuffer(VulkanDevice *device, VkFramebuffer framebuffer); ~VulkanFramebuffer(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER); } VulkanDevice *device; VkFramebuffer framebuffer; @@ -79,15 +91,16 @@ private: class VulkanImage { public: - VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels); + VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount); ~VulkanImage(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)image, VK_OBJECT_TYPE_IMAGE); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)image, VK_OBJECT_TYPE_IMAGE); } VkImage image = VK_NULL_HANDLE; int width = 0; int height = 0; int mipLevels = 1; + int layerCount = 1; void *Map(size_t offset, size_t size); void Unmap(); @@ -106,7 +119,7 @@ public: VulkanImageView(VulkanDevice *device, VkImageView view); ~VulkanImageView(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)view, VK_OBJECT_TYPE_IMAGE_VIEW); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)view, VK_OBJECT_TYPE_IMAGE_VIEW); } VkImageView view = VK_NULL_HANDLE; @@ -123,7 +136,7 @@ public: VulkanSampler(VulkanDevice *device, VkSampler sampler); ~VulkanSampler(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)sampler, VK_OBJECT_TYPE_SAMPLER); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)sampler, VK_OBJECT_TYPE_SAMPLER); } VkSampler sampler = VK_NULL_HANDLE; @@ -140,7 +153,7 @@ public: VulkanShader(VulkanDevice *device, VkShaderModule module); ~VulkanShader(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)module, VK_OBJECT_TYPE_SHADER_MODULE); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)module, VK_OBJECT_TYPE_SHADER_MODULE); } VkShaderModule module = VK_NULL_HANDLE; @@ -157,7 +170,7 @@ public: VulkanDescriptorSetLayout(VulkanDevice *device, VkDescriptorSetLayout layout); ~VulkanDescriptorSetLayout(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)layout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)layout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); } VulkanDevice *device; VkDescriptorSetLayout layout; @@ -173,7 +186,12 @@ public: VulkanDescriptorSet(VulkanDevice *device, VulkanDescriptorPool *pool, VkDescriptorSet set); ~VulkanDescriptorSet(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); } +#ifdef _DEBUG + void SetDebugName(const char* name) { debugName = name; device->SetObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); } + std::string debugName; +#else + void SetDebugName(const char* name) { device->SetObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); } +#endif VulkanDevice *device; VulkanDescriptorPool *pool; @@ -190,15 +208,26 @@ public: VulkanDescriptorPool(VulkanDevice *device, VkDescriptorPool pool); ~VulkanDescriptorPool(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); } +#ifdef _DEBUG + void SetDebugName(const char* name) { debugName = name; device->SetObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); } + std::string debugName; +#else + void SetDebugName(const char* name) { device->SetObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); } +#endif std::unique_ptr tryAllocate(VulkanDescriptorSetLayout *layout); + std::unique_ptr tryAllocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount); std::unique_ptr allocate(VulkanDescriptorSetLayout *layout); + std::unique_ptr allocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount); VulkanDevice *device; VkDescriptorPool pool; private: + enum class AllocType { TryAllocate, AlwaysAllocate }; + std::unique_ptr allocate(VulkanDescriptorSetLayout* layout, AllocType allocType); + std::unique_ptr allocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount, AllocType allocType); + VulkanDescriptorPool(const VulkanDescriptorPool &) = delete; VulkanDescriptorPool &operator=(const VulkanDescriptorPool &) = delete; }; @@ -209,7 +238,7 @@ public: VulkanQueryPool(VulkanDevice *device, VkQueryPool pool); ~VulkanQueryPool(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_QUERY_POOL); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_QUERY_POOL); } bool getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void *data, VkDeviceSize stride, VkQueryResultFlags flags); @@ -221,13 +250,36 @@ private: VulkanQueryPool &operator=(const VulkanQueryPool &) = delete; }; +class VulkanAccelerationStructure +{ +public: + VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct); + ~VulkanAccelerationStructure(); + + VkDeviceAddress GetDeviceAddress() + { + VkAccelerationStructureDeviceAddressInfoKHR addressInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR }; + addressInfo.accelerationStructure = accelstruct; + return vkGetAccelerationStructureDeviceAddressKHR(device->device, &addressInfo); + } + + void SetDebugName(const char* name) { device->SetObjectName(name, (uint64_t)accelstruct, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR); } + + VulkanDevice* device; + VkAccelerationStructureKHR accelstruct; + +private: + VulkanAccelerationStructure(const VulkanAccelerationStructure&) = delete; + VulkanAccelerationStructure& operator=(const VulkanAccelerationStructure&) = delete; +}; + class VulkanPipeline { public: VulkanPipeline(VulkanDevice *device, VkPipeline pipeline); ~VulkanPipeline(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)pipeline, VK_OBJECT_TYPE_PIPELINE); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)pipeline, VK_OBJECT_TYPE_PIPELINE); } VulkanDevice *device; VkPipeline pipeline; @@ -243,7 +295,7 @@ public: VulkanPipelineLayout(VulkanDevice *device, VkPipelineLayout layout); ~VulkanPipelineLayout(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)layout, VK_OBJECT_TYPE_PIPELINE_LAYOUT); } VulkanDevice *device; VkPipelineLayout layout; @@ -253,13 +305,31 @@ private: VulkanPipelineLayout &operator=(const VulkanPipelineLayout &) = delete; }; +class VulkanPipelineCache +{ +public: + VulkanPipelineCache(VulkanDevice* device, VkPipelineCache cache); + ~VulkanPipelineCache(); + + void SetDebugName(const char* name) { device->SetObjectName(name, (uint64_t)cache, VK_OBJECT_TYPE_PIPELINE_CACHE); } + + std::vector GetCacheData(); + + VulkanDevice* device; + VkPipelineCache cache; + +private: + VulkanPipelineCache(const VulkanPipelineCache&) = delete; + VulkanPipelineCache& operator=(const VulkanPipelineCache&) = delete; +}; + class VulkanRenderPass { public: VulkanRenderPass(VulkanDevice *device, VkRenderPass renderPass); ~VulkanRenderPass(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS); } VulkanDevice *device; VkRenderPass renderPass; @@ -274,13 +344,15 @@ class RenderPassBegin public: RenderPassBegin(); - void setRenderPass(VulkanRenderPass *renderpass); - void setRenderArea(int x, int y, int width, int height); - void setFramebuffer(VulkanFramebuffer *framebuffer); - void addClearColor(float r, float g, float b, float a); - void addClearDepth(float value); - void addClearStencil(int value); - void addClearDepthStencil(float depthValue, int stencilValue); + RenderPassBegin& RenderPass(VulkanRenderPass* renderpass); + RenderPassBegin& RenderArea(int x, int y, int width, int height); + RenderPassBegin& Framebuffer(VulkanFramebuffer* framebuffer); + RenderPassBegin& AddClearColor(float r, float g, float b, float a); + RenderPassBegin& AddClearDepth(float value); + RenderPassBegin& AddClearStencil(int value); + RenderPassBegin& AddClearDepthStencil(float depthValue, int stencilValue); + + void Execute(VulkanCommandBuffer* cmdbuffer, VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE); VkRenderPassBeginInfo renderPassInfo = {}; @@ -354,6 +426,10 @@ public: void endRenderPass(); void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); + void buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + void traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); + void writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); + void debugFullPipelineBarrier(); VkCommandBuffer buffer = nullptr; @@ -371,7 +447,7 @@ public: VulkanCommandPool(VulkanDevice *device, int queueFamilyIndex); ~VulkanCommandPool(); - void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_COMMAND_POOL); } + void SetDebugName(const char *name) { device->SetObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_COMMAND_POOL); } std::unique_ptr createBuffer(); @@ -469,35 +545,39 @@ inline RenderPassBegin::RenderPassBegin() renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; } -inline void RenderPassBegin::setRenderPass(VulkanRenderPass *renderPass) +inline RenderPassBegin& RenderPassBegin::RenderPass(VulkanRenderPass* renderPass) { renderPassInfo.renderPass = renderPass->renderPass; + return *this; } -inline void RenderPassBegin::setRenderArea(int x, int y, int width, int height) +inline RenderPassBegin& RenderPassBegin::RenderArea(int x, int y, int width, int height) { renderPassInfo.renderArea.offset.x = x; renderPassInfo.renderArea.offset.y = y; renderPassInfo.renderArea.extent.width = width; renderPassInfo.renderArea.extent.height = height; + return *this; } -inline void RenderPassBegin::setFramebuffer(VulkanFramebuffer *framebuffer) +inline RenderPassBegin& RenderPassBegin::Framebuffer(VulkanFramebuffer* framebuffer) { renderPassInfo.framebuffer = framebuffer->framebuffer; + return *this; } -inline void RenderPassBegin::addClearColor(float r, float g, float b, float a) +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(); renderPassInfo.pClearValues = clearValues.data(); + return *this; } -inline void RenderPassBegin::addClearDepth(float value) +inline RenderPassBegin& RenderPassBegin::AddClearDepth(float value) { VkClearValue clearValue = { }; clearValue.depthStencil.depth = value; @@ -505,9 +585,10 @@ inline void RenderPassBegin::addClearDepth(float value) renderPassInfo.clearValueCount = (uint32_t)clearValues.size(); renderPassInfo.pClearValues = clearValues.data(); + return *this; } -inline void RenderPassBegin::addClearStencil(int value) +inline RenderPassBegin& RenderPassBegin::AddClearStencil(int value) { VkClearValue clearValue = { }; clearValue.depthStencil.stencil = value; @@ -515,9 +596,10 @@ inline void RenderPassBegin::addClearStencil(int value) renderPassInfo.clearValueCount = (uint32_t)clearValues.size(); renderPassInfo.pClearValues = clearValues.data(); + return *this; } -inline void RenderPassBegin::addClearDepthStencil(float depthValue, int stencilValue) +inline RenderPassBegin& RenderPassBegin::AddClearDepthStencil(float depthValue, int stencilValue) { VkClearValue clearValue = { }; clearValue.depthStencil.depth = depthValue; @@ -526,6 +608,12 @@ inline void RenderPassBegin::addClearDepthStencil(float depthValue, int stencilV renderPassInfo.clearValueCount = (uint32_t)clearValues.size(); renderPassInfo.pClearValues = clearValues.data(); + return *this; +} + +inline void RenderPassBegin::Execute(VulkanCommandBuffer* cmdbuffer, VkSubpassContents contents) +{ + cmdbuffer->beginRenderPass(&renderPassInfo, contents); } ///////////////////////////////////////////////////////////////////////////// @@ -878,9 +966,24 @@ inline void VulkanCommandBuffer::executeCommands(uint32_t commandBufferCount, co vkCmdExecuteCommands(buffer, commandBufferCount, pCommandBuffers); } +inline void VulkanCommandBuffer::buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos) +{ + vkCmdBuildAccelerationStructuresKHR(buffer, infoCount, pInfos, ppBuildRangeInfos); +} + +inline void VulkanCommandBuffer::traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth) +{ + vkCmdTraceRaysKHR(buffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth); +} + +inline void VulkanCommandBuffer::writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery) +{ + vkCmdWriteAccelerationStructuresPropertiesKHR(buffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); +} + inline void VulkanCommandBuffer::SetDebugName(const char *name) { - pool->device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_COMMAND_BUFFER); + pool->device->SetObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_COMMAND_BUFFER); } ///////////////////////////////////////////////////////////////////////////// @@ -927,35 +1030,60 @@ inline VulkanDescriptorPool::~VulkanDescriptorPool() vkDestroyDescriptorPool(device->device, pool, nullptr); } -inline std::unique_ptr VulkanDescriptorPool::tryAllocate(VulkanDescriptorSetLayout *layout) +inline std::unique_ptr VulkanDescriptorPool::allocate(VulkanDescriptorSetLayout* layout, AllocType allocType) { - VkDescriptorSetAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + VkDescriptorSetAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; allocInfo.descriptorPool = pool; allocInfo.descriptorSetCount = 1; allocInfo.pSetLayouts = &layout->layout; VkDescriptorSet descriptorSet; VkResult result = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet); - if (result != VK_SUCCESS) + if (allocType == AllocType::TryAllocate && result != VK_SUCCESS) return nullptr; - + else + CheckVulkanError(result, "Could not allocate descriptor sets"); return std::make_unique(device, this, descriptorSet); } +inline std::unique_ptr VulkanDescriptorPool::allocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount, AllocType allocType) +{ + VkDescriptorSetAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + VkDescriptorSetVariableDescriptorCountAllocateInfoEXT countInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT }; + allocInfo.descriptorPool = pool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &layout->layout; + allocInfo.pNext = &countInfo; + countInfo.descriptorSetCount = 1; + countInfo.pDescriptorCounts = &bindlessCount; + + VkDescriptorSet descriptorSet; + VkResult result = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet); + if (allocType == AllocType::TryAllocate && result != VK_SUCCESS) + return nullptr; + else + CheckVulkanError(result, "Could not allocate descriptor sets"); + return std::make_unique(device, this, descriptorSet); +} + +inline std::unique_ptr VulkanDescriptorPool::tryAllocate(VulkanDescriptorSetLayout *layout) +{ + return allocate(layout, AllocType::TryAllocate); +} + inline std::unique_ptr VulkanDescriptorPool::allocate(VulkanDescriptorSetLayout *layout) { - VkDescriptorSetAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = pool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &layout->layout; + return allocate(layout, AllocType::AlwaysAllocate); +} - VkDescriptorSet descriptorSet; - VkResult result = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet); - CheckVulkanError(result, "Could not allocate descriptor sets"); +inline std::unique_ptr VulkanDescriptorPool::tryAllocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount) +{ + return allocate(layout, bindlessCount, AllocType::TryAllocate); +} - return std::make_unique(device, this, descriptorSet); +inline std::unique_ptr VulkanDescriptorPool::allocate(VulkanDescriptorSetLayout* layout, uint32_t bindlessCount) +{ + return allocate(layout, bindlessCount, AllocType::AlwaysAllocate); } ///////////////////////////////////////////////////////////////////////////// @@ -989,13 +1117,14 @@ inline VulkanFramebuffer::~VulkanFramebuffer() ///////////////////////////////////////////////////////////////////////////// -inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels) : image(image), width(width), height(height), mipLevels(mipLevels), device(device), allocation(allocation) +inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount) : image(image), width(width), height(height), mipLevels(mipLevels), layerCount(layerCount), device(device), allocation(allocation) { } inline VulkanImage::~VulkanImage() { - vmaDestroyImage(device->allocator, image, allocation); + if (allocation) + vmaDestroyImage(device->allocator, image, allocation); } inline void *VulkanImage::Map(size_t offset, size_t size) @@ -1034,6 +1163,18 @@ inline VulkanSampler::~VulkanSampler() ///////////////////////////////////////////////////////////////////////////// +inline VulkanAccelerationStructure::VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct) + : device(device), accelstruct(accelstruct) +{ +} + +inline VulkanAccelerationStructure::~VulkanAccelerationStructure() +{ + vkDestroyAccelerationStructureKHR(device->device, accelstruct, nullptr); +} + +///////////////////////////////////////////////////////////////////////////// + inline VulkanPipeline::VulkanPipeline(VulkanDevice *device, VkPipeline pipeline) : device(device), pipeline(pipeline) { } @@ -1056,6 +1197,33 @@ inline VulkanPipelineLayout::~VulkanPipelineLayout() ///////////////////////////////////////////////////////////////////////////// +inline VulkanPipelineCache::VulkanPipelineCache(VulkanDevice* device, VkPipelineCache cache) : device(device), cache(cache) +{ +} + +inline VulkanPipelineCache::~VulkanPipelineCache() +{ + vkDestroyPipelineCache(device->device, cache, nullptr); +} + +inline std::vector VulkanPipelineCache::GetCacheData() +{ + size_t dataSize = 0; + VkResult result = vkGetPipelineCacheData(device->device, cache, &dataSize, nullptr); + CheckVulkanError(result, "Could not get cache data size"); + + std::vector buffer; + buffer.resize(dataSize); + result = vkGetPipelineCacheData(device->device, cache, &dataSize, buffer.data()); + if (result == VK_INCOMPLETE) + VulkanError("Could not get cache data (incomplete)"); + CheckVulkanError(result, "Could not get cache data"); + buffer.resize(dataSize); + return buffer; +} + +///////////////////////////////////////////////////////////////////////////// + inline VulkanRenderPass::VulkanRenderPass(VulkanDevice *device, VkRenderPass renderPass) : device(device), renderPass(renderPass) { } diff --git a/libraries/ZVulkan/include/zvulkan/vulkansurface.h b/libraries/ZVulkan/include/zvulkan/vulkansurface.h new file mode 100644 index 000000000..398bfd39a --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkansurface.h @@ -0,0 +1,20 @@ +#pragma once + +#include "vulkaninstance.h" + +class VulkanSurface +{ +public: + VulkanSurface(std::shared_ptr instance, VkSurfaceKHR surface); + ~VulkanSurface(); + + std::shared_ptr Instance; + VkSurfaceKHR Surface = VK_NULL_HANDLE; + +#ifdef VK_USE_PLATFORM_WIN32_KHR + + VulkanSurface(std::shared_ptr instance, HWND window); + HWND Window = 0; + +#endif +}; diff --git a/libraries/ZVulkan/include/zvulkan/vulkanswapchain.h b/libraries/ZVulkan/include/zvulkan/vulkanswapchain.h new file mode 100644 index 000000000..cc9a9ed22 --- /dev/null +++ b/libraries/ZVulkan/include/zvulkan/vulkanswapchain.h @@ -0,0 +1,50 @@ +#pragma once + +#include "vulkandevice.h" +#include "vulkanobjects.h" + +class VulkanSemaphore; +class VulkanFence; + +class VulkanSwapChain +{ +public: + VulkanSwapChain(VulkanDevice* device); + ~VulkanSwapChain(); + + void Create(int width, int height, int imageCount, bool vsync, bool hdr, bool exclusivefullscreen); + bool Lost() const { return lost; } + + int Width() const { return actualExtent.width; } + int Height() const { return actualExtent.height; } + VkSurfaceFormatKHR Format() const { return format; } + + int ImageCount() const { return (int)images.size(); } + VulkanImage* GetImage(int index) { return images[index].get(); } + VulkanImageView* GetImageView(int index) { return views[index].get(); } + + int AcquireImage(VulkanSemaphore* semaphore = nullptr, VulkanFence* fence = nullptr); + void QueuePresent(int imageIndex, VulkanSemaphore* semaphore = nullptr); + +private: + void SelectFormat(bool hdr); + void SelectPresentMode(bool vsync, bool exclusivefullscreen); + + bool CreateSwapchain(int width, int height, int imageCount, bool exclusivefullscreen, VkSwapchainKHR oldSwapChain = VK_NULL_HANDLE); + + std::vector GetSurfaceFormats(); + std::vector GetPresentModes(bool exclusivefullscreen); + + VulkanDevice* device = nullptr; + bool lost = true; + + VkExtent2D actualExtent = {}; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + VkSurfaceFormatKHR format = {}; + VkPresentModeKHR presentMode; + std::vector> images; + std::vector> views; + + VulkanSwapChain(const VulkanSwapChain&) = delete; + VulkanSwapChain& operator=(const VulkanSwapChain&) = delete; +}; diff --git a/libraries/ZVulkan/src/glslang/LICENSE.txt b/libraries/ZVulkan/src/glslang/LICENSE.txt new file mode 100644 index 000000000..054e68a46 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/LICENSE.txt @@ -0,0 +1,1016 @@ +Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code +generation. Glslang proper requires use of a number of licenses, one that covers +preprocessing and others that covers non-preprocessing. + +Bison was removed long ago. You can build glslang from the source grammar, +using tools of your choice, without using bison or any bison files. + +Other parts, outside of glslang proper, include: + +- gl_types.h, only needed for OpenGL-like reflection, and can be left out of + a parse and codegen project. See it for its license. + +- update_glslang_sources.py, which is not part of the project proper and does + not need to be used. + +- the SPIR-V "remapper", which is optional, but has the same license as + glslang proper + +- Google tests and SPIR-V tools, and anything in the external subdirectory + are external and optional; see them for their respective licenses. + +-------------------------------------------------------------------------------- + +The core of glslang-proper, minus the preprocessor is licenced as follows: + +-------------------------------------------------------------------------------- +3-Clause BSD License +-------------------------------------------------------------------------------- + +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) +// +// 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 3Dlabs Inc. Ltd. 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 HOLDERS 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. +// + + +-------------------------------------------------------------------------------- +2-Clause BSD License +-------------------------------------------------------------------------------- + +Copyright 2020 The Khronos Group Inc + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +-------------------------------------------------------------------------------- +The MIT License +-------------------------------------------------------------------------------- + +Copyright 2020 The Khronos Group Inc + +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. + + +-------------------------------------------------------------------------------- +APACHE LICENSE, VERSION 2.0 +-------------------------------------------------------------------------------- + + 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. + + +-------------------------------------------------------------------------------- +GPL 3 with special bison exception +-------------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +Bison Exception + +As a special exception, you may create a larger work that contains part or all +of the Bison parser skeleton and distribute that work under terms of your +choice, so long as that work isn't itself a parser generator using the skeleton +or a modified version thereof as a parser skeleton. Alternatively, if you +modify or redistribute the parser skeleton itself, you may (at your option) +remove this special exception, which will cause the skeleton and the resulting +Bison output files to be licensed under the GNU General Public License without +this special exception. + +This special exception was added by the Free Software Foundation in version +2.2 of Bison. + + END OF TERMS AND CONDITIONS + +-------------------------------------------------------------------------------- +================================================================================ +-------------------------------------------------------------------------------- + +The preprocessor has the core licenses stated above, plus additional licences: + +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are 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 Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS 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. 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 MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ diff --git a/libraries/glslang/OGLCompilersDLL/InitializeDll.cpp b/libraries/ZVulkan/src/glslang/OGLCompilersDLL/InitializeDll.cpp similarity index 100% rename from libraries/glslang/OGLCompilersDLL/InitializeDll.cpp rename to libraries/ZVulkan/src/glslang/OGLCompilersDLL/InitializeDll.cpp diff --git a/libraries/glslang/OGLCompilersDLL/InitializeDll.h b/libraries/ZVulkan/src/glslang/OGLCompilersDLL/InitializeDll.h similarity index 100% rename from libraries/glslang/OGLCompilersDLL/InitializeDll.h rename to libraries/ZVulkan/src/glslang/OGLCompilersDLL/InitializeDll.h diff --git a/libraries/glslang/glslang/GenericCodeGen/CodeGen.cpp b/libraries/ZVulkan/src/glslang/glslang/GenericCodeGen/CodeGen.cpp similarity index 100% rename from libraries/glslang/glslang/GenericCodeGen/CodeGen.cpp rename to libraries/ZVulkan/src/glslang/glslang/GenericCodeGen/CodeGen.cpp diff --git a/libraries/glslang/glslang/GenericCodeGen/Link.cpp b/libraries/ZVulkan/src/glslang/glslang/GenericCodeGen/Link.cpp similarity index 100% rename from libraries/glslang/glslang/GenericCodeGen/Link.cpp rename to libraries/ZVulkan/src/glslang/glslang/GenericCodeGen/Link.cpp diff --git a/libraries/glslang/glslang/Include/BaseTypes.h b/libraries/ZVulkan/src/glslang/glslang/Include/BaseTypes.h similarity index 87% rename from libraries/glslang/glslang/Include/BaseTypes.h rename to libraries/ZVulkan/src/glslang/glslang/Include/BaseTypes.h index 6d4b4ff8e..c8203c223 100644 --- a/libraries/glslang/glslang/Include/BaseTypes.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/BaseTypes.h @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -61,8 +62,13 @@ enum TBasicType { EbtSampler, EbtStruct, EbtBlock, - EbtAccStructNV, + EbtAccStruct, EbtReference, + EbtRayQuery, +#ifndef GLSLANG_WEB + // SPIR-V type defined by spirv_type + EbtSpirvType, +#endif // HLSL types that live only temporarily. EbtString, @@ -89,12 +95,15 @@ enum TStorageQualifier { EvqUniform, // read only, shared with app EvqBuffer, // read/write, shared with app EvqShared, // compute shader's read/write 'shared' qualifier +#ifndef GLSLANG_WEB + EvqSpirvStorageClass, // spirv_storage_class +#endif - EvqPayloadNV, - EvqPayloadInNV, - EvqHitAttrNV, - EvqCallableDataNV, - EvqCallableDataInNV, + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, // parameters EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter @@ -226,9 +235,15 @@ enum TBuiltInVariable { EbvViewIndex, EbvDeviceIndex, + EbvShadingRateKHR, + EbvPrimitiveShadingRateKHR, + EbvFragSizeEXT, EbvFragInvocationCountEXT, + EbvSecondaryFragDataEXT, + EbvSecondaryFragColorEXT, + EbvViewportMaskNV, EbvSecondaryPositionNV, EbvSecondaryViewportMaskNV, @@ -238,20 +253,24 @@ enum TBuiltInVariable { EbvFragmentSizeNV, EbvInvocationsPerPixelNV, // ray tracing - EbvLaunchIdNV, - EbvLaunchSizeNV, - EbvInstanceCustomIndexNV, - EbvWorldRayOriginNV, - EbvWorldRayDirectionNV, - EbvObjectRayOriginNV, - EbvObjectRayDirectionNV, - EbvRayTminNV, - EbvRayTmaxNV, - EbvHitTNV, - EbvHitKindNV, - EbvObjectToWorldNV, - EbvWorldToObjectNV, - EbvIncomingRayFlagsNV, + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + EbvCurrentRayTimeNV, // barycentrics EbvBaryCoordNV, EbvBaryCoordNoPerspNV, @@ -310,6 +329,9 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q) case EvqGlobal: return "global"; break; case EvqConst: return "const"; break; case EvqConstReadOnly: return "const (read only)"; break; +#ifndef GLSLANG_WEB + case EvqSpirvStorageClass: return "spirv_storage_class"; break; +#endif case EvqVaryingIn: return "in"; break; case EvqVaryingOut: return "out"; break; case EvqUniform: return "uniform"; break; @@ -328,11 +350,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q) case EvqPointCoord: return "gl_PointCoord"; break; case EvqFragColor: return "fragColor"; break; case EvqFragDepth: return "gl_FragDepth"; break; - case EvqPayloadNV: return "rayPayloadNV"; break; - case EvqPayloadInNV: return "rayPayloadInNV"; break; - case EvqHitAttrNV: return "hitAttributeNV"; break; - case EvqCallableDataNV: return "callableDataNV"; break; - case EvqCallableDataInNV: return "callableDataInNV"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; default: return "unknown qualifier"; } } @@ -428,6 +450,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v) case EbvFragSizeEXT: return "FragSizeEXT"; case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT"; + case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT"; + case EbvViewportMaskNV: return "ViewportMaskNV"; case EbvSecondaryPositionNV: return "SecondaryPositionNV"; case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; @@ -436,20 +461,22 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v) case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; case EbvFragmentSizeNV: return "FragmentSizeNV"; case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; - case EbvLaunchIdNV: return "LaunchIdNV"; - case EbvLaunchSizeNV: return "LaunchSizeNV"; - case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV"; - case EbvWorldRayOriginNV: return "WorldRayOriginNV"; - case EbvWorldRayDirectionNV: return "WorldRayDirectionNV"; - case EbvObjectRayOriginNV: return "ObjectRayOriginNV"; - case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV"; - case EbvRayTminNV: return "ObjectRayTminNV"; - case EbvRayTmaxNV: return "ObjectRayTmaxNV"; - case EbvHitTNV: return "HitTNV"; - case EbvHitKindNV: return "HitKindNV"; - case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV"; - case EbvObjectToWorldNV: return "ObjectToWorldNV"; - case EbvWorldToObjectNV: return "WorldToObjectNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + case EbvCurrentRayTimeNV: return "CurrentRayTimeNV"; case EbvBaryCoordNV: return "BaryCoordNV"; case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; @@ -468,6 +495,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v) case EbvWarpID: return "WarpIDNV"; case EbvSMID: return "SMIDNV"; + case EbvShadingRateKHR: return "ShadingRateKHR"; + case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR"; + default: return "unknown built-in variable"; } } diff --git a/libraries/glslang/glslang/Include/Common.h b/libraries/ZVulkan/src/glslang/glslang/Include/Common.h similarity index 96% rename from libraries/glslang/glslang/Include/Common.h rename to libraries/ZVulkan/src/glslang/glslang/Include/Common.h index ddc1f5643..4f888ae16 100644 --- a/libraries/glslang/glslang/Include/Common.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/Common.h @@ -37,6 +37,17 @@ #ifndef _COMMON_INCLUDED_ #define _COMMON_INCLUDED_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) #include @@ -94,18 +105,6 @@ std::string to_string(const T& val) { #pragma warning(disable : 4201) // nameless union #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "PoolAlloc.h" // @@ -196,6 +195,10 @@ template , class PRED = std::equal_t class TUnorderedMap : public std::unordered_map > > { }; +template > +class TSet : public std::set > { +}; + // // Persistent string memory. Should only be used for strings that survive // across compiles/links. @@ -288,6 +291,18 @@ template bool IsMultipleOfPow2(T number, int powerOf2) return ! (number & (powerOf2 - 1)); } +// Returns log2 of an integer power of 2. +// T should be integral. +template int IntLog2(T n) +{ + assert(IsPow2(n)); + int result = 0; + while ((T(1) << result) != n) { + result++; + } + return result; +} + } // end namespace glslang #endif // _COMMON_INCLUDED_ diff --git a/libraries/glslang/glslang/Include/ConstantUnion.h b/libraries/ZVulkan/src/glslang/glslang/Include/ConstantUnion.h similarity index 99% rename from libraries/glslang/glslang/Include/ConstantUnion.h rename to libraries/ZVulkan/src/glslang/glslang/Include/ConstantUnion.h index 76b2d9c08..c4ffb8577 100644 --- a/libraries/glslang/glslang/Include/ConstantUnion.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/ConstantUnion.h @@ -921,7 +921,7 @@ public: else unionArray = new TConstUnionVector(size); } - TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { } + TConstUnionArray(const TConstUnionArray& a) = default; TConstUnionArray(const TConstUnionArray& a, int start, int size) { unionArray = new TConstUnionVector(size); diff --git a/libraries/glslang/glslang/Include/InfoSink.h b/libraries/ZVulkan/src/glslang/glslang/Include/InfoSink.h similarity index 100% rename from libraries/glslang/glslang/Include/InfoSink.h rename to libraries/ZVulkan/src/glslang/glslang/Include/InfoSink.h diff --git a/libraries/glslang/glslang/Include/InitializeGlobals.h b/libraries/ZVulkan/src/glslang/glslang/Include/InitializeGlobals.h similarity index 100% rename from libraries/glslang/glslang/Include/InitializeGlobals.h rename to libraries/ZVulkan/src/glslang/glslang/Include/InitializeGlobals.h diff --git a/libraries/glslang/glslang/Include/PoolAlloc.h b/libraries/ZVulkan/src/glslang/glslang/Include/PoolAlloc.h similarity index 100% rename from libraries/glslang/glslang/Include/PoolAlloc.h rename to libraries/ZVulkan/src/glslang/glslang/Include/PoolAlloc.h diff --git a/libraries/glslang/glslang/Include/ResourceLimits.h b/libraries/ZVulkan/src/glslang/glslang/Include/ResourceLimits.h similarity index 99% rename from libraries/glslang/glslang/Include/ResourceLimits.h rename to libraries/ZVulkan/src/glslang/glslang/Include/ResourceLimits.h index 106b21d9c..b670cf163 100644 --- a/libraries/glslang/glslang/Include/ResourceLimits.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/ResourceLimits.h @@ -142,6 +142,7 @@ struct TBuiltInResource { int maxTaskWorkGroupSizeY_NV; int maxTaskWorkGroupSizeZ_NV; int maxMeshViewCountNV; + int maxDualSourceDrawBuffersEXT; TLimits limits; }; diff --git a/libraries/glslang/glslang/Include/ShHandle.h b/libraries/ZVulkan/src/glslang/glslang/Include/ShHandle.h similarity index 100% rename from libraries/glslang/glslang/Include/ShHandle.h rename to libraries/ZVulkan/src/glslang/glslang/Include/ShHandle.h diff --git a/libraries/ZVulkan/src/glslang/glslang/Include/SpirvIntrinsics.h b/libraries/ZVulkan/src/glslang/glslang/Include/SpirvIntrinsics.h new file mode 100644 index 000000000..e7a999d40 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/Include/SpirvIntrinsics.h @@ -0,0 +1,136 @@ +// +// Copyright(C) 2021 Advanced Micro Devices, 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 3Dlabs Inc. Ltd. 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 HOLDERS 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. +// + +#pragma once + +#ifndef GLSLANG_WEB + +// +// GL_EXT_spirv_intrinsics +// +#include "Common.h" + +namespace glslang { + +class TIntermTyped; +class TIntermConstantUnion; +class TType; + +// SPIR-V requirements +struct TSpirvRequirement { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // capability = [..] + TSet extensions; + // extension = [..] + TSet capabilities; +}; + +// SPIR-V execution modes +struct TSpirvExecutionMode { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // spirv_execution_mode + TMap> modes; + // spirv_execution_mode_id + TMap > modeIds; +}; + +// SPIR-V decorations +struct TSpirvDecorate { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // spirv_decorate + TMap > decorates; + // spirv_decorate_id + TMap > decorateIds; + // spirv_decorate_string + TMap > decorateStrings; +}; + +// SPIR-V instruction +struct TSpirvInstruction { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSpirvInstruction() { set = ""; id = -1; } + + bool operator==(const TSpirvInstruction& rhs) const { return set == rhs.set && id == rhs.id; } + bool operator!=(const TSpirvInstruction& rhs) const { return !operator==(rhs); } + + // spirv_instruction + TString set; + int id; +}; + +// SPIR-V type parameter +struct TSpirvTypeParameter { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSpirvTypeParameter(const TIntermConstantUnion* arg) { isConstant = true; constant = arg; } + TSpirvTypeParameter(const TType* arg) { isConstant = false; type = arg; } + + bool operator==(const TSpirvTypeParameter& rhs) const + { + return isConstant == rhs.isConstant && ((isConstant && constant == rhs.constant) || (!isConstant && type == rhs.type)); + } + bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); } + + bool isConstant; + union { + const TIntermConstantUnion* constant; + const TType* type; + }; +}; + +typedef TVector TSpirvTypeParameters; + +// SPIR-V type +struct TSpirvType { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + bool operator==(const TSpirvType& rhs) const + { + return spirvInst == rhs.spirvInst && typeParams == rhs.typeParams; + } + bool operator!=(const TSpirvType& rhs) const { return !operator==(rhs); } + + // spirv_type + TSpirvInstruction spirvInst; + TSpirvTypeParameters typeParams; +}; + +} // end namespace glslang + +#endif // GLSLANG_WEB diff --git a/libraries/glslang/glslang/Include/Types.h b/libraries/ZVulkan/src/glslang/glslang/Include/Types.h similarity index 89% rename from libraries/glslang/glslang/Include/Types.h rename to libraries/ZVulkan/src/glslang/glslang/Include/Types.h index 3572099e3..a6bf191d7 100644 --- a/libraries/glslang/glslang/Include/Types.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/Types.h @@ -3,6 +3,7 @@ // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2015-2016 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -43,11 +44,14 @@ #include "../Include/BaseTypes.h" #include "../Public/ShaderLang.h" #include "arrays.h" +#include "SpirvIntrinsics.h" #include namespace glslang { +class TIntermAggregate; + const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed @@ -114,6 +118,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler, #endif bool is1D() const { return dim == Esd1D; } + bool is2D() const { return dim == Esd2D; } bool isBuffer() const { return dim == EsdBuffer; } bool isRect() const { return dim == EsdRect; } bool isSubpass() const { return dim == EsdSubpass; } @@ -405,6 +410,7 @@ enum TLayoutFormat { ElfRg8i, ElfR16i, ElfR8i, + ElfR64i, ElfIntGuard, // to help with comparisons @@ -422,6 +428,7 @@ enum TLayoutFormat { ElfRg8ui, ElfR16ui, ElfR8ui, + ElfR64ui, ElfCount }; @@ -472,6 +479,17 @@ enum TInterlockOrdering { EioCount, }; +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + class TQualifier { public: static const int layoutNotSet = -1; @@ -484,7 +502,11 @@ public: declaredBuiltIn = EbvNone; #ifndef GLSLANG_WEB noContraction = false; + nullInit = false; + spirvByReference = false; + spirvLiteral = false; #endif + defaultBlock = false; } // drop qualifiers that don't belong in a temporary variable @@ -497,7 +519,15 @@ public: clearMemory(); specConstant = false; nonUniform = false; + nullInit = false; + defaultBlock = false; clearLayout(); +#ifndef GLSLANG_WEB + spirvStorageClass = -1; + spirvDecorate = nullptr; + spirvByReference = false; + spirvLiteral = false; +#endif } void clearInterstage() @@ -532,6 +562,7 @@ public: queuefamilycoherent = false; workgroupcoherent = false; subgroupcoherent = false; + shadercallcoherent = false; nonprivate = false; volatil = false; restrict = false; @@ -553,6 +584,8 @@ public: // having a constant_id is not sufficient: expressions have no id, but are still specConstant bool specConstant : 1; bool nonUniform : 1; + bool explicitOffset : 1; + bool defaultBlock : 1; // default blocks with matching names have structures merged when linking #ifdef GLSLANG_WEB bool isWriteOnly() const { return false; } @@ -571,6 +604,12 @@ public: bool isNoContraction() const { return false; } void setNoContraction() { } bool isPervertexNV() const { return false; } + void setNullInit() { } + bool isNullInit() const { return false; } + void setSpirvByReference() { } + bool isSpirvByReference() { return false; } + void setSpirvLiteral() { } + bool isSpirvLiteral() { return false; } #else bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects bool nopersp : 1; @@ -590,7 +629,11 @@ public: bool queuefamilycoherent : 1; bool workgroupcoherent : 1; bool subgroupcoherent : 1; + bool shadercallcoherent : 1; bool nonprivate : 1; + bool nullInit : 1; + bool spirvByReference : 1; + bool spirvLiteral : 1; bool isWriteOnly() const { return writeonly; } bool isReadOnly() const { return readonly; } bool isRestrict() const { return restrict; } @@ -599,11 +642,11 @@ public: bool isSample() const { return sample; } bool isMemory() const { - return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; } bool isMemoryQualifierImageAndSSBOOnly() const { - return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; } bool bufferReferenceNeedsVulkanMemoryModel() const { @@ -626,6 +669,12 @@ public: bool isNoContraction() const { return noContraction; } void setNoContraction() { noContraction = true; } bool isPervertexNV() const { return pervertexNV; } + void setNullInit() { nullInit = true; } + bool isNullInit() const { return nullInit; } + void setSpirvByReference() { spirvByReference = true; } + bool isSpirvByReference() const { return spirvByReference; } + void setSpirvLiteral() { spirvLiteral = true; } + bool isSpirvLiteral() const { return spirvLiteral; } #endif bool isPipeInput() const @@ -731,6 +780,46 @@ public: } } + TBlockStorageClass getBlockStorage() const { + if (storage == EvqUniform && !isPushConstant()) { + return EbsUniform; + } + else if (storage == EvqUniform) { + return EbsPushConstant; + } + else if (storage == EvqBuffer) { + return EbsStorageBuffer; + } + return EbsNone; + } + + void setBlockStorage(TBlockStorageClass newBacking) { +#ifndef GLSLANG_WEB + layoutPushConstant = (newBacking == EbsPushConstant); +#endif + switch (newBacking) { + case EbsUniform : + if (layoutPacking == ElpStd430) { + // std430 would not be valid + layoutPacking = ElpStd140; + } + storage = EvqUniform; + break; + case EbsStorageBuffer : + storage = EvqBuffer; + break; +#ifndef GLSLANG_WEB + case EbsPushConstant : + storage = EvqUniform; + layoutSet = TQualifier::layoutSetEnd; + layoutBinding = TQualifier::layoutBindingEnd; + break; +#endif + default: + break; + } + } + #ifdef GLSLANG_WEB bool isPerView() const { return false; } bool isTaskMemory() const { return false; } @@ -739,6 +828,12 @@ public: bool isPerPrimitive() const { return perPrimitiveNV; } bool isPerView() const { return perViewNV; } bool isTaskMemory() const { return perTaskNV; } + bool isAnyPayload() const { + return storage == EvqPayload || storage == EvqPayloadIn; + } + bool isAnyCallable() const { + return storage == EvqCallableData || storage == EvqCallableDataIn; + } // True if this type of IO is supposed to be arrayed with extra level for per-vertex data bool isArrayedIo(EShLanguage language) const @@ -773,7 +868,7 @@ public: layoutViewportRelative = false; // -2048 as the default value indicating layoutSecondaryViewportRelative is not set layoutSecondaryViewportRelativeOffset = -2048; - layoutShaderRecordNV = false; + layoutShaderRecord = false; layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; layoutFormat = ElfNone; #endif @@ -812,7 +907,7 @@ public: hasAnyLocation() || hasStream() || hasFormat() || - isShaderRecordNV() || + isShaderRecord() || isPushConstant() || hasBufferReference(); } @@ -821,6 +916,7 @@ public: return hasNonXfbLayout() || hasXfb(); } + TLayoutMatrix layoutMatrix : 3; TLayoutPacking layoutPacking : 4; int layoutOffset; @@ -871,7 +967,11 @@ public: bool layoutPassthrough; bool layoutViewportRelative; int layoutSecondaryViewportRelativeOffset; - bool layoutShaderRecordNV; + bool layoutShaderRecord; + + // GL_EXT_spirv_intrinsics + int spirvStorageClass; + TSpirvDecorate* spirvDecorate; #endif bool hasUniformLayout() const @@ -942,7 +1042,7 @@ public: bool hasAttachment() const { return false; } TLayoutFormat getFormat() const { return ElfNone; } bool isPushConstant() const { return false; } - bool isShaderRecordNV() const { return false; } + bool isShaderRecord() const { return false; } bool hasBufferReference() const { return false; } bool hasBufferReferenceAlign() const { return false; } bool isNonUniform() const { return false; } @@ -993,7 +1093,7 @@ public: } TLayoutFormat getFormat() const { return layoutFormat; } bool isPushConstant() const { return layoutPushConstant; } - bool isShaderRecordNV() const { return layoutShaderRecordNV; } + bool isShaderRecord() const { return layoutShaderRecord; } bool hasBufferReference() const { return layoutBufferReference; } bool hasBufferReferenceAlign() const { @@ -1003,6 +1103,15 @@ public: { return nonUniform; } + + // GL_EXT_spirv_intrinsics + bool hasSprivDecorate() const { return spirvDecorate != nullptr; } + void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr); + void setSpirvDecorateId(int decoration, const TIntermAggregate* args); + void setSpirvDecorateString(int decoration, const TIntermAggregate* args); + const TSpirvDecorate& getSpirvDecorate() const { assert(spirvDecorate); return *spirvDecorate; } + TSpirvDecorate& getSpirvDecorate() { assert(spirvDecorate); return *spirvDecorate; } + TString getSpirvDecorateQualifierString() const; #endif bool hasSpecConstantId() const { @@ -1101,6 +1210,8 @@ public: case ElfR32ui: return "r32ui"; case ElfR16ui: return "r16ui"; case ElfR8ui: return "r8ui"; + case ElfR64ui: return "r64ui"; + case ElfR64i: return "r64i"; default: return "none"; } } @@ -1219,6 +1330,7 @@ struct TShaderQualifiers { bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + bool layoutPrimitiveCulling; // true if layout primitive_culling set TLayoutDepth getDepth() const { return layoutDepth; } #else TLayoutDepth getDepth() const { return EldNone; } @@ -1252,6 +1364,7 @@ struct TShaderQualifiers { layoutOverrideCoverage = false; layoutDerivativeGroupQuads = false; layoutDerivativeGroupLinear = false; + layoutPrimitiveCulling = false; primitives = TQualifier::layoutNotSet; interlockOrdering = EioNone; #endif @@ -1315,6 +1428,8 @@ struct TShaderQualifiers { primitives = src.primitives; if (src.interlockOrdering != EioNone) interlockOrdering = src.interlockOrdering; + if (src.layoutPrimitiveCulling) + layoutPrimitiveCulling = src.layoutPrimitiveCulling; #endif } }; @@ -1341,6 +1456,10 @@ public: const TType* userDef; TSourceLoc loc; TArraySizes* typeParameters; +#ifndef GLSLANG_WEB + // SPIR-V type defined by spirv_type directive + TSpirvType* spirvType; +#endif #ifdef GLSLANG_WEB bool isCoopmat() const { return false; } @@ -1359,6 +1478,9 @@ public: loc = l; typeParameters = nullptr; coopmat = false; +#ifndef GLSLANG_WEB + spirvType = nullptr; +#endif } void initQualifiers(bool global = false) @@ -1395,6 +1517,11 @@ public: return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; } +#ifndef GLSLANG_WEB + // GL_EXT_spirv_intrinsics + void setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams = nullptr); +#endif + // "Image" is a superset of "Subpass" bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } @@ -1412,6 +1539,9 @@ public: bool isVector = false) : basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { sampler.clear(); qualifier.clear(); @@ -1423,6 +1553,9 @@ public: bool isVector = false) : basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { sampler.clear(); qualifier.clear(); @@ -1436,6 +1569,9 @@ public: basicType(p.basicType), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) +#ifndef GLSLANG_WEB + , spirvType(p.spirvType) +#endif { if (basicType == EbtSampler) sampler = p.sampler; @@ -1470,6 +1606,9 @@ public: basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), sampler(sampler), typeParameters(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { qualifier.clear(); qualifier.storage = q; @@ -1520,6 +1659,9 @@ public: TType(TTypeList* userDef, const TString& n) : basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { sampler.clear(); qualifier.clear(); @@ -1529,6 +1671,9 @@ public: TType(TTypeList* userDef, const TString& n, const TQualifier& q) : basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { sampler.clear(); typeName = NewPoolTString(n.c_str()); @@ -1537,6 +1682,9 @@ public: explicit TType(TBasicType t, const TType &p, const TString& n) : basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) +#ifndef GLSLANG_WEB + , spirvType(nullptr) +#endif { assert(t == EbtReference); typeName = NewPoolTString(n.c_str()); @@ -1567,6 +1715,9 @@ public: referentType = copyOf.referentType; } typeParameters = copyOf.typeParameters; +#ifndef GLSLANG_WEB + spirvType = copyOf.spirvType; +#endif coopmat = copyOf.isCoopMat(); } @@ -1612,6 +1763,23 @@ public: assert(fieldName); return *fieldName; } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } virtual TBasicType getBasicType() const { return basicType; } virtual const TSampler& getSampler() const { return sampler; } @@ -1640,6 +1808,7 @@ public: virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); } virtual bool isVector() const { return vectorSize > 1 || vector1; } virtual bool isMatrix() const { return matrixCols ? true : false; } virtual bool isArray() const { return arraySizes != nullptr; } @@ -1670,7 +1839,7 @@ public: } virtual bool isOpaque() const { return basicType == EbtSampler #ifndef GLSLANG_WEB - || basicType == EbtAtomicUint || basicType == EbtAccStructNV + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery #endif ; } virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } @@ -1918,8 +2087,6 @@ public: } } - - const char* getBasicString() const { return TType::getBasicString(basicType); @@ -1946,8 +2113,11 @@ public: case EbtAtomicUint: return "atomic_uint"; case EbtStruct: return "structure"; case EbtBlock: return "block"; - case EbtAccStructNV: return "accelerationStructureNV"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; case EbtReference: return "reference"; + case EbtString: return "string"; + case EbtSpirvType: return "spirv_type"; #endif default: return "unknown type"; } @@ -1968,6 +2138,9 @@ public: const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + if (qualifier.hasSprivDecorate()) + appendStr(qualifier.getSpirvDecorateQualifierString().c_str()); + if (qualifier.hasLayout()) { // To reduce noise, skip this if the only layout is an xfb_buffer // with no triggering xfb_offset. @@ -2056,7 +2229,7 @@ public: appendStr(" layoutSecondaryViewportRelativeOffset="); appendInt(qualifier.layoutSecondaryViewportRelativeOffset); } - if (qualifier.layoutShaderRecordNV) + if (qualifier.layoutShaderRecord) appendStr(" shaderRecordNV"); appendStr(")"); @@ -2099,6 +2272,8 @@ public: appendStr(" workgroupcoherent"); if (qualifier.subgroupcoherent) appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); if (qualifier.nonprivate) appendStr(" nonprivate"); if (qualifier.volatil) @@ -2113,6 +2288,12 @@ public: appendStr(" specialization-constant"); if (qualifier.nonUniform) appendStr(" nonuniform"); + if (qualifier.isNullInit()) + appendStr(" null-init"); + if (qualifier.isSpirvByReference()) + appendStr(" spirv_by_reference"); + if (qualifier.isSpirvLiteral()) + appendStr(" spirv_literal"); appendStr(" "); appendStr(getStorageQualifierString()); if (isArray()) { @@ -2232,6 +2413,17 @@ public: name += ';' ; } + // These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now. + // They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts. + bool isInconsistentGLPerVertexMember(const TString& name) const + { + if (name == "gl_SecondaryPositionNV" || + name == "gl_PositionPerViewNV") + return true; + return false; + } + + // Do two structure types match? They could be declared independently, // in different places, but still might satisfy the definition of matching. // From the spec: @@ -2247,22 +2439,48 @@ public: (isStruct() && right.isStruct() && structure == right.structure)) return true; - // Both being nullptr was caught above, now they both have to be structures of the same number of elements - if (!isStruct() || !right.isStruct() || - structure->size() != right.structure->size()) - return false; - // Structure names have to match if (*typeName != *right.typeName) return false; - // Compare the names and types of all the members, which have to match - for (unsigned int i = 0; i < structure->size(); ++i) { - if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) - return false; + // There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they + // are known inconsistencies. + bool isGLPerVertex = *typeName == "gl_PerVertex"; - if (*(*structure)[i].type != *(*right.structure)[i].type) - return false; + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + (structure->size() != right.structure->size() && !isGLPerVertex)) + return false; + + // Compare the names and types of all the members, which have to match + for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) { + if (li < structure->size() && ri < right.structure->size()) { + if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) { + if (*(*structure)[li].type != *(*right.structure)[ri].type) + return false; + } else { + // If one of the members is something that's inconsistently declared, skip over it + // for now. + if (isGLPerVertex) { + if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) { + ri--; + continue; + } else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) { + li--; + continue; + } + } else { + return false; + } + } + // If we get here, then there should only be inconsistently declared members left + } else if (li < structure->size()) { + if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) + return false; + } else { + if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) + return false; + } } return true; @@ -2312,6 +2530,15 @@ public: (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); } +#ifndef GLSLANG_WEB + // See if two type's SPIR-V type contents match + bool sameSpirvType(const TType& right) const + { + return ((spirvType == nullptr && right.spirvType == nullptr) || + (spirvType != nullptr && right.spirvType != nullptr && *spirvType == *right.spirvType)); + } +#endif + // See if two type's elements match in all ways except basic type bool sameElementShape(const TType& right) const { @@ -2350,7 +2577,11 @@ public: // See if two types match in all ways (just the actual type, not qualification) bool operator==(const TType& right) const { +#ifndef GLSLANG_WEB + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right) && sameSpirvType(right); +#else return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); +#endif } bool operator!=(const TType& right) const @@ -2369,6 +2600,10 @@ public: return 0; } +#ifndef GLSLANG_WEB + const TSpirvType& getSpirvType() const { assert(spirvType); return *spirvType; } +#endif + protected: // Require consumer to pick between deep copy and shallow copy. TType(const TType& type); @@ -2381,6 +2616,19 @@ protected: { shallowCopy(copyOf); +#ifndef GLSLANG_WEB + // GL_EXT_spirv_intrinsics + if (copyOf.qualifier.spirvDecorate) { + qualifier.spirvDecorate = new TSpirvDecorate; + *qualifier.spirvDecorate = *copyOf.qualifier.spirvDecorate; + } + + if (copyOf.spirvType) { + spirvType = new TSpirvType; + *spirvType = *copyOf.spirvType; + } +#endif + if (copyOf.arraySizes) { arraySizes = new TArraySizes; *arraySizes = *copyOf.arraySizes; @@ -2440,6 +2688,9 @@ protected: TString *typeName; // for structure type name TSampler sampler; TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +#ifndef GLSLANG_WEB + TSpirvType* spirvType; // SPIR-V type defined by spirv_type directive +#endif }; } // end namespace glslang diff --git a/libraries/glslang/glslang/Include/arrays.h b/libraries/ZVulkan/src/glslang/glslang/Include/arrays.h similarity index 100% rename from libraries/glslang/glslang/Include/arrays.h rename to libraries/ZVulkan/src/glslang/glslang/Include/arrays.h diff --git a/libraries/glslang/glslang/MachineIndependent/pch.cpp b/libraries/ZVulkan/src/glslang/glslang/Include/build_info.h similarity index 51% rename from libraries/glslang/glslang/MachineIndependent/pch.cpp rename to libraries/ZVulkan/src/glslang/glslang/Include/build_info.h index b7a08654a..661c4a3c1 100644 --- a/libraries/glslang/glslang/MachineIndependent/pch.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/Include/build_info.h @@ -1,5 +1,5 @@ +// Copyright (C) 2020 The Khronos Group Inc. // -// Copyright (C) 2018 The Khronos Group Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -14,7 +14,7 @@ // disclaimer in the documentation and/or other materials provided // with the distribution. // -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// Neither the name of The Khronos Group Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // @@ -30,6 +30,33 @@ // 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 "pch.h" +#ifndef GLSLANG_BUILD_INFO +#define GLSLANG_BUILD_INFO + +#define GLSLANG_VERSION_MAJOR 11 +#define GLSLANG_VERSION_MINOR 6 +#define GLSLANG_VERSION_PATCH 0 +#define GLSLANG_VERSION_FLAVOR "" + +#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \ + (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) > GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \ + (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) >= GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \ + (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) < GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \ + (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) <= GLSLANG_VERSION_PATCH))))) + +#endif // GLSLANG_BUILD_INFO diff --git a/libraries/glslang/glslang/Include/intermediate.h b/libraries/ZVulkan/src/glslang/glslang/Include/intermediate.h similarity index 95% rename from libraries/glslang/glslang/Include/intermediate.h rename to libraries/ZVulkan/src/glslang/glslang/Include/intermediate.h index 29d58ca63..1e6ab4aa7 100644 --- a/libraries/glslang/glslang/Include/intermediate.h +++ b/libraries/ZVulkan/src/glslang/glslang/Include/intermediate.h @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -70,6 +71,9 @@ enum TOperator { EOpFunctionCall, EOpFunction, // For function definition EOpParameters, // an aggregate listing the parameters to a function +#ifndef GLSLANG_WEB + EOpSpirvInst, +#endif // // Unary operators @@ -279,6 +283,12 @@ enum TOperator { EOpConvUvec2ToPtr, EOpConvPtrToUvec2, + // uint64_t -> accelerationStructureEXT + EOpConvUint64ToAccStruct, + + // uvec2 -> accelerationStructureEXT + EOpConvUvec2ToAccStruct, + // // binary operations // @@ -586,6 +596,7 @@ enum TOperator { EOpTime, EOpAtomicAdd, + EOpAtomicSubtract, EOpAtomicMin, EOpAtomicMax, EOpAtomicAnd, @@ -621,17 +632,22 @@ enum TOperator { EOpIsHelperInvocation, + EOpDebugPrintf, + // // Branch // - EOpKill, // Fragment only + EOpKill, // Fragment only + EOpTerminateInvocation, // Fragment only + EOpDemote, // Fragment only + EOpTerminateRayKHR, // Any-hit only + EOpIgnoreIntersectionKHR, // Any-hit only EOpReturn, EOpBreak, EOpContinue, EOpCase, EOpDefault, - EOpDemote, // Fragment only // // Constructors @@ -748,6 +764,7 @@ enum TOperator { EOpConstructNonuniform, // expected to be transformed away, not present in final AST EOpConstructReference, EOpConstructCooperativeMatrix, + EOpConstructAccStruct, EOpConstructGuardEnd, // @@ -909,11 +926,43 @@ enum TOperator { EOpMul32x16, EOpTraceNV, - EOpReportIntersectionNV, + EOpTraceRayMotionNV, + EOpTraceKHR, + EOpReportIntersection, EOpIgnoreIntersectionNV, EOpTerminateRayNV, EOpExecuteCallableNV, + EOpExecuteCallableKHR, EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + // // HLSL operations // @@ -1091,6 +1140,8 @@ public: virtual TBasicType getBasicType() const { return type.getBasicType(); } virtual TQualifier& getQualifier() { return type.getQualifier(); } virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual TArraySizes* getArraySizes() { return type.getArraySizes(); } + virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); } virtual void propagatePrecision(TPrecisionQualifier); virtual int getVectorSize() const { return type.getVectorSize(); } virtual int getMatrixCols() const { return type.getMatrixCols(); } @@ -1199,6 +1250,7 @@ public: TOperator getFlowOp() const { return flowOp; } TIntermTyped* getExpression() const { return expression; } void setExpression(TIntermTyped* pExpression) { expression = pExpression; } + void updatePrecision(TPrecisionQualifier parentPrecision); protected: TOperator flowOp; TIntermTyped* expression; @@ -1230,15 +1282,15 @@ public: // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from // per process threadPoolAllocator, then it causes increased memory usage per compile // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& n, const TType& t) + TIntermSymbol(long long i, const TString& n, const TType& t) : TIntermTyped(t), id(i), #ifndef GLSLANG_WEB flattenSubset(-1), #endif constSubtree(nullptr) { name = n; } - virtual int getId() const { return id; } - virtual void changeId(int i) { id = i; } + virtual long long getId() const { return id; } + virtual void changeId(long long i) { id = i; } virtual const TString& getName() const { return name; } virtual void traverse(TIntermTraverser*); virtual TIntermSymbol* getAsSymbolNode() { return this; } @@ -1249,15 +1301,17 @@ public: TIntermTyped* getConstSubtree() const { return constSubtree; } #ifndef GLSLANG_WEB void setFlattenSubset(int subset) { flattenSubset = subset; } + virtual const TString& getAccessName() const; + int getFlattenSubset() const { return flattenSubset; } // -1 means full object #endif // This is meant for cases where a node has already been constructed, and // later on, it becomes necessary to switch to a different symbol. - virtual void switchId(int newId) { id = newId; } + virtual void switchId(long long newId) { id = newId; } protected: - int id; // the unique id of the symbol this node represents + long long id; // the unique id of the symbol this node represents #ifndef GLSLANG_WEB int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced #endif @@ -1566,8 +1620,15 @@ public: virtual TIntermUnary* getAsUnaryNode() { return this; } virtual const TIntermUnary* getAsUnaryNode() const { return this; } virtual void updatePrecision(); +#ifndef GLSLANG_WEB + void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; } + const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } +#endif protected: TIntermTyped* operand; +#ifndef GLSLANG_WEB + TSpirvInstruction spirvInst; +#endif }; typedef TVector TIntermSequence; @@ -1598,6 +1659,10 @@ public: bool getDebug() const { return debug; } void setPragmaTable(const TPragmaTable& pTable); const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +#ifndef GLSLANG_WEB + void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; } + const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } +#endif protected: TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator @@ -1608,6 +1673,9 @@ protected: bool optimize; bool debug; TPragmaTable* pragmaTable; +#ifndef GLSLANG_WEB + TSpirvInstruction spirvInst; +#endif }; // @@ -1625,8 +1693,11 @@ public: flatten(false), dontFlatten(false) {} virtual void traverse(TIntermTraverser*); virtual TIntermTyped* getCondition() const { return condition; } + virtual void setCondition(TIntermTyped* c) { condition = c; } virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual void setTrueBlock(TIntermTyped* tb) { trueBlock = tb; } virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual void setFalseBlock(TIntermTyped* fb) { falseBlock = fb; } virtual TIntermSelection* getAsSelectionNode() { return this; } virtual const TIntermSelection* getAsSelectionNode() const { return this; } diff --git a/libraries/glslang/glslang/MachineIndependent/Constant.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Constant.cpp similarity index 98% rename from libraries/glslang/glslang/MachineIndependent/Constant.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Constant.cpp index 98c2666fb..17b496c53 100644 --- a/libraries/glslang/glslang/MachineIndependent/Constant.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Constant.cpp @@ -2,7 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2018 Google, Inc. +// Copyright (C) 2018-2020 Google, Inc. // // All rights reserved. // @@ -42,6 +42,10 @@ #include #include +#ifdef _MSC_VER +#pragma warning(disable: 4146) // warning C4146: unary minus operator applied to unsigned type, result still unsigned +#endif + namespace { using namespace glslang; @@ -529,7 +533,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) case EbtDouble: case EbtFloat16: case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break; - case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break; + // Note: avoid UBSAN error regarding negating 0x80000000 + case EbtInt: newConstArray[i].setIConst( + unionArray[i].getIConst() == 0x80000000 + ? -0x7FFFFFFF - 1 + : -unionArray[i].getIConst()); + break; case EbtUint: newConstArray[i].setUConst(static_cast(-static_cast(unionArray[i].getUConst()))); break; #ifndef GLSLANG_WEB case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break; @@ -599,17 +608,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) newConstArray[i].setDConst(log(unionArray[i].getDConst())); break; case EOpExp2: - { - const double inv_log2_e = 0.69314718055994530941723212145818; - newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e)); - break; - } + newConstArray[i].setDConst(exp2(unionArray[i].getDConst())); + break; case EOpLog2: - { - const double log2_e = 1.4426950408889634073599246810019; - newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst())); - break; - } + newConstArray[i].setDConst(log2(unionArray[i].getDConst())); + break; case EOpSqrt: newConstArray[i].setDConst(sqrt(unionArray[i].getDConst())); break; @@ -1012,6 +1015,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) case EOpMin: case EOpMax: case EOpMix: + case EOpMod: case EOpClamp: case EOpLessThan: case EOpGreaterThan: @@ -1074,6 +1078,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) case EOpPow: newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); break; + case EOpMod: + { + double arg0 = childConstUnions[0][arg0comp].getDConst(); + double arg1 = childConstUnions[1][arg1comp].getDConst(); + double result = arg0 - arg1 * floor(arg0 / arg1); + newConstArray[comp].setDConst(result); + break; + } case EOpMin: switch(children[0]->getAsTyped()->getBasicType()) { case EbtFloat16: diff --git a/libraries/glslang/glslang/MachineIndependent/InfoSink.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/InfoSink.cpp similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/InfoSink.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/InfoSink.cpp diff --git a/libraries/glslang/glslang/MachineIndependent/Initialize.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Initialize.cpp similarity index 87% rename from libraries/glslang/glslang/MachineIndependent/Initialize.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Initialize.cpp index 90106d922..823406c18 100644 --- a/libraries/glslang/glslang/MachineIndependent/Initialize.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Initialize.cpp @@ -1,8 +1,9 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -125,8 +126,6 @@ enum ArgClass { }; // Mixtures of the above, to help the function tables const ArgClass ClassV1FIOCV = (ArgClass)(ClassV1 | ClassFIO | ClassCV); -const ArgClass ClassV1FOCV = (ArgClass)(ClassV1 | ClassFO | ClassCV); -const ArgClass ClassV1CV = (ArgClass)(ClassV1 | ClassCV); const ArgClass ClassBNS = (ArgClass)(ClassB | ClassNS); const ArgClass ClassRSNS = (ArgClass)(ClassRS | ClassNS); @@ -147,17 +146,21 @@ EProfile EDesktopProfile = static_cast(ENoProfile | ECoreProfile | ECo // Declare pointers to put into the table for versioning. #ifdef GLSLANG_WEB const Versioning* Es300Desktop130 = nullptr; - const Versioning* Es310Desktop430 = nullptr; + const Versioning* Es310Desktop420 = nullptr; +#elif defined(GLSLANG_ANGLE) + const Versioning* Es300Desktop130 = nullptr; + const Versioning* Es310Desktop420 = nullptr; + const Versioning* Es310Desktop450 = nullptr; #else const Versioning Es300Desktop130Version[] = { { EEsProfile, 0, 300, 0, nullptr }, { EDesktopProfile, 0, 130, 0, nullptr }, { EBadProfile } }; const Versioning* Es300Desktop130 = &Es300Desktop130Version[0]; - const Versioning Es310Desktop430Version[] = { { EEsProfile, 0, 310, 0, nullptr }, - { EDesktopProfile, 0, 430, 0, nullptr }, + const Versioning Es310Desktop420Version[] = { { EEsProfile, 0, 310, 0, nullptr }, + { EDesktopProfile, 0, 420, 0, nullptr }, { EBadProfile } }; - const Versioning* Es310Desktop430 = &Es310Desktop430Version[0]; + const Versioning* Es310Desktop420 = &Es310Desktop420Version[0]; const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr }, { EDesktopProfile, 0, 450, 0, nullptr }, @@ -257,14 +260,14 @@ const BuiltInFunction BaseFunctions[] = { { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, { EOpVectorEqual, "equal", 2, TypeU, ClassBNS, Es300Desktop130 }, { EOpVectorNotEqual, "notEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 }, - { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop430 }, + { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop420 }, + { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop420 }, #ifndef GLSLANG_WEB { EOpMix, "mix", 3, TypeB, ClassRegular, Es310Desktop450 }, { EOpMix, "mix", 3, TypeIU, ClassLB, Es310Desktop450 }, @@ -416,7 +419,7 @@ void AddTabledBuiltin(TString& decls, const BuiltInFunction& function) // See if the tabled versioning information allows the current version. bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */) { -#ifdef GLSLANG_WEB +#if defined(GLSLANG_WEB) || defined(GLSLANG_ANGLE) // all entries in table are valid return true; #endif @@ -480,7 +483,8 @@ void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */, inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion) { - return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && ARBCompatibility) || profile == ECompatibilityProfile); + return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && version == 140 && ARBCompatibility) || + profile == ECompatibilityProfile); } // Construct TBuiltInParseables base class. This can be used for language-common constructs. @@ -500,12 +504,14 @@ TBuiltIns::TBuiltIns() prefixes[EbtFloat] = ""; prefixes[EbtInt] = "i"; prefixes[EbtUint] = "u"; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) prefixes[EbtFloat16] = "f16"; prefixes[EbtInt8] = "i8"; prefixes[EbtUint8] = "u8"; prefixes[EbtInt16] = "i16"; prefixes[EbtUint16] = "u16"; + prefixes[EbtInt64] = "i64"; + prefixes[EbtUint64] = "u64"; #endif postfixes[2] = "2"; @@ -517,7 +523,9 @@ TBuiltIns::TBuiltIns() dimMap[Esd3D] = 3; dimMap[EsdCube] = 3; #ifndef GLSLANG_WEB +#ifndef GLSLANG_ANGLE dimMap[Esd1D] = 1; +#endif dimMap[EsdRect] = 2; dimMap[EsdBuffer] = 1; dimMap[EsdSubpass] = 2; // potentially unused for now @@ -542,6 +550,9 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV #ifdef GLSLANG_WEB version = 310; profile = EEsProfile; +#elif defined(GLSLANG_ANGLE) + version = 450; + profile = ECoreProfile; #endif addTabledBuiltins(version, profile, spvVersion); @@ -587,6 +598,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "vec4 fwidthCoarse(vec4 p);" ); +#ifndef GLSLANG_ANGLE TString derivativesAndControl16bits ( "float16_t dFdx(float16_t);" "f16vec2 dFdx(f16vec2);" @@ -690,7 +702,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack // - if (profile != EEsProfile && version >= 400) { + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double sqrt(double);" @@ -920,7 +932,203 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } - if (profile != EEsProfile && version >= 450) { + if (profile == EEsProfile && version >= 310) { // Explicit Types + commonBuiltins.append( + + "float64_t sqrt(float64_t);" + "f64vec2 sqrt(f64vec2);" + "f64vec3 sqrt(f64vec3);" + "f64vec4 sqrt(f64vec4);" + + "float64_t inversesqrt(float64_t);" + "f64vec2 inversesqrt(f64vec2);" + "f64vec3 inversesqrt(f64vec3);" + "f64vec4 inversesqrt(f64vec4);" + + "float64_t abs(float64_t);" + "f64vec2 abs(f64vec2);" + "f64vec3 abs(f64vec3);" + "f64vec4 abs(f64vec4);" + + "float64_t sign(float64_t);" + "f64vec2 sign(f64vec2);" + "f64vec3 sign(f64vec3);" + "f64vec4 sign(f64vec4);" + + "float64_t floor(float64_t);" + "f64vec2 floor(f64vec2);" + "f64vec3 floor(f64vec3);" + "f64vec4 floor(f64vec4);" + + "float64_t trunc(float64_t);" + "f64vec2 trunc(f64vec2);" + "f64vec3 trunc(f64vec3);" + "f64vec4 trunc(f64vec4);" + + "float64_t round(float64_t);" + "f64vec2 round(f64vec2);" + "f64vec3 round(f64vec3);" + "f64vec4 round(f64vec4);" + + "float64_t roundEven(float64_t);" + "f64vec2 roundEven(f64vec2);" + "f64vec3 roundEven(f64vec3);" + "f64vec4 roundEven(f64vec4);" + + "float64_t ceil(float64_t);" + "f64vec2 ceil(f64vec2);" + "f64vec3 ceil(f64vec3);" + "f64vec4 ceil(f64vec4);" + + "float64_t fract(float64_t);" + "f64vec2 fract(f64vec2);" + "f64vec3 fract(f64vec3);" + "f64vec4 fract(f64vec4);" + + "float64_t mod(float64_t, float64_t);" + "f64vec2 mod(f64vec2 , float64_t);" + "f64vec3 mod(f64vec3 , float64_t);" + "f64vec4 mod(f64vec4 , float64_t);" + "f64vec2 mod(f64vec2 , f64vec2);" + "f64vec3 mod(f64vec3 , f64vec3);" + "f64vec4 mod(f64vec4 , f64vec4);" + + "float64_t modf(float64_t, out float64_t);" + "f64vec2 modf(f64vec2, out f64vec2);" + "f64vec3 modf(f64vec3, out f64vec3);" + "f64vec4 modf(f64vec4, out f64vec4);" + + "float64_t min(float64_t, float64_t);" + "f64vec2 min(f64vec2, float64_t);" + "f64vec3 min(f64vec3, float64_t);" + "f64vec4 min(f64vec4, float64_t);" + "f64vec2 min(f64vec2, f64vec2);" + "f64vec3 min(f64vec3, f64vec3);" + "f64vec4 min(f64vec4, f64vec4);" + + "float64_t max(float64_t, float64_t);" + "f64vec2 max(f64vec2 , float64_t);" + "f64vec3 max(f64vec3 , float64_t);" + "f64vec4 max(f64vec4 , float64_t);" + "f64vec2 max(f64vec2 , f64vec2);" + "f64vec3 max(f64vec3 , f64vec3);" + "f64vec4 max(f64vec4 , f64vec4);" + + "float64_t clamp(float64_t, float64_t, float64_t);" + "f64vec2 clamp(f64vec2 , float64_t, float64_t);" + "f64vec3 clamp(f64vec3 , float64_t, float64_t);" + "f64vec4 clamp(f64vec4 , float64_t, float64_t);" + "f64vec2 clamp(f64vec2 , f64vec2 , f64vec2);" + "f64vec3 clamp(f64vec3 , f64vec3 , f64vec3);" + "f64vec4 clamp(f64vec4 , f64vec4 , f64vec4);" + + "float64_t mix(float64_t, float64_t, float64_t);" + "f64vec2 mix(f64vec2, f64vec2, float64_t);" + "f64vec3 mix(f64vec3, f64vec3, float64_t);" + "f64vec4 mix(f64vec4, f64vec4, float64_t);" + "f64vec2 mix(f64vec2, f64vec2, f64vec2);" + "f64vec3 mix(f64vec3, f64vec3, f64vec3);" + "f64vec4 mix(f64vec4, f64vec4, f64vec4);" + "float64_t mix(float64_t, float64_t, bool);" + "f64vec2 mix(f64vec2, f64vec2, bvec2);" + "f64vec3 mix(f64vec3, f64vec3, bvec3);" + "f64vec4 mix(f64vec4, f64vec4, bvec4);" + + "float64_t step(float64_t, float64_t);" + "f64vec2 step(f64vec2 , f64vec2);" + "f64vec3 step(f64vec3 , f64vec3);" + "f64vec4 step(f64vec4 , f64vec4);" + "f64vec2 step(float64_t, f64vec2);" + "f64vec3 step(float64_t, f64vec3);" + "f64vec4 step(float64_t, f64vec4);" + + "float64_t smoothstep(float64_t, float64_t, float64_t);" + "f64vec2 smoothstep(f64vec2 , f64vec2 , f64vec2);" + "f64vec3 smoothstep(f64vec3 , f64vec3 , f64vec3);" + "f64vec4 smoothstep(f64vec4 , f64vec4 , f64vec4);" + "f64vec2 smoothstep(float64_t, float64_t, f64vec2);" + "f64vec3 smoothstep(float64_t, float64_t, f64vec3);" + "f64vec4 smoothstep(float64_t, float64_t, f64vec4);" + + "float64_t length(float64_t);" + "float64_t length(f64vec2);" + "float64_t length(f64vec3);" + "float64_t length(f64vec4);" + + "float64_t distance(float64_t, float64_t);" + "float64_t distance(f64vec2 , f64vec2);" + "float64_t distance(f64vec3 , f64vec3);" + "float64_t distance(f64vec4 , f64vec4);" + + "float64_t dot(float64_t, float64_t);" + "float64_t dot(f64vec2 , f64vec2);" + "float64_t dot(f64vec3 , f64vec3);" + "float64_t dot(f64vec4 , f64vec4);" + + "f64vec3 cross(f64vec3, f64vec3);" + + "float64_t normalize(float64_t);" + "f64vec2 normalize(f64vec2);" + "f64vec3 normalize(f64vec3);" + "f64vec4 normalize(f64vec4);" + + "float64_t faceforward(float64_t, float64_t, float64_t);" + "f64vec2 faceforward(f64vec2, f64vec2, f64vec2);" + "f64vec3 faceforward(f64vec3, f64vec3, f64vec3);" + "f64vec4 faceforward(f64vec4, f64vec4, f64vec4);" + + "float64_t reflect(float64_t, float64_t);" + "f64vec2 reflect(f64vec2 , f64vec2 );" + "f64vec3 reflect(f64vec3 , f64vec3 );" + "f64vec4 reflect(f64vec4 , f64vec4 );" + + "float64_t refract(float64_t, float64_t, float64_t);" + "f64vec2 refract(f64vec2 , f64vec2 , float64_t);" + "f64vec3 refract(f64vec3 , f64vec3 , float64_t);" + "f64vec4 refract(f64vec4 , f64vec4 , float64_t);" + + "f64mat2 matrixCompMult(f64mat2, f64mat2);" + "f64mat3 matrixCompMult(f64mat3, f64mat3);" + "f64mat4 matrixCompMult(f64mat4, f64mat4);" + "f64mat2x3 matrixCompMult(f64mat2x3, f64mat2x3);" + "f64mat2x4 matrixCompMult(f64mat2x4, f64mat2x4);" + "f64mat3x2 matrixCompMult(f64mat3x2, f64mat3x2);" + "f64mat3x4 matrixCompMult(f64mat3x4, f64mat3x4);" + "f64mat4x2 matrixCompMult(f64mat4x2, f64mat4x2);" + "f64mat4x3 matrixCompMult(f64mat4x3, f64mat4x3);" + + "f64mat2 outerProduct(f64vec2, f64vec2);" + "f64mat3 outerProduct(f64vec3, f64vec3);" + "f64mat4 outerProduct(f64vec4, f64vec4);" + "f64mat2x3 outerProduct(f64vec3, f64vec2);" + "f64mat3x2 outerProduct(f64vec2, f64vec3);" + "f64mat2x4 outerProduct(f64vec4, f64vec2);" + "f64mat4x2 outerProduct(f64vec2, f64vec4);" + "f64mat3x4 outerProduct(f64vec4, f64vec3);" + "f64mat4x3 outerProduct(f64vec3, f64vec4);" + + "f64mat2 transpose(f64mat2);" + "f64mat3 transpose(f64mat3);" + "f64mat4 transpose(f64mat4);" + "f64mat2x3 transpose(f64mat3x2);" + "f64mat3x2 transpose(f64mat2x3);" + "f64mat2x4 transpose(f64mat4x2);" + "f64mat4x2 transpose(f64mat2x4);" + "f64mat3x4 transpose(f64mat4x3);" + "f64mat4x3 transpose(f64mat3x4);" + + "float64_t determinant(f64mat2);" + "float64_t determinant(f64mat3);" + "float64_t determinant(f64mat4);" + + "f64mat2 inverse(f64mat2);" + "f64mat3 inverse(f64mat3);" + "f64mat4 inverse(f64mat4);" + + "\n"); + } + + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { commonBuiltins.append( "int64_t abs(int64_t);" @@ -987,25 +1195,25 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "u64vec3 mix(u64vec3, u64vec3, bvec3);" "u64vec4 mix(u64vec4, u64vec4, bvec4);" - "int64_t doubleBitsToInt64(double);" - "i64vec2 doubleBitsToInt64(dvec2);" - "i64vec3 doubleBitsToInt64(dvec3);" - "i64vec4 doubleBitsToInt64(dvec4);" + "int64_t doubleBitsToInt64(float64_t);" + "i64vec2 doubleBitsToInt64(f64vec2);" + "i64vec3 doubleBitsToInt64(f64vec3);" + "i64vec4 doubleBitsToInt64(f64vec4);" - "uint64_t doubleBitsToUint64(double);" - "u64vec2 doubleBitsToUint64(dvec2);" - "u64vec3 doubleBitsToUint64(dvec3);" - "u64vec4 doubleBitsToUint64(dvec4);" + "uint64_t doubleBitsToUint64(float64_t);" + "u64vec2 doubleBitsToUint64(f64vec2);" + "u64vec3 doubleBitsToUint64(f64vec3);" + "u64vec4 doubleBitsToUint64(f64vec4);" - "double int64BitsToDouble(int64_t);" - "dvec2 int64BitsToDouble(i64vec2);" - "dvec3 int64BitsToDouble(i64vec3);" - "dvec4 int64BitsToDouble(i64vec4);" + "float64_t int64BitsToDouble(int64_t);" + "f64vec2 int64BitsToDouble(i64vec2);" + "f64vec3 int64BitsToDouble(i64vec3);" + "f64vec4 int64BitsToDouble(i64vec4);" - "double uint64BitsToDouble(uint64_t);" - "dvec2 uint64BitsToDouble(u64vec2);" - "dvec3 uint64BitsToDouble(u64vec3);" - "dvec4 uint64BitsToDouble(u64vec4);" + "float64_t uint64BitsToDouble(uint64_t);" + "f64vec2 uint64BitsToDouble(u64vec2);" + "f64vec3 uint64BitsToDouble(u64vec3);" + "f64vec4 uint64BitsToDouble(u64vec4);" "int64_t packInt2x32(ivec2);" "uint64_t packUint2x32(uvec2);" @@ -1054,6 +1262,16 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "bvec3 notEqual(u64vec3, u64vec3);" "bvec4 notEqual(u64vec4, u64vec4);" + "int64_t bitCount(int64_t);" + "i64vec2 bitCount(i64vec2);" + "i64vec3 bitCount(i64vec3);" + "i64vec4 bitCount(i64vec4);" + + "int64_t bitCount(uint64_t);" + "i64vec2 bitCount(u64vec2);" + "i64vec3 bitCount(u64vec3);" + "i64vec4 bitCount(u64vec4);" + "int64_t findLSB(int64_t);" "i64vec2 findLSB(i64vec2);" "i64vec3 findLSB(i64vec3);" @@ -1174,6 +1392,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n" ); } +#endif // !GLSLANG_ANGLE if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 430)) { @@ -1211,17 +1430,30 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } +#ifndef GLSLANG_ANGLE if (profile != EEsProfile && version >= 440) { commonBuiltins.append( "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t);" " int64_t atomicMin(coherent volatile inout int64_t, int64_t);" "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t, int, int, int);" " int64_t atomicMin(coherent volatile inout int64_t, int64_t, int, int, int);" + "float16_t atomicMin(coherent volatile inout float16_t, float16_t);" + "float16_t atomicMin(coherent volatile inout float16_t, float16_t, int, int, int);" + " float atomicMin(coherent volatile inout float, float);" + " float atomicMin(coherent volatile inout float, float, int, int, int);" + " double atomicMin(coherent volatile inout double, double);" + " double atomicMin(coherent volatile inout double, double, int, int, int);" "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);" " int64_t atomicMax(coherent volatile inout int64_t, int64_t);" "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t, int, int, int);" " int64_t atomicMax(coherent volatile inout int64_t, int64_t, int, int, int);" + "float16_t atomicMax(coherent volatile inout float16_t, float16_t);" + "float16_t atomicMax(coherent volatile inout float16_t, float16_t, int, int, int);" + " float atomicMax(coherent volatile inout float, float);" + " float atomicMax(coherent volatile inout float, float, int, int, int);" + " double atomicMax(coherent volatile inout double, double);" + " double atomicMax(coherent volatile inout double, double, int, int, int);" "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);" " int64_t atomicAnd(coherent volatile inout int64_t, int64_t);" @@ -1242,11 +1474,23 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV " int64_t atomicAdd(coherent volatile inout int64_t, int64_t);" "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t, int, int, int);" " int64_t atomicAdd(coherent volatile inout int64_t, int64_t, int, int, int);" + "float16_t atomicAdd(coherent volatile inout float16_t, float16_t);" + "float16_t atomicAdd(coherent volatile inout float16_t, float16_t, int, int, int);" + " float atomicAdd(coherent volatile inout float, float);" + " float atomicAdd(coherent volatile inout float, float, int, int, int);" + " double atomicAdd(coherent volatile inout double, double);" + " double atomicAdd(coherent volatile inout double, double, int, int, int);" "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t);" " int64_t atomicExchange(coherent volatile inout int64_t, int64_t);" "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t, int, int, int);" " int64_t atomicExchange(coherent volatile inout int64_t, int64_t, int, int, int);" + "float16_t atomicExchange(coherent volatile inout float16_t, float16_t);" + "float16_t atomicExchange(coherent volatile inout float16_t, float16_t, int, int, int);" + " float atomicExchange(coherent volatile inout float, float);" + " float atomicExchange(coherent volatile inout float, float, int, int, int);" + " double atomicExchange(coherent volatile inout double, double);" + " double atomicExchange(coherent volatile inout double, double, int, int, int);" "uint64_t atomicCompSwap(coherent volatile inout uint64_t, uint64_t, uint64_t);" " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t);" @@ -1255,15 +1499,22 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "uint64_t atomicLoad(coherent volatile in uint64_t, int, int, int);" " int64_t atomicLoad(coherent volatile in int64_t, int, int, int);" + "float16_t atomicLoad(coherent volatile in float16_t, int, int, int);" + " float atomicLoad(coherent volatile in float, int, int, int);" + " double atomicLoad(coherent volatile in double, int, int, int);" "void atomicStore(coherent volatile out uint64_t, uint64_t, int, int, int);" "void atomicStore(coherent volatile out int64_t, int64_t, int, int, int);" + "void atomicStore(coherent volatile out float16_t, float16_t, int, int, int);" + "void atomicStore(coherent volatile out float, float, int, int, int);" + "void atomicStore(coherent volatile out double, double, int, int, int);" "\n"); } -#endif +#endif // !GLSLANG_ANGLE +#endif // !GLSLANG_WEB if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 330)) { + (profile != EEsProfile && version >= 150)) { // GL_ARB_shader_bit_encoding commonBuiltins.append( "int floatBitsToInt(highp float value);" "ivec2 floatBitsToInt(highp vec2 value);" @@ -1298,17 +1549,28 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "vec3 fma(vec3, vec3, vec3 );" "vec4 fma(vec4, vec4, vec4 );" "\n"); + } - if (profile != EEsProfile) { +#ifndef GLSLANG_ANGLE + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double fma(double, double, double);" "dvec2 fma(dvec2, dvec2, dvec2 );" "dvec3 fma(dvec3, dvec3, dvec3 );" "dvec4 fma(dvec4, dvec4, dvec4 );" "\n"); - } } + if (profile == EEsProfile && version >= 310) { // ARB_gpu_shader_fp64 + commonBuiltins.append( + "float64_t fma(float64_t, float64_t, float64_t);" + "f64vec2 fma(f64vec2, f64vec2, f64vec2 );" + "f64vec3 fma(f64vec3, f64vec3, f64vec3 );" + "f64vec4 fma(f64vec4, f64vec4, f64vec4 );" + "\n"); + } +#endif + if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 400)) { commonBuiltins.append( @@ -1325,7 +1587,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } - if (profile != EEsProfile && version >= 400) { +#ifndef GLSLANG_ANGLE + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double frexp(double, out int);" "dvec2 frexp( dvec2, out ivec2);" @@ -1342,10 +1605,26 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } + + if (profile == EEsProfile && version >= 310) { // ARB_gpu_shader_fp64 + commonBuiltins.append( + "float64_t frexp(float64_t, out int);" + "f64vec2 frexp( f64vec2, out ivec2);" + "f64vec3 frexp( f64vec3, out ivec3);" + "f64vec4 frexp( f64vec4, out ivec4);" + + "float64_t ldexp(float64_t, int);" + "f64vec2 ldexp( f64vec2, ivec2);" + "f64vec3 ldexp( f64vec3, ivec3);" + "f64vec4 ldexp( f64vec4, ivec4);" + + "\n"); + } +#endif #endif if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 400)) { + (profile != EEsProfile && version >= 150)) { commonBuiltins.append( "highp uint packUnorm2x16(vec2);" "vec2 unpackUnorm2x16(highp uint);" @@ -1353,7 +1632,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 420)) { + (profile != EEsProfile && version >= 150)) { commonBuiltins.append( "highp uint packSnorm2x16(vec2);" " vec2 unpackSnorm2x16(highp uint);" @@ -1365,7 +1644,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append( "mediump vec2 unpackHalf2x16(highp uint);" "\n"); - } else if (profile != EEsProfile && version >= 420) { + } else if (profile != EEsProfile && version >= 150) { commonBuiltins.append( " vec2 unpackHalf2x16(highp uint);" "\n"); @@ -1373,7 +1652,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV #ifndef GLSLANG_WEB if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { + (profile != EEsProfile && version >= 150)) { commonBuiltins.append( "highp uint packSnorm4x8(vec4);" "highp uint packUnorm4x8(vec4);" @@ -1385,7 +1664,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "mediump vec4 unpackSnorm4x8(highp uint);" "mediump vec4 unpackUnorm4x8(highp uint);" "\n"); - } else if (profile != EEsProfile && version >= 400) { + } else if (profile != EEsProfile && version >= 150) { commonBuiltins.append( "vec4 unpackSnorm4x8(highp uint);" "vec4 unpackUnorm4x8(highp uint);" @@ -1451,6 +1730,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } #ifndef GLSLANG_WEB +#ifndef GLSLANG_ANGLE // // Original-style texture functions existing in all stages. // (Per-stage functions below.) @@ -1584,6 +1864,22 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } + if (profile != EEsProfile && version == 450) { + commonBuiltins.append( + "uint atomicCounterAddARB(atomic_uint, uint);" + "uint atomicCounterSubtractARB(atomic_uint, uint);" + "uint atomicCounterMinARB(atomic_uint, uint);" + "uint atomicCounterMaxARB(atomic_uint, uint);" + "uint atomicCounterAndARB(atomic_uint, uint);" + "uint atomicCounterOrARB(atomic_uint, uint);" + "uint atomicCounterXorARB(atomic_uint, uint);" + "uint atomicCounterExchangeARB(atomic_uint, uint);" + "uint atomicCounterCompSwapARB(atomic_uint, uint, uint);" + + "\n"); + } + + if (profile != EEsProfile && version >= 460) { commonBuiltins.append( "uint atomicCounterAdd(atomic_uint, uint);" @@ -1599,6 +1895,37 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } } + else if (spvVersion.vulkanRelaxed) { + // + // Atomic counter functions act as aliases to normal atomic functions. + // replace definitions to take 'volatile coherent uint' instead of 'atomic_uint' + // and map to equivalent non-counter atomic op + // + if ((profile != EEsProfile && version >= 300) || + (profile == EEsProfile && version >= 310)) { + commonBuiltins.append( + "uint atomicCounterIncrement(volatile coherent uint);" + "uint atomicCounterDecrement(volatile coherent uint);" + "uint atomicCounter(volatile coherent uint);" + + "\n"); + } + if (profile != EEsProfile && version >= 460) { + commonBuiltins.append( + "uint atomicCounterAdd(volatile coherent uint, uint);" + "uint atomicCounterSubtract(volatile coherent uint, uint);" + "uint atomicCounterMin(volatile coherent uint, uint);" + "uint atomicCounterMax(volatile coherent uint, uint);" + "uint atomicCounterAnd(volatile coherent uint, uint);" + "uint atomicCounterOr(volatile coherent uint, uint);" + "uint atomicCounterXor(volatile coherent uint, uint);" + "uint atomicCounterExchange(volatile coherent uint, uint);" + "uint atomicCounterCompSwap(volatile coherent uint, uint, uint);" + + "\n"); + } + } +#endif // !GLSLANG_ANGLE // Bitfield if ((profile == EEsProfile && version >= 310) || @@ -1741,6 +2068,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } +#ifndef GLSLANG_ANGLE // GL_ARB_shader_ballot if (profile != EEsProfile && version >= 450) { commonBuiltins.append( @@ -3061,9 +3389,29 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "bool textureFootprintGradClampNV(sampler2D, vec2, vec2, vec2, float, int, bool, out gl_TextureFootprint2DNV);" "\n"); } +#endif // !GLSLANG_ANGLE + if ((profile == EEsProfile && version >= 300 && version < 310) || + (profile != EEsProfile && version >= 150 && version < 450)) { // GL_EXT_shader_integer_mix + commonBuiltins.append("int mix(int, int, bool);" + "ivec2 mix(ivec2, ivec2, bvec2);" + "ivec3 mix(ivec3, ivec3, bvec3);" + "ivec4 mix(ivec4, ivec4, bvec4);" + "uint mix(uint, uint, bool );" + "uvec2 mix(uvec2, uvec2, bvec2);" + "uvec3 mix(uvec3, uvec3, bvec3);" + "uvec4 mix(uvec4, uvec4, bvec4);" + "bool mix(bool, bool, bool );" + "bvec2 mix(bvec2, bvec2, bvec2);" + "bvec3 mix(bvec3, bvec3, bvec3);" + "bvec4 mix(bvec4, bvec4, bvec4);" + + "\n"); + } + +#ifndef GLSLANG_ANGLE // GL_AMD_gpu_shader_half_float/Explicit types - if (profile != EEsProfile && version >= 450) { + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { commonBuiltins.append( "float16_t radians(float16_t);" "f16vec2 radians(f16vec2);" @@ -3411,7 +3759,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } // Explicit types - if (profile != EEsProfile && version >= 450) { + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { commonBuiltins.append( "int8_t abs(int8_t);" "i8vec2 abs(i8vec2);" @@ -3912,28 +4260,30 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "f64vec3 log2(f64vec3);" "f64vec4 log2(f64vec4);" "\n"); - } - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append(derivativesAndControl64bits); - stageBuiltins[EShLangFragment].append( - "float64_t interpolateAtCentroid(float64_t);" - "f64vec2 interpolateAtCentroid(f64vec2);" - "f64vec3 interpolateAtCentroid(f64vec3);" - "f64vec4 interpolateAtCentroid(f64vec4);" + } - "float64_t interpolateAtSample(float64_t, int);" - "f64vec2 interpolateAtSample(f64vec2, int);" - "f64vec3 interpolateAtSample(f64vec3, int);" - "f64vec4 interpolateAtSample(f64vec4, int);" + if (profile != EEsProfile && version >= 450) { + stageBuiltins[EShLangFragment].append(derivativesAndControl64bits); + stageBuiltins[EShLangFragment].append( + "float64_t interpolateAtCentroid(float64_t);" + "f64vec2 interpolateAtCentroid(f64vec2);" + "f64vec3 interpolateAtCentroid(f64vec3);" + "f64vec4 interpolateAtCentroid(f64vec4);" - "float64_t interpolateAtOffset(float64_t, f64vec2);" - "f64vec2 interpolateAtOffset(f64vec2, f64vec2);" - "f64vec3 interpolateAtOffset(f64vec3, f64vec2);" - "f64vec4 interpolateAtOffset(f64vec4, f64vec2);" + "float64_t interpolateAtSample(float64_t, int);" + "f64vec2 interpolateAtSample(f64vec2, int);" + "f64vec3 interpolateAtSample(f64vec3, int);" + "f64vec4 interpolateAtSample(f64vec4, int);" - "\n"); + "float64_t interpolateAtOffset(float64_t, f64vec2);" + "f64vec2 interpolateAtOffset(f64vec2, f64vec2);" + "f64vec3 interpolateAtOffset(f64vec3, f64vec2);" + "f64vec4 interpolateAtOffset(f64vec4, f64vec2);" + + "\n"); } +#endif // !GLSLANG_ANGLE //============================================================================ // @@ -3949,6 +4299,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion)) stageBuiltins[EShLangVertex].append("vec4 ftransform();"); +#ifndef GLSLANG_ANGLE // // Original-style texture Functions with lod. // @@ -4008,6 +4359,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } } +#endif // !GLSLANG_ANGLE if ((profile != EEsProfile && version >= 150) || (profile == EEsProfile && version >= 310)) { @@ -4028,7 +4380,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "void EndPrimitive();" "\n"); } -#endif +#endif // !GLSLANG_WEB //============================================================================ // @@ -4067,10 +4419,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } #ifndef GLSLANG_WEB if ((profile != EEsProfile && version >= 420) || esBarrier) { - commonBuiltins.append( - "void memoryBarrierAtomicCounter();" - "void memoryBarrierImage();" - ); + if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) { + commonBuiltins.append("void memoryBarrierAtomicCounter();"); + } + commonBuiltins.append("void memoryBarrierImage();"); } if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { stageBuiltins[EShLangMeshNV].append( @@ -4086,6 +4438,9 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append("void controlBarrier(int, int, int, int);\n" "void memoryBarrier(int, int, int);\n"); + commonBuiltins.append("void debugPrintfEXT();\n"); + +#ifndef GLSLANG_ANGLE if (profile != EEsProfile && version >= 450) { // coopMatStoreNV perhaps ought to have "out" on the buf parameter, but // adding it introduces undesirable tempArgs on the stack. What we want @@ -4209,6 +4564,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } +#endif // !GLSLANG_ANGLE // GL_ARB_derivative_control if (profile != EEsProfile && version >= 400) { @@ -4246,6 +4602,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "bool helperInvocationEXT();" "\n"); +#ifndef GLSLANG_ANGLE // GL_AMD_shader_explicit_vertex_parameter if (profile != EEsProfile && version >= 450) { stageBuiltins[EShLangFragment].append( @@ -4320,37 +4677,75 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } - // Builtins for GL_NV_ray_tracing + // Builtins for GL_NV_ray_tracing/GL_NV_ray_tracing_motion_blur/GL_EXT_ray_tracing/GL_EXT_ray_query if (profile != EEsProfile && version >= 460) { - stageBuiltins[EShLangRayGenNV].append( + commonBuiltins.append("void rayQueryInitializeEXT(rayQueryEXT, accelerationStructureEXT, uint, uint, vec3, float, vec3, float);" + "void rayQueryTerminateEXT(rayQueryEXT);" + "void rayQueryGenerateIntersectionEXT(rayQueryEXT, float);" + "void rayQueryConfirmIntersectionEXT(rayQueryEXT);" + "bool rayQueryProceedEXT(rayQueryEXT);" + "uint rayQueryGetIntersectionTypeEXT(rayQueryEXT, bool);" + "float rayQueryGetRayTMinEXT(rayQueryEXT);" + "uint rayQueryGetRayFlagsEXT(rayQueryEXT);" + "vec3 rayQueryGetWorldRayOriginEXT(rayQueryEXT);" + "vec3 rayQueryGetWorldRayDirectionEXT(rayQueryEXT);" + "float rayQueryGetIntersectionTEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionInstanceCustomIndexEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionInstanceIdEXT(rayQueryEXT, bool);" + "uint rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionGeometryIndexEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionPrimitiveIndexEXT(rayQueryEXT, bool);" + "vec2 rayQueryGetIntersectionBarycentricsEXT(rayQueryEXT, bool);" + "bool rayQueryGetIntersectionFrontFaceEXT(rayQueryEXT, bool);" + "bool rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQueryEXT);" + "vec3 rayQueryGetIntersectionObjectRayDirectionEXT(rayQueryEXT, bool);" + "vec3 rayQueryGetIntersectionObjectRayOriginEXT(rayQueryEXT, bool);" + "mat4x3 rayQueryGetIntersectionObjectToWorldEXT(rayQueryEXT, bool);" + "mat4x3 rayQueryGetIntersectionWorldToObjectEXT(rayQueryEXT, bool);" + "\n"); + + stageBuiltins[EShLangRayGen].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangIntersectNV].append( + stageBuiltins[EShLangIntersect].append( "bool reportIntersectionNV(float, uint);" + "bool reportIntersectionEXT(float, uint);" "\n"); - stageBuiltins[EShLangAnyHitNV].append( + stageBuiltins[EShLangAnyHit].append( "void ignoreIntersectionNV();" "void terminateRayNV();" "\n"); - stageBuiltins[EShLangClosestHitNV].append( + stageBuiltins[EShLangClosestHit].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangMissNV].append( + stageBuiltins[EShLangMiss].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangCallableNV].append( + stageBuiltins[EShLangCallable].append( "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); } +#endif // !GLSLANG_ANGLE //E_SPV_NV_compute_shader_derivatives if ((profile == EEsProfile && version >= 320) || (profile != EEsProfile && version >= 450)) { stageBuiltins[EShLangCompute].append(derivativeControls); stageBuiltins[EShLangCompute].append("\n"); } +#ifndef GLSLANG_ANGLE if (profile != EEsProfile && version >= 450) { stageBuiltins[EShLangCompute].append(derivativesAndControl16bits); stageBuiltins[EShLangCompute].append(derivativesAndControl64bits); @@ -4363,7 +4758,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "void writePackedPrimitiveIndices4x8NV(uint, uint);" "\n"); } -#endif +#endif // !GLSLANG_ANGLE +#endif // !GLSLANG_WEB //============================================================================ // @@ -4400,7 +4796,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { // // Matrix state. p. 31, 32, 37, 39, 40. @@ -4518,7 +4914,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } -#endif +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE //============================================================================ // @@ -4549,6 +4945,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } #ifndef GLSLANG_WEB +#ifndef GLSLANG_ANGLE //============================================================================ // // Define the interface to the mesh/task shader. @@ -4636,6 +5033,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } } +#endif // !GLSLANG_ANGLE //============================================================================ // @@ -4748,6 +5146,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in int gl_VertexIndex;" "in int gl_InstanceIndex;" ); + + if (spvVersion.vulkan > 0 && version >= 140 && spvVersion.vulkanRelaxed) + stageBuiltins[EShLangVertex].append( + "in int gl_VertexID;" // declare with 'in' qualifier + "in int gl_InstanceID;" + ); + if (version >= 440) { stageBuiltins[EShLangVertex].append( "in int gl_BaseVertexARB;" @@ -4785,7 +5190,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "mediump float gl_PointSize;" // needs qualifier fixed later ); } else { - if (spvVersion.vulkan == 0) + if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) stageBuiltins[EShLangVertex].append( "in highp int gl_VertexID;" // needs qualifier fixed later "in highp int gl_InstanceID;" // needs qualifier fixed later @@ -4828,6 +5233,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { + stageBuiltins[EShLangVertex].append( + "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate + "\n"); + } //============================================================================ // @@ -4941,6 +5351,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { + stageBuiltins[EShLangGeometry].append( + "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate + "\n"); + } + //============================================================================ // // Define the interface to the tessellation control shader. @@ -5238,6 +5654,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in vec3 gl_BaryCoordNoPerspNV;" ); + if (version >= 450) + stageBuiltins[EShLangFragment].append( + "flat in int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate + ); + } else { // ES profile @@ -5296,6 +5717,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in vec3 gl_BaryCoordNV;" "in vec3 gl_BaryCoordNoPerspNV;" ); + if (version >= 310) + stageBuiltins[EShLangFragment].append( + "flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate + ); } #endif @@ -5306,6 +5731,21 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV #ifndef GLSLANG_WEB + if ((profile != EEsProfile && version >= 140) || + (profile == EEsProfile && version >= 310)) { + stageBuiltins[EShLangFragment].append( + "flat in highp int gl_DeviceIndex;" // GL_EXT_device_group + "flat in highp int gl_ViewIndex;" // GL_EXT_multiview + "\n"); + } + + if (version >= 300 /* both ES and non-ES */) { + stageBuiltins[EShLangFragment].append( + "flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 + "\n"); + } + +#ifndef GLSLANG_ANGLE // GL_ARB_shader_ballot if (profile != EEsProfile && version >= 450) { const char* ballotDecls = @@ -5317,6 +5757,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in uint64_t gl_SubGroupLeMaskARB;" "in uint64_t gl_SubGroupLtMaskARB;" "\n"; + const char* rtBallotDecls = + "uniform volatile uint gl_SubGroupSizeARB;" + "in volatile uint gl_SubGroupInvocationARB;" + "in volatile uint64_t gl_SubGroupEqMaskARB;" + "in volatile uint64_t gl_SubGroupGeMaskARB;" + "in volatile uint64_t gl_SubGroupGtMaskARB;" + "in volatile uint64_t gl_SubGroupLeMaskARB;" + "in volatile uint64_t gl_SubGroupLtMaskARB;" + "\n"; const char* fragmentBallotDecls = "uniform uint gl_SubGroupSizeARB;" "flat in uint gl_SubGroupInvocationARB;" @@ -5334,14 +5783,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV stageBuiltins[EShLangFragment] .append(fragmentBallotDecls); stageBuiltins[EShLangMeshNV] .append(ballotDecls); stageBuiltins[EShLangTaskNV] .append(ballotDecls); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangFragment].append( - "flat in highp int gl_DeviceIndex;" // GL_EXT_device_group - "flat in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); + stageBuiltins[EShLangRayGen] .append(rtBallotDecls); + stageBuiltins[EShLangIntersect] .append(rtBallotDecls); + // No volatile qualifier on these builtins in any-hit + stageBuiltins[EShLangAnyHit] .append(ballotDecls); + stageBuiltins[EShLangClosestHit] .append(rtBallotDecls); + stageBuiltins[EShLangMiss] .append(rtBallotDecls); + stageBuiltins[EShLangCallable] .append(rtBallotDecls); } // GL_KHR_shader_subgroup @@ -5379,6 +5827,21 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in highp uint gl_NumSubgroups;" "in highp uint gl_SubgroupID;" "\n"; + // These builtins are volatile for RT stages + const char* rtSubgroupDecls = + "in mediump volatile uint gl_SubgroupSize;" + "in mediump volatile uint gl_SubgroupInvocationID;" + "in highp volatile uvec4 gl_SubgroupEqMask;" + "in highp volatile uvec4 gl_SubgroupGeMask;" + "in highp volatile uvec4 gl_SubgroupGtMask;" + "in highp volatile uvec4 gl_SubgroupLeMask;" + "in highp volatile uvec4 gl_SubgroupLtMask;" + // GL_NV_shader_sm_builtins + "in highp uint gl_WarpsPerSMNV;" + "in highp uint gl_SMCountNV;" + "in highp volatile uint gl_WarpIDNV;" + "in highp volatile uint gl_SMIDNV;" + "\n"; stageBuiltins[EShLangVertex] .append(subgroupDecls); stageBuiltins[EShLangTessControl] .append(subgroupDecls); @@ -5391,118 +5854,177 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV stageBuiltins[EShLangMeshNV] .append(computeSubgroupDecls); stageBuiltins[EShLangTaskNV] .append(subgroupDecls); stageBuiltins[EShLangTaskNV] .append(computeSubgroupDecls); - stageBuiltins[EShLangRayGenNV] .append(subgroupDecls); - stageBuiltins[EShLangIntersectNV] .append(subgroupDecls); - stageBuiltins[EShLangAnyHitNV] .append(subgroupDecls); - stageBuiltins[EShLangClosestHitNV] .append(subgroupDecls); - stageBuiltins[EShLangMissNV] .append(subgroupDecls); - stageBuiltins[EShLangCallableNV] .append(subgroupDecls); + stageBuiltins[EShLangRayGen] .append(rtSubgroupDecls); + stageBuiltins[EShLangIntersect] .append(rtSubgroupDecls); + // No volatile qualifier on these builtins in any-hit + stageBuiltins[EShLangAnyHit] .append(subgroupDecls); + stageBuiltins[EShLangClosestHit] .append(rtSubgroupDecls); + stageBuiltins[EShLangMiss] .append(rtSubgroupDecls); + stageBuiltins[EShLangCallable] .append(rtSubgroupDecls); } - // GL_NV_ray_tracing + // GL_NV_ray_tracing/GL_EXT_ray_tracing if (profile != EEsProfile && version >= 460) { const char *constRayFlags = "const uint gl_RayFlagsNoneNV = 0U;" + "const uint gl_RayFlagsNoneEXT = 0U;" "const uint gl_RayFlagsOpaqueNV = 1U;" + "const uint gl_RayFlagsOpaqueEXT = 1U;" "const uint gl_RayFlagsNoOpaqueNV = 2U;" + "const uint gl_RayFlagsNoOpaqueEXT = 2U;" "const uint gl_RayFlagsTerminateOnFirstHitNV = 4U;" + "const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;" "const uint gl_RayFlagsSkipClosestHitShaderNV = 8U;" + "const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;" "const uint gl_RayFlagsCullBackFacingTrianglesNV = 16U;" + "const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;" "const uint gl_RayFlagsCullFrontFacingTrianglesNV = 32U;" + "const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;" "const uint gl_RayFlagsCullOpaqueNV = 64U;" + "const uint gl_RayFlagsCullOpaqueEXT = 64U;" "const uint gl_RayFlagsCullNoOpaqueNV = 128U;" + "const uint gl_RayFlagsCullNoOpaqueEXT = 128U;" + "const uint gl_RayFlagsSkipTrianglesEXT = 256U;" + "const uint gl_RayFlagsSkipAABBEXT = 512U;" + "const uint gl_HitKindFrontFacingTriangleEXT = 254U;" + "const uint gl_HitKindBackFacingTriangleEXT = 255U;" "\n"; + + const char *constRayQueryIntersection = + "const uint gl_RayQueryCandidateIntersectionEXT = 0U;" + "const uint gl_RayQueryCommittedIntersectionEXT = 1U;" + "const uint gl_RayQueryCommittedIntersectionNoneEXT = 0U;" + "const uint gl_RayQueryCommittedIntersectionTriangleEXT = 1U;" + "const uint gl_RayQueryCommittedIntersectionGeneratedEXT = 2U;" + "const uint gl_RayQueryCandidateIntersectionTriangleEXT = 0U;" + "const uint gl_RayQueryCandidateIntersectionAABBEXT = 1U;" + "\n"; + const char *rayGenDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "\n"; const char *intersectDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in int gl_PrimitiveID;" "in int gl_InstanceID;" "in int gl_InstanceCustomIndexNV;" + "in int gl_InstanceCustomIndexEXT;" + "in int gl_GeometryIndexEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" + "in vec3 gl_ObjectRayOriginEXT;" "in vec3 gl_ObjectRayDirectionNV;" + "in vec3 gl_ObjectRayDirectionEXT;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in volatile float gl_RayTmaxEXT;" "in mat4x3 gl_ObjectToWorldNV;" + "in mat4x3 gl_ObjectToWorldEXT;" + "in mat3x4 gl_ObjectToWorld3x4EXT;" "in mat4x3 gl_WorldToObjectNV;" + "in mat4x3 gl_WorldToObjectEXT;" + "in mat3x4 gl_WorldToObject3x4EXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" + "in float gl_CurrentRayTimeNV;" "\n"; const char *hitDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in int gl_PrimitiveID;" "in int gl_InstanceID;" "in int gl_InstanceCustomIndexNV;" + "in int gl_InstanceCustomIndexEXT;" + "in int gl_GeometryIndexEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" + "in vec3 gl_ObjectRayOriginEXT;" "in vec3 gl_ObjectRayDirectionNV;" + "in vec3 gl_ObjectRayDirectionEXT;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in float gl_RayTmaxEXT;" "in float gl_HitTNV;" + "in float gl_HitTEXT;" "in uint gl_HitKindNV;" + "in uint gl_HitKindEXT;" "in mat4x3 gl_ObjectToWorldNV;" + "in mat4x3 gl_ObjectToWorldEXT;" + "in mat3x4 gl_ObjectToWorld3x4EXT;" "in mat4x3 gl_WorldToObjectNV;" + "in mat4x3 gl_WorldToObjectEXT;" + "in mat3x4 gl_WorldToObject3x4EXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" + "in float gl_CurrentRayTimeNV;" "\n"; const char *missDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" "in vec3 gl_ObjectRayDirectionNV;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in float gl_RayTmaxEXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" + "in float gl_CurrentRayTimeNV;" "\n"; const char *callableDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "\n"; - stageBuiltins[EShLangRayGenNV].append(rayGenDecls); - stageBuiltins[EShLangRayGenNV].append(constRayFlags); - stageBuiltins[EShLangIntersectNV].append(intersectDecls); - stageBuiltins[EShLangIntersectNV].append(constRayFlags); + commonBuiltins.append(constRayQueryIntersection); + commonBuiltins.append(constRayFlags); - stageBuiltins[EShLangAnyHitNV].append(hitDecls); - stageBuiltins[EShLangAnyHitNV].append(constRayFlags); - - stageBuiltins[EShLangClosestHitNV].append(hitDecls); - stageBuiltins[EShLangClosestHitNV].append(constRayFlags); - - stageBuiltins[EShLangMissNV].append(missDecls); - stageBuiltins[EShLangMissNV].append(constRayFlags); - - stageBuiltins[EShLangCallableNV].append(callableDecls); - stageBuiltins[EShLangCallableNV].append(constRayFlags); + stageBuiltins[EShLangRayGen].append(rayGenDecls); + stageBuiltins[EShLangIntersect].append(intersectDecls); + stageBuiltins[EShLangAnyHit].append(hitDecls); + stageBuiltins[EShLangClosestHit].append(hitDecls); + stageBuiltins[EShLangMiss].append(missDecls); + stageBuiltins[EShLangCallable].append(callableDecls); } + if ((profile != EEsProfile && version >= 140)) { const char *deviceIndex = "in highp int gl_DeviceIndex;" // GL_EXT_device_group "\n"; - stageBuiltins[EShLangRayGenNV].append(deviceIndex); - stageBuiltins[EShLangIntersectNV].append(deviceIndex); - stageBuiltins[EShLangAnyHitNV].append(deviceIndex); - stageBuiltins[EShLangClosestHitNV].append(deviceIndex); - stageBuiltins[EShLangMissNV].append(deviceIndex); - } - - if (version >= 300 /* both ES and non-ES */) { - stageBuiltins[EShLangFragment].append( - "flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 - "\n"); + stageBuiltins[EShLangRayGen].append(deviceIndex); + stageBuiltins[EShLangIntersect].append(deviceIndex); + stageBuiltins[EShLangAnyHit].append(deviceIndex); + stageBuiltins[EShLangClosestHit].append(deviceIndex); + stageBuiltins[EShLangMiss].append(deviceIndex); } if ((profile != EEsProfile && version >= 420) || @@ -5512,6 +6034,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append("const int gl_ScopeSubgroup = 3;\n"); commonBuiltins.append("const int gl_ScopeInvocation = 4;\n"); commonBuiltins.append("const int gl_ScopeQueueFamily = 5;\n"); + commonBuiltins.append("const int gl_ScopeShaderCallEXT = 6;\n"); commonBuiltins.append("const int gl_SemanticsRelaxed = 0x0;\n"); commonBuiltins.append("const int gl_SemanticsAcquire = 0x2;\n"); @@ -5527,7 +6050,59 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append("const int gl_StorageSemanticsImage = 0x800;\n"); commonBuiltins.append("const int gl_StorageSemanticsOutput = 0x1000;\n"); } -#endif + + // Adding these to common built-ins triggers an assert due to a memory corruption in related code when testing + // So instead add to each stage individually, avoiding the GLSLang bug + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { + for (int stage=EShLangVertex; stage(stage)].append("const highp int gl_ShadingRateFlag2VerticalPixelsEXT = 1;\n"); + stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag4VerticalPixelsEXT = 2;\n"); + stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag2HorizontalPixelsEXT = 4;\n"); + stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag4HorizontalPixelsEXT = 8;\n"); + } + } + + // GL_EXT_shader_image_int64 + if ((profile != EEsProfile && version >= 420) || + (profile == EEsProfile && version >= 310)) { + + const TBasicType bTypes[] = { EbtInt64, EbtUint64 }; + for (int ms = 0; ms <= 1; ++ms) { // loop over "bool" multisample or not + for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not + for (int dim = Esd1D; dim < EsdSubpass; ++dim) { // 1D, ..., buffer + if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile) + continue; + + if ((dim == Esd3D || dim == EsdRect || dim == EsdBuffer) && arrayed) + continue; + + if (dim != Esd2D && ms) + continue; + + // Loop over the bTypes + for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) { + // + // Now, make all the function prototypes for the type we just built... + // + TSampler sampler; + + sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, + false, + ms ? true : false); + + TString typeName = sampler.getString(); + + addQueryFunctions(sampler, typeName, version, profile); + addImageFunctions(sampler, typeName, version, profile); + } + } + } + } + } +#endif // !GLSLANG_ANGLE + +#endif // !GLSLANG_WEB // printf("%s\n", commonBuiltins.c_str()); // printf("%s\n", stageBuiltins[EShLangFragment].c_str()); @@ -5545,13 +6120,16 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c // // enumerate all the types + const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint, +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) + EbtFloat16 +#endif + }; #ifdef GLSLANG_WEB - const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint }; bool skipBuffer = true; bool skipCubeArrayed = true; const int image = 0; #else - const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint, EbtFloat16 }; bool skipBuffer = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 140); bool skipCubeArrayed = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 130); for (int image = 0; image <= 1; ++image) // loop over "bool" image vs sampler @@ -5576,8 +6154,12 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not #ifdef GLSLANG_WEB for (int dim = Esd2D; dim <= EsdCube; ++dim) { // 2D, 3D, and Cube +#else +#if defined(GLSLANG_ANGLE) + for (int dim = Esd2D; dim < EsdNumDims; ++dim) { // 2D, ..., buffer, subpass #else for (int dim = Esd1D; dim < EsdNumDims; ++dim) { // 1D, ..., buffer, subpass +#endif if (dim == EsdSubpass && spvVersion.vulkan == 0) continue; if (dim == EsdSubpass && (image || shadow || arrayed)) @@ -5616,7 +6198,6 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c #endif if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint)) continue; - // // Now, make all the function prototypes for the type we just built... // @@ -5708,7 +6289,7 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int return; #endif - if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430))) + if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 420))) return; if (profile == EEsProfile) @@ -5747,9 +6328,9 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int // // textureQueryLod(), fragment stage only - // + // Also enabled with extension GL_ARB_texture_query_lod - if (profile != EEsProfile && version >= 400 && sampler.isCombined() && sampler.dim != EsdRect && + if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect && ! sampler.isMultiSample() && ! sampler.isBuffer()) { for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) { if (f16TexAddr && sampler.type != EbtFloat16) @@ -5841,8 +6422,16 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int if ( profile != EEsProfile || (profile == EEsProfile && version >= 310)) { - if (sampler.type == EbtInt || sampler.type == EbtUint) { - const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint"; + if (sampler.type == EbtInt || sampler.type == EbtUint || sampler.type == EbtInt64 || sampler.type == EbtUint64 ) { + + const char* dataType; + switch (sampler.type) { + case(EbtInt): dataType = "highp int"; break; + case(EbtUint): dataType = "highp uint"; break; + case(EbtInt64): dataType = "highp int64_t"; break; + case(EbtUint64): dataType = "highp uint64_t"; break; + default: dataType = ""; + } const int numBuiltins = 7; @@ -5898,12 +6487,57 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int // not int or uint // GL_ARB_ES3_1_compatibility // TODO: spec issue: are there restrictions on the kind of layout() that can be used? what about dropping memory qualifiers? - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 310)) { + if (profile == EEsProfile && version >= 310) { commonBuiltins.append("float imageAtomicExchange(volatile coherent "); commonBuiltins.append(imageParams); commonBuiltins.append(", float);\n"); } + if (profile != EEsProfile && version >= 450) { + commonBuiltins.append("float imageAtomicAdd(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float);\n"); + + commonBuiltins.append("float imageAtomicAdd(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float"); + commonBuiltins.append(", int, int, int);\n"); + + commonBuiltins.append("float imageAtomicExchange(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float);\n"); + + commonBuiltins.append("float imageAtomicExchange(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float"); + commonBuiltins.append(", int, int, int);\n"); + + commonBuiltins.append("float imageAtomicLoad(readonly volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", int, int, int);\n"); + + commonBuiltins.append("void imageAtomicStore(writeonly volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float"); + commonBuiltins.append(", int, int, int);\n"); + + commonBuiltins.append("float imageAtomicMin(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float);\n"); + + commonBuiltins.append("float imageAtomicMin(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float"); + commonBuiltins.append(", int, int, int);\n"); + + commonBuiltins.append("float imageAtomicMax(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float);\n"); + + commonBuiltins.append("float imageAtomicMax(volatile coherent "); + commonBuiltins.append(imageParams); + commonBuiltins.append(", float"); + commonBuiltins.append(", int, int, int);\n"); + } } } @@ -5971,6 +6605,9 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; +#elif defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; #endif // @@ -6047,7 +6684,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, continue; // loop over 16-bit floating-point texel addressing -#ifdef GLSLANG_WEB +#if defined(GLSLANG_WEB) || defined(GLSLANG_ANGLE) const int f16TexAddr = 0; #else for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) @@ -6060,7 +6697,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, totalDims--; } // loop over "bool" lod clamp -#ifdef GLSLANG_WEB +#if defined(GLSLANG_WEB) || defined(GLSLANG_ANGLE) const int lodClamp = 0; #else for (int lodClamp = 0; lodClamp <= 1 ;++lodClamp) @@ -6072,7 +6709,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, continue; // loop over "bool" sparse or not -#ifdef GLSLANG_WEB +#if defined(GLSLANG_WEB) || defined(GLSLANG_ANGLE) const int sparse = 0; #else for (int sparse = 0; sparse <= 1; ++sparse) @@ -6127,7 +6764,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, s.append("Offset"); if (lodClamp) s.append("Clamp"); - if (lodClamp || sparse) + if (lodClamp != 0 || sparse) s.append("ARB"); s.append("("); @@ -6227,7 +6864,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, s.append(");\n"); // Add to the per-language set of built-ins - if (bias || lodClamp) { + if (!grad && (bias || lodClamp != 0)) { stageBuiltins[EShLangFragment].append(s); stageBuiltins[EShLangCompute].append(s); } else @@ -6256,6 +6893,9 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, in #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; +#elif defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; #endif switch (sampler.dim) { @@ -6499,6 +7139,9 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf #ifdef GLSLANG_WEB version = 310; profile = EEsProfile; +#elif defined(GLSLANG_ANGLE) + version = 450; + profile = ECoreProfile; #endif // @@ -6624,9 +7267,49 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf } } + if (version >= 320) { + // tessellation + + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.maxTessControlAtomicCounters); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.maxTessEvaluationAtomicCounters); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.maxTessControlAtomicCounterBuffers); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.maxTessEvaluationAtomicCounterBuffers); + s.append(builtInConstant); + } + + if (version >= 100) { + // GL_EXT_blend_func_extended + snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDualSourceDrawBuffersEXT = %d;", resources.maxDualSourceDrawBuffersEXT); + s.append(builtInConstant); + // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxDualSourceDrawBuffersEXT + if (language == EShLangFragment) { + s.append( + "mediump vec4 gl_SecondaryFragColorEXT;" + "mediump vec4 gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT];" + "\n"); + } + } } else { // non-ES profile + if (version > 400) { + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); + s.append(builtInConstant); + + snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); + s.append(builtInConstant); + + snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); + s.append(builtInConstant); + } + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); s.append(builtInConstant); @@ -6657,7 +7340,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); s.append(builtInConstant); - if (version < 150 || ARBCompatibility) { + // Moved from just being deprecated into compatibility profile only as of 4.20 + if (version < 420 || profile == ECompatibilityProfile) { snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); s.append(builtInConstant); } @@ -6890,6 +7574,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf s.append("\n"); } +#ifndef GLSLANG_ANGLE // atomic counters (some in compute below) if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) { @@ -6926,6 +7611,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf s.append("\n"); } +#endif // !GLSLANG_ANGLE // GL_ARB_cull_distance if (profile != EEsProfile && version >= 450) { @@ -6942,6 +7628,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf s.append(builtInConstant); } +#ifndef GLSLANG_ANGLE // SPV_NV_mesh_shader if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { snprintf(builtInConstant, maxSize, "const int gl_MaxMeshOutputVerticesNV = %d;", resources.maxMeshOutputVerticesNV); @@ -6964,6 +7651,7 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf s.append("\n"); } +#endif #endif s.append("\n"); @@ -7048,6 +7736,9 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion #ifdef GLSLANG_WEB version = 310; profile = EEsProfile; +#elif defined(GLSLANG_ANGLE) + version = 450; + profile = ECoreProfile; #endif // @@ -7075,6 +7766,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable); } + if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { + // treat these built-ins as aliases of VertexIndex and InstanceIndex + BuiltInVariable("gl_VertexID", EbvVertexIndex, symbolTable); + BuiltInVariable("gl_InstanceID", EbvInstanceIndex, symbolTable); + } + if (profile != EEsProfile) { if (version >= 440) { symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters); @@ -7237,7 +7934,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion case EShLangTessEvaluation: case EShLangGeometry: -#endif +#endif // !GLSLANG_WEB SpecialQualifier("gl_Position", EvqPosition, EbvPosition, symbolTable); SpecialQualifier("gl_PointSize", EvqPointSize, EbvPointSize, symbolTable); @@ -7398,7 +8095,21 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); } -#endif + + if (language == EShLangGeometry || language == EShLangVertex) { + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_PrimitiveShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate); + BuiltInVariable("gl_PrimitiveShadingRateEXT", EbvPrimitiveShadingRateKHR, symbolTable); + + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } + } + +#endif // !GLSLANG_WEB break; case EShLangFragment: @@ -7428,6 +8139,38 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable); } + if (profile != EEsProfile && version < 400) { + symbolTable.setFunctionExtensions("textureQueryLod", 1, &E_GL_ARB_texture_query_lod); + } + + if (profile != EEsProfile && version >= 460) { + symbolTable.setFunctionExtensions("rayQueryInitializeEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryTerminateEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGenerateIntersectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryConfirmIntersectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryProceedEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionTypeEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionTEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetRayFlagsEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetRayTMinEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceCustomIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceIdEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionGeometryIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionPrimitiveIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionBarycentricsEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionFrontFaceEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionCandidateAABBOpaqueEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayDirectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayOriginEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectToWorldEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionWorldToObjectEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetWorldRayOriginEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetWorldRayDirectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setVariableExtensions("gl_RayFlagsSkipAABBEXT", 1, &E_GL_EXT_ray_flags_primitive_culling); + symbolTable.setVariableExtensions("gl_RayFlagsSkipTrianglesEXT", 1, &E_GL_EXT_ray_flags_primitive_culling); + } + if ((profile != EEsProfile && version >= 130) || (profile == EEsProfile && version >= 310)) { BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable); @@ -7540,6 +8283,19 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("atomicCounter" , 1, &E_GL_ARB_shader_atomic_counters); } + // E_GL_ARB_shader_atomic_counter_ops + if (profile != EEsProfile && version == 450) { + symbolTable.setFunctionExtensions("atomicCounterAddARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterSubtractARB", 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterMinARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterMaxARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterAndARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterOrARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterXorARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterExchangeARB", 1, &E_GL_ARB_shader_atomic_counter_ops); + symbolTable.setFunctionExtensions("atomicCounterCompSwapARB", 1, &E_GL_ARB_shader_atomic_counter_ops); + } + // E_GL_ARB_derivative_control if (profile != EEsProfile && version < 450) { symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_ARB_derivative_control); @@ -7666,6 +8422,45 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic); } + if (profile != EEsProfile && version < 330 ) { + symbolTable.setFunctionExtensions("floatBitsToInt", 1, &E_GL_ARB_shader_bit_encoding); + symbolTable.setFunctionExtensions("floatBitsToUint", 1, &E_GL_ARB_shader_bit_encoding); + symbolTable.setFunctionExtensions("intBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding); + symbolTable.setFunctionExtensions("uintBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding); + } + + if (profile != EEsProfile && version < 430 ) { + symbolTable.setFunctionExtensions("imageSize", 1, &E_GL_ARB_shader_image_size); + } + + // GL_ARB_shader_storage_buffer_object + if (profile != EEsProfile && version < 430 ) { + symbolTable.setFunctionExtensions("atomicAdd", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicMin", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicMax", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicAnd", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicOr", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicXor", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicExchange", 1, &E_GL_ARB_shader_storage_buffer_object); + symbolTable.setFunctionExtensions("atomicCompSwap", 1, &E_GL_ARB_shader_storage_buffer_object); + } + + // GL_ARB_shading_language_packing + if (profile != EEsProfile && version < 400 ) { + symbolTable.setFunctionExtensions("packUnorm2x16", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("unpackUnorm2x16", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("packSnorm4x8", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("packUnorm4x8", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("unpackSnorm4x8", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("unpackUnorm4x8", 1, &E_GL_ARB_shading_language_packing); + } + if (profile != EEsProfile && version < 420 ) { + symbolTable.setFunctionExtensions("packSnorm2x16", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("unpackSnorm2x16", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("unpackHalf2x16", 1, &E_GL_ARB_shading_language_packing); + symbolTable.setFunctionExtensions("packHalf2x16", 1, &E_GL_ARB_shading_language_packing); + } + symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); @@ -7833,7 +8628,18 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion } symbolTable.setFunctionExtensions("helperInvocationEXT", 1, &E_GL_EXT_demote_to_helper_invocation); -#endif + + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_ShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate); + BuiltInVariable("gl_ShadingRateEXT", EbvShadingRateKHR, symbolTable); + + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } +#endif // !GLSLANG_WEB break; case EShLangCompute: @@ -7877,7 +8683,9 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader); } + symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics); + symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf); // GL_ARB_shader_ballot if (profile != EEsProfile) { @@ -7963,53 +8771,110 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_NV_compute_shader_derivatives); symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_NV_compute_shader_derivatives); } -#endif + + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } +#endif // !GLSLANG_WEB break; -#ifndef GLSLANG_WEB - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: if (profile != EEsProfile && version >= 460) { + const char *rtexts[] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; symbolTable.setVariableExtensions("gl_LaunchIDNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_LaunchIDEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_LaunchSizeNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_PrimitiveID", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_InstanceID", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_LaunchSizeEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_PrimitiveID", 2, rtexts); + symbolTable.setVariableExtensions("gl_InstanceID", 2, rtexts); symbolTable.setVariableExtensions("gl_InstanceCustomIndexNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_InstanceCustomIndexEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_GeometryIndexEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldRayOriginNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldRayOriginEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldRayDirectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectRayOriginNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectRayOriginEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectRayDirectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTminNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_HitKindEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectToWorldNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectToWorldEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectToWorld3x4EXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldToObjectNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldToObjectEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldToObject3x4EXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_IncomingRayFlagsNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_IncomingRayFlagsEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_CurrentRayTimeNV", 1, &E_GL_NV_ray_tracing_motion_blur); symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_LaunchIDNV", EbvLaunchIdNV, symbolTable); - BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSizeNV, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable); - BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndexNV,symbolTable); - BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOriginNV, symbolTable); - BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirectionNV, symbolTable); - BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOriginNV, symbolTable); - BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirectionNV, symbolTable); - BuiltInVariable("gl_RayTminNV", EbvRayTminNV, symbolTable); - BuiltInVariable("gl_RayTmaxNV", EbvRayTmaxNV, symbolTable); - BuiltInVariable("gl_HitTNV", EbvHitTNV, symbolTable); - BuiltInVariable("gl_HitKindNV", EbvHitKindNV, symbolTable); - BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorldNV, symbolTable); - BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObjectNV, symbolTable); - BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlagsNV, symbolTable); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); + + symbolTable.setFunctionExtensions("traceNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("traceRayMotionNV", 1, &E_GL_NV_ray_tracing_motion_blur); + symbolTable.setFunctionExtensions("traceRayEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing); + + + BuiltInVariable("gl_LaunchIDNV", EbvLaunchId, symbolTable); + BuiltInVariable("gl_LaunchIDEXT", EbvLaunchId, symbolTable); + BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSize, symbolTable); + BuiltInVariable("gl_LaunchSizeEXT", EbvLaunchSize, symbolTable); + BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); + BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable); + BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndex,symbolTable); + BuiltInVariable("gl_InstanceCustomIndexEXT", EbvInstanceCustomIndex,symbolTable); + BuiltInVariable("gl_GeometryIndexEXT", EbvGeometryIndex, symbolTable); + BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOrigin, symbolTable); + BuiltInVariable("gl_WorldRayOriginEXT", EbvWorldRayOrigin, symbolTable); + BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirection, symbolTable); + BuiltInVariable("gl_WorldRayDirectionEXT", EbvWorldRayDirection, symbolTable); + BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOrigin, symbolTable); + BuiltInVariable("gl_ObjectRayOriginEXT", EbvObjectRayOrigin, symbolTable); + BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirection, symbolTable); + BuiltInVariable("gl_ObjectRayDirectionEXT", EbvObjectRayDirection, symbolTable); + BuiltInVariable("gl_RayTminNV", EbvRayTmin, symbolTable); + BuiltInVariable("gl_RayTminEXT", EbvRayTmin, symbolTable); + BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable); + BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable); + BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable); + BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable); + BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable); + BuiltInVariable("gl_HitKindEXT", EbvHitKind, symbolTable); + BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorld, symbolTable); + BuiltInVariable("gl_ObjectToWorldEXT", EbvObjectToWorld, symbolTable); + BuiltInVariable("gl_ObjectToWorld3x4EXT", EbvObjectToWorld3x4, symbolTable); + BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObject, symbolTable); + BuiltInVariable("gl_WorldToObjectEXT", EbvWorldToObject, symbolTable); + BuiltInVariable("gl_WorldToObject3x4EXT", EbvWorldToObject3x4, symbolTable); + BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlags, symbolTable); + BuiltInVariable("gl_IncomingRayFlagsEXT", EbvIncomingRayFlags, symbolTable); + BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); + BuiltInVariable("gl_CurrentRayTimeNV", EbvCurrentRayTimeNV, symbolTable); // GL_ARB_shader_ballot symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); @@ -8064,6 +8929,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); } + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } break; case EShLangMeshNV: @@ -8208,6 +9080,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); } + + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } break; case EShLangTaskNV: @@ -8308,6 +9188,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); } + if ((profile == EEsProfile && version >= 310) || + (profile != EEsProfile && version >= 450)) { + symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); + } break; #endif @@ -8377,6 +9264,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter); symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage); + if (spvVersion.vulkanRelaxed) { + // + // functions signature have been replaced to take uint operations on buffer variables + // remap atomic counter functions to atomic operations + // + symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierBuffer); + } + symbolTable.relateToOperator("atomicLoad", EOpAtomicLoad); symbolTable.relateToOperator("atomicStore", EOpAtomicStore); @@ -8384,12 +9279,38 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement); symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter); + if (spvVersion.vulkanRelaxed) { + // + // functions signature have been replaced to take uint operations + // remap atomic counter functions to atomic operations + // + // these atomic counter functions do not match signatures of glsl + // atomic functions, so they will be remapped to semantically + // equivalent functions in the parser + // + symbolTable.relateToOperator("atomicCounterIncrement", EOpNull); + symbolTable.relateToOperator("atomicCounterDecrement", EOpNull); + symbolTable.relateToOperator("atomicCounter", EOpNull); + } + symbolTable.relateToOperator("clockARB", EOpReadClockSubgroupKHR); symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR); symbolTable.relateToOperator("clockRealtimeEXT", EOpReadClockDeviceKHR); symbolTable.relateToOperator("clockRealtime2x32EXT", EOpReadClockDeviceKHR); + if (profile != EEsProfile && version == 450) { + symbolTable.relateToOperator("atomicCounterAddARB", EOpAtomicCounterAdd); + symbolTable.relateToOperator("atomicCounterSubtractARB", EOpAtomicCounterSubtract); + symbolTable.relateToOperator("atomicCounterMinARB", EOpAtomicCounterMin); + symbolTable.relateToOperator("atomicCounterMaxARB", EOpAtomicCounterMax); + symbolTable.relateToOperator("atomicCounterAndARB", EOpAtomicCounterAnd); + symbolTable.relateToOperator("atomicCounterOrARB", EOpAtomicCounterOr); + symbolTable.relateToOperator("atomicCounterXorARB", EOpAtomicCounterXor); + symbolTable.relateToOperator("atomicCounterExchangeARB", EOpAtomicCounterExchange); + symbolTable.relateToOperator("atomicCounterCompSwapARB", EOpAtomicCounterCompSwap); + } + if (profile != EEsProfile && version >= 460) { symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd); symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract); @@ -8402,6 +9323,23 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap); } + if (spvVersion.vulkanRelaxed) { + // + // functions signature have been replaced to take 'uint' instead of 'atomic_uint' + // remap atomic counter functions to non-counter atomic ops so + // functions act as aliases to non-counter atomic ops + // + symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicAdd); + symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicSubtract); + symbolTable.relateToOperator("atomicCounterMin", EOpAtomicMin); + symbolTable.relateToOperator("atomicCounterMax", EOpAtomicMax); + symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicAnd); + symbolTable.relateToOperator("atomicCounterOr", EOpAtomicOr); + symbolTable.relateToOperator("atomicCounterXor", EOpAtomicXor); + symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicExchange); + symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCompSwap); + } + symbolTable.relateToOperator("fma", EOpFma); symbolTable.relateToOperator("frexp", EOpFrexp); symbolTable.relateToOperator("ldexp", EOpLdexp); @@ -8426,6 +9364,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("average", EOpAverage); symbolTable.relateToOperator("averageRounded", EOpAverageRounded); symbolTable.relateToOperator("multiply32x16", EOpMul32x16); + symbolTable.relateToOperator("debugPrintfEXT", EOpDebugPrintf); + if (PureOperatorBuiltins) { symbolTable.relateToOperator("imageSize", EOpImageQuerySize); @@ -8715,6 +9655,33 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse); symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse); } + + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("rayQueryInitializeEXT", EOpRayQueryInitialize); + symbolTable.relateToOperator("rayQueryTerminateEXT", EOpRayQueryTerminate); + symbolTable.relateToOperator("rayQueryGenerateIntersectionEXT", EOpRayQueryGenerateIntersection); + symbolTable.relateToOperator("rayQueryConfirmIntersectionEXT", EOpRayQueryConfirmIntersection); + symbolTable.relateToOperator("rayQueryProceedEXT", EOpRayQueryProceed); + symbolTable.relateToOperator("rayQueryGetIntersectionTypeEXT", EOpRayQueryGetIntersectionType); + symbolTable.relateToOperator("rayQueryGetRayTMinEXT", EOpRayQueryGetRayTMin); + symbolTable.relateToOperator("rayQueryGetRayFlagsEXT", EOpRayQueryGetRayFlags); + symbolTable.relateToOperator("rayQueryGetIntersectionTEXT", EOpRayQueryGetIntersectionT); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceCustomIndexEXT", EOpRayQueryGetIntersectionInstanceCustomIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceIdEXT", EOpRayQueryGetIntersectionInstanceId); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset); + symbolTable.relateToOperator("rayQueryGetIntersectionGeometryIndexEXT", EOpRayQueryGetIntersectionGeometryIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionPrimitiveIndexEXT", EOpRayQueryGetIntersectionPrimitiveIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionBarycentricsEXT", EOpRayQueryGetIntersectionBarycentrics); + symbolTable.relateToOperator("rayQueryGetIntersectionFrontFaceEXT", EOpRayQueryGetIntersectionFrontFace); + symbolTable.relateToOperator("rayQueryGetIntersectionCandidateAABBOpaqueEXT", EOpRayQueryGetIntersectionCandidateAABBOpaque); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayDirectionEXT", EOpRayQueryGetIntersectionObjectRayDirection); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayOriginEXT", EOpRayQueryGetIntersectionObjectRayOrigin); + symbolTable.relateToOperator("rayQueryGetWorldRayDirectionEXT", EOpRayQueryGetWorldRayDirection); + symbolTable.relateToOperator("rayQueryGetWorldRayOriginEXT", EOpRayQueryGetWorldRayOrigin); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectToWorldEXT", EOpRayQueryGetIntersectionObjectToWorld); + symbolTable.relateToOperator("rayQueryGetIntersectionWorldToObjectEXT", EOpRayQueryGetIntersectionWorldToObject); + } + symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid); symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample); symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset); @@ -8746,27 +9713,33 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("coopMatMulAddNV", EOpCooperativeMatrixMulAdd); break; - case EShLangRayGenNV: - case EShLangClosestHitNV: - case EShLangMissNV: + case EShLangRayGen: + case EShLangClosestHit: + case EShLangMiss: if (profile != EEsProfile && version >= 460) { symbolTable.relateToOperator("traceNV", EOpTraceNV); + symbolTable.relateToOperator("traceRayMotionNV", EOpTraceRayMotionNV); + symbolTable.relateToOperator("traceRayEXT", EOpTraceKHR); symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); + symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR); } break; - case EShLangIntersectNV: - if (profile != EEsProfile && version >= 460) - symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersectionNV); + case EShLangIntersect: + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersection); + symbolTable.relateToOperator("reportIntersectionEXT", EOpReportIntersection); + } break; - case EShLangAnyHitNV: + case EShLangAnyHit: if (profile != EEsProfile && version >= 460) { symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV); symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV); } break; - case EShLangCallableNV: + case EShLangCallable: if (profile != EEsProfile && version >= 460) { symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); + symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR); } break; case EShLangMeshNV: @@ -8785,7 +9758,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion default: assert(false && "Language not supported"); } -#endif +#endif // !GLSLANG_WEB } // @@ -8800,6 +9773,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) { #ifndef GLSLANG_WEB +#if defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; +#endif if (profile != EEsProfile && version >= 430 && version < 440) { symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &E_GL_ARB_enhanced_layouts); symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &E_GL_ARB_enhanced_layouts); @@ -8823,6 +9800,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable); } + + // GL_EXT_blend_func_extended + if (profile == EEsProfile && version >= 100) { + symbolTable.setVariableExtensions("gl_MaxDualSourceDrawBuffersEXT", 1, &E_GL_EXT_blend_func_extended); + symbolTable.setVariableExtensions("gl_SecondaryFragColorEXT", 1, &E_GL_EXT_blend_func_extended); + symbolTable.setVariableExtensions("gl_SecondaryFragDataEXT", 1, &E_GL_EXT_blend_func_extended); + SpecialQualifier("gl_SecondaryFragColorEXT", EvqVaryingOut, EbvSecondaryFragColorEXT, symbolTable); + SpecialQualifier("gl_SecondaryFragDataEXT", EvqVaryingOut, EbvSecondaryFragDataEXT, symbolTable); + } + break; case EShLangTessControl: diff --git a/libraries/glslang/glslang/MachineIndependent/Initialize.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Initialize.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/Initialize.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Initialize.h diff --git a/libraries/glslang/glslang/MachineIndependent/IntermTraverse.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/IntermTraverse.cpp similarity index 97% rename from libraries/glslang/glslang/MachineIndependent/IntermTraverse.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/IntermTraverse.cpp index f46010b71..553b1b5ff 100644 --- a/libraries/glslang/glslang/MachineIndependent/IntermTraverse.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/IntermTraverse.cpp @@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it) it->visitConstantUnion(this); } +const TString& TIntermSymbol::getAccessName() const { + if (getBasicType() == EbtBlock) + return getType().getTypeName(); + else + return getName(); +} + // // Traverse a binary node. // diff --git a/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Intermediate.cpp similarity index 91% rename from libraries/glslang/glslang/MachineIndependent/Intermediate.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Intermediate.cpp index d0f86e638..027844596 100644 --- a/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Intermediate.cpp @@ -1,7 +1,7 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. // // All rights reserved. @@ -65,7 +65,7 @@ namespace glslang { // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, +TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray, TIntermTyped* constSubtree, const TSourceLoc& loc) { TIntermSymbol* node = new TIntermSymbol(id, name, type); @@ -113,14 +113,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc // // Returns nullptr if the working conversions and promotions could not be found. // -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc) { // No operations work on blocks if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) return nullptr; // Convert "reference +/- int" and "reference - reference" to integer math - if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) { + if (op == EOpAdd || op == EOpSub) { // No addressing math on struct with unsized array. if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) || @@ -140,43 +140,44 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); return node; } - - if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) { - const TType& referenceType = right->getType(); - TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true); - right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); - - left = createConversion(EbtInt64, left); - left = addBinaryMath(EOpMul, left, size, loc); - - TIntermTyped *node = addBinaryMath(op, left, right, loc); - node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); - return node; - } - - if (op == EOpSub && left->isReference() && right->isReference()) { - TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true); - - left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64)); - right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); - - left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64)); - right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64)); - - left = addBinaryMath(EOpSub, left, right, loc); - - TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc); - return node; - } - - // No other math operators supported on references - if (left->isReference() || right->isReference()) { - return nullptr; - } } + if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) { + const TType& referenceType = right->getType(); + TIntermConstantUnion* size = + addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true); + right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); + + left = createConversion(EbtInt64, left); + left = addBinaryMath(EOpMul, left, size, loc); + + TIntermTyped *node = addBinaryMath(op, left, right, loc); + node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); + return node; + } + + if (op == EOpSub && left->isReference() && right->isReference()) { + TIntermConstantUnion* size = + addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true); + + left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64)); + right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); + + left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64)); + right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64)); + + left = addBinaryMath(EOpSub, left, right, loc); + + TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc); + return node; + } + + // No other math operators supported on references + if (left->isReference() || right->isReference()) + return nullptr; + // Try converting the children's base types to compatible types. - auto children = addConversion(op, left, right); + auto children = addPairConversion(op, left, right); left = std::get<0>(children); right = std::get<1>(children); @@ -226,13 +227,12 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // Low level: add binary node (no promotions or other argument modifications) // -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const +TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, + const TSourceLoc& loc) const { // build the node TIntermBinary* node = new TIntermBinary(op); - if (loc.line == 0) - loc = left->getLoc(); - node->setLoc(loc); + node->setLoc(loc.line != 0 ? loc : left->getLoc()); node->setLeft(left); node->setRight(right); @@ -242,7 +242,8 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI // // like non-type form, but sets node's type. // -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const +TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, + const TSourceLoc& loc, const TType& type) const { TIntermBinary* node = addBinaryNode(op, left, right, loc); node->setType(type); @@ -252,12 +253,10 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI // // Low level: add unary node (no promotions or other argument modifications) // -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const +TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const { TIntermUnary* node = new TIntermUnary(op); - if (loc.line == 0) - loc = child->getLoc(); - node->setLoc(loc); + node->setLoc(loc.line != 0 ? loc : child->getLoc()); node->setOperand(child); return node; @@ -266,7 +265,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo // // like non-type form, but sets node's type. // -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const +TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type) + const { TIntermUnary* node = addUnaryNode(op, child, loc); node->setType(type); @@ -281,7 +281,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo // Returns nullptr if the 'right' type could not be converted to match the 'left' type, // or the resulting operation cannot be properly promoted. // -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, + const TSourceLoc& loc) { // No block assignment if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) @@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // Convert "reference += int" to "reference = reference + int". We need this because the // "reference + int" calculation involves a cast back to the original type, which makes it // not an lvalue. - if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() && - extensionRequested(E_GL_EXT_buffer_reference2)) { - + if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) { if (!(right->getType().isScalar() && right->getType().isIntegerDomain())) return nullptr; @@ -338,7 +337,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // Returns the added node. // The caller should set the type of the returned node. // -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc) +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, + const TSourceLoc& loc) { // caller should set the type return addBinaryNode(op, base, index, loc); @@ -349,7 +349,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // Returns the added node. // -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc) +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, + const TSourceLoc& loc) { if (child == 0) return nullptr; @@ -495,7 +496,8 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper // Returns an aggregate node, which could be the one passed in if // it was already an aggregate. // -TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc) +TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, + const TSourceLoc& loc) { TIntermAggregate* aggNode; @@ -510,8 +512,6 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o // aggNode = new TIntermAggregate(); aggNode->getSequence().push_back(node); - if (loc.line == 0) - loc = node->getLoc(); } } else aggNode = new TIntermAggregate(); @@ -520,8 +520,8 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o // Set the operator. // aggNode->setOperator(op); - if (loc.line != 0) - aggNode->setLoc(loc); + if (loc.line != 0 || node != nullptr) + aggNode->setLoc(loc.line != 0 ? loc : node->getLoc()); aggNode->setType(type); @@ -538,7 +538,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const return false; case EbtAtomicUint: case EbtSampler: - case EbtAccStructNV: + case EbtAccStruct: // opaque types can be passed to functions if (op == EOpFunction) break; @@ -819,22 +819,25 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped node->getBasicType() == EbtFloat || node->getBasicType() == EbtDouble); - if (! getArithemeticInt8Enabled()) { - if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) || - ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) + if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) || + ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) { + if (! getArithemeticInt8Enabled()) { return nullptr; + } } - if (! getArithemeticInt16Enabled()) { - if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) || - ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) + if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) || + ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) { + if (! getArithemeticInt16Enabled()) { return nullptr; + } } - if (! getArithemeticFloat16Enabled()) { - if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) || - (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) + if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) || + (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) { + if (! getArithemeticFloat16Enabled()) { return nullptr; + } } #endif @@ -887,7 +890,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n // Returns the converted pair of nodes. // Returns when there is no conversion. std::tuple -TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) +TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) { if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1)) return std::make_tuple(nullptr, nullptr); @@ -940,7 +943,7 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no if (node0->getBasicType() == node1->getBasicType()) return std::make_tuple(node0, node1); - promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op); + promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op); if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes) return std::make_tuple(nullptr, nullptr); @@ -1040,64 +1043,30 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // Note: callers are responsible for other aspects of shape, // like vector and matrix sizes. - TBasicType promoteTo; - // GL_EXT_shader_16bit_storage can't do OpConstantComposite with - // 16-bit types, so disable promotion for those types. - bool canPromoteConstant = true; - switch (op) { // // Explicit conversions (unary operations) // case EOpConstructBool: - promoteTo = EbtBool; - break; case EOpConstructFloat: - promoteTo = EbtFloat; - break; case EOpConstructInt: - promoteTo = EbtInt; - break; case EOpConstructUint: - promoteTo = EbtUint; - break; #ifndef GLSLANG_WEB case EOpConstructDouble: - promoteTo = EbtDouble; - break; case EOpConstructFloat16: - promoteTo = EbtFloat16; - canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); - break; case EOpConstructInt8: - promoteTo = EbtInt8; - canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); - break; case EOpConstructUint8: - promoteTo = EbtUint8; - canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); - break; case EOpConstructInt16: - promoteTo = EbtInt16; - canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); - break; case EOpConstructUint16: - promoteTo = EbtUint16; - canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); - break; case EOpConstructInt64: - promoteTo = EbtInt64; - break; case EOpConstructUint64: - promoteTo = EbtUint64; break; + #endif + // + // Implicit conversions + // case EOpLogicalNot: case EOpFunctionCall: @@ -1152,9 +1121,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt if (type.getBasicType() == node->getType().getBasicType()) return node; - if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) - promoteTo = type.getBasicType(); - else + if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) return nullptr; break; @@ -1164,9 +1131,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EOpLeftShiftAssign: case EOpRightShiftAssign: { - if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool) - promoteTo = type.getBasicType(); - else { + if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) { if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType())) return node; else @@ -1184,13 +1149,44 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt return nullptr; } + bool canPromoteConstant = true; +#ifndef GLSLANG_WEB + // GL_EXT_shader_16bit_storage can't do OpConstantComposite with + // 16-bit types, so disable promotion for those types. + // Many issues with this, from JohnK: + // - this isn't really right to discuss SPIR-V here + // - this could easily be entirely about scalars, so is overstepping + // - we should be looking at what the shader asked for, and saying whether or + // not it can be done, in the parser, by calling requireExtensions(), not + // changing language sementics on the fly by asking what extensions are in use + // - at the time of this writing (14-Aug-2020), no test results are changed by this. + switch (op) { + case EOpConstructFloat16: + canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); + break; + case EOpConstructInt8: + case EOpConstructUint8: + canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); + break; + case EOpConstructInt16: + case EOpConstructUint16: + canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); + break; + default: + break; + } +#endif + if (canPromoteConstant && node->getAsConstantUnion()) - return promoteConstantUnion(promoteTo, node->getAsConstantUnion()); + return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion()); // // Add a new newNode for the conversion. // - TIntermTyped* newNode = createConversion(promoteTo, node); + TIntermTyped* newNode = createConversion(type.getBasicType(), node); return newNode; } @@ -1620,7 +1616,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const // bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const { - if (isEsProfile() || version == 110) + if ((isEsProfile() && version < 310 ) || version == 110) return false; if (from == to) @@ -1659,46 +1655,51 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat } } - bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64); - - if (explicitTypesEnabled) { - // integral promotions - if (isIntegralPromotion(from, to)) { + if (getSource() == EShSourceHlsl) { + // HLSL + if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat)) return true; - } + } else { + // GLSL + if (isIntegralPromotion(from, to) || + isFPPromotion(from, to) || + isIntegralConversion(from, to) || + isFPConversion(from, to) || + isFPIntegralConversion(from, to)) { - // floating-point promotions - if (isFPPromotion(from, to)) { - return true; - } - - // integral conversions - if (isIntegralConversion(from, to)) { - return true; - } - - // floating-point conversions - if (isFPConversion(from, to)) { - return true; - } - - // floating-integral conversions - if (isFPIntegralConversion(from, to)) { - return true; - } - - // hlsl supported conversions - if (getSource() == EShSourceHlsl) { - if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat)) + if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) { return true; + } } + } + + if (isEsProfile()) { + switch (to) { + case EbtFloat: + switch (from) { + case EbtInt: + case EbtUint: + return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions); + default: + return false; + } + case EbtUint: + switch (from) { + case EbtInt: + return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions); + default: + return false; + } + default: + return false; + } } else { switch (to) { case EbtDouble: @@ -1708,13 +1709,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtInt64: case EbtUint64: case EbtFloat: - case EbtDouble: - return true; + return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64); case EbtInt16: case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) && + numericFeatures.contains(TNumericFeatures::gpu_shader_int16); case EbtFloat16: - return extensionRequested(E_GL_AMD_gpu_shader_half_float); + return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) && + numericFeatures.contains(TNumericFeatures::gpu_shader_half_float); default: return false; } @@ -1722,16 +1724,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat switch (from) { case EbtInt: case EbtUint: - case EbtFloat: return true; case EbtBool: return getSource() == EShSourceHlsl; case EbtInt16: case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); case EbtFloat16: - return - extensionRequested(E_GL_AMD_gpu_shader_half_float) || + return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || getSource() == EShSourceHlsl; default: return false; @@ -1739,25 +1739,21 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtUint: switch (from) { case EbtInt: - return version >= 400 || getSource() == EShSourceHlsl; - case EbtUint: - return true; + return version >= 400 || getSource() == EShSourceHlsl || IsRequestedExtension(E_GL_ARB_gpu_shader5); case EbtBool: return getSource() == EShSourceHlsl; case EbtInt16: case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: return false; } case EbtInt: switch (from) { - case EbtInt: - return true; case EbtBool: return getSource() == EShSourceHlsl; case EbtInt16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: return false; } @@ -1766,21 +1762,19 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtInt: case EbtUint: case EbtInt64: - case EbtUint64: return true; case EbtInt16: case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: return false; } case EbtInt64: switch (from) { case EbtInt: - case EbtInt64: return true; case EbtInt16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: return false; } @@ -1788,9 +1782,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat switch (from) { case EbtInt16: case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); - case EbtFloat16: - return extensionRequested(E_GL_AMD_gpu_shader_half_float); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: break; } @@ -1798,8 +1790,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtUint16: switch (from) { case EbtInt16: - case EbtUint16: - return extensionRequested(E_GL_AMD_gpu_shader_int16); + return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); default: break; } @@ -1926,12 +1917,14 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type) // integer type corresponding to the type of the operand with signed // integer type. -std::tuple TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const +std::tuple TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const { TBasicType res0 = EbtNumTypes; TBasicType res1 = EbtNumTypes; - if (isEsProfile() || version == 110) + if ((isEsProfile() && + (version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) || + version == 110) return std::make_tuple(res0, res1); if (getSource() == EShSourceHlsl) { @@ -2305,6 +2298,10 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const case EbtReference: op = EOpConstructReference; break; + + case EbtAccStruct: + op = EOpConstructAccStruct; + break; #endif default: break; @@ -2463,7 +2460,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // // Get compatible types. // - auto children = addConversion(EOpSequence, trueBlock, falseBlock); + auto children = addPairConversion(EOpSequence, trueBlock, falseBlock); trueBlock = std::get<0>(children); falseBlock = std::get<1>(children); @@ -2679,7 +2676,11 @@ TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selecto // 'swizzleOkay' says whether or not it is okay to consider a swizzle // a valid part of the dereference chain. // -const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay) +// 'BufferReferenceOk' says if type is buffer_reference, the routine stop to find the most left node. +// +// + +const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay , bool bufferReferenceOk) { do { const TIntermBinary* binary = node->getAsBinaryNode(); @@ -2697,6 +2698,8 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool return nullptr; } node = node->getAsBinaryNode()->getLeft(); + if (bufferReferenceOk && node->isReference()) + return node; } while (true); } @@ -2750,6 +2753,22 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres return node; } +// Propagate precision from formal function return type to actual return type, +// and on to its subtree. +void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision) +{ + TIntermTyped* exp = getExpression(); + if (exp == nullptr) + return; + + if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint || + exp->getBasicType() == EbtFloat || exp->getBasicType() == EbtFloat16) { + if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) { + exp->propagatePrecision(parentPrecision); + } + } +} + // // This is to be executed after the final root is put on top by the parsing // process. @@ -2774,6 +2793,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) case EShTexSampTransUpgradeTextureRemoveSampler: performTextureUpgradeAndSamplerRemovalTransformation(root); break; + case EShTexSampTransCount: + assert(0); + break; } #endif @@ -2854,7 +2876,7 @@ void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& calle return; } - callGraph.push_front(TCall(caller, callee)); + callGraph.emplace_front(caller, callee); } // @@ -3234,10 +3256,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node) return false; break; - default: - if (operand->getBasicType() != EbtFloat) + // HLSL uses this path for initial function signature finding for built-ins + // taking a single argument, which generally don't participate in + // operator-based type promotion (type conversion will occur later). + // For now, scalar argument cases are relying on the setType() call below. + if (getSource() == EShSourceHlsl) + break; + // GLSL only allows integer arguments for the cases identified above in the + // case statements. + if (operand->getBasicType() != EbtFloat) return false; } @@ -3247,9 +3276,11 @@ bool TIntermediate::promoteUnary(TIntermUnary& node) return true; } +// Propagate precision qualifiers *up* from children to parent. void TIntermUnary::updatePrecision() { - if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { + if (getBasicType() == EbtInt || getBasicType() == EbtUint || + getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { if (operand->getQualifier().precision > getQualifier().precision) getQualifier().precision = operand->getQualifier().precision; } @@ -3745,20 +3776,33 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node) return false; } +// Propagate precision qualifiers *up* from children to parent, and then +// back *down* again to the children's subtrees. void TIntermBinary::updatePrecision() { - if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { - getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); - if (getQualifier().precision != EpqNone) { - left->propagatePrecision(getQualifier().precision); - right->propagatePrecision(getQualifier().precision); - } + if (getBasicType() == EbtInt || getBasicType() == EbtUint || + getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { + if (op == EOpRightShift || op == EOpLeftShift) { + // For shifts get precision from left side only and thus no need to propagate + getQualifier().precision = left->getQualifier().precision; + } else { + getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); + if (getQualifier().precision != EpqNone) { + left->propagatePrecision(getQualifier().precision); + right->propagatePrecision(getQualifier().precision); + } + } } } +// Recursively propagate precision qualifiers *down* the subtree of the current node, +// until reaching a node that already has a precision qualifier or otherwise does +// not participate in precision propagation. void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) { - if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) + if (getQualifier().precision != EpqNone || + (getBasicType() != EbtInt && getBasicType() != EbtUint && + getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) return; getQualifier().precision = newPrecision; diff --git a/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/LiveTraverser.h similarity index 76% rename from libraries/glslang/glslang/MachineIndependent/LiveTraverser.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/LiveTraverser.h index 7333bc964..9b39b5983 100644 --- a/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/LiveTraverser.h @@ -74,14 +74,33 @@ public: for (unsigned int f = 0; f < globals.size(); ++f) { TIntermAggregate* candidate = globals[f]->getAsAggregate(); if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { - functions.push_back(candidate); + destinations.push_back(candidate); break; } } } - typedef std::list TFunctionStack; - TFunctionStack functions; + void pushGlobalReference(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpSequence && + candidate->getSequence().size() == 1 && + candidate->getSequence()[0]->getAsBinaryNode()) { + TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode(); + TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode(); + if (symbol && symbol->getQualifier().storage == EvqGlobal && + symbol->getName() == name) { + destinations.push_back(candidate); + break; + } + } + } + } + + typedef std::list TDestinationStack; + TDestinationStack destinations; protected: // To catch which function calls are not dead, and hence which functions must be visited. @@ -117,16 +136,27 @@ protected: // and only visit each function once. void addFunctionCall(TIntermAggregate* call) { - // // just use the map to ensure we process each function at most once + // just use the map to ensure we process each function at most once if (liveFunctions.find(call->getName()) == liveFunctions.end()) { liveFunctions.insert(call->getName()); pushFunction(call->getName()); } } + void addGlobalReference(const TString& name) + { + // just use the map to ensure we process each global at most once + if (liveGlobals.find(name) == liveGlobals.end()) { + liveGlobals.insert(name); + pushGlobalReference(name); + } + } + const TIntermediate& intermediate; typedef std::unordered_set TLiveFunctions; TLiveFunctions liveFunctions; + typedef std::unordered_set TLiveGlobals; + TLiveGlobals liveGlobals; bool traverseAll; private: diff --git a/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseContextBase.cpp similarity index 80% rename from libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseContextBase.cpp index 282ecca0e..02cca409e 100644 --- a/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseContextBase.cpp @@ -127,22 +127,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, { TIntermBinary* binaryNode = node->getAsBinaryNode(); - if (binaryNode) { - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: // fall through - case EOpIndexDirectStruct: // fall through - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - return lValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; - } - error(loc, " l-value required", op, "", ""); - - return true; - } - const char* symbol = nullptr; TIntermSymbol* symNode = node->getAsSymbolNode(); if (symNode != nullptr) @@ -157,11 +141,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, case EvqBuffer: if (node->getQualifier().isReadOnly()) message = "can't modify a readonly buffer"; - if (node->getQualifier().isShaderRecordNV()) + if (node->getQualifier().isShaderRecord()) message = "can't modify a shaderrecordnv qualified buffer"; break; - case EvqHitAttrNV: - if (language != EShLangIntersectNV) + case EvqHitAttr: + if (language != EShLangIntersect) message = "cannot modify hitAttributeNV in this stage"; break; #endif @@ -181,9 +165,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, case EbtAtomicUint: message = "can't modify an atomic_uint"; break; - case EbtAccStructNV: + case EbtAccStruct: message = "can't modify accelerationStructureNV"; break; + case EbtRayQuery: + message = "can't modify rayQueryEXT"; + break; #endif default: break; @@ -200,15 +187,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, // Everything else is okay, no error. // if (message == nullptr) + { + if (binaryNode) { + switch (binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: // fall through + case EOpIndexDirectStruct: // fall through + case EOpVectorSwizzle: + case EOpMatrixSwizzle: + return lValueErrorCheck(loc, op, binaryNode->getLeft()); + default: + break; + } + error(loc, " l-value required", op, "", ""); + + return true; + } return false; + } // // If we get here, we have an error and a message. // + const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true); + if (symNode) error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); else - error(loc, " l-value required", op, "(%s)", message); + if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct) + if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName())) + error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message); + else + error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message); + else + error(loc, " l-value required", op, "(%s)", message); return true; } @@ -216,28 +228,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, // Test for and give an error if the node can't be read from. void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) { + TIntermBinary* binaryNode = node->getAsBinaryNode(); + const TIntermSymbol* symNode = node->getAsSymbolNode(); + if (! node) return; - TIntermBinary* binaryNode = node->getAsBinaryNode(); - if (binaryNode) { - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - rValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; + if (node->getQualifier().isWriteOnly()) { + const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true); + + if (symNode != nullptr) + error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); + else if (binaryNode && + (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct || + binaryNode->getAsOperator()->getOp() == EOpIndexDirect)) + if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName())) + error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str()); + else + error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str()); + else + error(loc, "can't read from writeonly object: ", op, ""); + + } else { + if (binaryNode) { + switch (binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + case EOpVectorSwizzle: + case EOpMatrixSwizzle: + rValueErrorCheck(loc, op, binaryNode->getLeft()); + default: + break; + } } - - return; } - - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode && symNode->getQualifier().isWriteOnly()) - error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); } // Add 'symbol' to the list of deferred linkage symbols, which @@ -576,7 +601,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin selector.push_back(0); } -#ifdef ENABLE_HLSL // // Make the passed-in variable information become a member of the // global uniform block. If this doesn't exist yet, make it. @@ -621,7 +645,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem ++firstNewMember; } -#endif + +void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) { + // Make the atomic counter block, if not yet made. + const auto &at = atomicCounterBuffers.find(binding); + if (at == atomicCounterBuffers.end()) { + atomicCounterBuffers.insert({binding, (TVariable*)nullptr }); + atomicCounterBlockFirstNewMember.insert({binding, 0}); + } + + TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding]; + int& bufferNewMember = atomicCounterBlockFirstNewMember[binding]; + + if (atomicCounterBuffer == nullptr) { + TQualifier blockQualifier; + blockQualifier.clear(); + blockQualifier.storage = EvqBuffer; + + char charBuffer[512]; + if (binding != TQualifier::layoutBindingEnd) { + snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding); + } else { + snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName()); + } + + TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier); + setUniformBlockDefaults(blockType); + blockType.getQualifier().layoutPacking = ElpStd430; + atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true); + // If we arn't auto mapping bindings then set the block to use the same + // binding as what the atomic was set to use + if (!intermediate.getAutoMapBindings()) { + atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding; + } + bufferNewMember = 0; + + atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet; + } + + // Add the requested member as a member to the global block. + TType* type = new TType; + type->shallowCopy(memberType); + type->setFieldName(memberName); + if (typeList) + type->setStruct(typeList); + TTypeLoc typeLoc = {type, loc}; + atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc); + + // Insert into the symbol table. + if (bufferNewMember == 0) { + // This is the first request; we need a normal symbol table insert + if (symbolTable.insert(*atomicCounterBuffer)) + trackLinkage(*atomicCounterBuffer); + else + error(loc, "failed to insert the global constant buffer", "buffer", ""); + } else { + // This is a follow-on request; we need to amend the first insert + symbolTable.amend(*atomicCounterBuffer, bufferNewMember); + } + + ++bufferNewMember; +} void TParseContextBase::finish() { diff --git a/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.cpp similarity index 86% rename from libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.cpp index b9ab5c822..b957bb87c 100644 --- a/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2012-2015 LunarG, Inc. // Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2017, 2019 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -86,6 +87,10 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b globalInputDefaults.clear(); globalOutputDefaults.clear(); + globalSharedDefaults.clear(); + globalSharedDefaults.layoutMatrix = ElmColumnMajor; + globalSharedDefaults.layoutPacking = ElpStd430; + #ifndef GLSLANG_WEB // "Shaders in the transform // feedback capturing mode have an initial global default of @@ -220,6 +225,118 @@ void TParseContext::parserError(const char* s) error(getCurrentLoc(), "compilation terminated", "", ""); } +void TParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) +{ + bool createBlock = globalUniformBlock == nullptr; + + if (createBlock) { + globalUniformBinding = intermediate.getGlobalUniformBinding(); + globalUniformSet = intermediate.getGlobalUniformSet(); + } + + // use base class function to create/expand block + TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, typeList); + + if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { + // check for a block storage override + TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getGlobalUniformBlockName()); + TQualifier& qualifier = globalUniformBlock->getWritableType().getQualifier(); + qualifier.defaultBlock = true; + + if (storageOverride != EbsNone) { + if (createBlock) { + // Remap block storage + qualifier.setBlockStorage(storageOverride); + + // check that the change didn't create errors + blockQualifierCheck(loc, qualifier, false); + } + + // remap meber storage as well + memberType.getQualifier().setBlockStorage(storageOverride); + } + } +} + +void TParseContext::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) +{ + bool createBlock = atomicCounterBuffers.find(binding) == atomicCounterBuffers.end(); + + if (createBlock) { + atomicCounterBlockSet = intermediate.getAtomicCounterBlockSet(); + } + + // use base class function to create/expand block + TParseContextBase::growAtomicCounterBlock(binding, loc, memberType, memberName, typeList); + TQualifier& qualifier = atomicCounterBuffers[binding]->getWritableType().getQualifier(); + qualifier.defaultBlock = true; + + if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { + // check for a Block storage override + TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getAtomicCounterBlockName()); + + if (storageOverride != EbsNone) { + if (createBlock) { + // Remap block storage + + qualifier.setBlockStorage(storageOverride); + + // check that the change didn't create errors + blockQualifierCheck(loc, qualifier, false); + } + + // remap meber storage as well + memberType.getQualifier().setBlockStorage(storageOverride); + } + } +} + +const char* TParseContext::getGlobalUniformBlockName() const +{ + const char* name = intermediate.getGlobalUniformBlockName(); + if (std::string(name) == "") + return "gl_DefaultUniformBlock"; + else + return name; +} +void TParseContext::finalizeGlobalUniformBlockLayout(TVariable&) +{ +} +void TParseContext::setUniformBlockDefaults(TType& block) const +{ + block.getQualifier().layoutPacking = ElpStd140; + block.getQualifier().layoutMatrix = ElmColumnMajor; +} + + +const char* TParseContext::getAtomicCounterBlockName() const +{ + const char* name = intermediate.getAtomicCounterBlockName(); + if (std::string(name) == "") + return "gl_AtomicCounterBlock"; + else + return name; +} +void TParseContext::finalizeAtomicCounterBlockLayout(TVariable&) +{ +} + +void TParseContext::setAtomicCounterBlockDefaults(TType& block) const +{ + block.getQualifier().layoutPacking = ElpStd430; + block.getQualifier().layoutMatrix = ElmRowMajor; +} + +void TParseContext::setInvariant(const TSourceLoc& loc, const char* builtin) { + TSymbol* symbol = symbolTable.find(builtin); + if (symbol && symbol->getType().getQualifier().isPipeOutput()) { + if (intermediate.inIoAccessed(builtin)) + warn(loc, "changing qualification after use", "invariant", builtin); + TSymbol* csymbol = symbolTable.copyUp(symbol); + csymbol->getWritableType().getQualifier().invariant = true; + } +} + void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) { #ifndef GLSLANG_WEB @@ -245,7 +362,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& else if (tokens[2].compare("off") == 0) contextPragma.optimize = false; else { - error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); + if(relaxedErrors()) + // If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma. + warn(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); return; } @@ -269,7 +388,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& else if (tokens[2].compare("off") == 0) contextPragma.debug = false; else { - error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); + if(relaxedErrors()) + // If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma. + warn(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); return; } @@ -293,8 +414,33 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& intermediate.setUseVariablePointers(); } else if (tokens[0].compare("once") == 0) { warn(loc, "not implemented", "#pragma once", ""); - } else if (tokens[0].compare("glslang_binary_double_output") == 0) + } else if (tokens[0].compare("glslang_binary_double_output") == 0) { intermediate.setBinaryDoubleOutput(); + } else if (spvVersion.spv > 0 && tokens[0].compare("STDGL") == 0 && + tokens[1].compare("invariant") == 0 && tokens[3].compare("all") == 0) { + intermediate.setInvariantAll(); + // Set all builtin out variables invariant if declared + setInvariant(loc, "gl_Position"); + setInvariant(loc, "gl_PointSize"); + setInvariant(loc, "gl_ClipDistance"); + setInvariant(loc, "gl_CullDistance"); + setInvariant(loc, "gl_TessLevelOuter"); + setInvariant(loc, "gl_TessLevelInner"); + setInvariant(loc, "gl_PrimitiveID"); + setInvariant(loc, "gl_Layer"); + setInvariant(loc, "gl_ViewportIndex"); + setInvariant(loc, "gl_FragDepth"); + setInvariant(loc, "gl_SampleMask"); + setInvariant(loc, "gl_ClipVertex"); + setInvariant(loc, "gl_FrontColor"); + setInvariant(loc, "gl_BackColor"); + setInvariant(loc, "gl_FrontSecondaryColor"); + setInvariant(loc, "gl_BackSecondaryColor"); + setInvariant(loc, "gl_TexCoord"); + setInvariant(loc, "gl_FogFragCoord"); + setInvariant(loc, "gl_FragColor"); + setInvariant(loc, "gl_FragData"); + } #endif } @@ -427,8 +573,18 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn #ifndef GLSLANG_WEB if (base->isReference() && ! base->isArray()) { requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing"); - result = intermediate.addBinaryMath(EOpAdd, base, index, loc); - result->setType(base->getType()); + if (base->getType().getReferentType()->containsUnsizedArray()) { + error(loc, "cannot index reference to buffer containing an unsized array", "", ""); + result = nullptr; + } else { + result = intermediate.addBinaryMath(EOpAdd, base, index, loc); + if (result != nullptr) + result->setType(base->getType()); + } + if (result == nullptr) { + error(loc, "cannot index buffer reference", "", ""); + result = intermediate.addConstantUnion(0.0, EbtFloat, loc); + } return result; } if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) @@ -740,8 +896,11 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* } TIntermTyped* result = nullptr; - if (allowed) + if (allowed) { + if ((left->isReference() || right->isReference())) + requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference math"); result = intermediate.addBinaryMath(op, left, right, loc); + } if (result == nullptr) binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); @@ -821,50 +980,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm TIntermTyped* result = base; if ((base->isVector() || base->isScalar()) && (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) { - if (base->isScalar()) { - const char* dotFeature = "scalar swizzle"; - requireProfile(loc, ~EEsProfile, dotFeature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); - } - - TSwizzleSelectors selectors; - parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); - - if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat()) - requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16"); - if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt()) - requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16"); - if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt()) - requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8"); - - if (base->isScalar()) { - if (selectors.size() == 1) - return result; - else { - TType type(base->getBasicType(), EvqTemporary, selectors.size()); - // Swizzle operations propagate specialization-constantness - if (base->getQualifier().isSpecConstant()) - type.getQualifier().makeSpecConstant(); - return addConstructor(loc, base, type); - } - } - - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, selectors, loc); - else { - if (selectors.size() == 1) { - TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); - } else { - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); - } - // Swizzle operations propagate specialization-constantness - if (base->getType().getQualifier().isSpecConstant()) - result->getWritableType().getQualifier().makeSpecConstant(); - } + result = handleDotSwizzle(loc, base, field); } else if (base->isStruct() || base->isReference()) { const TTypeList* fields = base->isReference() ? base->getType().getReferentType()->getStruct() : @@ -905,6 +1021,60 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm return result; } +// +// Handle seeing a base.swizzle, a subset of base.identifier in the grammar. +// +TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermTyped* base, const TString& field) +{ + TIntermTyped* result = base; + if (base->isScalar()) { + const char* dotFeature = "scalar swizzle"; + requireProfile(loc, ~EEsProfile, dotFeature); + profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); + } + + TSwizzleSelectors selectors; + parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); + + if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat()) + requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16"); + if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt()) + requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16"); + if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt()) + requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8"); + + if (base->isScalar()) { + if (selectors.size() == 1) + return result; + else { + TType type(base->getBasicType(), EvqTemporary, selectors.size()); + // Swizzle operations propagate specialization-constantness + if (base->getQualifier().isSpecConstant()) + type.getQualifier().makeSpecConstant(); + return addConstructor(loc, base, type); + } + } + + if (base->getType().getQualifier().isFrontEndConstant()) + result = intermediate.foldSwizzle(base, selectors, loc); + else { + if (selectors.size() == 1) { + TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); + result = intermediate.addIndex(EOpIndexDirect, base, index, loc); + result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); + } else { + TIntermTyped* index = intermediate.addSwizzle(selectors, loc); + result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); + result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); + } + // Swizzle operations propagate specialization-constantness + if (base->getType().getQualifier().isSpecConstant()) + result->getWritableType().getQualifier().makeSpecConstant(); + } + + return result; +} + void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName) { // a block that needs extension checking is either 'base', or if arrayed, @@ -957,12 +1127,31 @@ TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunct TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); if (symbol && symbol->getAsFunction() && builtIn) requireProfile(loc, ~EEsProfile, "redefinition of built-in function"); +#ifndef GLSLANG_WEB + // Check the validity of using spirv_literal qualifier + for (int i = 0; i < function.getParamCount(); ++i) { + if (function[i].type->getQualifier().isSpirvLiteral() && function.getBuiltInOp() != EOpSpirvInst) + error(loc, "'spirv_literal' can only be used on functions defined with 'spirv_instruction' for argument", + function.getName().c_str(), "%d", i + 1); + } + + // For function declaration with SPIR-V instruction qualifier, always ignore the built-in function and + // respect this redeclared one. + if (symbol && builtIn && function.getBuiltInOp() == EOpSpirvInst) + symbol = nullptr; +#endif const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; if (prevDec) { if (prevDec->isPrototyped() && prototype) profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function"); if (prevDec->getType() != function.getType()) error(loc, "overloaded functions must have the same return type", function.getName().c_str(), ""); +#ifndef GLSLANG_WEB + if (prevDec->getSpirvInstruction() != function.getSpirvInstruction()) { + error(loc, "overloaded functions must have the same qualifiers", function.getName().c_str(), + "spirv_instruction"); + } +#endif for (int i = 0; i < prevDec->getParamCount(); ++i) { if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1); @@ -1102,6 +1291,14 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction { TIntermTyped* result = nullptr; + if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) { + // allow calls that are invalid in Vulkan Semantics to be invisibily + // remapped to equivalent valid functions + result = vkRelaxedRemapFunctionCall(loc, function, arguments); + if (result) + return result; + } + if (function->getBuiltInOp() == EOpArrayLength) result = handleLengthMethod(loc, function, arguments); else if (function->getBuiltInOp() != EOpNull) { @@ -1156,6 +1353,15 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped())) error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); } +#ifndef GLSLANG_WEB + if (formalQualifier.isSpirvLiteral()) { + if (!arg->getAsTyped()->getQualifier().isFrontEndConstant()) { + error(arguments->getLoc(), + "Non front-end constant expressions cannot be passed for 'spirv_literal' parameters.", + "spirv_literal", ""); + } + } +#endif const TType& argType = arg->getAsTyped()->getType(); const TQualifier& argQualifier = argType.getQualifier(); if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) { @@ -1210,6 +1416,11 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) { // A function call mapped to a built-in operation. result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); +#ifndef GLSLANG_WEB + } else if (fnCandidate->getBuiltInOp() == EOpSpirvInst) { + // When SPIR-V instruction qualifier is specified, the function call is still mapped to a built-in operation. + result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); +#endif } else { // This is a function call not mapped to built-in operator. // It could still be a built-in function, but only if PureOperatorBuiltins == false. @@ -1273,7 +1484,7 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), function.getParamCount() == 1, arguments, function.getType()); - if (obeyPrecisionQualifiers()) + if (result != nullptr && obeyPrecisionQualifiers()) computeBuiltinPrecisions(*result, function); if (result == nullptr) { @@ -1287,6 +1498,35 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo } else if (result->getAsOperator()) builtInOpCheck(loc, function, *result->getAsOperator()); +#ifndef GLSLANG_WEB + // Special handling for function call with SPIR-V instruction qualifier specified + if (function.getBuiltInOp() == EOpSpirvInst) { + if (auto agg = result->getAsAggregate()) { + // Propogate spirv_by_reference/spirv_literal from parameters to arguments + auto& sequence = agg->getSequence(); + for (unsigned i = 0; i < sequence.size(); ++i) { + if (function[i].type->getQualifier().isSpirvByReference()) + sequence[i]->getAsTyped()->getQualifier().setSpirvByReference(); + if (function[i].type->getQualifier().isSpirvLiteral()) + sequence[i]->getAsTyped()->getQualifier().setSpirvLiteral(); + } + + // Attach the function call to SPIR-V intruction + agg->setSpirvInstruction(function.getSpirvInstruction()); + } else if (auto unaryNode = result->getAsUnaryNode()) { + // Propogate spirv_by_reference/spirv_literal from parameters to arguments + if (function[0].type->getQualifier().isSpirvByReference()) + unaryNode->getOperand()->getQualifier().setSpirvByReference(); + if (function[0].type->getQualifier().isSpirvLiteral()) + unaryNode->getOperand()->getQualifier().setSpirvLiteral(); + + // Attach the function call to SPIR-V intruction + unaryNode->setSpirvInstruction(function.getSpirvInstruction()); + } else + assert(0); + } +#endif + return result; } @@ -1353,6 +1593,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction case EOpInterpolateAtSample: numArgs = 1; break; + case EOpDebugPrintf: + numArgs = 0; + break; default: break; } @@ -1390,23 +1633,28 @@ TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermType #endif functionReturnsValue = true; + TIntermBranch* branch = nullptr; if (currentFunctionType->getBasicType() == EbtVoid) { error(loc, "void function cannot return a value", "return", ""); - return intermediate.addBranch(EOpReturn, loc); + branch = intermediate.addBranch(EOpReturn, loc); } else if (*currentFunctionType != value->getType()) { TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value); if (converted) { if (*currentFunctionType != converted->getType()) error(loc, "cannot convert return value to function return type", "return", ""); if (version < 420) - warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", ""); - return intermediate.addBranch(EOpReturn, converted, loc); + warn(loc, "type conversion on return values was not explicitly allowed until version 420", + "return", ""); + branch = intermediate.addBranch(EOpReturn, converted, loc); } else { error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); - return intermediate.addBranch(EOpReturn, value, loc); + branch = intermediate.addBranch(EOpReturn, value, loc); } } else - return intermediate.addBranch(EOpReturn, value, loc); + branch = intermediate.addBranch(EOpReturn, value, loc); + + branch->updatePrecision(currentFunctionType->getQualifier().precision); + return branch; } // See if the operation is being done in an illegal location. @@ -1650,6 +1898,14 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct #endif } +TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right) +{ + if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) + requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference"); + + return intermediate.addAssign(op, left, right, loc); +} + void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode) { const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence(); @@ -1672,9 +1928,13 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& unsigned int semantics = 0, storageClassSemantics = 0; unsigned int semantics2 = 0, storageClassSemantics2 = 0; + const TIntermTyped* arg0 = (*argp)[0]->getAsTyped(); + const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample(); + // Grab the semantics and storage class semantics from the operands, based on opcode switch (callNode.getOp()) { case EOpAtomicAdd: + case EOpAtomicSubtract: case EOpAtomicMin: case EOpAtomicMax: case EOpAtomicAnd: @@ -1704,18 +1964,18 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& case EOpImageAtomicXor: case EOpImageAtomicExchange: case EOpImageAtomicStore: - storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpImageAtomicLoad: - storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpImageAtomicCompSwap: - storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst(); - storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpBarrier: @@ -1933,7 +2193,13 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan profileRequires(loc, ~EEsProfile, 450, nullptr, feature); requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); } - + // As per GL_ARB_sparse_texture2 extension "Offsets" parameter must be constant integral expression + // for sparseTextureGatherOffsetsARB just as textureGatherOffsets + if (callNode.getOp() == EOpSparseTextureGatherOffsets) { + int offsetsArg = arg0->getType().getSampler().shadow ? 3 : 2; + if (!(*argp)[offsetsArg]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "offsets", ""); + } break; } @@ -2006,18 +2272,30 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan if (arg > 0) { #ifndef GLSLANG_WEB - bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow; + bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && + arg0->getType().getSampler().shadow; if (f16ShadowCompare) ++arg; #endif - if (! (*argp)[arg]->getAsConstantUnion()) + if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant()) error(loc, "argument must be compile-time constant", "texel offset", ""); - else { + else if ((*argp)[arg]->getAsConstantUnion()) { const TType& type = (*argp)[arg]->getAsTyped()->getType(); for (int c = 0; c < type.getVectorSize(); ++c) { int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); + error(loc, "value is out of range:", "texel offset", + "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); + } + } + + if (callNode.getOp() == EOpTextureOffset) { + TSampler s = arg0->getType().getSampler(); + if (s.is2D() && s.isArrayed() && s.isShadow()) { + if (isEsProfile()) + error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "ES Profile"); + else if (version <= 420) + error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "version <= 420"); } } } @@ -2028,12 +2306,51 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan #ifndef GLSLANG_WEB case EOpTraceNV: if (!(*argp)[10]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", ""); + error(loc, "argument must be compile-time constant", "payload number", "a"); + break; + case EOpTraceRayMotionNV: + if (!(*argp)[11]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "payload number", "a"); + break; + case EOpTraceKHR: + if (!(*argp)[10]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "payload number", "a"); + else { + unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); + if (intermediate.checkLocationRT(0, location) < 0) + error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); + } break; case EOpExecuteCallableNV: if (!(*argp)[1]->getAsConstantUnion()) error(loc, "argument must be compile-time constant", "callable data number", ""); break; + case EOpExecuteCallableKHR: + if (!(*argp)[1]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "callable data number", ""); + else { + unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); + if (intermediate.checkLocationRT(1, location) < 0) + error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location); + } + break; + + case EOpRayQueryGetIntersectionType: + case EOpRayQueryGetIntersectionT: + case EOpRayQueryGetIntersectionInstanceCustomIndex: + case EOpRayQueryGetIntersectionInstanceId: + case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case EOpRayQueryGetIntersectionGeometryIndex: + case EOpRayQueryGetIntersectionPrimitiveIndex: + case EOpRayQueryGetIntersectionBarycentrics: + case EOpRayQueryGetIntersectionFrontFace: + case EOpRayQueryGetIntersectionObjectRayDirection: + case EOpRayQueryGetIntersectionObjectRayOrigin: + case EOpRayQueryGetIntersectionObjectToWorld: + case EOpRayQueryGetIntersectionWorldToObject: + if (!(*argp)[1]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "committed", ""); + break; case EOpTextureQuerySamples: case EOpImageQuerySamples: @@ -2054,14 +2371,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan { // Make sure the image types have the correct layout() format and correct argument types const TType& imageType = arg0->getType(); - if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { - if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui) + if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint || + imageType.getSampler().type == EbtInt64 || imageType.getSampler().type == EbtUint64) { + if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui && + imageType.getQualifier().getFormat() != ElfR64i && imageType.getQualifier().getFormat() != ElfR64ui) error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); - } else { - if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) + if (callNode.getType().getBasicType() == EbtInt64 && imageType.getQualifier().getFormat() != ElfR64i) + error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), ""); + else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui) + error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), ""); + } else if (imageType.getSampler().type == EbtFloat) { + if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0) { + // imageAtomicExchange doesn't require an extension + } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) || + (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) || + (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0)) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); + } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicMin") == 0) || + (fnCandidate.getName().compare(0, 14, "imageAtomicMax") == 0)) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); + } else { error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); - else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile()) + } + if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile()) error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); + } else { + error(loc, "not supported on this image type", fnCandidate.getName().c_str(), ""); } const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4; @@ -2074,6 +2409,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } case EOpAtomicAdd: + case EOpAtomicSubtract: case EOpAtomicMin: case EOpAtomicMax: case EOpAtomicAnd: @@ -2087,11 +2423,39 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan if (argp->size() > 3) { requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); memorySemanticsCheck(loc, fnCandidate, callNode); + if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || + callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) && + (arg0->getType().getBasicType() == EbtFloat || + arg0->getType().getBasicType() == EbtDouble)) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); + } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || + callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore || + callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) && + arg0->getType().isFloatingDomain()) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); + } } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) { const char* const extensions[2] = { E_GL_NV_shader_atomic_int64, E_GL_EXT_shader_atomic_int64 }; requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str()); + } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) && + (arg0->getType().getBasicType() == EbtFloat || + arg0->getType().getBasicType() == EbtDouble)) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); + } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || + callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore || + callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) && + arg0->getType().isFloatingDomain()) { + requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); } + + const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true , true); + const TType* refType = (base->getType().isReference()) ? base->getType().getReferentType() : nullptr; + const TQualifier& qualifier = (refType != nullptr) ? refType->getQualifier() : base->getType().getQualifier(); + if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer) + error(loc,"Atomic memory function can only be used for shader storage block member or shared variable.", + fnCandidate.getName().c_str(), ""); + break; } @@ -2172,6 +2536,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan memorySemanticsCheck(loc, fnCandidate, callNode); } break; + + case EOpMix: + if (profile == EEsProfile && version < 310) { + // Look for specific signatures + if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat && + (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat && + (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) { + requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, "specific signature of builtin mix"); + } + } + + if (profile != EEsProfile && version < 450) { + if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat && + (*argp)[0]->getAsTyped()->getBasicType() != EbtDouble && + (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat && + (*argp)[1]->getAsTyped()->getBasicType() != EbtDouble && + (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) { + requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, fnCandidate.getName().c_str()); + } + } + + break; #endif default: @@ -2624,6 +3010,11 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks if (symNode && symNode->getQualifier().isExplicitInterpolation()) error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); + + // local_size_{xyz} must be assigned or specialized before gl_WorkGroupSize can be assigned. + if(node->getQualifier().builtIn == EbvWorkGroupSize && + !(intermediate.isLocalSizeSet() || intermediate.isLocalSizeSpecialized())) + error(loc, "can't read from gl_WorkGroupSize before a fixed workgroup size has been declared", op, ""); } // @@ -2666,7 +3057,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be // declared in a shader; this results in a compile-time error." if (! symbolTable.atBuiltInLevel()) { - if (builtInName(identifier)) + if (builtInName(identifier) && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) + // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "gl_". error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); // "__" are not supposed to be an error. ES 300 (and desktop) added the clarification: @@ -2674,7 +3066,8 @@ void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& ide // reserved; using such a name does not itself result in an error, but may result // in undefined behavior." // however, before that, ES tests required an error. - if (identifier.find("__") != TString::npos) { + if (identifier.find("__") != TString::npos && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) { + // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "__". if (isEsProfile() && version < 300) error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), ""); else @@ -2695,18 +3088,23 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden // single underscore) are also reserved, and defining such a name results in a // compile-time error." // however, before that, ES tests required an error. - if (strncmp(identifier, "GL_", 3) == 0) + if (strncmp(identifier, "GL_", 3) == 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) + // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "GL_". ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier); else if (strncmp(identifier, "defined", 8) == 0) - ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); - else if (strstr(identifier, "__") != 0) { + if (relaxedErrors()) + ppWarn(loc, "\"defined\" is (un)defined:", op, identifier); + else + ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); + else if (strstr(identifier, "__") != 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) { + // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "__". if (isEsProfile() && version >= 300 && (strcmp(identifier, "__LINE__") == 0 || strcmp(identifier, "__FILE__") == 0 || strcmp(identifier, "__VERSION__") == 0)) ppError(loc, "predefined names can't be (un)defined:", op, identifier); else { - if (isEsProfile() && version < 300) + if (isEsProfile() && version < 300 && !relaxedErrors()) ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier); else ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier); @@ -2847,6 +3245,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T bool matrixInMatrix = false; bool arrayArg = false; bool floatArgument = false; + bool intArgument = false; for (int arg = 0; arg < function.getParamCount(); ++arg) { if (function[arg].type->isArray()) { if (function[arg].type->isUnsizedArray()) { @@ -2877,6 +3276,8 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T specConstType = true; if (function[arg].type->isFloatingDomain()) floatArgument = true; + if (function[arg].type->isIntegerDomain()) + intArgument = true; if (type.isStruct()) { if (function[arg].type->contains16BitFloat()) { requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type"); @@ -2982,6 +3383,15 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T // and aren't making an array. makeSpecConst = ! floatArgument && ! type.isArray(); break; + + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + // This was the list of valid ones, if they aren't converting from int + // and aren't making an array. + makeSpecConst = ! intArgument && !type.isArray(); + break; + default: // anything else wasn't white-listed in the spec as a conversion makeSpecConst = false; @@ -3083,7 +3493,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T error(loc, "constructor argument does not have a type", "constructor", ""); return true; } - if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) { + if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) { error(loc, "cannot convert a sampler", "constructor", ""); return true; } @@ -3128,7 +3538,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const if (function[0].type->getBasicType() != EbtSampler || ! function[0].type->getSampler().isTexture() || function[0].type->isArray()) { - error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, ""); + error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, ""); return true; } // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() @@ -3136,7 +3546,8 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const texture.setCombined(false); texture.shadow = false; if (texture != function[0].type->getSampler()) { - error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, ""); + error(loc, "sampler-constructor first argument must be a *texture* type" + " matching the dimensionality and sampled type of the constructor", token, ""); return true; } @@ -3146,7 +3557,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const if ( function[1].type->getBasicType() != EbtSampler || ! function[1].type->getSampler().isPureSampler() || function[1].type->isArray()) { - error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, ""); + error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, ""); return true; } @@ -3222,14 +3633,14 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); } -void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) +void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) { if (type.getQualifier().storage == EvqUniform) return; - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV)) + if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct)) error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform) + else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform) error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); @@ -3247,7 +3658,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t if (type.containsNonOpaque()) { // Vulkan doesn't allow transparent uniforms outside of blocks - if (spvVersion.vulkan > 0) + if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed) vulkanRemoved(loc, "non-opaque uniforms outside a block"); // OpenGL wants locations on these (unless they are getting automapped) if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations()) @@ -3260,7 +3671,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t // void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType) { - globalQualifierFixCheck(publicType.loc, publicType.qualifier); + globalQualifierFixCheck(publicType.loc, publicType.qualifier, true); checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers); if (publicType.qualifier.isNonUniform()) { error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", ""); @@ -3271,7 +3682,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType) // // Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. // -void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier) +void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck) { bool nonuniformOkay = false; @@ -3287,6 +3698,8 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs"); profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs"); qualifier.storage = EvqVaryingOut; + if (intermediate.isInvariantAll()) + qualifier.invariant = true; break; case EvqInOut: qualifier.storage = EvqVaryingIn; @@ -3296,6 +3709,16 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q case EvqTemporary: nonuniformOkay = true; break; + case EvqUniform: + // According to GLSL spec: The std430 qualifier is supported only for shader storage blocks; a shader using + // the std430 qualifier on a uniform block will fail to compile. + // Only check the global declaration: layout(std430) uniform; + if (blockName == nullptr && + qualifier.layoutPacking == ElpStd430) + { + requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "default std430 layout for uniform"); + } + break; default: break; } @@ -3303,7 +3726,17 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q if (!nonuniformOkay && qualifier.isNonUniform()) error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", ""); - invariantCheck(loc, qualifier); +#ifndef GLSLANG_WEB + if (qualifier.isSpirvByReference()) + error(loc, "can only apply to parameter", "spirv_by_reference", ""); + + if (qualifier.isSpirvLiteral()) + error(loc, "can only apply to parameter", "spirv_literal", ""); +#endif + + // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it. + if (!isMemberCheck || structNestingLevel > 0) + invariantCheck(loc, qualifier); } // @@ -3314,7 +3747,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali if (! symbolTable.atGlobalLevel()) return; - if (!(publicType.userDef && publicType.userDef->isReference())) { + if (!(publicType.userDef && publicType.userDef->isReference()) && !parsingBuiltins) { if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) { error(loc, "memory qualifiers cannot be used on this type", "", ""); } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) { @@ -3327,6 +3760,11 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali !qualifier.hasBufferReference()) error(loc, "buffers can be declared only as blocks", "buffer", ""); + if (qualifier.storage != EvqVaryingIn && publicType.basicType == EbtDouble && + extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) && language == EShLangVertex && + version < 400) { + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, E_GL_ARB_gpu_shader_fp64, "vertex-shader `double` type"); + } if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) return; @@ -3377,7 +3815,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); } if (publicType.basicType == EbtDouble) - profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input"); + profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_vertex_attrib_64bit, "vertex-shader `double` type input"); if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant) error(loc, "vertex input cannot be further qualified", "", ""); break; @@ -3513,12 +3951,14 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons dst.precision = src.precision; #ifndef GLSLANG_WEB - if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) || - (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) { - error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), ""); + if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) || + (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) { + error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed", + GetPrecisionQualifierString(src.precision), ""); } #endif // Layout qualifiers @@ -3546,6 +3986,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons MERGE_SINGLETON(queuefamilycoherent); MERGE_SINGLETON(workgroupcoherent); MERGE_SINGLETON(subgroupcoherent); + MERGE_SINGLETON(shadercallcoherent); MERGE_SINGLETON(nonprivate); MERGE_SINGLETON(volatil); MERGE_SINGLETON(restrict); @@ -3554,6 +3995,41 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons MERGE_SINGLETON(nonUniform); #endif +#ifndef GLSLANG_WEB + // SPIR-V storage class qualifier (GL_EXT_spirv_intrinsics) + dst.spirvStorageClass = src.spirvStorageClass; + + // SPIR-V decorate qualifiers (GL_EXT_spirv_intrinsics) + if (src.hasSprivDecorate()) { + if (dst.hasSprivDecorate()) { + const TSpirvDecorate& srcSpirvDecorate = src.getSpirvDecorate(); + TSpirvDecorate& dstSpirvDecorate = dst.getSpirvDecorate(); + for (auto& decorate : srcSpirvDecorate.decorates) { + if (dstSpirvDecorate.decorates.find(decorate.first) != dstSpirvDecorate.decorates.end()) + error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate", "(decoration=%u)", decorate.first); + else + dstSpirvDecorate.decorates.insert(decorate); + } + + for (auto& decorateId : srcSpirvDecorate.decorateIds) { + if (dstSpirvDecorate.decorateIds.find(decorateId.first) != dstSpirvDecorate.decorateIds.end()) + error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_id", "(decoration=%u)", decorateId.first); + else + dstSpirvDecorate.decorateIds.insert(decorateId); + } + + for (auto& decorateString : srcSpirvDecorate.decorateStrings) { + if (dstSpirvDecorate.decorates.find(decorateString.first) != dstSpirvDecorate.decorates.end()) + error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_string", "(decoration=%u)", decorateString.first); + else + dstSpirvDecorate.decorates.insert(decorateString); + } + } else { + dst.spirvDecorate = src.spirvDecorate; + } + } +#endif + if (repeated) error(loc, "replicated qualifiers", "", ""); } @@ -3967,6 +4443,9 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType if (isRuntimeLength(base)) return; + if (base.getType().getQualifier().builtIn == EbvSampleMask) + return; + // Check for last member of a bufferreference type, which is runtime sizeable // but doesn't support runtime length if (base.getType().getQualifier().storage == EvqBuffer) { @@ -3983,7 +4462,7 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType } // check for additional things allowed by GL_EXT_nonuniform_qualifier - if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV || + if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery || (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer())) requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index"); else @@ -4110,6 +4589,8 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) || identifier == "gl_ClipDistance" || identifier == "gl_CullDistance" || + identifier == "gl_ShadingRateEXT" || + identifier == "gl_PrimitiveShadingRateEXT" || identifier == "gl_FrontColor" || identifier == "gl_BackColor" || identifier == "gl_FrontSecondaryColor" || @@ -4135,8 +4616,10 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS // If it wasn't at a built-in level, then it's already been redeclared; // that is, this is a redeclaration of a redeclaration; reuse that initial // redeclaration. Otherwise, make the new one. - if (builtIn) + if (builtIn) { makeEditable(symbol); + symbolTable.amendSymbolIdLevel(*symbol); + } // Now, modify the type of the copy, as per the type of the current redeclaration. @@ -4487,6 +4970,7 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent; type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent; type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent; + type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent; type.getQualifier().nonprivate = qualifier.nonprivate; type.getQualifier().readonly = qualifier.readonly; type.getQualifier().writeonly = qualifier.writeonly; @@ -4509,20 +4993,31 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali } if (qualifier.isNonUniform()) type.getQualifier().nonUniform = qualifier.nonUniform; +#ifndef GLSLANG_WEB + if (qualifier.isSpirvByReference()) + type.getQualifier().setSpirvByReference(); + if (qualifier.isSpirvLiteral()) { + if (type.getBasicType() == EbtFloat || type.getBasicType() == EbtInt || type.getBasicType() == EbtUint || + type.getBasicType() == EbtBool) + type.getQualifier().setSpirvLiteral(); + else + error(loc, "cannot use spirv_literal qualifier", type.getBasicTypeString().c_str(), ""); +#endif + } paramCheckFixStorage(loc, qualifier.storage, type); } void TParseContext::nestedBlockCheck(const TSourceLoc& loc) { - if (structNestingLevel > 0) + if (structNestingLevel > 0 || blockNestingLevel > 0) error(loc, "cannot nest a block definition inside a structure or block", "", ""); - ++structNestingLevel; + ++blockNestingLevel; } void TParseContext::nestedStructCheck(const TSourceLoc& loc) { - if (structNestingLevel > 0) + if (structNestingLevel > 0 || blockNestingLevel > 0) error(loc, "cannot nest a structure definition inside a structure or block", "", ""); ++structNestingLevel; } @@ -4664,7 +5159,7 @@ void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, } // get the unique id of the loop index - int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); + long long loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); inductiveLoopIds.insert(loopIndex); // condition's form must be "loop-index relational-operator constant-expression" @@ -4850,14 +5345,22 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } if (id == TQualifier::getLayoutPackingString(ElpPacked)) { - if (spvVersion.spv != 0) - spvRemoved(loc, "packed"); + if (spvVersion.spv != 0) { + if (spvVersion.vulkanRelaxed) + return; // silently ignore qualifier + else + spvRemoved(loc, "packed"); + } publicType.qualifier.layoutPacking = ElpPacked; return; } if (id == TQualifier::getLayoutPackingString(ElpShared)) { - if (spvVersion.spv != 0) - spvRemoved(loc, "shared"); + if (spvVersion.spv != 0) { + if (spvVersion.vulkanRelaxed) + return; // silently ignore qualifier + else + spvRemoved(loc, "shared"); + } publicType.qualifier.layoutPacking = ElpShared; return; } @@ -4868,7 +5371,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi #ifndef GLSLANG_WEB if (id == TQualifier::getLayoutPackingString(ElpStd430)) { requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430"); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "std430"); profileRequires(loc, EEsProfile, 310, nullptr, "std430"); publicType.qualifier.layoutPacking = ElpStd430; return; @@ -5067,13 +5570,19 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } } else { - if (language == EShLangRayGenNV || language == EShLangIntersectNV || - language == EShLangAnyHitNV || language == EShLangClosestHitNV || - language == EShLangMissNV || language == EShLangCallableNV) { - if (id == "shaderrecordnv") { - publicType.qualifier.layoutShaderRecordNV = true; + if (language == EShLangRayGen || language == EShLangIntersect || + language == EShLangAnyHit || language == EShLangClosestHit || + language == EShLangMiss || language == EShLangCallable) { + if (id == "shaderrecordnv" || id == "shaderrecordext") { + if (id == "shaderrecordnv") { + requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV"); + } else { + requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT"); + } + publicType.qualifier.layoutShaderRecord = true; return; } + } } if (language == EShLangCompute) { @@ -5088,6 +5597,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi } } } + + if (id == "primitive_culling") { + requireExtensions(loc, 1, &E_GL_EXT_ray_flags_primitive_culling, "primitive culling"); + publicType.shaderQualifiers.layoutPrimitiveCulling = true; + return; + } #endif error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); @@ -5135,6 +5650,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi profileRequires(loc, EEsProfile, 310, nullptr, feature); } publicType.qualifier.layoutOffset = value; + publicType.qualifier.explicitOffset = true; if (nonLiteral) error(loc, "needs a literal integer", "offset", ""); return; @@ -5294,7 +5810,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi if (! IsPow2(value)) error(loc, "must be a power of 2", "buffer_reference_align", ""); else - publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value); + publicType.qualifier.layoutBufferReferenceAlign = IntLog2(value); if (nonLiteral) error(loc, "needs a literal integer", "buffer_reference_align", ""); return; @@ -5347,10 +5863,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi case EShLangFragment: if (id == "index") { - requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output"); + requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, "index layout qualifier on fragment output"); const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output"); - + profileRequires(loc, EEsProfile ,310, E_GL_EXT_blend_func_extended, "index layout qualifier on fragment output"); // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1." if (value < 0 || value > 1) { value = 0; @@ -5514,8 +6030,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie dst.layoutViewportRelative = true; if (src.layoutSecondaryViewportRelativeOffset != -2048) dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; - if (src.layoutShaderRecordNV) - dst.layoutShaderRecordNV = true; + if (src.layoutShaderRecord) + dst.layoutShaderRecord = true; if (src.pervertexNV) dst.pervertexNV = true; #endif @@ -5555,6 +6071,9 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb case EvqVaryingIn: case EvqVaryingOut: if (!type.getQualifier().isTaskMemory() && +#ifndef GLSLANG_WEB + !type.getQualifier().hasSprivDecorate() && +#endif (type.getBasicType() != EbtBlock || (!(*type.getStruct())[0].type->getQualifier().hasLocation() && (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))) @@ -5583,8 +6102,10 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb error(loc, "cannot specify on a variable declaration", "align", ""); if (qualifier.isPushConstant()) error(loc, "can only specify on a uniform block", "push_constant", ""); - if (qualifier.isShaderRecordNV()) + if (qualifier.isShaderRecord()) error(loc, "can only specify on a buffer block", "shaderRecordNV", ""); + if (qualifier.hasLocation() && type.isAtomic()) + error(loc, "cannot specify on atomic counter", "location", ""); } break; default: @@ -5614,6 +6135,11 @@ void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool m // Do layout error checking with respect to a type. void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) { +#ifndef GLSLANG_WEB + if (extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) + return; // Skip any check if GL_EXT_spirv_intrinsics is turned on +#endif + const TQualifier& qualifier = type.getQualifier(); // first, intra-layout qualifier-only error checking @@ -5657,11 +6183,11 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) error(loc, "cannot apply to uniform or buffer block", "location", ""); break; #ifndef GLSLANG_WEB - case EvqPayloadNV: - case EvqPayloadInNV: - case EvqHitAttrNV: - case EvqCallableDataNV: - case EvqCallableDataInNV: + case EvqPayload: + case EvqPayloadIn: + case EvqHitAttr: + case EvqCallableData: + case EvqCallableDataIn: break; #endif default: @@ -5684,6 +6210,8 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) int repeated = intermediate.addXfbBufferOffset(type); if (repeated >= 0) error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer); + if (type.isUnsizedArray()) + error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer); // "The offset must be a multiple of the size of the first component of the first // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate @@ -5720,16 +6248,12 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) if (type.getBasicType() == EbtSampler) { int lastBinding = qualifier.layoutBinding; if (type.isArray()) { - if (spvVersion.vulkan > 0) - lastBinding += 1; - else { + if (spvVersion.vulkan == 0) { if (type.isSizedArray()) - lastBinding += type.getCumulativeArraySize(); + lastBinding += (type.getCumulativeArraySize() - 1); else { - lastBinding += 1; #ifndef GLSLANG_WEB - if (spvVersion.vulkan == 0) - warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", ""); + warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", ""); #endif } } @@ -5739,7 +6263,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); #endif } - if (type.isAtomic()) { + if (type.isAtomic() && !spvVersion.vulkanRelaxed) { if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); return; @@ -5756,7 +6280,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) if (spvVersion.spv > 0) { if (qualifier.isUniformOrBuffer()) { if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() && - !qualifier.isShaderRecordNV() && + !qualifier.isShaderRecord() && !qualifier.hasAttachment() && !qualifier.hasBufferReference()) error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); @@ -5813,7 +6337,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock) error(loc, "can only be used with a block", "buffer_reference", ""); - if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock) + if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock) error(loc, "can only be used with a block", "shaderRecordNV", ""); // input attachment @@ -5853,12 +6377,28 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) } } +static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage) +{ + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } +} + // Do layout error checking that can be done within a layout qualifier proper, not needing to know // if there are blocks, atomic counters, variables, etc. void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) { - if (qualifier.storage == EvqShared && qualifier.hasLayout()) - error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); + if (qualifier.storage == EvqShared && qualifier.hasLayout()) { + if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { + error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); + } + profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); + } // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." if (qualifier.hasComponent() && ! qualifier.hasLocation()) @@ -5941,7 +6481,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier error(loc, "can only be used on an output", "xfb layout qualifier", ""); } if (qualifier.hasUniformLayout()) { - if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) { + if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) { if (qualifier.hasMatrix() || qualifier.hasPacking()) error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); if (qualifier.hasOffset() || qualifier.hasAlign()) @@ -5958,7 +6498,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier if (qualifier.storage != EvqBuffer) error(loc, "can only be used with buffer", "buffer_reference", ""); } - if (qualifier.isShaderRecordNV()) { + if (qualifier.isShaderRecord()) { if (qualifier.storage != EvqBuffer) error(loc, "can only be used with a buffer", "shaderRecordNV", ""); if (qualifier.hasBinding()) @@ -5967,7 +6507,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier error(loc, "cannot be used with shaderRecordNV", "set", ""); } - if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) { + if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) { error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", ""); } } @@ -6018,6 +6558,8 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua error(loc, message, "num_views", ""); if (shaderQualifiers.interlockOrdering != EioNone) error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), ""); + if (shaderQualifiers.layoutPrimitiveCulling) + error(loc, "can only be applied as standalone", "primitive_culling", ""); #endif } @@ -6079,6 +6621,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct #endif const TFunction* function = nullptr; + + // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()", + // mangled to "debugPrintfEXT(" + if (call.getName() == "debugPrintfEXT") { + TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn); + if (symbol) + return symbol->getAsFunction(); + } + bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) || extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) || @@ -6088,10 +6639,16 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) || extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64); - if (isEsProfile() || version < 120) + if (isEsProfile()) + function = (explicitTypesEnabled && version >= 310) + ? findFunctionExplicitTypes(loc, call, builtIn) + : ((extensionTurnedOn(E_GL_EXT_shader_implicit_conversions) && version >= 310) + ? findFunction120(loc, call, builtIn) + : findFunctionExact(loc, call, builtIn)); + else if (version < 120) function = findFunctionExact(loc, call, builtIn); else if (version < 400) - function = findFunction120(loc, call, builtIn); + function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn); else if (explicitTypesEnabled) function = findFunctionExplicitTypes(loc, call, builtIn); else @@ -6379,26 +6936,177 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, return bestMatch; } +// +// Adjust function calls that aren't declared in Vulkan to a +// calls with equivalent effects +// +TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) +{ + TIntermTyped* result = nullptr; + +#ifndef GLSLANG_WEB + if (function->getBuiltInOp() != EOpNull) { + return nullptr; + } + + if (function->getName() == "atomicCounterIncrement") { + // change atomicCounterIncrement into an atomicAdd of 1 + TString name("atomicAdd"); + TType uintType(EbtUint); + + TFunction realFunc(&name, function->getType()); + + for (int i = 0; i < function->getParamCount(); ++i) { + realFunc.addParameter((*function)[i]); + } + + TParameter tmpP = { 0, &uintType }; + realFunc.addParameter(tmpP); + arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true)); + + result = handleFunctionCall(loc, &realFunc, arguments); + } else if (function->getName() == "atomicCounterDecrement") { + // change atomicCounterDecrement into an atomicAdd with -1 + // and subtract 1 from result, to return post-decrement value + TString name("atomicAdd"); + TType uintType(EbtUint); + + TFunction realFunc(&name, function->getType()); + + for (int i = 0; i < function->getParamCount(); ++i) { + realFunc.addParameter((*function)[i]); + } + + TParameter tmpP = { 0, &uintType }; + realFunc.addParameter(tmpP); + arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true)); + + result = handleFunctionCall(loc, &realFunc, arguments); + + // post decrement, so that it matches AtomicCounterDecrement semantics + if (result) { + result = handleBinaryMath(loc, "-", EOpSub, result, intermediate.addConstantUnion(1, loc, true)); + } + } else if (function->getName() == "atomicCounter") { + // change atomicCounter into a direct read of the variable + if (arguments->getAsTyped()) { + result = arguments->getAsTyped(); + } + } +#endif + + return result; +} + // When a declaration includes a type, but not a variable name, it can be used // to establish defaults. void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) { #ifndef GLSLANG_WEB - if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && - publicType.qualifier.hasOffset()) { + if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding()) { if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { error(loc, "atomic_uint binding is too large", "binding", ""); return; } - atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; + if (publicType.qualifier.hasOffset()) + atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; return; } + if (publicType.arraySizes) { + error(loc, "expect an array name", "", ""); + } + if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference()) warn(loc, "useless application of layout qualifier", "layout", ""); #endif } +bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType&, + TArraySizes*, TIntermTyped* initializer, TType& type) +{ + if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() || + type.getQualifier().storage != EvqUniform || + !(type.containsNonOpaque() +#ifndef GLSLANG_WEB + || type.getBasicType() == EbtAtomicUint +#endif + )) { + return false; + } + + if (type.getQualifier().hasLocation()) { + warn(loc, "ignoring layout qualifier for uniform", identifier.c_str(), "location"); + type.getQualifier().layoutLocation = TQualifier::layoutLocationEnd; + } + + if (initializer) { + warn(loc, "Ignoring initializer for uniform", identifier.c_str(), ""); + initializer = nullptr; + } + + if (type.isArray()) { + // do array size checks here + arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false); + + if (arrayQualifierError(loc, type.getQualifier()) || arrayError(loc, type)) { + error(loc, "array param error", identifier.c_str(), ""); + } + } + + // do some checking on the type as it was declared + layoutTypeCheck(loc, type); + + int bufferBinding = TQualifier::layoutBindingEnd; + TVariable* updatedBlock = nullptr; + +#ifndef GLSLANG_WEB + // Convert atomic_uint into members of a buffer block + if (type.isAtomic()) { + type.setBasicType(EbtUint); + type.getQualifier().storage = EvqBuffer; + + type.getQualifier().volatil = true; + type.getQualifier().coherent = true; + + // xxTODO: use logic from fixOffset() to apply explicit member offset + bufferBinding = type.getQualifier().layoutBinding; + type.getQualifier().layoutBinding = TQualifier::layoutBindingEnd; + type.getQualifier().explicitOffset = false; + growAtomicCounterBlock(bufferBinding, loc, type, identifier, nullptr); + updatedBlock = atomicCounterBuffers[bufferBinding]; + } +#endif + + if (!updatedBlock) { + growGlobalUniformBlock(loc, type, identifier, nullptr); + updatedBlock = globalUniformBlock; + } + + // + // don't assign explicit member offsets here + // if any are assigned, need to be updated here and in the merge/link step + // fixBlockUniformOffsets(updatedBlock->getWritableType().getQualifier(), *updatedBlock->getWritableType().getWritableStruct()); + + // checks on update buffer object + layoutObjectCheck(loc, *updatedBlock); + + TSymbol* symbol = symbolTable.find(identifier); + + if (!symbol) { + if (updatedBlock == globalUniformBlock) + error(loc, "error adding uniform to default uniform block", identifier.c_str(), ""); + else + error(loc, "error adding atomic counter to atomic counter block", identifier.c_str(), ""); + return false; + } + + // merge qualifiers + mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true); + + return true; +} + // // Do everything necessary to handle a variable (non-block) declaration. // Either redeclaring a variable, or making a new one, updating the symbol @@ -6420,6 +7128,12 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden type.copyArrayInnerSizes(publicType.arraySizes); arrayOfArrayVersionCheck(loc, type.getArraySizes()); + if (initializer) { + if (type.getBasicType() == EbtRayQuery) { + error(loc, "ray queries can only be initialized by using the rayQueryInitializeEXT intrinsic:", "=", identifier.c_str()); + } + } + if (type.isCoopMat()) { intermediate.setUseVulkanMemoryModel(); intermediate.setUseStorageBuffer(); @@ -6459,7 +7173,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden transparentOpaqueCheck(loc, type, identifier); #ifndef GLSLANG_WEB atomicUintCheck(loc, type, identifier); - accStructNVCheck(loc, type, identifier); + accStructCheck(loc, type, identifier); checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false); #endif if (type.getQualifier().storage == EvqConst && type.containsReference()) { @@ -6478,6 +7192,22 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden if (type.getQualifier().storage == EvqShared && type.containsCoopMat()) error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", ""); + if (profile == EEsProfile) { + if (type.getQualifier().isPipeInput() && type.getBasicType() == EbtStruct) { + if (type.getQualifier().isArrayedIo(language)) { + TType perVertexType(type, 0); + if (perVertexType.containsArray() && perVertexType.containsBuiltIn() == false) { + error(loc, "A per vertex structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), ""); + } + } + else if (type.containsArray() && type.containsBuiltIn() == false) { + error(loc, "A structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), ""); + } + if (type.containsStructure()) + error(loc, "A structure containing an struct is not allowed as input in ES", type.getTypeName().c_str(), ""); + } + } + if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone) @@ -6488,6 +7218,14 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden if (symbol == nullptr) reservedErrorCheck(loc, identifier); + if (symbol == nullptr && spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { + bool remapped = vkRelaxedRemapUniformVariable(loc, identifier, publicType, arraySizes, initializer, type); + + if (remapped) { + return nullptr; + } + } + inheritGlobalDefaults(type.getQualifier()); // Declare the variable @@ -6595,6 +7333,11 @@ TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& // TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) { + // A null initializer is an aggregate that hasn't had an op assigned yet + // (still EOpNull, no relation to nullInit), and has no children. + bool nullInit = initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull && + initializer->getAsAggregate()->getSequence().size() == 0; + // // Identifier must be of type constant, a global, or a temporary, and // starting at version 120, desktop allows uniforms to have initializers. @@ -6602,9 +7345,36 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp TStorageQualifier qualifier = variable->getType().getQualifier().storage; if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst || (qualifier == EvqUniform && !isEsProfile() && version >= 120))) { - error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), ""); + if (qualifier == EvqShared) { + // GL_EXT_null_initializer allows this for shared, if it's a null initializer + if (nullInit) { + const char* feature = "initialization with shared qualifier"; + profileRequires(loc, EEsProfile, 0, E_GL_EXT_null_initializer, feature); + profileRequires(loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, feature); + } else { + error(loc, "initializer can only be a null initializer ('{}')", "shared", ""); + } + } else { + error(loc, " cannot initialize this type of qualifier ", + variable->getType().getStorageQualifierString(), ""); + return nullptr; + } + } + + if (nullInit) { + // only some types can be null initialized + if (variable->getType().containsUnsizedArray()) { + error(loc, "null initializers can't size unsized arrays", "{}", ""); + return nullptr; + } + if (variable->getType().containsOpaque()) { + error(loc, "null initializers can't be used on opaque values", "{}", ""); + return nullptr; + } + variable->getWritableType().getQualifier().setNullInit(); return nullptr; } + arrayObjectCheck(loc, variable->getType(), "array initializer"); // @@ -6648,13 +7418,15 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // Uniforms require a compile-time constant initializer if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { - error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); + error(loc, "uniform initializers must be constant", "=", "'%s'", + variable->getType().getCompleteString().c_str()); variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } // Global consts require a constant initializer (specialization constant is okay) if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); + error(loc, "global const initializers must be constant", "=", "'%s'", + variable->getType().getCompleteString().c_str()); variable->getWritableType().getQualifier().makeTemporary(); return nullptr; } @@ -6674,7 +7446,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // "In declarations of global variables with no storage qualifier or with a const // qualifier any initializer must be a constant expression." if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; + const char* initFeature = + "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; if (isEsProfile()) { if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers)) warn(loc, "not allowed in this version", initFeature, ""); @@ -6688,7 +7461,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp // Compile-time tagging of the variable with its constant value... initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) { + if (! initializer || ! initializer->getType().getQualifier().isConstant() || + variable->getType() != initializer->getType()) { error(loc, "non-matching or non-convertible constant type for const initializer", variable->getType().getStorageQualifierString(), ""); variable->getWritableType().getQualifier().makeTemporary(); @@ -6800,6 +7574,15 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str()); return nullptr; } + TBasicType destType = type.getBasicType(); + for (int i = 0; i < type.getVectorSize(); ++i) { + TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType(); + if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) { + error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString().c_str()); + return nullptr; + } + + } } else { error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); return nullptr; @@ -7175,6 +7958,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T if (!node->getType().isCoopMat()) { if (type.getBasicType() != node->getType().getBasicType()) { node = intermediate.addConversion(type.getBasicType(), node); + if (node == nullptr) + return nullptr; } node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc()); } else { @@ -7254,6 +8039,19 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T return node; + case EOpConstructAccStruct: + if ((node->getType().isScalar() && node->getType().getBasicType() == EbtUint64)) { + // construct acceleration structure from uint64 + requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uint64_t conversion to acclerationStructureEXT"); + return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToAccStruct, true, node, + type); + } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint && node->getVectorSize() == 2) { + // construct acceleration structure from uint64 + requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uvec2 conversion to accelerationStructureEXT"); + return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToAccStruct, true, node, + type); + } else + return nullptr; #endif // GLSLANG_WEB default: @@ -7320,6 +8118,8 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier& void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes) { + if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) + blockStorageRemap(loc, blockName, currentBlockQualifier); blockStageIoCheck(loc, currentBlockQualifier); blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); if (arraySizes != nullptr) { @@ -7334,10 +8134,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con TType& memberType = *typeList[member].type; TQualifier& memberQualifier = memberType.getQualifier(); const TSourceLoc& memberLoc = typeList[member].loc; - globalQualifierFixCheck(memberLoc, memberQualifier); if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); memberQualifier.storage = currentBlockQualifier.storage; + globalQualifierFixCheck(memberLoc, memberQualifier); #ifndef GLSLANG_WEB inheritMemoryQualifiers(currentBlockQualifier, memberQualifier); if (currentBlockQualifier.perPrimitiveNV) @@ -7346,6 +8146,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con memberQualifier.perViewNV = currentBlockQualifier.perViewNV; if (currentBlockQualifier.perTaskNV) memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV; + if (memberQualifier.storage == EvqSpirvStorageClass) + error(memberLoc, "member cannot have a spirv_storage_class qualifier", memberType.getFieldName().c_str(), ""); + if (memberQualifier.hasSprivDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty()) + error(memberLoc, "member cannot have a spirv_decorate_id qualifier", memberType.getFieldName().c_str(), ""); #endif if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); @@ -7353,8 +8157,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1); if (memberQualifier.hasOffset()) { if (spvVersion.spv == 0) { - requireProfile(memberLoc, ~EEsProfile, "offset on block member"); - profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member"); + profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "\"offset\" on block member"); + profileRequires(memberLoc, EEsProfile, 300, E_GL_ARB_enhanced_layouts, "\"offset\" on block member"); } } @@ -7387,13 +8191,14 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con case EvqBuffer: defaultQualification = globalBufferDefaults; break; case EvqVaryingIn: defaultQualification = globalInputDefaults; break; case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; + case EvqShared: defaultQualification = globalSharedDefaults; break; default: defaultQualification.clear(); break; } // Special case for "push_constant uniform", which has a default of std430, // contrary to normal uniform defaults, and can't have a default tracked for it. if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) || - (currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking())) + (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking())) currentBlockQualifier.layoutPacking = ElpStd430; // Special case for "taskNV in/out", which has a default of std430, @@ -7493,6 +8298,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); fixXfbOffsets(currentBlockQualifier, typeList); fixBlockUniformOffsets(currentBlockQualifier, typeList); + fixBlockUniformLayoutMatrix(currentBlockQualifier, &typeList, nullptr); + fixBlockUniformLayoutPacking(currentBlockQualifier, &typeList, nullptr); for (unsigned int member = 0; member < typeList.size(); ++member) layoutTypeCheck(typeList[member].loc, *typeList[member].type); @@ -7606,10 +8413,22 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con trackLinkage(variable); } +// +// allow storage type of block to be remapped at compile time +// +void TParseContext::blockStorageRemap(const TSourceLoc&, const TString* instanceName, TQualifier& qualifier) +{ + TBlockStorageClass type = intermediate.getBlockStorageOverride(instanceName->c_str()); + if (type != EbsNone) { + qualifier.setBlockStorage(type); + } +} + // Do all block-declaration checking regarding the combination of in/out/uniform/buffer // with a particular stage. void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) { + const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; switch (qualifier.storage) { case EvqUniform: profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); @@ -7619,7 +8438,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q break; case EvqBuffer: requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block"); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "buffer block"); profileRequires(loc, EEsProfile, 310, nullptr, "buffer block"); break; case EvqVaryingIn: @@ -7647,29 +8466,35 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q error(loc, "output blocks cannot be used in a task shader", "out", ""); } break; + case EvqShared: + if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { + error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); + } + profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); + break; #ifndef GLSLANG_WEB - case EvqPayloadNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), + case EvqPayload: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block"); + requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), "rayPayloadNV block"); break; - case EvqPayloadInNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), + case EvqPayloadIn: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block"); + requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), "rayPayloadInNV block"); break; - case EvqHitAttrNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block"); - requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block"); + case EvqHitAttr: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block"); + requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block"); break; - case EvqCallableDataNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), + case EvqCallableData: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block"); + requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV block"); break; - case EvqCallableDataInNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block"); + case EvqCallableDataIn: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block"); + requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block"); break; #endif default: @@ -7708,8 +8533,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); if (qualifier.isPushConstant()) intermediate.addPushConstantCount(); - if (qualifier.isShaderRecordNV()) - intermediate.addShaderRecordNVCount(); + if (qualifier.isShaderRecord()) + intermediate.addShaderRecordCount(); if (qualifier.isTaskMemory()) intermediate.addTaskNVCount(); } @@ -7805,7 +8630,7 @@ void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) // void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) { - if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) + if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) return; if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) return; @@ -7862,6 +8687,103 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ } } +// +// Spread LayoutMatrix to uniform block member, if a uniform block member is a struct, +// we need spread LayoutMatrix to this struct member too. and keep this rule for recursive. +// +void TParseContext::fixBlockUniformLayoutMatrix(TQualifier& qualifier, TTypeList* originTypeList, + TTypeList* tmpTypeList) +{ + assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size()); + for (unsigned int member = 0; member < originTypeList->size(); ++member) { + if (qualifier.layoutPacking != ElpNone) { + if (tmpTypeList == nullptr) { + if (((*originTypeList)[member].type->isMatrix() || + (*originTypeList)[member].type->getBasicType() == EbtStruct) && + (*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { + (*originTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix; + } + } else { + if (((*tmpTypeList)[member].type->isMatrix() || + (*tmpTypeList)[member].type->getBasicType() == EbtStruct) && + (*tmpTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { + (*tmpTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix; + } + } + } + + if ((*originTypeList)[member].type->getBasicType() == EbtStruct) { + TQualifier* memberQualifier = nullptr; + // block member can be declare a matrix style, so it should be update to the member's style + if ((*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { + memberQualifier = &qualifier; + } else { + memberQualifier = &((*originTypeList)[member].type->getQualifier()); + } + + const TType* tmpType = tmpTypeList == nullptr ? + (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type; + + fixBlockUniformLayoutMatrix(*memberQualifier, (*originTypeList)[member].type->getWritableStruct(), + tmpType->getWritableStruct()); + + const TTypeList* structure = recordStructCopy(matrixFixRecord, (*originTypeList)[member].type, tmpType); + + if (tmpTypeList == nullptr) { + (*originTypeList)[member].type->setStruct(const_cast(structure)); + } + if (tmpTypeList != nullptr) { + (*tmpTypeList)[member].type->setStruct(const_cast(structure)); + } + } + } +} + +// +// Spread LayoutPacking to matrix or aggregate block members. If a block member is a struct or +// array of struct, spread LayoutPacking recursively to its matrix or aggregate members. +// +void TParseContext::fixBlockUniformLayoutPacking(TQualifier& qualifier, TTypeList* originTypeList, + TTypeList* tmpTypeList) +{ + assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size()); + for (unsigned int member = 0; member < originTypeList->size(); ++member) { + if (qualifier.layoutPacking != ElpNone) { + if (tmpTypeList == nullptr) { + if ((*originTypeList)[member].type->getQualifier().layoutPacking == ElpNone && + !(*originTypeList)[member].type->isScalarOrVector()) { + (*originTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking; + } + } else { + if ((*tmpTypeList)[member].type->getQualifier().layoutPacking == ElpNone && + !(*tmpTypeList)[member].type->isScalarOrVector()) { + (*tmpTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking; + } + } + } + + if ((*originTypeList)[member].type->getBasicType() == EbtStruct) { + // Deep copy the type in pool. + // Because, struct use in different block may have different layout qualifier. + // We have to new a object to distinguish between them. + const TType* tmpType = tmpTypeList == nullptr ? + (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type; + + fixBlockUniformLayoutPacking(qualifier, (*originTypeList)[member].type->getWritableStruct(), + tmpType->getWritableStruct()); + + const TTypeList* structure = recordStructCopy(packingFixRecord, (*originTypeList)[member].type, tmpType); + + if (tmpTypeList == nullptr) { + (*originTypeList)[member].type->setStruct(const_cast(structure)); + } + if (tmpTypeList != nullptr) { + (*tmpTypeList)[member].type->setStruct(const_cast(structure)); + } + } + } +} + // For an identifier that is already declared, add more qualification to it. void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) { @@ -7937,7 +8859,7 @@ void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qual bool pipeOut = qualifier.isPipeOutput(); bool pipeIn = qualifier.isPipeInput(); - if (version >= 300 || (!isEsProfile() && version >= 420)) { + if ((version >= 300 && isEsProfile()) || (!isEsProfile() && version >= 420)) { if (! pipeOut) error(loc, "can only apply to an output", "invariant", ""); } else { @@ -8170,6 +9092,16 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con { checkIoArraysConsistency(loc); } + + if (publicType.shaderQualifiers.layoutPrimitiveCulling) { + if (publicType.qualifier.storage != EvqTemporary) + error(loc, "layout qualifier can not have storage qualifiers", "primitive_culling","", ""); + else { + intermediate.setLayoutPrimitiveCulling(); + } + // Exit early as further checks are not valid + return; + } #endif const TQualifier& qualifier = publicType.qualifier; @@ -8214,8 +9146,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con } #endif break; + case EvqShared: + if (qualifier.hasMatrix()) + globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix; + if (qualifier.hasPacking()) + globalSharedDefaults.layoutPacking = qualifier.layoutPacking; + break; default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); + error(loc, "default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification", "", ""); return; } @@ -8231,7 +9169,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", ""); if (qualifier.hasSpecConstantId()) error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); - if (qualifier.isShaderRecordNV()) + if (qualifier.isShaderRecord()) error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", ""); } @@ -8320,5 +9258,43 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre return switchNode; } +// +// When a struct used in block, and has it's own layout packing, layout matrix, +// record the origin structure of a struct to map, and Record the structure copy to the copy table, +// +const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TType* originType, const TType* tmpType) +{ + size_t memberCount = tmpType->getStruct()->size(); + size_t originHash = 0, tmpHash = 0; + std::hash hasher; + for (size_t i = 0; i < memberCount; i++) { + size_t originMemberHash = hasher(originType->getStruct()->at(i).type->getQualifier().layoutPacking + + originType->getStruct()->at(i).type->getQualifier().layoutMatrix); + size_t tmpMemberHash = hasher(tmpType->getStruct()->at(i).type->getQualifier().layoutPacking + + tmpType->getStruct()->at(i).type->getQualifier().layoutMatrix); + originHash = hasher((originHash ^ originMemberHash) << 1); + tmpHash = hasher((tmpHash ^ tmpMemberHash) << 1); + } + const TTypeList* originStruct = originType->getStruct(); + const TTypeList* tmpStruct = tmpType->getStruct(); + if (originHash != tmpHash) { + auto fixRecords = record.find(originStruct); + if (fixRecords != record.end()) { + auto fixRecord = fixRecords->second.find(tmpHash); + if (fixRecord != fixRecords->second.end()) { + return fixRecord->second; + } else { + record[originStruct][tmpHash] = tmpStruct; + return tmpStruct; + } + } else { + record[originStruct] = std::map(); + record[originStruct][tmpHash] = tmpStruct; + return tmpStruct; + } + } + return originStruct; +} + } // end namespace glslang diff --git a/libraries/glslang/glslang/MachineIndependent/ParseHelper.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.h similarity index 84% rename from libraries/glslang/glslang/MachineIndependent/ParseHelper.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.h index 39363f1a2..de4488465 100644 --- a/libraries/glslang/glslang/MachineIndependent/ParseHelper.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ParseHelper.h @@ -67,7 +67,8 @@ struct TPragma { class TScanContext; class TPpContext; -typedef std::set TIdSetType; +typedef std::set TIdSetType; +typedef std::map> TStructRecord; // // Sharable code (as well as what's in TParseVersions) across @@ -82,7 +83,8 @@ public: : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), scopeMangler("::"), symbolTable(symbolTable), - statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0), + currentFunctionType(nullptr), postEntryPointReturn(false), contextPragma(true, false), beginInvocationInterlockCount(0), endInvocationInterlockCount(0), @@ -90,7 +92,8 @@ public: limits(resources.limits), globalUniformBlock(nullptr), globalUniformBinding(TQualifier::layoutBindingEnd), - globalUniformSet(TQualifier::layoutSetEnd) + globalUniformSet(TQualifier::layoutSetEnd), + atomicCounterBlockSet(TQualifier::layoutSetEnd) { if (entryPoint != nullptr) sourceEntryPointName = *entryPoint; @@ -152,10 +155,11 @@ public: extensionCallback(line, extension, behavior); } -#ifdef ENABLE_HLSL // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); -#endif + + // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics) + virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); // Potentially rename shader entry point function void renameShaderFunction(TString*& name) const @@ -176,7 +180,8 @@ public: TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile int statementNestingLevel; // 0 if outside all flow control or compound statements int loopNestingLevel; // 0 if outside all loops - int structNestingLevel; // 0 if outside blocks and structures + int structNestingLevel; // 0 if outside structures + int blockNestingLevel; // 0 if outside blocks int controlFlowNestingLevel; // 0 if outside all flow control const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return @@ -227,7 +232,25 @@ protected: // override this to set the language-specific name virtual const char* getGlobalUniformBlockName() const { return ""; } virtual void setUniformBlockDefaults(TType&) const { } - virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) {} + + // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed) + TMap atomicCounterBuffers; + unsigned int atomicCounterBlockSet; + TMap atomicCounterBlockFirstNewMember; + // override this to set the language-specific name + virtual const char* getAtomicCounterBlockName() const { return ""; } + virtual void setAtomicCounterBlockDefaults(TType&) const {} + virtual void setInvariant(const TSourceLoc& loc, const char* builtin) {} + virtual void finalizeAtomicCounterBlockLayout(TVariable&) {} + bool isAtomicCounterBlock(const TSymbol& symbol) { + const TVariable* var = symbol.getAsVariable(); + if (!var) + return false; + const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding); + return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType()); + } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, const char* szExtraInfoFormat, TPrefixType prefix, va_list args); @@ -290,6 +313,9 @@ public: bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; void parserError(const char* s); // for bison's yyerror + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; + virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; + void reservedErrorCheck(const TSourceLoc&, const TString&); void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; @@ -315,6 +341,7 @@ public: TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field); void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); @@ -326,6 +353,7 @@ public: TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); @@ -335,6 +363,10 @@ public: void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + // returns true if the variable was remapped to something else + bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&); + void assignError(const TSourceLoc&, const char* op, TString left, TString right); void unaryOpError(const TSourceLoc&, const char* op, TString operand); void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); @@ -358,10 +390,10 @@ public: void boolCheck(const TSourceLoc&, const TPublicType&); void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); - void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); void memberQualifierCheck(glslang::TPublicType&); - void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false); void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); @@ -387,7 +419,7 @@ public: void arrayLimitCheck(const TSourceLoc&, const TString&, int size); void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); - void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&); void constantIndexExpressionCheck(TIntermNode*); void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); @@ -412,17 +444,21 @@ public: TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&); void blockStageIoCheck(const TSourceLoc&, const TQualifier&); void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixXfbOffsets(TQualifier&, TTypeList&); void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*); + void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*); void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); void invariantCheck(const TSourceLoc&, const TQualifier&); void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*); #ifndef GLSLANG_WEB TAttributeType attributeFromName(const TString& name) const; @@ -435,6 +471,22 @@ public: void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); // Determine loop control from attributes void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); + // Function attributes + void handleFunctionAttributes(const TSourceLoc&, const TAttributes&, TFunction*); + + // GL_EXT_spirv_intrinsics + TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name, + const TIntermAggregate* extensions, const TIntermAggregate* capabilities); + TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, + TSpirvRequirement* spirvReq2); + TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant); + TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type); + TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, + TSpirvTypeParameters* spirvTypeParams2); + TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value); + TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value); + TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, + TSpirvInstruction* spirvInst2); #endif void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); @@ -453,6 +505,15 @@ protected: void finish() override; #endif + virtual const char* getGlobalUniformBlockName() const override; + virtual void finalizeGlobalUniformBlockLayout(TVariable&) override; + virtual void setUniformBlockDefaults(TType& block) const override; + + virtual const char* getAtomicCounterBlockName() const override; + virtual void finalizeAtomicCounterBlockLayout(TVariable&) override; + virtual void setAtomicCounterBlockDefaults(TType& block) const override; + virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override; + public: // // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access @@ -477,12 +538,15 @@ protected: TQualifier globalUniformDefaults; TQualifier globalInputDefaults; TQualifier globalOutputDefaults; + TQualifier globalSharedDefaults; TString currentCaller; // name of last function body entered (not valid when at global scope) #ifndef GLSLANG_WEB int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point bool anyIndexLimits; TIdSetType inductiveLoopIds; TVector needsIndexLimitationChecking; + TStructRecord matrixFixRecord; + TStructRecord packingFixRecord; // // Geometry shader input arrays: diff --git a/libraries/glslang/glslang/MachineIndependent/PoolAlloc.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/PoolAlloc.cpp similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/PoolAlloc.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/PoolAlloc.cpp diff --git a/libraries/glslang/glslang/MachineIndependent/RemoveTree.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/RemoveTree.cpp similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/RemoveTree.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/RemoveTree.cpp diff --git a/libraries/glslang/glslang/MachineIndependent/RemoveTree.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/RemoveTree.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/RemoveTree.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/RemoveTree.h diff --git a/libraries/glslang/glslang/MachineIndependent/Scan.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Scan.cpp similarity index 89% rename from libraries/glslang/glslang/MachineIndependent/Scan.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Scan.cpp index 710af4ab8..c387aede0 100644 --- a/libraries/glslang/glslang/MachineIndependent/Scan.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Scan.cpp @@ -2,6 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Copyright (C) 2020 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT if (lookingInMiddle) { notFirstToken = true; // make forward progress by finishing off the current line plus extra new lines - if (peek() == '\n' || peek() == '\r') { - while (peek() == '\n' || peek() == '\r') - get(); - } else + if (peek() != '\n' && peek() != '\r') { do { c = get(); } while (c != EndOfInput && c != '\n' && c != '\r'); - while (peek() == '\n' || peek() == '\r') - get(); - if (peek() == EndOfInput) - return true; + } + while (peek() == '\n' || peek() == '\r') + get(); + if (peek() == EndOfInput) + return true; } lookingInMiddle = true; @@ -365,6 +365,9 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["if"] = IF; (*KeywordMap)["else"] = ELSE; (*KeywordMap)["discard"] = DISCARD; + (*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION; + (*KeywordMap)["terminateRayEXT"] = TERMINATE_RAY; + (*KeywordMap)["ignoreIntersectionEXT"] = IGNORE_INTERSECTION; (*KeywordMap)["return"] = RETURN; (*KeywordMap)["void"] = VOID; (*KeywordMap)["bool"] = BOOL; @@ -416,6 +419,7 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT; (*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT; (*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT; + (*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT; (*KeywordMap)["nonprivate"] = NONPRIVATE; (*KeywordMap)["restrict"] = RESTRICT; (*KeywordMap)["readonly"] = READONLY; @@ -470,6 +474,28 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY; (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY; (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY; + (*KeywordMap)["i64image1D"] = I64IMAGE1D; + (*KeywordMap)["u64image1D"] = U64IMAGE1D; + (*KeywordMap)["i64image2D"] = I64IMAGE2D; + (*KeywordMap)["u64image2D"] = U64IMAGE2D; + (*KeywordMap)["i64image3D"] = I64IMAGE3D; + (*KeywordMap)["u64image3D"] = U64IMAGE3D; + (*KeywordMap)["i64image2DRect"] = I64IMAGE2DRECT; + (*KeywordMap)["u64image2DRect"] = U64IMAGE2DRECT; + (*KeywordMap)["i64imageCube"] = I64IMAGECUBE; + (*KeywordMap)["u64imageCube"] = U64IMAGECUBE; + (*KeywordMap)["i64imageBuffer"] = I64IMAGEBUFFER; + (*KeywordMap)["u64imageBuffer"] = U64IMAGEBUFFER; + (*KeywordMap)["i64image1DArray"] = I64IMAGE1DARRAY; + (*KeywordMap)["u64image1DArray"] = U64IMAGE1DARRAY; + (*KeywordMap)["i64image2DArray"] = I64IMAGE2DARRAY; + (*KeywordMap)["u64image2DArray"] = U64IMAGE2DARRAY; + (*KeywordMap)["i64imageCubeArray"] = I64IMAGECUBEARRAY; + (*KeywordMap)["u64imageCubeArray"] = U64IMAGECUBEARRAY; + (*KeywordMap)["i64image2DMS"] = I64IMAGE2DMS; + (*KeywordMap)["u64image2DMS"] = U64IMAGE2DMS; + (*KeywordMap)["i64image2DMSArray"] = I64IMAGE2DMSARRAY; + (*KeywordMap)["u64image2DMSArray"] = U64IMAGE2DMSARRAY; (*KeywordMap)["double"] = DOUBLE; (*KeywordMap)["dvec2"] = DVEC2; (*KeywordMap)["dvec3"] = DVEC3; @@ -560,6 +586,18 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["f64mat4x2"] = F64MAT4X2; (*KeywordMap)["f64mat4x3"] = F64MAT4X3; (*KeywordMap)["f64mat4x4"] = F64MAT4X4; + + // GL_EXT_spirv_intrinsics + (*KeywordMap)["spirv_instruction"] = SPIRV_INSTRUCTION; + (*KeywordMap)["spirv_execution_mode"] = SPIRV_EXECUTION_MODE; + (*KeywordMap)["spirv_execution_mode_id"] = SPIRV_EXECUTION_MODE_ID; + (*KeywordMap)["spirv_decorate"] = SPIRV_DECORATE; + (*KeywordMap)["spirv_decorate_id"] = SPIRV_DECORATE_ID; + (*KeywordMap)["spirv_decorate_string"] = SPIRV_DECORATE_STRING; + (*KeywordMap)["spirv_type"] = SPIRV_TYPE; + (*KeywordMap)["spirv_storage_class"] = SPIRV_STORAGE_CLASS; + (*KeywordMap)["spirv_by_reference"] = SPIRV_BY_REFERENCE; + (*KeywordMap)["spirv_literal"] = SPIRV_LITERAL; #endif (*KeywordMap)["sampler2D"] = SAMPLER2D; @@ -704,11 +742,18 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["precise"] = PRECISE; (*KeywordMap)["rayPayloadNV"] = PAYLOADNV; + (*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT; (*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV; + (*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT; (*KeywordMap)["hitAttributeNV"] = HITATTRNV; + (*KeywordMap)["hitAttributeEXT"] = HITATTREXT; (*KeywordMap)["callableDataNV"] = CALLDATANV; + (*KeywordMap)["callableDataEXT"] = CALLDATAEXT; (*KeywordMap)["callableDataInNV"] = CALLDATAINNV; + (*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT; (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV; + (*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT; + (*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT; (*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV; (*KeywordMap)["perviewNV"] = PERVIEWNV; (*KeywordMap)["taskNV"] = PERTASKNV; @@ -843,6 +888,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token) parseContext.error(loc, "not supported", "::", ""); break; + case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL; case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT; case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT; case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT; @@ -905,10 +951,22 @@ int TScanContext::tokenizeIdentifier() case CASE: return keyword; + case TERMINATE_INVOCATION: + if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation)) + return identifierOrType(); + return keyword; + + case TERMINATE_RAY: + case IGNORE_INTERSECTION: + if (!parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing)) + return identifierOrType(); + return keyword; + case BUFFER: afterBuffer = true; if ((parseContext.isEsProfile() && parseContext.version < 310) || - (!parseContext.isEsProfile() && parseContext.version < 430)) + (!parseContext.isEsProfile() && (parseContext.version < 430 && + !parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object)))) return identifierOrType(); return keyword; @@ -972,7 +1030,7 @@ int TScanContext::tokenizeIdentifier() return keyword; case PACKED: if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 330)) + (!parseContext.isEsProfile() && parseContext.version < 140)) return reservedWord(); return identifierOrType(); @@ -1014,6 +1072,23 @@ int TScanContext::tokenizeIdentifier() parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)) return keyword; return identifierOrType(); + case PAYLOADEXT: + case PAYLOADINEXT: + case HITATTREXT: + case CALLDATAEXT: + case CALLDATAINEXT: + case ACCSTRUCTEXT: + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || + parseContext.extensionTurnedOn(E_GL_EXT_ray_query)) + return keyword; + return identifierOrType(); + case RAYQUERYEXT: + if (parseContext.symbolTable.atBuiltInLevel() || + (!parseContext.isEsProfile() && parseContext.version >= 460 + && parseContext.extensionTurnedOn(E_GL_EXT_ray_query))) + return keyword; + return identifierOrType(); case ATOMIC_UINT: if ((parseContext.isEsProfile() && parseContext.version >= 310) || parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) @@ -1025,6 +1100,7 @@ int TScanContext::tokenizeIdentifier() case QUEUEFAMILYCOHERENT: case WORKGROUPCOHERENT: case SUBGROUPCOHERENT: + case SHADERCALLCOHERENT: case NONPRIVATE: case RESTRICT: case READONLY: @@ -1119,6 +1195,19 @@ int TScanContext::tokenizeIdentifier() afterType = true; return firstGenerationImage(false); + case I64IMAGE1D: + case U64IMAGE1D: + case I64IMAGE1DARRAY: + case U64IMAGE1DARRAY: + case I64IMAGE2DRECT: + case U64IMAGE2DRECT: + afterType = true; + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { + return firstGenerationImage(false); + } + return identifierOrType(); + case IMAGEBUFFER: case IIMAGEBUFFER: case UIMAGEBUFFER: @@ -1127,6 +1216,18 @@ int TScanContext::tokenizeIdentifier() parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) return keyword; return firstGenerationImage(false); + + case I64IMAGEBUFFER: + case U64IMAGEBUFFER: + afterType = true; + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { + if ((parseContext.isEsProfile() && parseContext.version >= 320) || + parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) + return keyword; + return firstGenerationImage(false); + } + return identifierOrType(); case IMAGE2D: case IIMAGE2D: @@ -1143,6 +1244,20 @@ int TScanContext::tokenizeIdentifier() afterType = true; return firstGenerationImage(true); + case I64IMAGE2D: + case U64IMAGE2D: + case I64IMAGE3D: + case U64IMAGE3D: + case I64IMAGECUBE: + case U64IMAGECUBE: + case I64IMAGE2DARRAY: + case U64IMAGE2DARRAY: + afterType = true; + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) + return firstGenerationImage(true); + return identifierOrType(); + case IMAGECUBEARRAY: case IIMAGECUBEARRAY: case UIMAGECUBEARRAY: @@ -1151,6 +1266,18 @@ int TScanContext::tokenizeIdentifier() parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) return keyword; return secondGenerationImage(); + + case I64IMAGECUBEARRAY: + case U64IMAGECUBEARRAY: + afterType = true; + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { + if ((parseContext.isEsProfile() && parseContext.version >= 320) || + parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) + return keyword; + return secondGenerationImage(); + } + return identifierOrType(); case IMAGE2DMS: case IIMAGE2DMS: @@ -1160,13 +1287,27 @@ int TScanContext::tokenizeIdentifier() case UIMAGE2DMSARRAY: afterType = true; return secondGenerationImage(); + + case I64IMAGE2DMS: + case U64IMAGE2DMS: + case I64IMAGE2DMSARRAY: + case U64IMAGE2DMSARRAY: + afterType = true; + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { + return secondGenerationImage(); + } + return identifierOrType(); case DOUBLE: case DVEC2: case DVEC3: case DVEC4: afterType = true; - if (parseContext.isEsProfile() || parseContext.version < 400) + if (parseContext.isEsProfile() || parseContext.version < 150 || + (!parseContext.symbolTable.atBuiltInLevel() && + (parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) && + (parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit))))) reservedWord(); return keyword; @@ -1618,6 +1759,21 @@ int TScanContext::tokenizeIdentifier() return keyword; else return identifierOrType(); + + case SPIRV_INSTRUCTION: + case SPIRV_EXECUTION_MODE: + case SPIRV_EXECUTION_MODE_ID: + case SPIRV_DECORATE: + case SPIRV_DECORATE_ID: + case SPIRV_DECORATE_STRING: + case SPIRV_TYPE: + case SPIRV_STORAGE_CLASS: + case SPIRV_BY_REFERENCE: + case SPIRV_LITERAL: + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) + return keyword; + return identifierOrType(); #endif default: @@ -1741,7 +1897,11 @@ int TScanContext::dMat() return keyword; } - if (!parseContext.isEsProfile() && parseContext.version >= 400) + if (!parseContext.isEsProfile() && (parseContext.version >= 400 || + parseContext.symbolTable.atBuiltInLevel() || + (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) || + (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) + && parseContext.language == EShLangVertex))) return keyword; if (parseContext.isForwardCompatible()) diff --git a/libraries/glslang/glslang/MachineIndependent/Scan.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Scan.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/Scan.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Scan.h diff --git a/libraries/glslang/glslang/MachineIndependent/ScanContext.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ScanContext.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/ScanContext.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ScanContext.h diff --git a/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ShaderLang.cpp similarity index 92% rename from libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ShaderLang.cpp index 44ce1c19d..17902b5da 100644 --- a/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/ShaderLang.cpp @@ -1,7 +1,7 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // // All rights reserved. // @@ -51,9 +51,9 @@ #include "ScanContext.h" #ifdef ENABLE_HLSL -#include "../../hlsl/hlslParseHelper.h" -#include "../../hlsl/hlslParseables.h" -#include "../../hlsl/hlslScanContext.h" +#include "../HLSL/hlslParseHelper.h" +#include "../HLSL/hlslParseables.h" +#include "../HLSL/hlslScanContext.h" #endif #include "../Include/ShHandle.h" @@ -72,6 +72,9 @@ // token to print ", but none of that seems appropriate for this file. #include "preprocessor/PpTokens.h" +// Build-time generated includes +#include "../Include/build_info.h" + namespace { // anonymous namespace for file-local functions and symbols // Total number of successful initializers of glslang: a refcount @@ -156,7 +159,7 @@ int MapVersionToIndex(int version) return index; } -const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex +const int SpvVersionCount = 4; // index range in MapSpvVersionToIndex int MapSpvVersionToIndex(const SpvVersion& spvVersion) { @@ -164,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion) if (spvVersion.openGl > 0) index = 1; - else if (spvVersion.vulkan > 0) - index = 2; + else if (spvVersion.vulkan > 0) { + if (!spvVersion.vulkanRelaxed) + index = 2; + else + index = 3; + } assert(index < SpvVersionCount); @@ -291,6 +298,9 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; +#elif defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; #endif (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]); @@ -312,6 +322,9 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; +#elif defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; #endif std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); @@ -351,7 +364,6 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS (profile == EEsProfile && version >= 310)) InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, infoSink, commonTable, symbolTables); -#endif // check for compute if ((profile != EEsProfile && version >= 420) || @@ -359,19 +371,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, infoSink, commonTable, symbolTables); +#ifndef GLSLANG_ANGLE // check for ray tracing stages if (profile != EEsProfile && version >= 450) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source, infoSink, commonTable, symbolTables); } @@ -386,6 +399,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS (profile == EEsProfile && version >= 320)) InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source, infoSink, commonTable, symbolTables); +#endif // !GLSLANG_ANGLE +#endif // !GLSLANG_WEB return true; } @@ -487,7 +502,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp // Function to Print all builtins void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable) { -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) infoSink.debug << "BuiltinSymbolTable {\n"; symbolTable.dump(infoSink, true); @@ -591,7 +606,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo break; } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // Correct for stage type... switch (stage) { case EShLangGeometry: @@ -623,12 +638,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo version = profile == EEsProfile ? 310 : 420; } break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: if (profile == EEsProfile || version < 460) { correct = false; infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above"); @@ -712,10 +727,14 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages break; case EShClientVulkan: spvVersion.vulkanGlsl = environment->input.dialectVersion; + spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed; break; case EShClientOpenGL: spvVersion.openGl = environment->input.dialectVersion; break; + case EShClientCount: + assert(0); + break; } switch (environment->input.languageFamily) { case EShSourceNone: @@ -728,6 +747,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages source = EShSourceHlsl; messages = static_cast(messages | EShMsgReadHlsl); break; + case EShSourceCount: + assert(0); + break; } } @@ -861,7 +883,7 @@ bool ProcessDeferred( : userInput.scanVersion(version, profile, versionNotFirstToken); bool versionNotFound = version == 0; if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && (version != defaultVersion || profile != defaultProfile)) { compiler->infoSink.info << "Warning, (version, profile) forced to be (" @@ -884,10 +906,13 @@ bool ProcessDeferred( #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; +#elif defined(GLSLANG_ANGLE) + profile = ECoreProfile; + version = 450; #endif bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) bool warnVersionNotFirst = false; if (! versionWillBeError && versionNotFirstToken) { if (messages & EShMsgRelaxedErrors) @@ -929,6 +954,9 @@ bool ProcessDeferred( if (cachedTable) symbolTable->adoptLevels(*cachedTable); + if (intermediate.getUniqueId() != 0) + symbolTable->overwriteUniqueId(intermediate.getUniqueId()); + // Add built-in symbols that are potentially context dependent; // they get popped again further down. if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, @@ -957,7 +985,7 @@ bool ProcessDeferred( parseContext->setLimits(*resources); if (! goodVersion) parseContext->addError(); -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) if (warnVersionNotFirst) { TSourceLoc loc; loc.init(); @@ -991,10 +1019,11 @@ bool ProcessDeferred( bool success = processingContext(*parseContext, ppContext, fullInput, versionWillBeError, *symbolTable, intermediate, optLevel, messages); + intermediate.setUniqueId(symbolTable->getMaxSymbolId()); return success; } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // Responsible for keeping track of the most recent source string and line in // the preprocessor and outputting newlines appropriately if the source string @@ -1217,14 +1246,16 @@ struct DoFullParse{ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; } +#ifndef GLSLANG_ANGLE if (messages & EShMsgAST) intermediate.output(parseContext.infoSink, true); +#endif return success; } }; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // Take a single compilation unit, and run the preprocessor on it. // Return: True if there were no issues found in preprocessing, // False if during preprocessing any unknown version, pragmas or @@ -1248,14 +1279,15 @@ bool PreprocessDeferred( EShMessages messages, // warnings/errors/AST; things to print out TShader::Includer& includer, TIntermediate& intermediate, // returned tree, etc. - std::string* outputString) + std::string* outputString, + TEnvironment* environment = nullptr) { DoPreprocessing parser(outputString); return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, intermediate, parser, - false, includer); + false, includer, "", environment); } #endif @@ -1678,19 +1710,29 @@ int ShGetUniformLocation(const ShHandle handle, const char* name) namespace glslang { -#include "../Include/revision.h" +Version GetVersion() +{ + Version version; + version.major = GLSLANG_VERSION_MAJOR; + version.minor = GLSLANG_VERSION_MINOR; + version.patch = GLSLANG_VERSION_PATCH; + version.flavor = GLSLANG_VERSION_FLAVOR; + return version; +} #define QUOTE(s) #s #define STR(n) QUOTE(n) const char* GetEsslVersionString() { - return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); + return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( + GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; } const char* GetGlslVersionString() { - return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); + return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( + GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; } int GetKhronosToolId() @@ -1725,6 +1767,7 @@ TShader::TShader(EShLanguage s) // clear environment (avoid constructors in them for use in a C interface) environment.input.languageFamily = EShSourceNone; environment.input.dialect = EShClientNone; + environment.input.vulkanRulesRelaxed = false; environment.client.client = EShClientNone; environment.target.language = EShTargetNone; environment.target.hlslFunctionality1 = false; @@ -1771,11 +1814,18 @@ void TShader::setSourceEntryPoint(const char* name) sourceEntryPointName = name; } +// Log initial settings and transforms. +// See comment for class TProcesses. void TShader::addProcesses(const std::vector& p) { intermediate->addProcesses(p); } +void TShader::setUniqueId(unsigned long long id) +{ + intermediate->setUniqueId(id); +} + void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); } @@ -1824,6 +1874,15 @@ void TShader::setResourceSetBinding(const std::vector& base) { in void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } #endif +void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); } + +void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); } +void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); } +void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); } + +void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); } +void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); } + #ifdef ENABLE_HLSL // See comment above TDefaultHlslIoMapper in iomapper.cpp: void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } @@ -1852,7 +1911,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion &environment); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // Fill in a string with the result of preprocessing ShaderStrings // Returns true if all extensions, pragmas and version strings were valid. // @@ -1875,7 +1934,8 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, message, includer, *intermediate, output_string); + forwardCompatible, message, includer, *intermediate, output_string, + &environment); } #endif @@ -1890,7 +1950,7 @@ const char* TShader::getInfoDebugLog() } TProgram::TProgram() : -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) reflection(0), #endif linked(false) @@ -1906,7 +1966,7 @@ TProgram::TProgram() : TProgram::~TProgram() { delete infoSink; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) delete reflection; #endif @@ -1938,7 +1998,10 @@ bool TProgram::link(EShMessages messages) error = true; } - // TODO: Link: cross-stage error checking + if (!error) { + if (! crossStageCheck(messages)) + error = true; + } return ! error; } @@ -1953,7 +2016,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) if (stages[stage].size() == 0) return true; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) int numEsShaders = 0, numNonEsShaders = 0; for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { if ((*it)->intermediate->getProfile() == EEsProfile) { @@ -1982,7 +2045,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) intermediate[stage] = new TIntermediate(stage, firstIntermediate->getVersion(), firstIntermediate->getProfile()); - + intermediate[stage]->setLimits(firstIntermediate->getLimits()); // The new TIntermediate must use the same origin as the original TIntermediates. // Otherwise linking will fail due to different coordinate systems. @@ -2007,12 +2070,77 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) #endif intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0); +#ifndef GLSLANG_ANGLE if (messages & EShMsgAST) intermediate[stage]->output(*infoSink, true); +#endif return intermediate[stage]->getNumErrors() == 0; } +// +// Check that there are no errors in linker objects accross stages +// +// Return true if no errors. +// +bool TProgram::crossStageCheck(EShMessages) { + + // make temporary intermediates to hold the linkage symbols for each linking interface + // while we do the checks + // Independent interfaces are: + // all uniform variables and blocks + // all buffer blocks + // all in/out on a stage boundary + + TVector activeStages; + for (int s = 0; s < EShLangCount; ++s) { + if (intermediate[s]) + activeStages.push_back(intermediate[s]); + } + + // no extra linking if there is only one stage + if (! (activeStages.size() > 1)) + return true; + + // setup temporary tree to hold unfirom objects from different stages + TIntermediate* firstIntermediate = activeStages.front(); + TIntermediate uniforms(EShLangCount, + firstIntermediate->getVersion(), + firstIntermediate->getProfile()); + uniforms.setSpv(firstIntermediate->getSpv()); + + TIntermAggregate uniformObjects(EOpLinkerObjects); + TIntermAggregate root(EOpSequence); + root.getSequence().push_back(&uniformObjects); + uniforms.setTreeRoot(&root); + + bool error = false; + + // merge uniforms from all stages into a single intermediate + for (unsigned int i = 0; i < activeStages.size(); ++i) { + uniforms.mergeUniformObjects(*infoSink, *activeStages[i]); + } + error |= uniforms.getNumErrors() != 0; + + // copy final definition of global block back into each stage + for (unsigned int i = 0; i < activeStages.size(); ++i) { + // We only want to merge into already existing global uniform blocks. + // A stage that doesn't already know about the global doesn't care about it's content. + // Otherwise we end up pointing to the same object between different stages + // and that will break binding/set remappings + bool mergeExistingOnly = true; + activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly); + } + + // compare cross stage symbols for each stage boundary + for (unsigned int i = 1; i < activeStages.size(); ++i) { + activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]); + error |= (activeStages[i - 1]->getNumErrors() != 0); + } + + return !error; +} + const char* TProgram::getInfoLog() { return infoSink->info.c_str(); @@ -2023,7 +2151,7 @@ const char* TProgram::getInfoDebugLog() return infoSink->debug.c_str(); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // // Reflection implementation. @@ -2105,6 +2233,6 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper) return ioMapper->doMap(pResolver, *infoSink); } -#endif // GLSLANG_WEB +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE } // end namespace glslang diff --git a/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp new file mode 100644 index 000000000..38094eaaf --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp @@ -0,0 +1,355 @@ +// +// Copyright(C) 2021 Advanced Micro Devices, 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 3Dlabs Inc. Ltd. 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 HOLDERS 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. +// + +#ifndef GLSLANG_WEB + +// +// GL_EXT_spirv_intrinsics +// +#include "../Include/intermediate.h" +#include "../Include/SpirvIntrinsics.h" +#include "../Include/Types.h" +#include "ParseHelper.h" + +namespace glslang { + +// +// Handle SPIR-V requirements +// +TSpirvRequirement* TParseContext::makeSpirvRequirement(const TSourceLoc& loc, const TString& name, + const TIntermAggregate* extensions, + const TIntermAggregate* capabilities) +{ + TSpirvRequirement* spirvReq = new TSpirvRequirement; + + if (name == "extensions") { + assert(extensions); + for (auto extension : extensions->getSequence()) { + assert(extension->getAsConstantUnion()); + spirvReq->extensions.insert(*extension->getAsConstantUnion()->getConstArray()[0].getSConst()); + } + } else if (name == "capabilities") { + assert(capabilities); + for (auto capability : capabilities->getSequence()) { + assert(capability->getAsConstantUnion()); + spirvReq->capabilities.insert(capability->getAsConstantUnion()->getConstArray()[0].getIConst()); + } + } else + error(loc, "unknow SPIR-V requirement", name.c_str(), ""); + + return spirvReq; +} + +TSpirvRequirement* TParseContext::mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, + TSpirvRequirement* spirvReq2) +{ + // Merge the second SPIR-V requirement to the first one + if (!spirvReq2->extensions.empty()) { + if (spirvReq1->extensions.empty()) + spirvReq1->extensions = spirvReq2->extensions; + else + error(loc, "too many SPIR-V requirements", "extensions", ""); + } + + if (!spirvReq2->capabilities.empty()) { + if (spirvReq1->capabilities.empty()) + spirvReq1->capabilities = spirvReq2->capabilities; + else + error(loc, "too many SPIR-V requirements", "capabilities", ""); + } + + return spirvReq1; +} + +void TIntermediate::insertSpirvRequirement(const TSpirvRequirement* spirvReq) +{ + if (!spirvRequirement) + spirvRequirement = new TSpirvRequirement; + + for (auto extension : spirvReq->extensions) + spirvRequirement->extensions.insert(extension); + + for (auto capability : spirvReq->capabilities) + spirvRequirement->capabilities.insert(capability); +} + +// +// Handle SPIR-V execution modes +// +void TIntermediate::insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args) +{ + if (!spirvExecutionMode) + spirvExecutionMode = new TSpirvExecutionMode; + + TVector extraOperands; + if (args) { + for (auto arg : args->getSequence()) { + auto extraOperand = arg->getAsConstantUnion(); + assert(extraOperand != nullptr); + extraOperands.push_back(extraOperand); + } + } + spirvExecutionMode->modes[executionMode] = extraOperands; +} + +void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args) +{ + if (!spirvExecutionMode) + spirvExecutionMode = new TSpirvExecutionMode; + + assert(args); + TVector extraOperands; + + for (auto arg : args->getSequence()) { + auto extraOperand = arg->getAsConstantUnion(); + assert(extraOperand != nullptr); + extraOperands.push_back(extraOperand); + } + spirvExecutionMode->modeIds[executionMode] = extraOperands; +} + +// +// Handle SPIR-V decorate qualifiers +// +void TQualifier::setSpirvDecorate(int decoration, const TIntermAggregate* args) +{ + if (!spirvDecorate) + spirvDecorate = new TSpirvDecorate; + + TVector extraOperands; + if (args) { + for (auto arg : args->getSequence()) { + auto extraOperand = arg->getAsConstantUnion(); + assert(extraOperand != nullptr); + extraOperands.push_back(extraOperand); + } + } + spirvDecorate->decorates[decoration] = extraOperands; +} + +void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args) +{ + if (!spirvDecorate) + spirvDecorate = new TSpirvDecorate; + + assert(args); + TVector extraOperands; + for (auto arg : args->getSequence()) { + auto extraOperand = arg->getAsConstantUnion(); + assert(extraOperand != nullptr); + extraOperands.push_back(extraOperand); + } + spirvDecorate->decorateIds[decoration] = extraOperands; +} + +void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args) +{ + if (!spirvDecorate) + spirvDecorate = new TSpirvDecorate; + + assert(args); + TVector extraOperands; + for (auto arg : args->getSequence()) { + auto extraOperand = arg->getAsConstantUnion(); + assert(extraOperand != nullptr); + extraOperands.push_back(extraOperand); + } + spirvDecorate->decorateStrings[decoration] = extraOperands; +} + +TString TQualifier::getSpirvDecorateQualifierString() const +{ + assert(spirvDecorate); + + TString qualifierString; + + const auto appendFloat = [&](float f) { qualifierString.append(std::to_string(f).c_str()); }; + const auto appendInt = [&](int i) { qualifierString.append(std::to_string(i).c_str()); }; + const auto appendUint = [&](unsigned int u) { qualifierString.append(std::to_string(u).c_str()); }; + const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); }; + const auto appendStr = [&](const char* s) { qualifierString.append(s); }; + + const auto appendDecorate = [&](const TIntermConstantUnion* constant) { + if (constant->getBasicType() == EbtFloat) { + float value = static_cast(constant->getConstArray()[0].getDConst()); + appendFloat(value); + } + else if (constant->getBasicType() == EbtInt) { + int value = constant->getConstArray()[0].getIConst(); + appendInt(value); + } + else if (constant->getBasicType() == EbtUint) { + unsigned value = constant->getConstArray()[0].getUConst(); + appendUint(value); + } + else if (constant->getBasicType() == EbtBool) { + bool value = constant->getConstArray()[0].getBConst(); + appendBool(value); + } + else if (constant->getBasicType() == EbtString) { + const TString* value = constant->getConstArray()[0].getSConst(); + appendStr(value->c_str()); + } + else + assert(0); + }; + + for (auto& decorate : spirvDecorate->decorates) { + appendStr("spirv_decorate("); + appendInt(decorate.first); + for (auto extraOperand : decorate.second) { + appendStr(", "); + appendDecorate(extraOperand); + } + appendStr(") "); + } + + for (auto& decorateId : spirvDecorate->decorateIds) { + appendStr("spirv_decorate_id("); + appendInt(decorateId.first); + for (auto extraOperand : decorateId.second) { + appendStr(", "); + appendDecorate(extraOperand); + } + appendStr(") "); + } + + for (auto& decorateString : spirvDecorate->decorateStrings) { + appendStr("spirv_decorate_string("); + appendInt(decorateString.first); + for (auto extraOperand : decorateString.second) { + appendStr(", "); + appendDecorate(extraOperand); + } + appendStr(") "); + } + + return qualifierString; +} + +// +// Handle SPIR-V type specifiers +// +void TPublicType::setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams) +{ + if (!spirvType) + spirvType = new TSpirvType; + + basicType = EbtSpirvType; + spirvType->spirvInst = spirvInst; + if (typeParams) + spirvType->typeParams = *typeParams; +} + +TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant) +{ + TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters; + if (constant->getBasicType() != EbtFloat && + constant->getBasicType() != EbtInt && + constant->getBasicType() != EbtUint && + constant->getBasicType() != EbtBool && + constant->getBasicType() != EbtString) + error(loc, "this type not allowed", constant->getType().getBasicString(), ""); + else { + assert(constant); + spirvTypeParams->push_back(TSpirvTypeParameter(constant)); + } + + return spirvTypeParams; +} + +TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TPublicType& type) +{ + TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters; + spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type))); + return spirvTypeParams; +} + +TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2) +{ + // Merge SPIR-V type parameters of the second one to the first one + for (const auto& spirvTypeParam : *spirvTypeParams2) + spirvTypeParams1->push_back(spirvTypeParam); + return spirvTypeParams1; +} + +// +// Handle SPIR-V instruction qualifiers +// +TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value) +{ + TSpirvInstruction* spirvInst = new TSpirvInstruction; + if (name == "set") + spirvInst->set = value; + else + error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), ""); + + return spirvInst; +} + +TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value) +{ + TSpirvInstruction* spirvInstuction = new TSpirvInstruction; + if (name == "id") + spirvInstuction->id = value; + else + error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), ""); + + return spirvInstuction; +} + +TSpirvInstruction* TParseContext::mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, TSpirvInstruction* spirvInst2) +{ + // Merge qualifiers of the second SPIR-V instruction to those of the first one + if (!spirvInst2->set.empty()) { + if (spirvInst1->set.empty()) + spirvInst1->set = spirvInst2->set; + else + error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(set)"); + } + + if (spirvInst2->id != -1) { + if (spirvInst1->id == -1) + spirvInst1->id = spirvInst2->id; + else + error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(id)"); + } + + return spirvInst1; +} + +} // end namespace glslang + +#endif // GLSLANG_WEB diff --git a/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.cpp similarity index 95% rename from libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.cpp index 44682379f..747b43666 100644 --- a/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -74,7 +75,9 @@ void TType::buildMangledName(TString& mangledName) const case EbtInt64: mangledName += "i64"; break; case EbtUint64: mangledName += "u64"; break; case EbtAtomicUint: mangledName += "au"; break; - case EbtAccStructNV: mangledName += "asnv"; break; + case EbtAccStruct: mangledName += "as"; break; + case EbtRayQuery: mangledName += "rq"; break; + case EbtSpirvType: mangledName += "spv-t"; break; #endif case EbtSampler: switch (sampler.type) { @@ -83,6 +86,8 @@ void TType::buildMangledName(TString& mangledName) const #endif case EbtInt: mangledName += "i"; break; case EbtUint: mangledName += "u"; break; + case EbtInt64: mangledName += "i64"; break; + case EbtUint64: mangledName += "u64"; break; default: break; // some compilers want this } if (sampler.isImageClass()) @@ -120,7 +125,7 @@ void TType::buildMangledName(TString& mangledName) const mangledName += "-tx-struct"; char text[16]; // plenty enough space for the small integers. - snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex()); + snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex()); mangledName += text; } else { switch (sampler.getVectorSize()) { @@ -144,6 +149,8 @@ void TType::buildMangledName(TString& mangledName) const if (typeName) mangledName += *typeName; for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getBasicType() == EbtVoid) + continue; mangledName += '-'; (*structure)[i].type->buildMangledName(mangledName); } @@ -164,7 +171,7 @@ void TType::buildMangledName(TString& mangledName) const for (int i = 0; i < arraySizes->getNumDims(); ++i) { if (arraySizes->getDimNode(i)) { if (arraySizes->getDimNode(i)->getAsSymbolNode()) - snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); + snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); else snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i)); } else @@ -176,7 +183,7 @@ void TType::buildMangledName(TString& mangledName) const } } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // // Dump functions. @@ -384,6 +391,9 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) implicitThis = copyOf.implicitThis; illegalImplicitThis = copyOf.illegalImplicitThis; defaultParamCount = copyOf.defaultParamCount; +#ifndef GLSLANG_WEB + spirvInst = copyOf.spirvInst; +#endif } TFunction* TFunction::clone() const diff --git a/libraries/glslang/glslang/MachineIndependent/SymbolTable.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.h similarity index 92% rename from libraries/glslang/glslang/MachineIndependent/SymbolTable.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.h index 40ca3da53..219609307 100644 --- a/libraries/glslang/glslang/MachineIndependent/SymbolTable.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/SymbolTable.h @@ -104,8 +104,8 @@ public: virtual const TAnonMember* getAsAnonMember() const { return 0; } virtual const TType& getType() const = 0; virtual TType& getWritableType() = 0; - virtual void setUniqueId(int id) { uniqueId = id; } - virtual int getUniqueId() const { return uniqueId; } + virtual void setUniqueId(long long id) { uniqueId = id; } + virtual long long getUniqueId() const { return uniqueId; } virtual void setExtensions(int numExts, const char* const exts[]) { assert(extensions == 0); @@ -117,7 +117,7 @@ public: virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } virtual const char** getExtensions() const { return extensions->data(); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; void dumpExtensions(TInfoSink& infoSink) const; #endif @@ -130,7 +130,7 @@ protected: TSymbol& operator=(const TSymbol&); const TString *name; - unsigned int uniqueId; // For cross-scope comparing during code generation + unsigned long long uniqueId; // For cross-scope comparing during code generation // For tracking what extensions must be present // (don't use if correct version/profile is present). @@ -196,7 +196,7 @@ public: } virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) virtual void dump(TInfoSink& infoSink, bool complete = false) const; #endif @@ -320,6 +320,15 @@ public: virtual const TParameter& operator[](int i) const { return parameters[i]; } #ifndef GLSLANG_WEB + virtual void setSpirvInstruction(const TSpirvInstruction& inst) + { + relateToOperator(EOpSpirvInst); + spirvInst = inst; + } + virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } +#endif + +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) virtual void dump(TInfoSink& infoSink, bool complete = false) const override; #endif @@ -342,6 +351,10 @@ protected: // This is important for a static member function that has member variables in scope, // but is not allowed to use them, or see hidden symbols instead. int defaultParamCount; + +#ifndef GLSLANG_WEB + TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers +#endif }; // @@ -381,7 +394,7 @@ public: virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } virtual int getAnonId() const { return anonId; } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) virtual void dump(TInfoSink& infoSink, bool complete = false) const override; #endif @@ -551,7 +564,7 @@ public: void relateToOperator(const char* name, TOperator op); void setFunctionExtensions(const char* name, int num, const char* const extensions[]); -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) void dump(TInfoSink& infoSink, bool complete = false) const; #endif TSymbolTableLevel* clone() const; @@ -612,21 +625,28 @@ public: // 3: user-shader globals // protected: + static const uint32_t LevelFlagBitOffset = 56; static const int globalLevel = 3; - bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels - bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals - bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals + static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals public: bool isEmpty() { return table.size() == 0; } bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } - + static bool isBuiltInSymbol(long long uniqueId) { + int level = static_cast(uniqueId >> LevelFlagBitOffset); + return isBuiltInLevel(level); + } + static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1; + static const uint32_t MaxLevelInUniqueID = 127; void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } void setSeparateNameSpaces() { separateNameSpaces = true; } void push() { table.push_back(new TSymbolTableLevel); + updateUniqueIdLevelFlag(); } // Make a new symbol-table level to represent the scope introduced by a structure @@ -639,6 +659,7 @@ public: { assert(thisSymbol.getName().size() == 0); table.push_back(new TSymbolTableLevel); + updateUniqueIdLevelFlag(); table.back()->setThisLevel(); insert(thisSymbol); } @@ -648,6 +669,7 @@ public: table[currentLevel()]->getPreviousDefaultPrecisions(p); delete table.back(); table.pop_back(); + updateUniqueIdLevelFlag(); } // @@ -685,6 +707,16 @@ public: return table[currentLevel()]->amend(symbol, firstNewMember); } + // Update the level info in symbol's unique ID to current level + void amendSymbolIdLevel(TSymbol& symbol) + { + // clamp level to avoid overflow + uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel(); + uint64_t symbolId = symbol.getUniqueId(); + symbolId &= uniqueIdMask; + symbolId |= (level << LevelFlagBitOffset); + symbol.setUniqueId(symbolId); + } // // To allocate an internal temporary, which will need to be uniquely // identified by the consumer of the AST, but never need to @@ -853,8 +885,8 @@ public: } } - int getMaxSymbolId() { return uniqueId; } -#ifndef GLSLANG_WEB + long long getMaxSymbolId() { return uniqueId; } +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) void dump(TInfoSink& infoSink, bool complete = false) const; #endif void copyTable(const TSymbolTable& copyOf); @@ -867,14 +899,27 @@ public: table[level]->readOnly(); } + // Add current level in the high-bits of unique id + void updateUniqueIdLevelFlag() { + // clamp level to avoid overflow + uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel(); + uniqueId &= uniqueIdMask; + uniqueId |= (level << LevelFlagBitOffset); + } + + void overwriteUniqueId(long long id) + { + uniqueId = id; + updateUniqueIdLevelFlag(); + } + protected: TSymbolTable(TSymbolTable&); TSymbolTable& operator=(TSymbolTableLevel&); int currentLevel() const { return static_cast(table.size()) - 1; } - std::vector table; - int uniqueId; // for unique identification in code generation + long long uniqueId; // for unique identification in code generation bool noBuiltInRedeclarations; bool separateNameSpaces; unsigned int adoptedLevels; diff --git a/libraries/glslang/glslang/MachineIndependent/Versions.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.cpp similarity index 83% rename from libraries/glslang/glslang/MachineIndependent/Versions.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.cpp index 23f74232b..097ee8455 100644 --- a/libraries/glslang/glslang/MachineIndependent/Versions.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.cpp @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -63,6 +64,7 @@ // checkDeprecated() // requireNotRemoved() // requireExtensions() +// extensionRequires() // // Typically, only the first two calls are needed. They go into a code path that // implements Feature F, and will log the proper error/warning messages. Parsing @@ -77,9 +79,11 @@ // const char* const XXX_extension_X = "XXX_extension_X"; // // 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(), -// the first function below: +// the first function below and optionally a entry to extensionData for additional +// error checks: // // extensionBehavior[XXX_extension_X] = EBhDisable; +// (Optional) exts[] = {XXX_extension_X, EShTargetSpv_1_4} // // 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble(): // @@ -139,6 +143,8 @@ // set of extensions that both enable them and are necessary, given the version of the symbol // table. (There is a different symbol table for each version.) // +// 7) If the extension has additional requirements like minimum SPIR-V version required, add them +// to extensionRequires() #include "parseVersions.h" #include "localintermediate.h" @@ -154,6 +160,22 @@ namespace glslang { // void TParseVersions::initializeExtensionBehavior() { + typedef struct { + const char *const extensionName; + EShTargetLanguageVersion minSpvVersion; + } extensionData; + + const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4}, + {E_GL_NV_ray_tracing_motion_blur, EShTargetSpv_1_4} + }; + + for (size_t ii = 0; ii < sizeof(exts) / sizeof(exts[0]); ii++) { + // Add only extensions which require > spv1.0 to save space in map + if (exts[ii].minSpvVersion > EShTargetSpv_1_0) { + extensionMinSpv[exts[ii].extensionName] = exts[ii].minSpvVersion; + } + } + extensionBehavior[E_GL_OES_texture_3D] = EBhDisable; extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable; extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable; @@ -178,12 +200,14 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable; extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable; extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable; + extensionBehavior[E_GL_ARB_shader_atomic_counter_ops] = EBhDisable; extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable; extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable; extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable; extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable; extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable; extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable; + extensionBehavior[E_GL_ARB_gpu_shader_fp64] = EBhDisable; extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable; extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable; extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable; @@ -195,6 +219,12 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable; extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable; extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable; + extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable; + extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable; + extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = EBhDisable; + extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable; + extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable; + extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; @@ -220,9 +250,11 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable; extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable; extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable; + extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable; extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; + extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable; // #line and #include extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable; @@ -252,6 +284,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable; extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable; extensionBehavior[E_GL_NV_ray_tracing] = EBhDisable; + extensionBehavior[E_GL_NV_ray_tracing_motion_blur] = EBhDisable; extensionBehavior[E_GL_NV_fragment_shader_barycentric] = EBhDisable; extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable; extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable; @@ -277,6 +310,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable; extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable; extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable; + extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable; // OES matching AEP extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable; @@ -288,11 +322,22 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable; extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable; extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable; // EXT extensions - extensionBehavior[E_GL_EXT_device_group] = EBhDisable; - extensionBehavior[E_GL_EXT_multiview] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable; + extensionBehavior[E_GL_EXT_device_group] = EBhDisable; + extensionBehavior[E_GL_EXT_multiview] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable; + extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable; + extensionBehavior[E_GL_EXT_ray_query] = EBhDisable; + extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable; + extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable; + extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable; + extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable; + extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable; + extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable; // OVR extensions extensionBehavior[E_GL_OVR_multiview] = EBhDisable; @@ -313,7 +358,10 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = EBhDisable; extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = EBhDisable; extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable; + extensionBehavior[E_GL_EXT_shader_atomic_float2] = EBhDisable; } + #endif // GLSLANG_WEB // Get code that is not part of a shared symbol table, is specific to this shader, @@ -335,10 +383,10 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_YUV_target 1\n" "#define GL_EXT_shader_texture_lod 1\n" "#define GL_EXT_shadow_samplers 1\n" + "#define GL_EXT_fragment_shading_rate 1\n" // AEP "#define GL_ANDROID_extension_pack_es31a 1\n" - "#define GL_KHR_blend_equation_advanced 1\n" "#define GL_OES_sample_variables 1\n" "#define GL_OES_shader_image_atomic 1\n" "#define GL_OES_shader_multisample_interpolation 1\n" @@ -352,6 +400,9 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_tessellation_point_size 1\n" "#define GL_EXT_texture_buffer 1\n" "#define GL_EXT_texture_cube_map_array 1\n" + "#define GL_EXT_shader_implicit_conversions 1\n" + "#define GL_EXT_shader_integer_mix 1\n" + "#define GL_EXT_blend_func_extended 1\n" // OES matching AEP "#define GL_OES_geometry_shader 1\n" @@ -366,11 +417,15 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_shader_non_constant_global_initializers 1\n" ; - if (isEsProfile() && version >= 300) { + if (version >= 300) { preamble += "#define GL_NV_shader_noperspective_interpolation 1\n"; } + if (version >= 310) { + preamble += "#define GL_EXT_null_initializer 1\n"; + preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; + } - } else { + } else { // !isEsProfile() preamble = "#define GL_FRAGMENT_PRECISION_HIGH 1\n" "#define GL_ARB_texture_rectangle 1\n" @@ -394,15 +449,22 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_shader_texture_image_samples 1\n" "#define GL_ARB_viewport_array 1\n" "#define GL_ARB_gpu_shader_int64 1\n" + "#define GL_ARB_gpu_shader_fp64 1\n" "#define GL_ARB_shader_ballot 1\n" "#define GL_ARB_sparse_texture2 1\n" "#define GL_ARB_sparse_texture_clamp 1\n" "#define GL_ARB_shader_stencil_export 1\n" "#define GL_ARB_sample_shading 1\n" + "#define GL_ARB_shader_image_size 1\n" + "#define GL_ARB_shading_language_packing 1\n" // "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members "#define GL_ARB_post_depth_coverage 1\n" "#define GL_ARB_fragment_shader_interlock 1\n" "#define GL_ARB_uniform_buffer_object 1\n" + "#define GL_ARB_shader_bit_encoding 1\n" + "#define GL_ARB_shader_storage_buffer_object 1\n" + "#define GL_ARB_texture_query_lod 1\n" + "#define GL_ARB_vertex_attrib_64bit 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n" "#define GL_EXT_shader_image_load_formatted 1\n" "#define GL_EXT_post_depth_coverage 1\n" @@ -417,6 +479,9 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_buffer_reference2 1\n" "#define GL_EXT_buffer_reference_uvec2 1\n" "#define GL_EXT_demote_to_helper_invocation 1\n" + "#define GL_EXT_debug_printf 1\n" + "#define GL_EXT_fragment_shading_rate 1\n" + "#define GL_EXT_shared_memory_block 1\n" // GL_KHR_shader_subgroup "#define GL_KHR_shader_subgroup_basic 1\n" @@ -428,8 +493,13 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_KHR_shader_subgroup_clustered 1\n" "#define GL_KHR_shader_subgroup_quad 1\n" - "#define E_GL_EXT_shader_atomic_int64 1\n" - "#define E_GL_EXT_shader_realtime_clock 1\n" + "#define GL_EXT_shader_image_int64 1\n" + "#define GL_EXT_shader_atomic_int64 1\n" + "#define GL_EXT_shader_realtime_clock 1\n" + "#define GL_EXT_ray_tracing 1\n" + "#define GL_EXT_ray_query 1\n" + "#define GL_EXT_ray_flags_primitive_culling 1\n" + "#define GL_EXT_spirv_intrinsics 1\n" "#define GL_AMD_shader_ballot 1\n" "#define GL_AMD_shader_trinary_minmax 1\n" @@ -452,6 +522,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_NV_shader_subgroup_partitioned 1\n" "#define GL_NV_shading_rate_image 1\n" "#define GL_NV_ray_tracing 1\n" + "#define GL_NV_ray_tracing_motion_blur 1\n" "#define GL_NV_fragment_shader_barycentric 1\n" "#define GL_NV_compute_shader_derivatives 1\n" "#define GL_NV_shader_texture_footprint 1\n" @@ -472,6 +543,9 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_shader_subgroup_extended_types_int16 1\n" "#define GL_EXT_shader_subgroup_extended_types_int64 1\n" "#define GL_EXT_shader_subgroup_extended_types_float16 1\n" + + "#define GL_EXT_shader_atomic_float 1\n" + "#define GL_EXT_shader_atomic_float2 1\n" ; if (version >= 150) { @@ -481,6 +555,10 @@ void TParseVersions::getPreamble(std::string& preamble) if (profile == ECompatibilityProfile) preamble += "#define GL_compatibility_profile 1\n"; } + if (version >= 140) { + preamble += "#define GL_EXT_null_initializer 1\n"; + preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; + } #endif // GLSLANG_WEB } @@ -505,6 +583,12 @@ void TParseVersions::getPreamble(std::string& preamble) preamble += "#define GL_GOOGLE_cpp_style_line_directive 1\n" "#define GL_GOOGLE_include_directive 1\n" + "#define GL_KHR_blend_equation_advanced 1\n" + ; + + // other general extensions + preamble += + "#define GL_EXT_terminate_invocation 1\n" ; #endif @@ -527,6 +611,29 @@ void TParseVersions::getPreamble(std::string& preamble) preamble += "\n"; } #endif + +#ifndef GLSLANG_WEB + // GL_EXT_spirv_intrinsics + if (!isEsProfile()) { + switch (language) { + case EShLangVertex: preamble += "#define GL_VERTEX_SHADER 1 \n"; break; + case EShLangTessControl: preamble += "#define GL_TESSELLATION_CONTROL_SHADER 1 \n"; break; + case EShLangTessEvaluation: preamble += "#define GL_TESSELLATION_EVALUATION_SHADER 1 \n"; break; + case EShLangGeometry: preamble += "#define GL_GEOMETRY_SHADER 1 \n"; break; + case EShLangFragment: preamble += "#define GL_FRAGMENT_SHADER 1 \n"; break; + case EShLangCompute: preamble += "#define GL_COMPUTE_SHADER 1 \n"; break; + case EShLangRayGen: preamble += "#define GL_RAY_GENERATION_SHADER_EXT 1 \n"; break; + case EShLangIntersect: preamble += "#define GL_INTERSECTION_SHADER_EXT 1 \n"; break; + case EShLangAnyHit: preamble += "#define GL_ANY_HIT_SHADER_EXT 1 \n"; break; + case EShLangClosestHit: preamble += "#define GL_CLOSEST_HIT_SHADER_EXT 1 \n"; break; + case EShLangMiss: preamble += "#define GL_MISS_SHADER_EXT 1 \n"; break; + case EShLangCallable: preamble += "#define GL_CALLABLE_SHADER_EXT 1 \n"; break; + case EShLangTaskNV: preamble += "#define GL_TASK_SHADER_NV 1 \n"; break; + case EShLangMeshNV: preamble += "#define GL_MESH_SHADER_NV 1 \n"; break; + default: break; + } + } +#endif } // @@ -542,12 +649,12 @@ const char* StageName(EShLanguage stage) case EShLangTessControl: return "tessellation control"; case EShLangTessEvaluation: return "tessellation evaluation"; case EShLangGeometry: return "geometry"; - case EShLangRayGenNV: return "ray-generation"; - case EShLangIntersectNV: return "intersection"; - case EShLangAnyHitNV: return "any-hit"; - case EShLangClosestHitNV: return "closest-hit"; - case EShLangMissNV: return "miss"; - case EShLangCallableNV: return "callable"; + case EShLangRayGen: return "ray-generation"; + case EShLangIntersect: return "intersection"; + case EShLangAnyHit: return "any-hit"; + case EShLangClosestHit: return "closest-hit"; + case EShLangMiss: return "miss"; + case EShLangCallable: return "callable"; case EShLangMeshNV: return "mesh"; case EShLangTaskNV: return "task"; #endif @@ -710,7 +817,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte // Use when there are no profile/version to check, it's just an error if one of the // extensions is not present. // -void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) +void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], + const char* featureDesc) { if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return; @@ -729,7 +837,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, // Use by preprocessor when there are no profile/version to check, it's just an error if one of the // extensions is not present. // -void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) +void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], + const char* featureDesc) { if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return; @@ -795,10 +904,14 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString); return; } + bool on = behavior != EBhDisable; // check if extension is used with correct shader stage checkExtensionStage(getCurrentLoc(), extension); + // check if extension has additional requirements + extensionRequires(getCurrentLoc(), extension, behaviorString); + // update the requested extension updateExtensionBehavior(extension, behavior); @@ -861,6 +974,32 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString); else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0) updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString); + + // see if we need to update the numeric features + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int8") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int8, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int16") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int16, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int32") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int32, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int64") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int64, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float16") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float16, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float32") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float32, on); + else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float64") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float64, on); + else if (strcmp(extension, "GL_EXT_shader_implicit_conversions") == 0) + intermediate.updateNumericFeature(TNumericFeatures::shader_implicit_conversions, on); + else if (strcmp(extension, "GL_ARB_gpu_shader_fp64") == 0) + intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_fp64, on); + else if (strcmp(extension, "GL_AMD_gpu_shader_int16") == 0) + intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_int16, on); + else if (strcmp(extension, "GL_AMD_gpu_shader_half_float") == 0) + intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_half_float, on); } void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior) @@ -896,7 +1035,7 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe } else { if (iter->second == EBhDisablePartial) warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension); - if (behavior == EBhEnable || behavior == EBhRequire) + if (behavior != EBhDisable) intermediate.addRequestedExtension(extension); iter->second = behavior; } @@ -915,6 +1054,24 @@ void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * con } } +// Check if extension has additional requirements +void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const extension, const char *behaviorString) +{ + bool isEnabled = false; + if (!strcmp("require", behaviorString)) + isEnabled = true; + else if (!strcmp("enable", behaviorString)) + isEnabled = true; + + if (isEnabled) { + unsigned int minSpvVersion = 0; + auto iter = extensionMinSpv.find(TString(extension)); + if (iter != extensionMinSpv.end()) + minSpvVersion = iter->second; + requireSpv(loc, extension, minSpvVersion); + } +} + // Call for any operation needing full GLSL integer data-type support. void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) { @@ -925,8 +1082,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) // Call for any operation needing GLSL double data-type support. void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); + + //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); + if (language == EShLangVertex) { + const char* const f64_Extensions[] = {E_GL_ARB_gpu_shader_fp64, E_GL_ARB_vertex_attrib_64bit}; + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, 2, f64_Extensions, op); + } else + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op); } // Call for any operation needing GLSL float16 data-type support. @@ -1146,7 +1308,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op) // Call for any operation removed because Vulkan SPIR-V is being generated. void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op) { - if (spvVersion.vulkan > 0) + if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed) error(loc, "not allowed when using GLSL for Vulkan", op, ""); } @@ -1167,5 +1329,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op) error(loc, "only allowed when generating SPIR-V", op, ""); #endif } +void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version) +{ +#ifndef GLSLANG_WEB + if (spvVersion.spv < version) + error(loc, "not supported for current targeted SPIR-V version", op, ""); +#endif +} } // end namespace glslang diff --git a/libraries/glslang/glslang/MachineIndependent/Versions.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.h similarity index 88% rename from libraries/glslang/glslang/MachineIndependent/Versions.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.h index d319a2d54..949a7a173 100644 --- a/libraries/glslang/glslang/MachineIndependent/Versions.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/Versions.h @@ -3,6 +3,7 @@ // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -35,9 +36,12 @@ // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // + #ifndef _VERSIONS_INCLUDED_ #define _VERSIONS_INCLUDED_ +#define LAST_ELEMENT_MARKER(x) x + // // Help manage multiple profiles, versions, extensions etc. // @@ -49,12 +53,13 @@ // Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible // defects from mixing the two different forms. // -typedef enum { +typedef enum : unsigned { EBadProfile = 0, ENoProfile = (1 << 0), // only for desktop, before profiles showed up ECoreProfile = (1 << 1), ECompatibilityProfile = (1 << 2), - EEsProfile = (1 << 3) + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), } EProfile; namespace glslang { @@ -82,11 +87,12 @@ inline const char* ProfileName(EProfile profile) // The union of all requested rule sets will be applied. // struct SpvVersion { - SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {} unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" + bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target }; // @@ -130,12 +136,14 @@ const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attri const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_atomic_counter_ops = "GL_ARB_shader_atomic_counter_ops"; const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; @@ -147,6 +155,12 @@ const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shade const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; +const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit"; const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; @@ -181,6 +195,18 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; +const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended"; +const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions"; +const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate"; +const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64"; +const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer"; +const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block"; +const char* const E_GL_EXT_subgroup_uniform_control_flow = "GL_EXT_subgroup_uniform_control_flow"; +const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intrinsics"; // Arrays of extensions for the above viewportEXTs duplications @@ -222,6 +248,7 @@ const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_ const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_ray_tracing_motion_blur = "GL_NV_ray_tracing_motion_blur"; const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; @@ -252,6 +279,7 @@ const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessel const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; +const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix"; // OES matching AEP const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; @@ -278,6 +306,10 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; +const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation"; + +const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float"; +const char* const E_GL_EXT_shader_atomic_float2 = "GL_EXT_shader_atomic_float2"; // Arrays of extensions for the above AEP duplications diff --git a/libraries/glslang/glslang/MachineIndependent/attribute.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.cpp similarity index 93% rename from libraries/glslang/glslang/MachineIndependent/attribute.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.cpp index 958551834..8a92f6ae0 100644 --- a/libraries/glslang/glslang/MachineIndependent/attribute.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.cpp @@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const return EatPeelCount; else if (name == "partial_count") return EatPartialCount; + else if (name == "subgroup_uniform_control_flow") + return EatSubgroupUniformControlFlow; else return EatNone; } @@ -341,6 +343,29 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN } } + +// +// Function attributes +// +void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes, TFunction* function) +{ + for (auto it = attributes.begin(); it != attributes.end(); ++it) { + if (it->size() > 0) { + warn(loc, "attribute with arguments not recognized, skipping", "", ""); + continue; + } + + switch (it->name) { + case EatSubgroupUniformControlFlow: + intermediate.setSubgroupUniformControlFlow(); + break; + default: + warn(loc, "attribute does not apply to a function", "", ""); + break; + } + } +} + } // end namespace glslang #endif // GLSLANG_WEB diff --git a/libraries/glslang/glslang/MachineIndependent/attribute.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.h similarity index 98% rename from libraries/glslang/glslang/MachineIndependent/attribute.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.h index 38a943d28..c5b29176c 100644 --- a/libraries/glslang/glslang/MachineIndependent/attribute.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/attribute.h @@ -118,7 +118,8 @@ namespace glslang { EatFormatR8ui, EatFormatUnknown, EatNonWritable, - EatNonReadable + EatNonReadable, + EatSubgroupUniformControlFlow, }; class TIntermAggregate; diff --git a/libraries/glslang/glslang/MachineIndependent/gl_types.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/gl_types.h similarity index 95% rename from libraries/glslang/glslang/MachineIndependent/gl_types.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/gl_types.h index b6f613bce..d6c939374 100644 --- a/libraries/glslang/glslang/MachineIndependent/gl_types.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/gl_types.h @@ -49,9 +49,17 @@ #define GL_INT64_VEC4_ARB 0x8FEB #define GL_UNSIGNED_INT64_ARB 0x140F -#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 -#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 -#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 + +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 #define GL_BOOL 0x8B56 #define GL_BOOL_VEC2 0x8B57 diff --git a/libraries/glslang/glslang/MachineIndependent/glslang.m4 b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.m4 similarity index 82% rename from libraries/glslang/glslang/MachineIndependent/glslang.m4 rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.m4 index 20f2ba40d..93041ce39 100644 --- a/libraries/glslang/glslang/MachineIndependent/glslang.m4 +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.m4 @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2019 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -115,6 +116,9 @@ using namespace glslang; glslang::TIntermNodePair nodePair; glslang::TIntermTyped* intermTypedNode; glslang::TAttributes* attributes; + glslang::TSpirvRequirement* spirvReq; + glslang::TSpirvInstruction* spirvInst; + glslang::TSpirvTypeParameters* spirvTypeParams; }; union { glslang::TPublicType type; @@ -204,6 +208,8 @@ GLSLANG_WEB_EXCLUDE_ON %token F64MAT4X2 F64MAT4X3 F64MAT4X4 %token ATOMIC_UINT %token ACCSTRUCTNV +%token ACCSTRUCTEXT +%token RAYQUERYEXT %token FCOOPMATNV ICOOPMATNV UCOOPMATNV // combined image/sampler @@ -239,6 +245,18 @@ GLSLANG_WEB_EXCLUDE_ON %token F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY %token F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY +%token I64IMAGE1D U64IMAGE1D +%token I64IMAGE2D U64IMAGE2D +%token I64IMAGE3D U64IMAGE3D +%token I64IMAGE2DRECT U64IMAGE2DRECT +%token I64IMAGECUBE U64IMAGECUBE +%token I64IMAGEBUFFER U64IMAGEBUFFER +%token I64IMAGE1DARRAY U64IMAGE1DARRAY +%token I64IMAGE2DARRAY U64IMAGE2DARRAY +%token I64IMAGECUBEARRAY U64IMAGECUBEARRAY +%token I64IMAGE2DMS U64IMAGE2DMS +%token I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY + // texture without sampler %token TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY %token TEXTURE1D ITEXTURE1D UTEXTURE1D @@ -256,6 +274,11 @@ GLSLANG_WEB_EXCLUDE_ON %token SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS %token F16SUBPASSINPUT F16SUBPASSINPUTMS +// spirv intrinsics +%token SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID +%token SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING +%token SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL + GLSLANG_WEB_EXCLUDE_OFF %token LEFT_OP RIGHT_OP @@ -263,6 +286,7 @@ GLSLANG_WEB_EXCLUDE_OFF %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token SUB_ASSIGN +%token STRING_LITERAL %token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT @@ -277,6 +301,8 @@ GLSLANG_WEB_EXCLUDE_OFF %token CENTROID IN OUT INOUT %token STRUCT VOID WHILE %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT +%token TERMINATE_INVOCATION +%token TERMINATE_RAY IGNORE_INTERSECTION %token UNIFORM SHARED BUFFER %token FLAT SMOOTH LAYOUT @@ -285,9 +311,10 @@ GLSLANG_WEB_EXCLUDE_ON %token INT64CONSTANT UINT64CONSTANT %token SUBROUTINE DEMOTE %token PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV +%token PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT %token PATCH SAMPLE NONUNIFORM %token COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT -%token SUBGROUPCOHERENT NONPRIVATE +%token SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token PRECISE GLSLANG_WEB_EXCLUDE_OFF @@ -343,6 +370,19 @@ GLSLANG_WEB_EXCLUDE_ON %type attribute attribute_list single_attribute %type demote_statement %type initializer_list +%type spirv_requirements_list spirv_requirements_parameter +%type spirv_extension_list spirv_capability_list +%type spirv_execution_mode_qualifier +%type spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list +%type spirv_storage_class_qualifier +%type spirv_decorate_qualifier +%type spirv_decorate_parameter_list spirv_decorate_parameter +%type spirv_decorate_id_parameter_list +%type spirv_decorate_string_parameter_list +%type spirv_type_specifier +%type spirv_type_parameter_list spirv_type_parameter +%type spirv_instruction_qualifier +%type spirv_instruction_qualifier_list spirv_instruction_qualifier_id GLSLANG_WEB_EXCLUDE_OFF %start translation_unit @@ -377,6 +417,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); } GLSLANG_WEB_EXCLUDE_ON + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } | INT32CONSTANT { parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); @@ -402,7 +445,9 @@ GLSLANG_WEB_EXCLUDE_ON $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); } | DOUBLECONSTANT { - parseContext.doubleCheck($1.loc, "double literal"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double literal"); $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); } | FLOAT16CONSTANT { @@ -768,7 +813,7 @@ assignment_expression parseContext.specializationCheck($2.loc, $1->getType(), "="); parseContext.lValueErrorCheck($2.loc, "assign", $1); parseContext.rValueErrorCheck($2.loc, "assign", $3); - $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc); + $$ = parseContext.addAssign($2.loc, $2.op, $1, $3); if ($$ == 0) { parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString()); $$ = $1; @@ -851,6 +896,20 @@ declaration $$ = 0; // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature } +GLSLANG_WEB_EXCLUDE_ON + | spirv_instruction_qualifier function_prototype SEMICOLON { + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); + $2.function->setSpirvInstruction(*$1); // Attach SPIR-V intruction qualifier + parseContext.handleFunctionDeclarator($2.loc, *$2.function, true /* prototype */); + $$ = 0; + // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature + } + | spirv_execution_mode_qualifier SEMICOLON { + parseContext.globalCheck($2.loc, "SPIR-V execution mode qualifier"); + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); + $$ = 0; + } +GLSLANG_WEB_EXCLUDE_OFF | init_declarator_list SEMICOLON { if ($1.intermNode && $1.intermNode->getAsAggregate()) $1.intermNode->getAsAggregate()->setOperator(EOpSequence); @@ -895,7 +954,7 @@ declaration block_structure : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - --parseContext.structNestingLevel; + --parseContext.blockNestingLevel; parseContext.blockName = $2.string; parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); @@ -920,6 +979,25 @@ function_prototype $$.function = $1; $$.loc = $2.loc; } + | function_declarator RIGHT_PAREN attribute { + $$.function = $1; + $$.loc = $2.loc; + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($2.loc, *$3, $$.function); + } + | attribute function_declarator RIGHT_PAREN { + $$.function = $2; + $$.loc = $3.loc; + parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); + } + | attribute function_declarator RIGHT_PAREN attribute { + $$.function = $2; + $$.loc = $3.loc; + parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); + parseContext.handleFunctionAttributes($3.loc, *$4, $$.function); + } ; function_declarator @@ -1323,6 +1401,25 @@ GLSLANG_WEB_EXCLUDE_ON | non_uniform_qualifier { $$ = $1; } + | spirv_storage_class_qualifier { + parseContext.globalCheck($1.loc, "spirv_storage_class"); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); + $$ = $1; + } + | spirv_decorate_qualifier { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); + $$ = $1; + } + | SPIRV_BY_REFERENCE { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); + $$.init($1.loc); + $$.qualifier.setSpirvByReference(); + } + | SPIRV_LITERAL { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); + $$.init($1.loc); + $$.qualifier.setSpirvLiteral(); + } GLSLANG_WEB_EXCLUDE_OFF ; @@ -1413,42 +1510,81 @@ GLSLANG_WEB_EXCLUDE_ON } | HITATTRNV { parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); $$.init($1.loc); - $$.qualifier.storage = EvqHitAttrNV; + $$.qualifier.storage = EvqHitAttr; + } + | HITATTREXT { + parseContext.globalCheck($1.loc, "hitAttributeEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + $$.init($1.loc); + $$.qualifier.storage = EvqHitAttr; } | PAYLOADNV { parseContext.globalCheck($1.loc, "rayPayloadNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadNV; + $$.qualifier.storage = EvqPayload; + } + | PAYLOADEXT { + parseContext.globalCheck($1.loc, "rayPayloadEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayload; } | PAYLOADINNV { parseContext.globalCheck($1.loc, "rayPayloadInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadInNV; + $$.qualifier.storage = EvqPayloadIn; + } + | PAYLOADINEXT { + parseContext.globalCheck($1.loc, "rayPayloadInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayloadIn; } | CALLDATANV { parseContext.globalCheck($1.loc, "callableDataNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataNV; + $$.qualifier.storage = EvqCallableData; + } + | CALLDATAEXT { + parseContext.globalCheck($1.loc, "callableDataEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableData; } | CALLDATAINNV { parseContext.globalCheck($1.loc, "callableDataInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataInNV; + $$.qualifier.storage = EvqCallableDataIn; + } + | CALLDATAINEXT { + parseContext.globalCheck($1.loc, "callableDataInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableDataIn; } | COHERENT { $$.init($1.loc); @@ -1479,6 +1615,11 @@ GLSLANG_WEB_EXCLUDE_ON parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); $$.qualifier.nonprivate = true; } + | SHADERCALLCOHERENT { + $$.init($1.loc); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + $$.qualifier.shadercallcoherent = true; + } | VOLATILE { $$.init($1.loc); $$.qualifier.volatil = true; @@ -1751,7 +1892,9 @@ type_specifier_nonarray } GLSLANG_WEB_EXCLUDE_ON | DOUBLE { - parseContext.doubleCheck($1.loc, "double"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; } @@ -1811,19 +1954,25 @@ GLSLANG_WEB_EXCLUDE_ON $$.basicType = EbtUint64; } | DVEC2 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(2); } | DVEC3 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(3); } | DVEC4 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(4); @@ -2027,73 +2176,97 @@ GLSLANG_WEB_EXCLUDE_ON $$.setVector(4); } | DMAT2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); } | DMAT2X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT2X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 3); } | DMAT2X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 4); } | DMAT3X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 2); } | DMAT3X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT3X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 4); } | DMAT4X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 2); } | DMAT4X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 3); } | DMAT4X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); @@ -2316,7 +2489,15 @@ GLSLANG_WEB_EXCLUDE_ON } | ACCSTRUCTNV { $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStructNV; + $$.basicType = EbtAccStruct; + } + | ACCSTRUCTEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtAccStruct; + } + | RAYQUERYEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtRayQuery; } | ATOMIC_UINT { parseContext.vulkanRemoved($1.loc, "atomic counter types"); @@ -3109,6 +3290,116 @@ GLSLANG_WEB_EXCLUDE_ON $$.basicType = EbtSampler; $$.sampler.setImage(EbtUint, Esd2D, true, false, true); } + | I64IMAGE1D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd1D); + } + | U64IMAGE1D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd1D); + } + | I64IMAGE2D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D); + } + | U64IMAGE2D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D); + } + | I64IMAGE3D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd3D); + } + | U64IMAGE3D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd3D); + } + | I64IMAGE2DRECT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdRect); + } + | U64IMAGE2DRECT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdRect); + } + | I64IMAGECUBE { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdCube); + } + | U64IMAGECUBE { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdCube); + } + | I64IMAGEBUFFER { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdBuffer); + } + | U64IMAGEBUFFER { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdBuffer); + } + | I64IMAGE1DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd1D, true); + } + | U64IMAGE1DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd1D, true); + } + | I64IMAGE2DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, true); + } + | U64IMAGE2DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, true); + } + | I64IMAGECUBEARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdCube, true); + } + | U64IMAGECUBEARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdCube, true); + } + | I64IMAGE2DMS { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, false, false, true); + } + | U64IMAGE2DMS { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, false, false, true); + } + | I64IMAGE2DMSARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, true, false, true); + } + | U64IMAGE2DMSARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, true, false, true); + } | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtSampler; @@ -3189,6 +3480,10 @@ GLSLANG_WEB_EXCLUDE_ON $$.basicType = EbtUint; $$.coopmat = true; } + | spirv_type_specifier { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); + $$ = $1; + } GLSLANG_WEB_EXCLUDE_OFF | struct_specifier { $$ = $1; @@ -3357,6 +3652,12 @@ GLSLANG_WEB_EXCLUDE_ON parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); $$ = $2; } + | LEFT_BRACE RIGHT_BRACE { + const char* initFeature = "empty { } initializer"; + parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + parseContext.profileRequires($1.loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + $$ = parseContext.intermediate.makeAggregate($1.loc); + } GLSLANG_WEB_EXCLUDE_OFF ; @@ -3489,6 +3790,7 @@ selection_statement } GLSLANG_WEB_EXCLUDE_ON | attribute selection_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSelectionAttributes(*$1, $2); $$ = $2; } @@ -3536,6 +3838,7 @@ switch_statement } GLSLANG_WEB_EXCLUDE_ON | attribute switch_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSwitchAttributes(*$1, $2); $$ = $2; } @@ -3600,6 +3903,7 @@ iteration_statement } GLSLANG_WEB_EXCLUDE_ON | attribute iteration_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleLoopAttributes(*$1, $2); $$ = $2; } @@ -3711,6 +4015,20 @@ jump_statement parseContext.requireStage($1.loc, EShLangFragment, "discard"); $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); } + | TERMINATE_INVOCATION SEMICOLON { + parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation"); + $$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc); + } +GLSLANG_WEB_EXCLUDE_ON + | TERMINATE_RAY SEMICOLON { + parseContext.requireStage($1.loc, EShLangAnyHit, "terminateRayEXT"); + $$ = parseContext.intermediate.addBranch(EOpTerminateRayKHR, $1.loc); + } + | IGNORE_INTERSECTION SEMICOLON { + parseContext.requireStage($1.loc, EShLangAnyHit, "ignoreIntersectionEXT"); + $$ = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, $1.loc); + } +GLSLANG_WEB_EXCLUDE_OFF ; // Grammar Note: No 'goto'. Gotos are not supported. @@ -3748,6 +4066,14 @@ function_definition : function_prototype { $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.push(); + ++parseContext.statementNestingLevel; + } } compound_statement_no_new_scope { // May be best done as post process phase on intermediate code @@ -3763,6 +4089,17 @@ function_definition $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); $$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); + + // Set currentFunctionType to empty pointer when goes outside of the function + parseContext.currentFunctionType = nullptr; + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + } } ; @@ -3770,7 +4107,6 @@ GLSLANG_WEB_EXCLUDE_ON attribute : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { $$ = $3; - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); } attribute_list @@ -3790,4 +4126,273 @@ single_attribute } GLSLANG_WEB_EXCLUDE_OFF +GLSLANG_WEB_EXCLUDE_ON +spirv_requirements_list + : spirv_requirements_parameter { + $$ = $1; + } + | spirv_requirements_list COMMA spirv_requirements_parameter { + $$ = parseContext.mergeSpirvRequirements($2.loc, $1, $3); + } + +spirv_requirements_parameter + : IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET { + $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, $4->getAsAggregate(), nullptr); + } + | IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET { + $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, nullptr, $4->getAsAggregate()); + } + +spirv_extension_list + : STRING_LITERAL { + $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); + } + | spirv_extension_list COMMA STRING_LITERAL { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); + } + +spirv_capability_list + : INTCONSTANT { + $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.i, $1.loc, true)); + } + | spirv_capability_list COMMA INTCONSTANT { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.i, $3.loc, true)); + } + +spirv_execution_mode_qualifier + : SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionMode($3.i); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionMode($5.i); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionMode($3.i, $5->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionMode($5.i, $7->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionModeId($3.i, $5->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionModeId($5.i, $7->getAsAggregate()); + $$ = 0; + } + +spirv_execution_mode_parameter_list + : spirv_execution_mode_parameter { + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter { + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_execution_mode_parameter + : FLOATCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); + } + | INTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); + } + | UINTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); + } + | BOOLCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); + } + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } + +spirv_execution_mode_id_parameter_list + : constant_expression { + if ($1->getBasicType() != EbtFloat && + $1->getBasicType() != EbtInt && + $1->getBasicType() != EbtUint && + $1->getBasicType() != EbtBool && + $1->getBasicType() != EbtString) + parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), ""); + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_execution_mode_id_parameter_list COMMA constant_expression { + if ($3->getBasicType() != EbtFloat && + $3->getBasicType() != EbtInt && + $3->getBasicType() != EbtUint && + $3->getBasicType() != EbtBool && + $3->getBasicType() != EbtString) + parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), ""); + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_storage_class_qualifier + : SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.storage = EvqSpirvStorageClass; + $$.qualifier.spirvStorageClass = $3.i; + } + | SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.storage = EvqSpirvStorageClass; + $$.qualifier.spirvStorageClass = $5.i; + } + +spirv_decorate_qualifier + : SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN{ + $$.init($1.loc); + $$.qualifier.setSpirvDecorate($3.i); + } + | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN{ + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorate($5.i); + } + | SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorate($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorate($5.i, $7->getAsAggregate()); + } + | SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorateId($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorateId($5.i, $7->getAsAggregate()); + } + | SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorateString($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorateString($5.i, $7->getAsAggregate()); + } + +spirv_decorate_parameter_list + : spirv_decorate_parameter { + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_decorate_parameter_list COMMA spirv_decorate_parameter { + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_decorate_parameter + : FLOATCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); + } + | INTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); + } + | UINTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); + } + | BOOLCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); + } + +spirv_decorate_id_parameter_list + : constant_expression { + if ($1->getBasicType() != EbtFloat && + $1->getBasicType() != EbtInt && + $1->getBasicType() != EbtUint && + $1->getBasicType() != EbtBool) + parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), ""); + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_decorate_id_parameter_list COMMA constant_expression { + if ($3->getBasicType() != EbtFloat && + $3->getBasicType() != EbtInt && + $3->getBasicType() != EbtUint && + $3->getBasicType() != EbtBool) + parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), ""); + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_decorate_string_parameter_list + : STRING_LITERAL { + $$ = parseContext.intermediate.makeAggregate( + parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); + } + | spirv_decorate_string_parameter_list COMMA STRING_LITERAL { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); + } + +spirv_type_specifier + : SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.setSpirvType(*$3, $5); + } + | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement($3); + $$.setSpirvType(*$5, $7); + } + | SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.setSpirvType(*$3); + } + | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement($3); + $$.setSpirvType(*$5); + } + +spirv_type_parameter_list + : spirv_type_parameter { + $$ = $1; + } + | spirv_type_parameter_list COMMA spirv_type_parameter { + $$ = parseContext.mergeSpirvTypeParameters($1, $3); + } + +spirv_type_parameter + : constant_expression { + $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion()); + } + | type_specifier { + $$ = parseContext.makeSpirvTypeParameters($1); + } + +spirv_instruction_qualifier + : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { + $$ = $3; + } + | SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + $$ = $5; + } + +spirv_instruction_qualifier_list + : spirv_instruction_qualifier_id { + $$ = $1; + } + | spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id { + $$ = parseContext.mergeSpirvInstruction($2.loc, $1, $3); + } + +spirv_instruction_qualifier_id + : IDENTIFIER EQUAL STRING_LITERAL { + $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, *$3.string); + } + | IDENTIFIER EQUAL INTCONSTANT { + $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, $3.i); + } +GLSLANG_WEB_EXCLUDE_OFF + %% diff --git a/libraries/glslang/glslang/MachineIndependent/glslang.y b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.y similarity index 82% rename from libraries/glslang/glslang/MachineIndependent/glslang.y rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.y index e263f3d7a..b77f4617b 100644 --- a/libraries/glslang/glslang/MachineIndependent/glslang.y +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang.y @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2019 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -115,6 +116,9 @@ using namespace glslang; glslang::TIntermNodePair nodePair; glslang::TIntermTyped* intermTypedNode; glslang::TAttributes* attributes; + glslang::TSpirvRequirement* spirvReq; + glslang::TSpirvInstruction* spirvInst; + glslang::TSpirvTypeParameters* spirvTypeParams; }; union { glslang::TPublicType type; @@ -204,6 +208,8 @@ extern int yylex(YYSTYPE*, TParseContext&); %token F64MAT4X2 F64MAT4X3 F64MAT4X4 %token ATOMIC_UINT %token ACCSTRUCTNV +%token ACCSTRUCTEXT +%token RAYQUERYEXT %token FCOOPMATNV ICOOPMATNV UCOOPMATNV // combined image/sampler @@ -239,6 +245,18 @@ extern int yylex(YYSTYPE*, TParseContext&); %token F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY %token F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY +%token I64IMAGE1D U64IMAGE1D +%token I64IMAGE2D U64IMAGE2D +%token I64IMAGE3D U64IMAGE3D +%token I64IMAGE2DRECT U64IMAGE2DRECT +%token I64IMAGECUBE U64IMAGECUBE +%token I64IMAGEBUFFER U64IMAGEBUFFER +%token I64IMAGE1DARRAY U64IMAGE1DARRAY +%token I64IMAGE2DARRAY U64IMAGE2DARRAY +%token I64IMAGECUBEARRAY U64IMAGECUBEARRAY +%token I64IMAGE2DMS U64IMAGE2DMS +%token I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY + // texture without sampler %token TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY %token TEXTURE1D ITEXTURE1D UTEXTURE1D @@ -256,6 +274,11 @@ extern int yylex(YYSTYPE*, TParseContext&); %token SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS %token F16SUBPASSINPUT F16SUBPASSINPUTMS +// spirv intrinsics +%token SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID +%token SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING +%token SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL + %token LEFT_OP RIGHT_OP @@ -263,6 +286,7 @@ extern int yylex(YYSTYPE*, TParseContext&); %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token SUB_ASSIGN +%token STRING_LITERAL %token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT @@ -277,6 +301,8 @@ extern int yylex(YYSTYPE*, TParseContext&); %token CENTROID IN OUT INOUT %token STRUCT VOID WHILE %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT +%token TERMINATE_INVOCATION +%token TERMINATE_RAY IGNORE_INTERSECTION %token UNIFORM SHARED BUFFER %token FLAT SMOOTH LAYOUT @@ -285,9 +311,10 @@ extern int yylex(YYSTYPE*, TParseContext&); %token INT64CONSTANT UINT64CONSTANT %token SUBROUTINE DEMOTE %token PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV +%token PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT %token PATCH SAMPLE NONUNIFORM %token COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT -%token SUBGROUPCOHERENT NONPRIVATE +%token SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token PRECISE @@ -343,6 +370,19 @@ extern int yylex(YYSTYPE*, TParseContext&); %type attribute attribute_list single_attribute %type demote_statement %type initializer_list +%type spirv_requirements_list spirv_requirements_parameter +%type spirv_extension_list spirv_capability_list +%type spirv_execution_mode_qualifier +%type spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list +%type spirv_storage_class_qualifier +%type spirv_decorate_qualifier +%type spirv_decorate_parameter_list spirv_decorate_parameter +%type spirv_decorate_id_parameter_list +%type spirv_decorate_string_parameter_list +%type spirv_type_specifier +%type spirv_type_parameter_list spirv_type_parameter +%type spirv_instruction_qualifier +%type spirv_instruction_qualifier_list spirv_instruction_qualifier_id %start translation_unit @@ -377,6 +417,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); } + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } | INT32CONSTANT { parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); @@ -402,7 +445,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); } | DOUBLECONSTANT { - parseContext.doubleCheck($1.loc, "double literal"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double literal"); $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); } | FLOAT16CONSTANT { @@ -768,7 +813,7 @@ assignment_expression parseContext.specializationCheck($2.loc, $1->getType(), "="); parseContext.lValueErrorCheck($2.loc, "assign", $1); parseContext.rValueErrorCheck($2.loc, "assign", $3); - $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc); + $$ = parseContext.addAssign($2.loc, $2.op, $1, $3); if ($$ == 0) { parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString()); $$ = $1; @@ -851,6 +896,20 @@ declaration $$ = 0; // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature } + + | spirv_instruction_qualifier function_prototype SEMICOLON { + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); + $2.function->setSpirvInstruction(*$1); // Attach SPIR-V intruction qualifier + parseContext.handleFunctionDeclarator($2.loc, *$2.function, true /* prototype */); + $$ = 0; + // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature + } + | spirv_execution_mode_qualifier SEMICOLON { + parseContext.globalCheck($2.loc, "SPIR-V execution mode qualifier"); + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); + $$ = 0; + } + | init_declarator_list SEMICOLON { if ($1.intermNode && $1.intermNode->getAsAggregate()) $1.intermNode->getAsAggregate()->setOperator(EOpSequence); @@ -895,7 +954,7 @@ declaration block_structure : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - --parseContext.structNestingLevel; + --parseContext.blockNestingLevel; parseContext.blockName = $2.string; parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); @@ -920,6 +979,25 @@ function_prototype $$.function = $1; $$.loc = $2.loc; } + | function_declarator RIGHT_PAREN attribute { + $$.function = $1; + $$.loc = $2.loc; + parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($2.loc, *$3, $$.function); + } + | attribute function_declarator RIGHT_PAREN { + $$.function = $2; + $$.loc = $3.loc; + parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); + } + | attribute function_declarator RIGHT_PAREN attribute { + $$.function = $2; + $$.loc = $3.loc; + parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes($3.loc, *$1, $$.function); + parseContext.handleFunctionAttributes($3.loc, *$4, $$.function); + } ; function_declarator @@ -1323,6 +1401,25 @@ single_type_qualifier | non_uniform_qualifier { $$ = $1; } + | spirv_storage_class_qualifier { + parseContext.globalCheck($1.loc, "spirv_storage_class"); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); + $$ = $1; + } + | spirv_decorate_qualifier { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); + $$ = $1; + } + | SPIRV_BY_REFERENCE { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); + $$.init($1.loc); + $$.qualifier.setSpirvByReference(); + } + | SPIRV_LITERAL { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); + $$.init($1.loc); + $$.qualifier.setSpirvLiteral(); + } ; @@ -1413,42 +1510,81 @@ storage_qualifier } | HITATTRNV { parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); $$.init($1.loc); - $$.qualifier.storage = EvqHitAttrNV; + $$.qualifier.storage = EvqHitAttr; + } + | HITATTREXT { + parseContext.globalCheck($1.loc, "hitAttributeEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + $$.init($1.loc); + $$.qualifier.storage = EvqHitAttr; } | PAYLOADNV { parseContext.globalCheck($1.loc, "rayPayloadNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadNV; + $$.qualifier.storage = EvqPayload; + } + | PAYLOADEXT { + parseContext.globalCheck($1.loc, "rayPayloadEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayload; } | PAYLOADINNV { parseContext.globalCheck($1.loc, "rayPayloadInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadInNV; + $$.qualifier.storage = EvqPayloadIn; + } + | PAYLOADINEXT { + parseContext.globalCheck($1.loc, "rayPayloadInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayloadIn; } | CALLDATANV { parseContext.globalCheck($1.loc, "callableDataNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataNV; + $$.qualifier.storage = EvqCallableData; + } + | CALLDATAEXT { + parseContext.globalCheck($1.loc, "callableDataEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableData; } | CALLDATAINNV { parseContext.globalCheck($1.loc, "callableDataInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataInNV; + $$.qualifier.storage = EvqCallableDataIn; + } + | CALLDATAINEXT { + parseContext.globalCheck($1.loc, "callableDataInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableDataIn; } | COHERENT { $$.init($1.loc); @@ -1479,6 +1615,11 @@ storage_qualifier parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); $$.qualifier.nonprivate = true; } + | SHADERCALLCOHERENT { + $$.init($1.loc); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + $$.qualifier.shadercallcoherent = true; + } | VOLATILE { $$.init($1.loc); $$.qualifier.volatil = true; @@ -1751,7 +1892,9 @@ type_specifier_nonarray } | DOUBLE { - parseContext.doubleCheck($1.loc, "double"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; } @@ -1811,19 +1954,25 @@ type_specifier_nonarray $$.basicType = EbtUint64; } | DVEC2 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(2); } | DVEC3 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(3); } | DVEC4 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(4); @@ -2027,73 +2176,97 @@ type_specifier_nonarray $$.setVector(4); } | DMAT2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); } | DMAT2X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT2X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 3); } | DMAT2X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 4); } | DMAT3X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 2); } | DMAT3X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT3X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 4); } | DMAT4X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 2); } | DMAT4X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 3); } | DMAT4X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); @@ -2316,7 +2489,15 @@ type_specifier_nonarray } | ACCSTRUCTNV { $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStructNV; + $$.basicType = EbtAccStruct; + } + | ACCSTRUCTEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtAccStruct; + } + | RAYQUERYEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtRayQuery; } | ATOMIC_UINT { parseContext.vulkanRemoved($1.loc, "atomic counter types"); @@ -3109,6 +3290,116 @@ type_specifier_nonarray $$.basicType = EbtSampler; $$.sampler.setImage(EbtUint, Esd2D, true, false, true); } + | I64IMAGE1D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd1D); + } + | U64IMAGE1D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd1D); + } + | I64IMAGE2D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D); + } + | U64IMAGE2D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D); + } + | I64IMAGE3D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd3D); + } + | U64IMAGE3D { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd3D); + } + | I64IMAGE2DRECT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdRect); + } + | U64IMAGE2DRECT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdRect); + } + | I64IMAGECUBE { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdCube); + } + | U64IMAGECUBE { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdCube); + } + | I64IMAGEBUFFER { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdBuffer); + } + | U64IMAGEBUFFER { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdBuffer); + } + | I64IMAGE1DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd1D, true); + } + | U64IMAGE1DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd1D, true); + } + | I64IMAGE2DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, true); + } + | U64IMAGE2DARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, true); + } + | I64IMAGECUBEARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, EsdCube, true); + } + | U64IMAGECUBEARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, EsdCube, true); + } + | I64IMAGE2DMS { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, false, false, true); + } + | U64IMAGE2DMS { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, false, false, true); + } + | I64IMAGE2DMSARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtInt64, Esd2D, true, false, true); + } + | U64IMAGE2DMSARRAY { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtSampler; + $$.sampler.setImage(EbtUint64, Esd2D, true, false, true); + } | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtSampler; @@ -3189,6 +3480,10 @@ type_specifier_nonarray $$.basicType = EbtUint; $$.coopmat = true; } + | spirv_type_specifier { + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); + $$ = $1; + } | struct_specifier { $$ = $1; @@ -3357,6 +3652,12 @@ initializer parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); $$ = $2; } + | LEFT_BRACE RIGHT_BRACE { + const char* initFeature = "empty { } initializer"; + parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + parseContext.profileRequires($1.loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + $$ = parseContext.intermediate.makeAggregate($1.loc); + } ; @@ -3489,6 +3790,7 @@ selection_statement } | attribute selection_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSelectionAttributes(*$1, $2); $$ = $2; } @@ -3536,6 +3838,7 @@ switch_statement } | attribute switch_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleSwitchAttributes(*$1, $2); $$ = $2; } @@ -3600,6 +3903,7 @@ iteration_statement } | attribute iteration_statement_nonattributed { + parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); parseContext.handleLoopAttributes(*$1, $2); $$ = $2; } @@ -3711,6 +4015,20 @@ jump_statement parseContext.requireStage($1.loc, EShLangFragment, "discard"); $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); } + | TERMINATE_INVOCATION SEMICOLON { + parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation"); + $$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc); + } + + | TERMINATE_RAY SEMICOLON { + parseContext.requireStage($1.loc, EShLangAnyHit, "terminateRayEXT"); + $$ = parseContext.intermediate.addBranch(EOpTerminateRayKHR, $1.loc); + } + | IGNORE_INTERSECTION SEMICOLON { + parseContext.requireStage($1.loc, EShLangAnyHit, "ignoreIntersectionEXT"); + $$ = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, $1.loc); + } + ; // Grammar Note: No 'goto'. Gotos are not supported. @@ -3748,6 +4066,14 @@ function_definition : function_prototype { $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.push(); + ++parseContext.statementNestingLevel; + } } compound_statement_no_new_scope { // May be best done as post process phase on intermediate code @@ -3763,6 +4089,17 @@ function_definition $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); $$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); + + // Set currentFunctionType to empty pointer when goes outside of the function + parseContext.currentFunctionType = nullptr; + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + } } ; @@ -3770,7 +4107,6 @@ function_definition attribute : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { $$ = $3; - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); } attribute_list @@ -3790,4 +4126,273 @@ single_attribute } + +spirv_requirements_list + : spirv_requirements_parameter { + $$ = $1; + } + | spirv_requirements_list COMMA spirv_requirements_parameter { + $$ = parseContext.mergeSpirvRequirements($2.loc, $1, $3); + } + +spirv_requirements_parameter + : IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET { + $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, $4->getAsAggregate(), nullptr); + } + | IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET { + $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, nullptr, $4->getAsAggregate()); + } + +spirv_extension_list + : STRING_LITERAL { + $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); + } + | spirv_extension_list COMMA STRING_LITERAL { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); + } + +spirv_capability_list + : INTCONSTANT { + $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.i, $1.loc, true)); + } + | spirv_capability_list COMMA INTCONSTANT { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.i, $3.loc, true)); + } + +spirv_execution_mode_qualifier + : SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionMode($3.i); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionMode($5.i); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionMode($3.i, $5->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionMode($5.i, $7->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvExecutionModeId($3.i, $5->getAsAggregate()); + $$ = 0; + } + | SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + parseContext.intermediate.insertSpirvExecutionModeId($5.i, $7->getAsAggregate()); + $$ = 0; + } + +spirv_execution_mode_parameter_list + : spirv_execution_mode_parameter { + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter { + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_execution_mode_parameter + : FLOATCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); + } + | INTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); + } + | UINTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); + } + | BOOLCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); + } + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } + +spirv_execution_mode_id_parameter_list + : constant_expression { + if ($1->getBasicType() != EbtFloat && + $1->getBasicType() != EbtInt && + $1->getBasicType() != EbtUint && + $1->getBasicType() != EbtBool && + $1->getBasicType() != EbtString) + parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), ""); + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_execution_mode_id_parameter_list COMMA constant_expression { + if ($3->getBasicType() != EbtFloat && + $3->getBasicType() != EbtInt && + $3->getBasicType() != EbtUint && + $3->getBasicType() != EbtBool && + $3->getBasicType() != EbtString) + parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), ""); + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_storage_class_qualifier + : SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.storage = EvqSpirvStorageClass; + $$.qualifier.spirvStorageClass = $3.i; + } + | SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.storage = EvqSpirvStorageClass; + $$.qualifier.spirvStorageClass = $5.i; + } + +spirv_decorate_qualifier + : SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN{ + $$.init($1.loc); + $$.qualifier.setSpirvDecorate($3.i); + } + | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN{ + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorate($5.i); + } + | SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorate($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorate($5.i, $7->getAsAggregate()); + } + | SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorateId($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorateId($5.i, $7->getAsAggregate()); + } + | SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { + $$.init($1.loc); + $$.qualifier.setSpirvDecorateString($3.i, $5->getAsAggregate()); + } + | SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { + $$.init($1.loc); + parseContext.intermediate.insertSpirvRequirement($3); + $$.qualifier.setSpirvDecorateString($5.i, $7->getAsAggregate()); + } + +spirv_decorate_parameter_list + : spirv_decorate_parameter { + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_decorate_parameter_list COMMA spirv_decorate_parameter { + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_decorate_parameter + : FLOATCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); + } + | INTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); + } + | UINTCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); + } + | BOOLCONSTANT { + $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); + } + +spirv_decorate_id_parameter_list + : constant_expression { + if ($1->getBasicType() != EbtFloat && + $1->getBasicType() != EbtInt && + $1->getBasicType() != EbtUint && + $1->getBasicType() != EbtBool) + parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), ""); + $$ = parseContext.intermediate.makeAggregate($1); + } + | spirv_decorate_id_parameter_list COMMA constant_expression { + if ($3->getBasicType() != EbtFloat && + $3->getBasicType() != EbtInt && + $3->getBasicType() != EbtUint && + $3->getBasicType() != EbtBool) + parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), ""); + $$ = parseContext.intermediate.growAggregate($1, $3); + } + +spirv_decorate_string_parameter_list + : STRING_LITERAL { + $$ = parseContext.intermediate.makeAggregate( + parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); + } + | spirv_decorate_string_parameter_list COMMA STRING_LITERAL { + $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); + } + +spirv_type_specifier + : SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.setSpirvType(*$3, $5); + } + | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement($3); + $$.setSpirvType(*$5, $7); + } + | SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.setSpirvType(*$3); + } + | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement($3); + $$.setSpirvType(*$5); + } + +spirv_type_parameter_list + : spirv_type_parameter { + $$ = $1; + } + | spirv_type_parameter_list COMMA spirv_type_parameter { + $$ = parseContext.mergeSpirvTypeParameters($1, $3); + } + +spirv_type_parameter + : constant_expression { + $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion()); + } + | type_specifier { + $$ = parseContext.makeSpirvTypeParameters($1); + } + +spirv_instruction_qualifier + : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { + $$ = $3; + } + | SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { + parseContext.intermediate.insertSpirvRequirement($3); + $$ = $5; + } + +spirv_instruction_qualifier_list + : spirv_instruction_qualifier_id { + $$ = $1; + } + | spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id { + $$ = parseContext.mergeSpirvInstruction($2.loc, $1, $3); + } + +spirv_instruction_qualifier_id + : IDENTIFIER EQUAL STRING_LITERAL { + $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, *$3.string); + } + | IDENTIFIER EQUAL INTCONSTANT { + $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, $3.i); + } + + %% diff --git a/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp new file mode 100644 index 000000000..dba06aefe --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp @@ -0,0 +1,12440 @@ +/* A Bison parser, made by GNU Bison 3.7.4. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Inc. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30704 + +/* Bison version string. */ +#define YYBISON_VERSION "3.7.4" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* First part of user prologue. */ +#line 69 "MachineIndependent/glslang.y" + + +/* Based on: +ANSI C Yacc grammar + +In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a +matching Lex specification) for the April 30, 1985 draft version of the +ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that +original, as mentioned in the answer to question 17.25 of the comp.lang.c +FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. + +I intend to keep this version as close to the current C Standard grammar as +possible; please let me know if you discover discrepancies. + +Jutta Degener, 1995 +*/ + +#include "SymbolTable.h" +#include "ParseHelper.h" +#include "../Public/ShaderLang.h" +#include "attribute.h" + +using namespace glslang; + + +#line 97 "MachineIndependent/glslang_tab.cpp" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +#include "glslang_tab.cpp.h" +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_CONST = 3, /* CONST */ + YYSYMBOL_BOOL = 4, /* BOOL */ + YYSYMBOL_INT = 5, /* INT */ + YYSYMBOL_UINT = 6, /* UINT */ + YYSYMBOL_FLOAT = 7, /* FLOAT */ + YYSYMBOL_BVEC2 = 8, /* BVEC2 */ + YYSYMBOL_BVEC3 = 9, /* BVEC3 */ + YYSYMBOL_BVEC4 = 10, /* BVEC4 */ + YYSYMBOL_IVEC2 = 11, /* IVEC2 */ + YYSYMBOL_IVEC3 = 12, /* IVEC3 */ + YYSYMBOL_IVEC4 = 13, /* IVEC4 */ + YYSYMBOL_UVEC2 = 14, /* UVEC2 */ + YYSYMBOL_UVEC3 = 15, /* UVEC3 */ + YYSYMBOL_UVEC4 = 16, /* UVEC4 */ + YYSYMBOL_VEC2 = 17, /* VEC2 */ + YYSYMBOL_VEC3 = 18, /* VEC3 */ + YYSYMBOL_VEC4 = 19, /* VEC4 */ + YYSYMBOL_MAT2 = 20, /* MAT2 */ + YYSYMBOL_MAT3 = 21, /* MAT3 */ + YYSYMBOL_MAT4 = 22, /* MAT4 */ + YYSYMBOL_MAT2X2 = 23, /* MAT2X2 */ + YYSYMBOL_MAT2X3 = 24, /* MAT2X3 */ + YYSYMBOL_MAT2X4 = 25, /* MAT2X4 */ + YYSYMBOL_MAT3X2 = 26, /* MAT3X2 */ + YYSYMBOL_MAT3X3 = 27, /* MAT3X3 */ + YYSYMBOL_MAT3X4 = 28, /* MAT3X4 */ + YYSYMBOL_MAT4X2 = 29, /* MAT4X2 */ + YYSYMBOL_MAT4X3 = 30, /* MAT4X3 */ + YYSYMBOL_MAT4X4 = 31, /* MAT4X4 */ + YYSYMBOL_SAMPLER2D = 32, /* SAMPLER2D */ + YYSYMBOL_SAMPLER3D = 33, /* SAMPLER3D */ + YYSYMBOL_SAMPLERCUBE = 34, /* SAMPLERCUBE */ + YYSYMBOL_SAMPLER2DSHADOW = 35, /* SAMPLER2DSHADOW */ + YYSYMBOL_SAMPLERCUBESHADOW = 36, /* SAMPLERCUBESHADOW */ + YYSYMBOL_SAMPLER2DARRAY = 37, /* SAMPLER2DARRAY */ + YYSYMBOL_SAMPLER2DARRAYSHADOW = 38, /* SAMPLER2DARRAYSHADOW */ + YYSYMBOL_ISAMPLER2D = 39, /* ISAMPLER2D */ + YYSYMBOL_ISAMPLER3D = 40, /* ISAMPLER3D */ + YYSYMBOL_ISAMPLERCUBE = 41, /* ISAMPLERCUBE */ + YYSYMBOL_ISAMPLER2DARRAY = 42, /* ISAMPLER2DARRAY */ + YYSYMBOL_USAMPLER2D = 43, /* USAMPLER2D */ + YYSYMBOL_USAMPLER3D = 44, /* USAMPLER3D */ + YYSYMBOL_USAMPLERCUBE = 45, /* USAMPLERCUBE */ + YYSYMBOL_USAMPLER2DARRAY = 46, /* USAMPLER2DARRAY */ + YYSYMBOL_SAMPLER = 47, /* SAMPLER */ + YYSYMBOL_SAMPLERSHADOW = 48, /* SAMPLERSHADOW */ + YYSYMBOL_TEXTURE2D = 49, /* TEXTURE2D */ + YYSYMBOL_TEXTURE3D = 50, /* TEXTURE3D */ + YYSYMBOL_TEXTURECUBE = 51, /* TEXTURECUBE */ + YYSYMBOL_TEXTURE2DARRAY = 52, /* TEXTURE2DARRAY */ + YYSYMBOL_ITEXTURE2D = 53, /* ITEXTURE2D */ + YYSYMBOL_ITEXTURE3D = 54, /* ITEXTURE3D */ + YYSYMBOL_ITEXTURECUBE = 55, /* ITEXTURECUBE */ + YYSYMBOL_ITEXTURE2DARRAY = 56, /* ITEXTURE2DARRAY */ + YYSYMBOL_UTEXTURE2D = 57, /* UTEXTURE2D */ + YYSYMBOL_UTEXTURE3D = 58, /* UTEXTURE3D */ + YYSYMBOL_UTEXTURECUBE = 59, /* UTEXTURECUBE */ + YYSYMBOL_UTEXTURE2DARRAY = 60, /* UTEXTURE2DARRAY */ + YYSYMBOL_ATTRIBUTE = 61, /* ATTRIBUTE */ + YYSYMBOL_VARYING = 62, /* VARYING */ + YYSYMBOL_FLOAT16_T = 63, /* FLOAT16_T */ + YYSYMBOL_FLOAT32_T = 64, /* FLOAT32_T */ + YYSYMBOL_DOUBLE = 65, /* DOUBLE */ + YYSYMBOL_FLOAT64_T = 66, /* FLOAT64_T */ + YYSYMBOL_INT64_T = 67, /* INT64_T */ + YYSYMBOL_UINT64_T = 68, /* UINT64_T */ + YYSYMBOL_INT32_T = 69, /* INT32_T */ + YYSYMBOL_UINT32_T = 70, /* UINT32_T */ + YYSYMBOL_INT16_T = 71, /* INT16_T */ + YYSYMBOL_UINT16_T = 72, /* UINT16_T */ + YYSYMBOL_INT8_T = 73, /* INT8_T */ + YYSYMBOL_UINT8_T = 74, /* UINT8_T */ + YYSYMBOL_I64VEC2 = 75, /* I64VEC2 */ + YYSYMBOL_I64VEC3 = 76, /* I64VEC3 */ + YYSYMBOL_I64VEC4 = 77, /* I64VEC4 */ + YYSYMBOL_U64VEC2 = 78, /* U64VEC2 */ + YYSYMBOL_U64VEC3 = 79, /* U64VEC3 */ + YYSYMBOL_U64VEC4 = 80, /* U64VEC4 */ + YYSYMBOL_I32VEC2 = 81, /* I32VEC2 */ + YYSYMBOL_I32VEC3 = 82, /* I32VEC3 */ + YYSYMBOL_I32VEC4 = 83, /* I32VEC4 */ + YYSYMBOL_U32VEC2 = 84, /* U32VEC2 */ + YYSYMBOL_U32VEC3 = 85, /* U32VEC3 */ + YYSYMBOL_U32VEC4 = 86, /* U32VEC4 */ + YYSYMBOL_I16VEC2 = 87, /* I16VEC2 */ + YYSYMBOL_I16VEC3 = 88, /* I16VEC3 */ + YYSYMBOL_I16VEC4 = 89, /* I16VEC4 */ + YYSYMBOL_U16VEC2 = 90, /* U16VEC2 */ + YYSYMBOL_U16VEC3 = 91, /* U16VEC3 */ + YYSYMBOL_U16VEC4 = 92, /* U16VEC4 */ + YYSYMBOL_I8VEC2 = 93, /* I8VEC2 */ + YYSYMBOL_I8VEC3 = 94, /* I8VEC3 */ + YYSYMBOL_I8VEC4 = 95, /* I8VEC4 */ + YYSYMBOL_U8VEC2 = 96, /* U8VEC2 */ + YYSYMBOL_U8VEC3 = 97, /* U8VEC3 */ + YYSYMBOL_U8VEC4 = 98, /* U8VEC4 */ + YYSYMBOL_DVEC2 = 99, /* DVEC2 */ + YYSYMBOL_DVEC3 = 100, /* DVEC3 */ + YYSYMBOL_DVEC4 = 101, /* DVEC4 */ + YYSYMBOL_DMAT2 = 102, /* DMAT2 */ + YYSYMBOL_DMAT3 = 103, /* DMAT3 */ + YYSYMBOL_DMAT4 = 104, /* DMAT4 */ + YYSYMBOL_F16VEC2 = 105, /* F16VEC2 */ + YYSYMBOL_F16VEC3 = 106, /* F16VEC3 */ + YYSYMBOL_F16VEC4 = 107, /* F16VEC4 */ + YYSYMBOL_F16MAT2 = 108, /* F16MAT2 */ + YYSYMBOL_F16MAT3 = 109, /* F16MAT3 */ + YYSYMBOL_F16MAT4 = 110, /* F16MAT4 */ + YYSYMBOL_F32VEC2 = 111, /* F32VEC2 */ + YYSYMBOL_F32VEC3 = 112, /* F32VEC3 */ + YYSYMBOL_F32VEC4 = 113, /* F32VEC4 */ + YYSYMBOL_F32MAT2 = 114, /* F32MAT2 */ + YYSYMBOL_F32MAT3 = 115, /* F32MAT3 */ + YYSYMBOL_F32MAT4 = 116, /* F32MAT4 */ + YYSYMBOL_F64VEC2 = 117, /* F64VEC2 */ + YYSYMBOL_F64VEC3 = 118, /* F64VEC3 */ + YYSYMBOL_F64VEC4 = 119, /* F64VEC4 */ + YYSYMBOL_F64MAT2 = 120, /* F64MAT2 */ + YYSYMBOL_F64MAT3 = 121, /* F64MAT3 */ + YYSYMBOL_F64MAT4 = 122, /* F64MAT4 */ + YYSYMBOL_DMAT2X2 = 123, /* DMAT2X2 */ + YYSYMBOL_DMAT2X3 = 124, /* DMAT2X3 */ + YYSYMBOL_DMAT2X4 = 125, /* DMAT2X4 */ + YYSYMBOL_DMAT3X2 = 126, /* DMAT3X2 */ + YYSYMBOL_DMAT3X3 = 127, /* DMAT3X3 */ + YYSYMBOL_DMAT3X4 = 128, /* DMAT3X4 */ + YYSYMBOL_DMAT4X2 = 129, /* DMAT4X2 */ + YYSYMBOL_DMAT4X3 = 130, /* DMAT4X3 */ + YYSYMBOL_DMAT4X4 = 131, /* DMAT4X4 */ + YYSYMBOL_F16MAT2X2 = 132, /* F16MAT2X2 */ + YYSYMBOL_F16MAT2X3 = 133, /* F16MAT2X3 */ + YYSYMBOL_F16MAT2X4 = 134, /* F16MAT2X4 */ + YYSYMBOL_F16MAT3X2 = 135, /* F16MAT3X2 */ + YYSYMBOL_F16MAT3X3 = 136, /* F16MAT3X3 */ + YYSYMBOL_F16MAT3X4 = 137, /* F16MAT3X4 */ + YYSYMBOL_F16MAT4X2 = 138, /* F16MAT4X2 */ + YYSYMBOL_F16MAT4X3 = 139, /* F16MAT4X3 */ + YYSYMBOL_F16MAT4X4 = 140, /* F16MAT4X4 */ + YYSYMBOL_F32MAT2X2 = 141, /* F32MAT2X2 */ + YYSYMBOL_F32MAT2X3 = 142, /* F32MAT2X3 */ + YYSYMBOL_F32MAT2X4 = 143, /* F32MAT2X4 */ + YYSYMBOL_F32MAT3X2 = 144, /* F32MAT3X2 */ + YYSYMBOL_F32MAT3X3 = 145, /* F32MAT3X3 */ + YYSYMBOL_F32MAT3X4 = 146, /* F32MAT3X4 */ + YYSYMBOL_F32MAT4X2 = 147, /* F32MAT4X2 */ + YYSYMBOL_F32MAT4X3 = 148, /* F32MAT4X3 */ + YYSYMBOL_F32MAT4X4 = 149, /* F32MAT4X4 */ + YYSYMBOL_F64MAT2X2 = 150, /* F64MAT2X2 */ + YYSYMBOL_F64MAT2X3 = 151, /* F64MAT2X3 */ + YYSYMBOL_F64MAT2X4 = 152, /* F64MAT2X4 */ + YYSYMBOL_F64MAT3X2 = 153, /* F64MAT3X2 */ + YYSYMBOL_F64MAT3X3 = 154, /* F64MAT3X3 */ + YYSYMBOL_F64MAT3X4 = 155, /* F64MAT3X4 */ + YYSYMBOL_F64MAT4X2 = 156, /* F64MAT4X2 */ + YYSYMBOL_F64MAT4X3 = 157, /* F64MAT4X3 */ + YYSYMBOL_F64MAT4X4 = 158, /* F64MAT4X4 */ + YYSYMBOL_ATOMIC_UINT = 159, /* ATOMIC_UINT */ + YYSYMBOL_ACCSTRUCTNV = 160, /* ACCSTRUCTNV */ + YYSYMBOL_ACCSTRUCTEXT = 161, /* ACCSTRUCTEXT */ + YYSYMBOL_RAYQUERYEXT = 162, /* RAYQUERYEXT */ + YYSYMBOL_FCOOPMATNV = 163, /* FCOOPMATNV */ + YYSYMBOL_ICOOPMATNV = 164, /* ICOOPMATNV */ + YYSYMBOL_UCOOPMATNV = 165, /* UCOOPMATNV */ + YYSYMBOL_SAMPLERCUBEARRAY = 166, /* SAMPLERCUBEARRAY */ + YYSYMBOL_SAMPLERCUBEARRAYSHADOW = 167, /* SAMPLERCUBEARRAYSHADOW */ + YYSYMBOL_ISAMPLERCUBEARRAY = 168, /* ISAMPLERCUBEARRAY */ + YYSYMBOL_USAMPLERCUBEARRAY = 169, /* USAMPLERCUBEARRAY */ + YYSYMBOL_SAMPLER1D = 170, /* SAMPLER1D */ + YYSYMBOL_SAMPLER1DARRAY = 171, /* SAMPLER1DARRAY */ + YYSYMBOL_SAMPLER1DARRAYSHADOW = 172, /* SAMPLER1DARRAYSHADOW */ + YYSYMBOL_ISAMPLER1D = 173, /* ISAMPLER1D */ + YYSYMBOL_SAMPLER1DSHADOW = 174, /* SAMPLER1DSHADOW */ + YYSYMBOL_SAMPLER2DRECT = 175, /* SAMPLER2DRECT */ + YYSYMBOL_SAMPLER2DRECTSHADOW = 176, /* SAMPLER2DRECTSHADOW */ + YYSYMBOL_ISAMPLER2DRECT = 177, /* ISAMPLER2DRECT */ + YYSYMBOL_USAMPLER2DRECT = 178, /* USAMPLER2DRECT */ + YYSYMBOL_SAMPLERBUFFER = 179, /* SAMPLERBUFFER */ + YYSYMBOL_ISAMPLERBUFFER = 180, /* ISAMPLERBUFFER */ + YYSYMBOL_USAMPLERBUFFER = 181, /* USAMPLERBUFFER */ + YYSYMBOL_SAMPLER2DMS = 182, /* SAMPLER2DMS */ + YYSYMBOL_ISAMPLER2DMS = 183, /* ISAMPLER2DMS */ + YYSYMBOL_USAMPLER2DMS = 184, /* USAMPLER2DMS */ + YYSYMBOL_SAMPLER2DMSARRAY = 185, /* SAMPLER2DMSARRAY */ + YYSYMBOL_ISAMPLER2DMSARRAY = 186, /* ISAMPLER2DMSARRAY */ + YYSYMBOL_USAMPLER2DMSARRAY = 187, /* USAMPLER2DMSARRAY */ + YYSYMBOL_SAMPLEREXTERNALOES = 188, /* SAMPLEREXTERNALOES */ + YYSYMBOL_SAMPLEREXTERNAL2DY2YEXT = 189, /* SAMPLEREXTERNAL2DY2YEXT */ + YYSYMBOL_ISAMPLER1DARRAY = 190, /* ISAMPLER1DARRAY */ + YYSYMBOL_USAMPLER1D = 191, /* USAMPLER1D */ + YYSYMBOL_USAMPLER1DARRAY = 192, /* USAMPLER1DARRAY */ + YYSYMBOL_F16SAMPLER1D = 193, /* F16SAMPLER1D */ + YYSYMBOL_F16SAMPLER2D = 194, /* F16SAMPLER2D */ + YYSYMBOL_F16SAMPLER3D = 195, /* F16SAMPLER3D */ + YYSYMBOL_F16SAMPLER2DRECT = 196, /* F16SAMPLER2DRECT */ + YYSYMBOL_F16SAMPLERCUBE = 197, /* F16SAMPLERCUBE */ + YYSYMBOL_F16SAMPLER1DARRAY = 198, /* F16SAMPLER1DARRAY */ + YYSYMBOL_F16SAMPLER2DARRAY = 199, /* F16SAMPLER2DARRAY */ + YYSYMBOL_F16SAMPLERCUBEARRAY = 200, /* F16SAMPLERCUBEARRAY */ + YYSYMBOL_F16SAMPLERBUFFER = 201, /* F16SAMPLERBUFFER */ + YYSYMBOL_F16SAMPLER2DMS = 202, /* F16SAMPLER2DMS */ + YYSYMBOL_F16SAMPLER2DMSARRAY = 203, /* F16SAMPLER2DMSARRAY */ + YYSYMBOL_F16SAMPLER1DSHADOW = 204, /* F16SAMPLER1DSHADOW */ + YYSYMBOL_F16SAMPLER2DSHADOW = 205, /* F16SAMPLER2DSHADOW */ + YYSYMBOL_F16SAMPLER1DARRAYSHADOW = 206, /* F16SAMPLER1DARRAYSHADOW */ + YYSYMBOL_F16SAMPLER2DARRAYSHADOW = 207, /* F16SAMPLER2DARRAYSHADOW */ + YYSYMBOL_F16SAMPLER2DRECTSHADOW = 208, /* F16SAMPLER2DRECTSHADOW */ + YYSYMBOL_F16SAMPLERCUBESHADOW = 209, /* F16SAMPLERCUBESHADOW */ + YYSYMBOL_F16SAMPLERCUBEARRAYSHADOW = 210, /* F16SAMPLERCUBEARRAYSHADOW */ + YYSYMBOL_IMAGE1D = 211, /* IMAGE1D */ + YYSYMBOL_IIMAGE1D = 212, /* IIMAGE1D */ + YYSYMBOL_UIMAGE1D = 213, /* UIMAGE1D */ + YYSYMBOL_IMAGE2D = 214, /* IMAGE2D */ + YYSYMBOL_IIMAGE2D = 215, /* IIMAGE2D */ + YYSYMBOL_UIMAGE2D = 216, /* UIMAGE2D */ + YYSYMBOL_IMAGE3D = 217, /* IMAGE3D */ + YYSYMBOL_IIMAGE3D = 218, /* IIMAGE3D */ + YYSYMBOL_UIMAGE3D = 219, /* UIMAGE3D */ + YYSYMBOL_IMAGE2DRECT = 220, /* IMAGE2DRECT */ + YYSYMBOL_IIMAGE2DRECT = 221, /* IIMAGE2DRECT */ + YYSYMBOL_UIMAGE2DRECT = 222, /* UIMAGE2DRECT */ + YYSYMBOL_IMAGECUBE = 223, /* IMAGECUBE */ + YYSYMBOL_IIMAGECUBE = 224, /* IIMAGECUBE */ + YYSYMBOL_UIMAGECUBE = 225, /* UIMAGECUBE */ + YYSYMBOL_IMAGEBUFFER = 226, /* IMAGEBUFFER */ + YYSYMBOL_IIMAGEBUFFER = 227, /* IIMAGEBUFFER */ + YYSYMBOL_UIMAGEBUFFER = 228, /* UIMAGEBUFFER */ + YYSYMBOL_IMAGE1DARRAY = 229, /* IMAGE1DARRAY */ + YYSYMBOL_IIMAGE1DARRAY = 230, /* IIMAGE1DARRAY */ + YYSYMBOL_UIMAGE1DARRAY = 231, /* UIMAGE1DARRAY */ + YYSYMBOL_IMAGE2DARRAY = 232, /* IMAGE2DARRAY */ + YYSYMBOL_IIMAGE2DARRAY = 233, /* IIMAGE2DARRAY */ + YYSYMBOL_UIMAGE2DARRAY = 234, /* UIMAGE2DARRAY */ + YYSYMBOL_IMAGECUBEARRAY = 235, /* IMAGECUBEARRAY */ + YYSYMBOL_IIMAGECUBEARRAY = 236, /* IIMAGECUBEARRAY */ + YYSYMBOL_UIMAGECUBEARRAY = 237, /* UIMAGECUBEARRAY */ + YYSYMBOL_IMAGE2DMS = 238, /* IMAGE2DMS */ + YYSYMBOL_IIMAGE2DMS = 239, /* IIMAGE2DMS */ + YYSYMBOL_UIMAGE2DMS = 240, /* UIMAGE2DMS */ + YYSYMBOL_IMAGE2DMSARRAY = 241, /* IMAGE2DMSARRAY */ + YYSYMBOL_IIMAGE2DMSARRAY = 242, /* IIMAGE2DMSARRAY */ + YYSYMBOL_UIMAGE2DMSARRAY = 243, /* UIMAGE2DMSARRAY */ + YYSYMBOL_F16IMAGE1D = 244, /* F16IMAGE1D */ + YYSYMBOL_F16IMAGE2D = 245, /* F16IMAGE2D */ + YYSYMBOL_F16IMAGE3D = 246, /* F16IMAGE3D */ + YYSYMBOL_F16IMAGE2DRECT = 247, /* F16IMAGE2DRECT */ + YYSYMBOL_F16IMAGECUBE = 248, /* F16IMAGECUBE */ + YYSYMBOL_F16IMAGE1DARRAY = 249, /* F16IMAGE1DARRAY */ + YYSYMBOL_F16IMAGE2DARRAY = 250, /* F16IMAGE2DARRAY */ + YYSYMBOL_F16IMAGECUBEARRAY = 251, /* F16IMAGECUBEARRAY */ + YYSYMBOL_F16IMAGEBUFFER = 252, /* F16IMAGEBUFFER */ + YYSYMBOL_F16IMAGE2DMS = 253, /* F16IMAGE2DMS */ + YYSYMBOL_F16IMAGE2DMSARRAY = 254, /* F16IMAGE2DMSARRAY */ + YYSYMBOL_I64IMAGE1D = 255, /* I64IMAGE1D */ + YYSYMBOL_U64IMAGE1D = 256, /* U64IMAGE1D */ + YYSYMBOL_I64IMAGE2D = 257, /* I64IMAGE2D */ + YYSYMBOL_U64IMAGE2D = 258, /* U64IMAGE2D */ + YYSYMBOL_I64IMAGE3D = 259, /* I64IMAGE3D */ + YYSYMBOL_U64IMAGE3D = 260, /* U64IMAGE3D */ + YYSYMBOL_I64IMAGE2DRECT = 261, /* I64IMAGE2DRECT */ + YYSYMBOL_U64IMAGE2DRECT = 262, /* U64IMAGE2DRECT */ + YYSYMBOL_I64IMAGECUBE = 263, /* I64IMAGECUBE */ + YYSYMBOL_U64IMAGECUBE = 264, /* U64IMAGECUBE */ + YYSYMBOL_I64IMAGEBUFFER = 265, /* I64IMAGEBUFFER */ + YYSYMBOL_U64IMAGEBUFFER = 266, /* U64IMAGEBUFFER */ + YYSYMBOL_I64IMAGE1DARRAY = 267, /* I64IMAGE1DARRAY */ + YYSYMBOL_U64IMAGE1DARRAY = 268, /* U64IMAGE1DARRAY */ + YYSYMBOL_I64IMAGE2DARRAY = 269, /* I64IMAGE2DARRAY */ + YYSYMBOL_U64IMAGE2DARRAY = 270, /* U64IMAGE2DARRAY */ + YYSYMBOL_I64IMAGECUBEARRAY = 271, /* I64IMAGECUBEARRAY */ + YYSYMBOL_U64IMAGECUBEARRAY = 272, /* U64IMAGECUBEARRAY */ + YYSYMBOL_I64IMAGE2DMS = 273, /* I64IMAGE2DMS */ + YYSYMBOL_U64IMAGE2DMS = 274, /* U64IMAGE2DMS */ + YYSYMBOL_I64IMAGE2DMSARRAY = 275, /* I64IMAGE2DMSARRAY */ + YYSYMBOL_U64IMAGE2DMSARRAY = 276, /* U64IMAGE2DMSARRAY */ + YYSYMBOL_TEXTURECUBEARRAY = 277, /* TEXTURECUBEARRAY */ + YYSYMBOL_ITEXTURECUBEARRAY = 278, /* ITEXTURECUBEARRAY */ + YYSYMBOL_UTEXTURECUBEARRAY = 279, /* UTEXTURECUBEARRAY */ + YYSYMBOL_TEXTURE1D = 280, /* TEXTURE1D */ + YYSYMBOL_ITEXTURE1D = 281, /* ITEXTURE1D */ + YYSYMBOL_UTEXTURE1D = 282, /* UTEXTURE1D */ + YYSYMBOL_TEXTURE1DARRAY = 283, /* TEXTURE1DARRAY */ + YYSYMBOL_ITEXTURE1DARRAY = 284, /* ITEXTURE1DARRAY */ + YYSYMBOL_UTEXTURE1DARRAY = 285, /* UTEXTURE1DARRAY */ + YYSYMBOL_TEXTURE2DRECT = 286, /* TEXTURE2DRECT */ + YYSYMBOL_ITEXTURE2DRECT = 287, /* ITEXTURE2DRECT */ + YYSYMBOL_UTEXTURE2DRECT = 288, /* UTEXTURE2DRECT */ + YYSYMBOL_TEXTUREBUFFER = 289, /* TEXTUREBUFFER */ + YYSYMBOL_ITEXTUREBUFFER = 290, /* ITEXTUREBUFFER */ + YYSYMBOL_UTEXTUREBUFFER = 291, /* UTEXTUREBUFFER */ + YYSYMBOL_TEXTURE2DMS = 292, /* TEXTURE2DMS */ + YYSYMBOL_ITEXTURE2DMS = 293, /* ITEXTURE2DMS */ + YYSYMBOL_UTEXTURE2DMS = 294, /* UTEXTURE2DMS */ + YYSYMBOL_TEXTURE2DMSARRAY = 295, /* TEXTURE2DMSARRAY */ + YYSYMBOL_ITEXTURE2DMSARRAY = 296, /* ITEXTURE2DMSARRAY */ + YYSYMBOL_UTEXTURE2DMSARRAY = 297, /* UTEXTURE2DMSARRAY */ + YYSYMBOL_F16TEXTURE1D = 298, /* F16TEXTURE1D */ + YYSYMBOL_F16TEXTURE2D = 299, /* F16TEXTURE2D */ + YYSYMBOL_F16TEXTURE3D = 300, /* F16TEXTURE3D */ + YYSYMBOL_F16TEXTURE2DRECT = 301, /* F16TEXTURE2DRECT */ + YYSYMBOL_F16TEXTURECUBE = 302, /* F16TEXTURECUBE */ + YYSYMBOL_F16TEXTURE1DARRAY = 303, /* F16TEXTURE1DARRAY */ + YYSYMBOL_F16TEXTURE2DARRAY = 304, /* F16TEXTURE2DARRAY */ + YYSYMBOL_F16TEXTURECUBEARRAY = 305, /* F16TEXTURECUBEARRAY */ + YYSYMBOL_F16TEXTUREBUFFER = 306, /* F16TEXTUREBUFFER */ + YYSYMBOL_F16TEXTURE2DMS = 307, /* F16TEXTURE2DMS */ + YYSYMBOL_F16TEXTURE2DMSARRAY = 308, /* F16TEXTURE2DMSARRAY */ + YYSYMBOL_SUBPASSINPUT = 309, /* SUBPASSINPUT */ + YYSYMBOL_SUBPASSINPUTMS = 310, /* SUBPASSINPUTMS */ + YYSYMBOL_ISUBPASSINPUT = 311, /* ISUBPASSINPUT */ + YYSYMBOL_ISUBPASSINPUTMS = 312, /* ISUBPASSINPUTMS */ + YYSYMBOL_USUBPASSINPUT = 313, /* USUBPASSINPUT */ + YYSYMBOL_USUBPASSINPUTMS = 314, /* USUBPASSINPUTMS */ + YYSYMBOL_F16SUBPASSINPUT = 315, /* F16SUBPASSINPUT */ + YYSYMBOL_F16SUBPASSINPUTMS = 316, /* F16SUBPASSINPUTMS */ + YYSYMBOL_SPIRV_INSTRUCTION = 317, /* SPIRV_INSTRUCTION */ + YYSYMBOL_SPIRV_EXECUTION_MODE = 318, /* SPIRV_EXECUTION_MODE */ + YYSYMBOL_SPIRV_EXECUTION_MODE_ID = 319, /* SPIRV_EXECUTION_MODE_ID */ + YYSYMBOL_SPIRV_DECORATE = 320, /* SPIRV_DECORATE */ + YYSYMBOL_SPIRV_DECORATE_ID = 321, /* SPIRV_DECORATE_ID */ + YYSYMBOL_SPIRV_DECORATE_STRING = 322, /* SPIRV_DECORATE_STRING */ + YYSYMBOL_SPIRV_TYPE = 323, /* SPIRV_TYPE */ + YYSYMBOL_SPIRV_STORAGE_CLASS = 324, /* SPIRV_STORAGE_CLASS */ + YYSYMBOL_SPIRV_BY_REFERENCE = 325, /* SPIRV_BY_REFERENCE */ + YYSYMBOL_SPIRV_LITERAL = 326, /* SPIRV_LITERAL */ + YYSYMBOL_LEFT_OP = 327, /* LEFT_OP */ + YYSYMBOL_RIGHT_OP = 328, /* RIGHT_OP */ + YYSYMBOL_INC_OP = 329, /* INC_OP */ + YYSYMBOL_DEC_OP = 330, /* DEC_OP */ + YYSYMBOL_LE_OP = 331, /* LE_OP */ + YYSYMBOL_GE_OP = 332, /* GE_OP */ + YYSYMBOL_EQ_OP = 333, /* EQ_OP */ + YYSYMBOL_NE_OP = 334, /* NE_OP */ + YYSYMBOL_AND_OP = 335, /* AND_OP */ + YYSYMBOL_OR_OP = 336, /* OR_OP */ + YYSYMBOL_XOR_OP = 337, /* XOR_OP */ + YYSYMBOL_MUL_ASSIGN = 338, /* MUL_ASSIGN */ + YYSYMBOL_DIV_ASSIGN = 339, /* DIV_ASSIGN */ + YYSYMBOL_ADD_ASSIGN = 340, /* ADD_ASSIGN */ + YYSYMBOL_MOD_ASSIGN = 341, /* MOD_ASSIGN */ + YYSYMBOL_LEFT_ASSIGN = 342, /* LEFT_ASSIGN */ + YYSYMBOL_RIGHT_ASSIGN = 343, /* RIGHT_ASSIGN */ + YYSYMBOL_AND_ASSIGN = 344, /* AND_ASSIGN */ + YYSYMBOL_XOR_ASSIGN = 345, /* XOR_ASSIGN */ + YYSYMBOL_OR_ASSIGN = 346, /* OR_ASSIGN */ + YYSYMBOL_SUB_ASSIGN = 347, /* SUB_ASSIGN */ + YYSYMBOL_STRING_LITERAL = 348, /* STRING_LITERAL */ + YYSYMBOL_LEFT_PAREN = 349, /* LEFT_PAREN */ + YYSYMBOL_RIGHT_PAREN = 350, /* RIGHT_PAREN */ + YYSYMBOL_LEFT_BRACKET = 351, /* LEFT_BRACKET */ + YYSYMBOL_RIGHT_BRACKET = 352, /* RIGHT_BRACKET */ + YYSYMBOL_LEFT_BRACE = 353, /* LEFT_BRACE */ + YYSYMBOL_RIGHT_BRACE = 354, /* RIGHT_BRACE */ + YYSYMBOL_DOT = 355, /* DOT */ + YYSYMBOL_COMMA = 356, /* COMMA */ + YYSYMBOL_COLON = 357, /* COLON */ + YYSYMBOL_EQUAL = 358, /* EQUAL */ + YYSYMBOL_SEMICOLON = 359, /* SEMICOLON */ + YYSYMBOL_BANG = 360, /* BANG */ + YYSYMBOL_DASH = 361, /* DASH */ + YYSYMBOL_TILDE = 362, /* TILDE */ + YYSYMBOL_PLUS = 363, /* PLUS */ + YYSYMBOL_STAR = 364, /* STAR */ + YYSYMBOL_SLASH = 365, /* SLASH */ + YYSYMBOL_PERCENT = 366, /* PERCENT */ + YYSYMBOL_LEFT_ANGLE = 367, /* LEFT_ANGLE */ + YYSYMBOL_RIGHT_ANGLE = 368, /* RIGHT_ANGLE */ + YYSYMBOL_VERTICAL_BAR = 369, /* VERTICAL_BAR */ + YYSYMBOL_CARET = 370, /* CARET */ + YYSYMBOL_AMPERSAND = 371, /* AMPERSAND */ + YYSYMBOL_QUESTION = 372, /* QUESTION */ + YYSYMBOL_INVARIANT = 373, /* INVARIANT */ + YYSYMBOL_HIGH_PRECISION = 374, /* HIGH_PRECISION */ + YYSYMBOL_MEDIUM_PRECISION = 375, /* MEDIUM_PRECISION */ + YYSYMBOL_LOW_PRECISION = 376, /* LOW_PRECISION */ + YYSYMBOL_PRECISION = 377, /* PRECISION */ + YYSYMBOL_PACKED = 378, /* PACKED */ + YYSYMBOL_RESOURCE = 379, /* RESOURCE */ + YYSYMBOL_SUPERP = 380, /* SUPERP */ + YYSYMBOL_FLOATCONSTANT = 381, /* FLOATCONSTANT */ + YYSYMBOL_INTCONSTANT = 382, /* INTCONSTANT */ + YYSYMBOL_UINTCONSTANT = 383, /* UINTCONSTANT */ + YYSYMBOL_BOOLCONSTANT = 384, /* BOOLCONSTANT */ + YYSYMBOL_IDENTIFIER = 385, /* IDENTIFIER */ + YYSYMBOL_TYPE_NAME = 386, /* TYPE_NAME */ + YYSYMBOL_CENTROID = 387, /* CENTROID */ + YYSYMBOL_IN = 388, /* IN */ + YYSYMBOL_OUT = 389, /* OUT */ + YYSYMBOL_INOUT = 390, /* INOUT */ + YYSYMBOL_STRUCT = 391, /* STRUCT */ + YYSYMBOL_VOID = 392, /* VOID */ + YYSYMBOL_WHILE = 393, /* WHILE */ + YYSYMBOL_BREAK = 394, /* BREAK */ + YYSYMBOL_CONTINUE = 395, /* CONTINUE */ + YYSYMBOL_DO = 396, /* DO */ + YYSYMBOL_ELSE = 397, /* ELSE */ + YYSYMBOL_FOR = 398, /* FOR */ + YYSYMBOL_IF = 399, /* IF */ + YYSYMBOL_DISCARD = 400, /* DISCARD */ + YYSYMBOL_RETURN = 401, /* RETURN */ + YYSYMBOL_SWITCH = 402, /* SWITCH */ + YYSYMBOL_CASE = 403, /* CASE */ + YYSYMBOL_DEFAULT = 404, /* DEFAULT */ + YYSYMBOL_TERMINATE_INVOCATION = 405, /* TERMINATE_INVOCATION */ + YYSYMBOL_TERMINATE_RAY = 406, /* TERMINATE_RAY */ + YYSYMBOL_IGNORE_INTERSECTION = 407, /* IGNORE_INTERSECTION */ + YYSYMBOL_UNIFORM = 408, /* UNIFORM */ + YYSYMBOL_SHARED = 409, /* SHARED */ + YYSYMBOL_BUFFER = 410, /* BUFFER */ + YYSYMBOL_FLAT = 411, /* FLAT */ + YYSYMBOL_SMOOTH = 412, /* SMOOTH */ + YYSYMBOL_LAYOUT = 413, /* LAYOUT */ + YYSYMBOL_DOUBLECONSTANT = 414, /* DOUBLECONSTANT */ + YYSYMBOL_INT16CONSTANT = 415, /* INT16CONSTANT */ + YYSYMBOL_UINT16CONSTANT = 416, /* UINT16CONSTANT */ + YYSYMBOL_FLOAT16CONSTANT = 417, /* FLOAT16CONSTANT */ + YYSYMBOL_INT32CONSTANT = 418, /* INT32CONSTANT */ + YYSYMBOL_UINT32CONSTANT = 419, /* UINT32CONSTANT */ + YYSYMBOL_INT64CONSTANT = 420, /* INT64CONSTANT */ + YYSYMBOL_UINT64CONSTANT = 421, /* UINT64CONSTANT */ + YYSYMBOL_SUBROUTINE = 422, /* SUBROUTINE */ + YYSYMBOL_DEMOTE = 423, /* DEMOTE */ + YYSYMBOL_PAYLOADNV = 424, /* PAYLOADNV */ + YYSYMBOL_PAYLOADINNV = 425, /* PAYLOADINNV */ + YYSYMBOL_HITATTRNV = 426, /* HITATTRNV */ + YYSYMBOL_CALLDATANV = 427, /* CALLDATANV */ + YYSYMBOL_CALLDATAINNV = 428, /* CALLDATAINNV */ + YYSYMBOL_PAYLOADEXT = 429, /* PAYLOADEXT */ + YYSYMBOL_PAYLOADINEXT = 430, /* PAYLOADINEXT */ + YYSYMBOL_HITATTREXT = 431, /* HITATTREXT */ + YYSYMBOL_CALLDATAEXT = 432, /* CALLDATAEXT */ + YYSYMBOL_CALLDATAINEXT = 433, /* CALLDATAINEXT */ + YYSYMBOL_PATCH = 434, /* PATCH */ + YYSYMBOL_SAMPLE = 435, /* SAMPLE */ + YYSYMBOL_NONUNIFORM = 436, /* NONUNIFORM */ + YYSYMBOL_COHERENT = 437, /* COHERENT */ + YYSYMBOL_VOLATILE = 438, /* VOLATILE */ + YYSYMBOL_RESTRICT = 439, /* RESTRICT */ + YYSYMBOL_READONLY = 440, /* READONLY */ + YYSYMBOL_WRITEONLY = 441, /* WRITEONLY */ + YYSYMBOL_DEVICECOHERENT = 442, /* DEVICECOHERENT */ + YYSYMBOL_QUEUEFAMILYCOHERENT = 443, /* QUEUEFAMILYCOHERENT */ + YYSYMBOL_WORKGROUPCOHERENT = 444, /* WORKGROUPCOHERENT */ + YYSYMBOL_SUBGROUPCOHERENT = 445, /* SUBGROUPCOHERENT */ + YYSYMBOL_NONPRIVATE = 446, /* NONPRIVATE */ + YYSYMBOL_SHADERCALLCOHERENT = 447, /* SHADERCALLCOHERENT */ + YYSYMBOL_NOPERSPECTIVE = 448, /* NOPERSPECTIVE */ + YYSYMBOL_EXPLICITINTERPAMD = 449, /* EXPLICITINTERPAMD */ + YYSYMBOL_PERVERTEXNV = 450, /* PERVERTEXNV */ + YYSYMBOL_PERPRIMITIVENV = 451, /* PERPRIMITIVENV */ + YYSYMBOL_PERVIEWNV = 452, /* PERVIEWNV */ + YYSYMBOL_PERTASKNV = 453, /* PERTASKNV */ + YYSYMBOL_PRECISE = 454, /* PRECISE */ + YYSYMBOL_YYACCEPT = 455, /* $accept */ + YYSYMBOL_variable_identifier = 456, /* variable_identifier */ + YYSYMBOL_primary_expression = 457, /* primary_expression */ + YYSYMBOL_postfix_expression = 458, /* postfix_expression */ + YYSYMBOL_integer_expression = 459, /* integer_expression */ + YYSYMBOL_function_call = 460, /* function_call */ + YYSYMBOL_function_call_or_method = 461, /* function_call_or_method */ + YYSYMBOL_function_call_generic = 462, /* function_call_generic */ + YYSYMBOL_function_call_header_no_parameters = 463, /* function_call_header_no_parameters */ + YYSYMBOL_function_call_header_with_parameters = 464, /* function_call_header_with_parameters */ + YYSYMBOL_function_call_header = 465, /* function_call_header */ + YYSYMBOL_function_identifier = 466, /* function_identifier */ + YYSYMBOL_unary_expression = 467, /* unary_expression */ + YYSYMBOL_unary_operator = 468, /* unary_operator */ + YYSYMBOL_multiplicative_expression = 469, /* multiplicative_expression */ + YYSYMBOL_additive_expression = 470, /* additive_expression */ + YYSYMBOL_shift_expression = 471, /* shift_expression */ + YYSYMBOL_relational_expression = 472, /* relational_expression */ + YYSYMBOL_equality_expression = 473, /* equality_expression */ + YYSYMBOL_and_expression = 474, /* and_expression */ + YYSYMBOL_exclusive_or_expression = 475, /* exclusive_or_expression */ + YYSYMBOL_inclusive_or_expression = 476, /* inclusive_or_expression */ + YYSYMBOL_logical_and_expression = 477, /* logical_and_expression */ + YYSYMBOL_logical_xor_expression = 478, /* logical_xor_expression */ + YYSYMBOL_logical_or_expression = 479, /* logical_or_expression */ + YYSYMBOL_conditional_expression = 480, /* conditional_expression */ + YYSYMBOL_481_1 = 481, /* $@1 */ + YYSYMBOL_assignment_expression = 482, /* assignment_expression */ + YYSYMBOL_assignment_operator = 483, /* assignment_operator */ + YYSYMBOL_expression = 484, /* expression */ + YYSYMBOL_constant_expression = 485, /* constant_expression */ + YYSYMBOL_declaration = 486, /* declaration */ + YYSYMBOL_block_structure = 487, /* block_structure */ + YYSYMBOL_488_2 = 488, /* $@2 */ + YYSYMBOL_identifier_list = 489, /* identifier_list */ + YYSYMBOL_function_prototype = 490, /* function_prototype */ + YYSYMBOL_function_declarator = 491, /* function_declarator */ + YYSYMBOL_function_header_with_parameters = 492, /* function_header_with_parameters */ + YYSYMBOL_function_header = 493, /* function_header */ + YYSYMBOL_parameter_declarator = 494, /* parameter_declarator */ + YYSYMBOL_parameter_declaration = 495, /* parameter_declaration */ + YYSYMBOL_parameter_type_specifier = 496, /* parameter_type_specifier */ + YYSYMBOL_init_declarator_list = 497, /* init_declarator_list */ + YYSYMBOL_single_declaration = 498, /* single_declaration */ + YYSYMBOL_fully_specified_type = 499, /* fully_specified_type */ + YYSYMBOL_invariant_qualifier = 500, /* invariant_qualifier */ + YYSYMBOL_interpolation_qualifier = 501, /* interpolation_qualifier */ + YYSYMBOL_layout_qualifier = 502, /* layout_qualifier */ + YYSYMBOL_layout_qualifier_id_list = 503, /* layout_qualifier_id_list */ + YYSYMBOL_layout_qualifier_id = 504, /* layout_qualifier_id */ + YYSYMBOL_precise_qualifier = 505, /* precise_qualifier */ + YYSYMBOL_type_qualifier = 506, /* type_qualifier */ + YYSYMBOL_single_type_qualifier = 507, /* single_type_qualifier */ + YYSYMBOL_storage_qualifier = 508, /* storage_qualifier */ + YYSYMBOL_non_uniform_qualifier = 509, /* non_uniform_qualifier */ + YYSYMBOL_type_name_list = 510, /* type_name_list */ + YYSYMBOL_type_specifier = 511, /* type_specifier */ + YYSYMBOL_array_specifier = 512, /* array_specifier */ + YYSYMBOL_type_parameter_specifier_opt = 513, /* type_parameter_specifier_opt */ + YYSYMBOL_type_parameter_specifier = 514, /* type_parameter_specifier */ + YYSYMBOL_type_parameter_specifier_list = 515, /* type_parameter_specifier_list */ + YYSYMBOL_type_specifier_nonarray = 516, /* type_specifier_nonarray */ + YYSYMBOL_precision_qualifier = 517, /* precision_qualifier */ + YYSYMBOL_struct_specifier = 518, /* struct_specifier */ + YYSYMBOL_519_3 = 519, /* $@3 */ + YYSYMBOL_520_4 = 520, /* $@4 */ + YYSYMBOL_struct_declaration_list = 521, /* struct_declaration_list */ + YYSYMBOL_struct_declaration = 522, /* struct_declaration */ + YYSYMBOL_struct_declarator_list = 523, /* struct_declarator_list */ + YYSYMBOL_struct_declarator = 524, /* struct_declarator */ + YYSYMBOL_initializer = 525, /* initializer */ + YYSYMBOL_initializer_list = 526, /* initializer_list */ + YYSYMBOL_declaration_statement = 527, /* declaration_statement */ + YYSYMBOL_statement = 528, /* statement */ + YYSYMBOL_simple_statement = 529, /* simple_statement */ + YYSYMBOL_demote_statement = 530, /* demote_statement */ + YYSYMBOL_compound_statement = 531, /* compound_statement */ + YYSYMBOL_532_5 = 532, /* $@5 */ + YYSYMBOL_533_6 = 533, /* $@6 */ + YYSYMBOL_statement_no_new_scope = 534, /* statement_no_new_scope */ + YYSYMBOL_statement_scoped = 535, /* statement_scoped */ + YYSYMBOL_536_7 = 536, /* $@7 */ + YYSYMBOL_537_8 = 537, /* $@8 */ + YYSYMBOL_compound_statement_no_new_scope = 538, /* compound_statement_no_new_scope */ + YYSYMBOL_statement_list = 539, /* statement_list */ + YYSYMBOL_expression_statement = 540, /* expression_statement */ + YYSYMBOL_selection_statement = 541, /* selection_statement */ + YYSYMBOL_selection_statement_nonattributed = 542, /* selection_statement_nonattributed */ + YYSYMBOL_selection_rest_statement = 543, /* selection_rest_statement */ + YYSYMBOL_condition = 544, /* condition */ + YYSYMBOL_switch_statement = 545, /* switch_statement */ + YYSYMBOL_switch_statement_nonattributed = 546, /* switch_statement_nonattributed */ + YYSYMBOL_547_9 = 547, /* $@9 */ + YYSYMBOL_switch_statement_list = 548, /* switch_statement_list */ + YYSYMBOL_case_label = 549, /* case_label */ + YYSYMBOL_iteration_statement = 550, /* iteration_statement */ + YYSYMBOL_iteration_statement_nonattributed = 551, /* iteration_statement_nonattributed */ + YYSYMBOL_552_10 = 552, /* $@10 */ + YYSYMBOL_553_11 = 553, /* $@11 */ + YYSYMBOL_554_12 = 554, /* $@12 */ + YYSYMBOL_for_init_statement = 555, /* for_init_statement */ + YYSYMBOL_conditionopt = 556, /* conditionopt */ + YYSYMBOL_for_rest_statement = 557, /* for_rest_statement */ + YYSYMBOL_jump_statement = 558, /* jump_statement */ + YYSYMBOL_translation_unit = 559, /* translation_unit */ + YYSYMBOL_external_declaration = 560, /* external_declaration */ + YYSYMBOL_function_definition = 561, /* function_definition */ + YYSYMBOL_562_13 = 562, /* $@13 */ + YYSYMBOL_attribute = 563, /* attribute */ + YYSYMBOL_attribute_list = 564, /* attribute_list */ + YYSYMBOL_single_attribute = 565, /* single_attribute */ + YYSYMBOL_spirv_requirements_list = 566, /* spirv_requirements_list */ + YYSYMBOL_spirv_requirements_parameter = 567, /* spirv_requirements_parameter */ + YYSYMBOL_spirv_extension_list = 568, /* spirv_extension_list */ + YYSYMBOL_spirv_capability_list = 569, /* spirv_capability_list */ + YYSYMBOL_spirv_execution_mode_qualifier = 570, /* spirv_execution_mode_qualifier */ + YYSYMBOL_spirv_execution_mode_parameter_list = 571, /* spirv_execution_mode_parameter_list */ + YYSYMBOL_spirv_execution_mode_parameter = 572, /* spirv_execution_mode_parameter */ + YYSYMBOL_spirv_execution_mode_id_parameter_list = 573, /* spirv_execution_mode_id_parameter_list */ + YYSYMBOL_spirv_storage_class_qualifier = 574, /* spirv_storage_class_qualifier */ + YYSYMBOL_spirv_decorate_qualifier = 575, /* spirv_decorate_qualifier */ + YYSYMBOL_spirv_decorate_parameter_list = 576, /* spirv_decorate_parameter_list */ + YYSYMBOL_spirv_decorate_parameter = 577, /* spirv_decorate_parameter */ + YYSYMBOL_spirv_decorate_id_parameter_list = 578, /* spirv_decorate_id_parameter_list */ + YYSYMBOL_spirv_decorate_string_parameter_list = 579, /* spirv_decorate_string_parameter_list */ + YYSYMBOL_spirv_type_specifier = 580, /* spirv_type_specifier */ + YYSYMBOL_spirv_type_parameter_list = 581, /* spirv_type_parameter_list */ + YYSYMBOL_spirv_type_parameter = 582, /* spirv_type_parameter */ + YYSYMBOL_spirv_instruction_qualifier = 583, /* spirv_instruction_qualifier */ + YYSYMBOL_spirv_instruction_qualifier_list = 584, /* spirv_instruction_qualifier_list */ + YYSYMBOL_spirv_instruction_qualifier_id = 585 /* spirv_instruction_qualifier_id */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + +/* Second part of user prologue. */ +#line 136 "MachineIndependent/glslang.y" + + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4065) + #pragma warning(disable : 4127) + #pragma warning(disable : 4244) +#endif + +#define parseContext (*pParseContext) +#define yyerror(context, msg) context->parserError(msg) + +extern int yylex(YYSTYPE*, TParseContext&); + + +#line 732 "MachineIndependent/glslang_tab.cpp" + + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if 1 + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* 1 */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 442 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 12453 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 455 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 131 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 684 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 930 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 709 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int16 yytranslate[] = +{ + 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, 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, 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, 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, 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, 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, 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, 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, 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 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = +{ + 0, 392, 392, 398, 401, 406, 409, 412, 416, 420, + 423, 427, 431, 435, 439, 443, 447, 453, 461, 464, + 467, 470, 473, 478, 486, 493, 500, 506, 510, 517, + 520, 526, 533, 543, 551, 556, 584, 593, 599, 603, + 607, 627, 628, 629, 630, 636, 637, 642, 647, 656, + 657, 662, 670, 671, 677, 686, 687, 692, 697, 702, + 710, 711, 720, 732, 733, 742, 743, 752, 753, 762, + 763, 771, 772, 780, 781, 789, 790, 790, 808, 809, + 825, 829, 833, 837, 842, 846, 850, 854, 858, 862, + 866, 873, 876, 887, 894, 900, 907, 913, 918, 925, + 929, 933, 937, 942, 947, 956, 956, 967, 971, 978, + 982, 988, 994, 1004, 1007, 1014, 1022, 1042, 1065, 1080, + 1105, 1116, 1126, 1136, 1146, 1155, 1158, 1162, 1166, 1171, + 1179, 1186, 1191, 1196, 1201, 1210, 1220, 1247, 1256, 1263, + 1271, 1278, 1285, 1293, 1303, 1310, 1321, 1327, 1330, 1337, + 1341, 1345, 1354, 1364, 1367, 1378, 1381, 1384, 1388, 1392, + 1397, 1401, 1404, 1409, 1413, 1418, 1427, 1431, 1436, 1442, + 1448, 1455, 1460, 1468, 1474, 1486, 1500, 1506, 1511, 1519, + 1527, 1535, 1543, 1551, 1559, 1567, 1575, 1582, 1589, 1593, + 1598, 1603, 1608, 1613, 1618, 1623, 1627, 1631, 1635, 1639, + 1645, 1656, 1663, 1666, 1675, 1680, 1690, 1695, 1703, 1707, + 1717, 1720, 1726, 1732, 1739, 1749, 1753, 1757, 1761, 1766, + 1770, 1775, 1780, 1785, 1790, 1795, 1800, 1805, 1810, 1815, + 1821, 1827, 1833, 1838, 1843, 1848, 1853, 1858, 1863, 1868, + 1873, 1878, 1883, 1888, 1894, 1901, 1906, 1911, 1916, 1921, + 1926, 1931, 1936, 1941, 1946, 1951, 1956, 1964, 1972, 1980, + 1986, 1992, 1998, 2004, 2010, 2016, 2022, 2028, 2034, 2040, + 2046, 2052, 2058, 2064, 2070, 2076, 2082, 2088, 2094, 2100, + 2106, 2112, 2118, 2124, 2130, 2136, 2142, 2148, 2154, 2160, + 2166, 2172, 2178, 2186, 2194, 2202, 2210, 2218, 2226, 2234, + 2242, 2250, 2258, 2266, 2274, 2280, 2286, 2292, 2298, 2304, + 2310, 2316, 2322, 2328, 2334, 2340, 2346, 2352, 2358, 2364, + 2370, 2376, 2382, 2388, 2394, 2400, 2406, 2412, 2418, 2424, + 2430, 2436, 2442, 2448, 2454, 2460, 2466, 2472, 2478, 2484, + 2490, 2494, 2498, 2502, 2507, 2513, 2518, 2523, 2528, 2533, + 2538, 2543, 2549, 2554, 2559, 2564, 2569, 2574, 2580, 2586, + 2592, 2598, 2604, 2610, 2616, 2622, 2628, 2634, 2640, 2646, + 2652, 2658, 2663, 2668, 2673, 2678, 2683, 2688, 2694, 2699, + 2704, 2709, 2714, 2719, 2724, 2729, 2735, 2740, 2745, 2750, + 2755, 2760, 2765, 2770, 2775, 2780, 2785, 2790, 2795, 2800, + 2805, 2811, 2816, 2821, 2827, 2833, 2838, 2843, 2848, 2854, + 2859, 2864, 2869, 2875, 2880, 2885, 2890, 2896, 2901, 2906, + 2911, 2917, 2923, 2929, 2935, 2940, 2946, 2952, 2958, 2963, + 2968, 2973, 2978, 2983, 2989, 2994, 2999, 3004, 3010, 3015, + 3020, 3025, 3031, 3036, 3041, 3046, 3052, 3057, 3062, 3067, + 3073, 3078, 3083, 3088, 3094, 3099, 3104, 3109, 3115, 3120, + 3125, 3130, 3136, 3141, 3146, 3151, 3157, 3162, 3167, 3172, + 3178, 3183, 3188, 3193, 3199, 3204, 3209, 3214, 3220, 3225, + 3230, 3235, 3241, 3246, 3251, 3256, 3262, 3267, 3272, 3277, + 3283, 3288, 3293, 3298, 3303, 3308, 3313, 3318, 3323, 3328, + 3333, 3338, 3343, 3348, 3353, 3358, 3363, 3368, 3373, 3378, + 3383, 3388, 3393, 3398, 3403, 3409, 3415, 3421, 3427, 3434, + 3441, 3447, 3453, 3459, 3465, 3471, 3477, 3483, 3488, 3493, + 3509, 3514, 3519, 3527, 3527, 3538, 3538, 3548, 3551, 3564, + 3586, 3613, 3617, 3623, 3628, 3639, 3643, 3649, 3655, 3666, + 3669, 3676, 3680, 3681, 3687, 3688, 3689, 3690, 3691, 3692, + 3693, 3695, 3701, 3710, 3711, 3715, 3711, 3727, 3728, 3732, + 3732, 3739, 3739, 3753, 3756, 3764, 3772, 3783, 3784, 3788, + 3792, 3800, 3807, 3811, 3819, 3823, 3836, 3840, 3848, 3848, + 3868, 3871, 3877, 3889, 3901, 3905, 3913, 3913, 3928, 3928, + 3944, 3944, 3965, 3968, 3974, 3977, 3983, 3987, 3994, 3999, + 4004, 4011, 4014, 4018, 4023, 4027, 4037, 4041, 4050, 4053, + 4057, 4066, 4066, 4108, 4113, 4116, 4121, 4124, 4131, 4134, + 4139, 4142, 4147, 4150, 4155, 4158, 4163, 4167, 4172, 4176, + 4181, 4185, 4192, 4195, 4200, 4203, 4206, 4209, 4212, 4217, + 4226, 4237, 4242, 4250, 4254, 4259, 4263, 4268, 4272, 4277, + 4281, 4288, 4291, 4296, 4299, 4302, 4305, 4310, 4318, 4328, + 4332, 4337, 4341, 4346, 4350, 4357, 4360, 4365, 4368, 4373, + 4376, 4382, 4385, 4390, 4393 +}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if 1 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "CONST", "BOOL", "INT", + "UINT", "FLOAT", "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", + "UVEC2", "UVEC3", "UVEC4", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", + "MAT4", "MAT2X2", "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", + "MAT4X2", "MAT4X3", "MAT4X4", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE", + "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW", "SAMPLER2DARRAY", + "SAMPLER2DARRAYSHADOW", "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", + "ISAMPLER2DARRAY", "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", + "USAMPLER2DARRAY", "SAMPLER", "SAMPLERSHADOW", "TEXTURE2D", "TEXTURE3D", + "TEXTURECUBE", "TEXTURE2DARRAY", "ITEXTURE2D", "ITEXTURE3D", + "ITEXTURECUBE", "ITEXTURE2DARRAY", "UTEXTURE2D", "UTEXTURE3D", + "UTEXTURECUBE", "UTEXTURE2DARRAY", "ATTRIBUTE", "VARYING", "FLOAT16_T", + "FLOAT32_T", "DOUBLE", "FLOAT64_T", "INT64_T", "UINT64_T", "INT32_T", + "UINT32_T", "INT16_T", "UINT16_T", "INT8_T", "UINT8_T", "I64VEC2", + "I64VEC3", "I64VEC4", "U64VEC2", "U64VEC3", "U64VEC4", "I32VEC2", + "I32VEC3", "I32VEC4", "U32VEC2", "U32VEC3", "U32VEC4", "I16VEC2", + "I16VEC3", "I16VEC4", "U16VEC2", "U16VEC3", "U16VEC4", "I8VEC2", + "I8VEC3", "I8VEC4", "U8VEC2", "U8VEC3", "U8VEC4", "DVEC2", "DVEC3", + "DVEC4", "DMAT2", "DMAT3", "DMAT4", "F16VEC2", "F16VEC3", "F16VEC4", + "F16MAT2", "F16MAT3", "F16MAT4", "F32VEC2", "F32VEC3", "F32VEC4", + "F32MAT2", "F32MAT3", "F32MAT4", "F64VEC2", "F64VEC3", "F64VEC4", + "F64MAT2", "F64MAT3", "F64MAT4", "DMAT2X2", "DMAT2X3", "DMAT2X4", + "DMAT3X2", "DMAT3X3", "DMAT3X4", "DMAT4X2", "DMAT4X3", "DMAT4X4", + "F16MAT2X2", "F16MAT2X3", "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", + "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", "F16MAT4X4", "F32MAT2X2", + "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", + "F32MAT4X2", "F32MAT4X3", "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", + "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", + "F64MAT4X3", "F64MAT4X4", "ATOMIC_UINT", "ACCSTRUCTNV", "ACCSTRUCTEXT", + "RAYQUERYEXT", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", + "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", + "USAMPLERCUBEARRAY", "SAMPLER1D", "SAMPLER1DARRAY", + "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", "SAMPLER1DSHADOW", "SAMPLER2DRECT", + "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT", + "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLER2DMS", + "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", + "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", + "ISAMPLER1DARRAY", "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", + "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", + "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY", + "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY", + "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW", + "F16SAMPLER2DARRAYSHADOW", "F16SAMPLER2DRECTSHADOW", + "F16SAMPLERCUBESHADOW", "F16SAMPLERCUBEARRAYSHADOW", "IMAGE1D", + "IIMAGE1D", "UIMAGE1D", "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", + "IIMAGE3D", "UIMAGE3D", "IMAGE2DRECT", "IIMAGE2DRECT", "UIMAGE2DRECT", + "IMAGECUBE", "IIMAGECUBE", "UIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", + "UIMAGEBUFFER", "IMAGE1DARRAY", "IIMAGE1DARRAY", "UIMAGE1DARRAY", + "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBEARRAY", + "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "IMAGE2DMS", "IIMAGE2DMS", + "UIMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY", + "F16IMAGE1D", "F16IMAGE2D", "F16IMAGE3D", "F16IMAGE2DRECT", + "F16IMAGECUBE", "F16IMAGE1DARRAY", "F16IMAGE2DARRAY", + "F16IMAGECUBEARRAY", "F16IMAGEBUFFER", "F16IMAGE2DMS", + "F16IMAGE2DMSARRAY", "I64IMAGE1D", "U64IMAGE1D", "I64IMAGE2D", + "U64IMAGE2D", "I64IMAGE3D", "U64IMAGE3D", "I64IMAGE2DRECT", + "U64IMAGE2DRECT", "I64IMAGECUBE", "U64IMAGECUBE", "I64IMAGEBUFFER", + "U64IMAGEBUFFER", "I64IMAGE1DARRAY", "U64IMAGE1DARRAY", + "I64IMAGE2DARRAY", "U64IMAGE2DARRAY", "I64IMAGECUBEARRAY", + "U64IMAGECUBEARRAY", "I64IMAGE2DMS", "U64IMAGE2DMS", "I64IMAGE2DMSARRAY", + "U64IMAGE2DMSARRAY", "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY", + "UTEXTURECUBEARRAY", "TEXTURE1D", "ITEXTURE1D", "UTEXTURE1D", + "TEXTURE1DARRAY", "ITEXTURE1DARRAY", "UTEXTURE1DARRAY", "TEXTURE2DRECT", + "ITEXTURE2DRECT", "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER", + "UTEXTUREBUFFER", "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS", + "TEXTURE2DMSARRAY", "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY", + "F16TEXTURE1D", "F16TEXTURE2D", "F16TEXTURE3D", "F16TEXTURE2DRECT", + "F16TEXTURECUBE", "F16TEXTURE1DARRAY", "F16TEXTURE2DARRAY", + "F16TEXTURECUBEARRAY", "F16TEXTUREBUFFER", "F16TEXTURE2DMS", + "F16TEXTURE2DMSARRAY", "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT", + "ISUBPASSINPUTMS", "USUBPASSINPUT", "USUBPASSINPUTMS", "F16SUBPASSINPUT", + "F16SUBPASSINPUTMS", "SPIRV_INSTRUCTION", "SPIRV_EXECUTION_MODE", + "SPIRV_EXECUTION_MODE_ID", "SPIRV_DECORATE", "SPIRV_DECORATE_ID", + "SPIRV_DECORATE_STRING", "SPIRV_TYPE", "SPIRV_STORAGE_CLASS", + "SPIRV_BY_REFERENCE", "SPIRV_LITERAL", "LEFT_OP", "RIGHT_OP", "INC_OP", + "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", + "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", + "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", + "SUB_ASSIGN", "STRING_LITERAL", "LEFT_PAREN", "RIGHT_PAREN", + "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", + "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", + "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", + "CARET", "AMPERSAND", "QUESTION", "INVARIANT", "HIGH_PRECISION", + "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "PACKED", "RESOURCE", + "SUPERP", "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", + "IDENTIFIER", "TYPE_NAME", "CENTROID", "IN", "OUT", "INOUT", "STRUCT", + "VOID", "WHILE", "BREAK", "CONTINUE", "DO", "ELSE", "FOR", "IF", + "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", "TERMINATE_INVOCATION", + "TERMINATE_RAY", "IGNORE_INTERSECTION", "UNIFORM", "SHARED", "BUFFER", + "FLAT", "SMOOTH", "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT", + "UINT16CONSTANT", "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", + "INT64CONSTANT", "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV", + "PAYLOADINNV", "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PAYLOADEXT", + "PAYLOADINEXT", "HITATTREXT", "CALLDATAEXT", "CALLDATAINEXT", "PATCH", + "SAMPLE", "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY", + "WRITEONLY", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", + "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", + "SHADERCALLCOHERENT", "NOPERSPECTIVE", "EXPLICITINTERPAMD", + "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV", "PERTASKNV", "PRECISE", + "$accept", "variable_identifier", "primary_expression", + "postfix_expression", "integer_expression", "function_call", + "function_call_or_method", "function_call_generic", + "function_call_header_no_parameters", + "function_call_header_with_parameters", "function_call_header", + "function_identifier", "unary_expression", "unary_operator", + "multiplicative_expression", "additive_expression", "shift_expression", + "relational_expression", "equality_expression", "and_expression", + "exclusive_or_expression", "inclusive_or_expression", + "logical_and_expression", "logical_xor_expression", + "logical_or_expression", "conditional_expression", "$@1", + "assignment_expression", "assignment_operator", "expression", + "constant_expression", "declaration", "block_structure", "$@2", + "identifier_list", "function_prototype", "function_declarator", + "function_header_with_parameters", "function_header", + "parameter_declarator", "parameter_declaration", + "parameter_type_specifier", "init_declarator_list", "single_declaration", + "fully_specified_type", "invariant_qualifier", "interpolation_qualifier", + "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id", + "precise_qualifier", "type_qualifier", "single_type_qualifier", + "storage_qualifier", "non_uniform_qualifier", "type_name_list", + "type_specifier", "array_specifier", "type_parameter_specifier_opt", + "type_parameter_specifier", "type_parameter_specifier_list", + "type_specifier_nonarray", "precision_qualifier", "struct_specifier", + "$@3", "$@4", "struct_declaration_list", "struct_declaration", + "struct_declarator_list", "struct_declarator", "initializer", + "initializer_list", "declaration_statement", "statement", + "simple_statement", "demote_statement", "compound_statement", "$@5", + "$@6", "statement_no_new_scope", "statement_scoped", "$@7", "$@8", + "compound_statement_no_new_scope", "statement_list", + "expression_statement", "selection_statement", + "selection_statement_nonattributed", "selection_rest_statement", + "condition", "switch_statement", "switch_statement_nonattributed", "$@9", + "switch_statement_list", "case_label", "iteration_statement", + "iteration_statement_nonattributed", "$@10", "$@11", "$@12", + "for_init_statement", "conditionopt", "for_rest_statement", + "jump_statement", "translation_unit", "external_declaration", + "function_definition", "$@13", "attribute", "attribute_list", + "single_attribute", "spirv_requirements_list", + "spirv_requirements_parameter", "spirv_extension_list", + "spirv_capability_list", "spirv_execution_mode_qualifier", + "spirv_execution_mode_parameter_list", "spirv_execution_mode_parameter", + "spirv_execution_mode_id_parameter_list", + "spirv_storage_class_qualifier", "spirv_decorate_qualifier", + "spirv_decorate_parameter_list", "spirv_decorate_parameter", + "spirv_decorate_id_parameter_list", + "spirv_decorate_string_parameter_list", "spirv_type_specifier", + "spirv_type_parameter_list", "spirv_type_parameter", + "spirv_instruction_qualifier", "spirv_instruction_qualifier_list", + "spirv_instruction_qualifier_id", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_int16 yytoknum[] = +{ + 0, 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, 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, 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, 596, 597, 598, 599, 600, 601, 602, 603, 604, + 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, + 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, + 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, + 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, + 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, + 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, + 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, + 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, + 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, + 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, + 705, 706, 707, 708, 709 +}; +#endif + +#define YYPACT_NINF (-863) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-570) + +#define yytable_value_is_error(Yyn) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = +{ + 4549, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -260, -182, -177, -163, -130, + -115, -100, -89, -863, -863, -196, -863, -863, -863, -863, + -863, -324, -863, -863, -863, -863, -863, -306, -863, -863, + -863, -863, -863, -863, -77, -66, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -332, -175, + -153, -161, 7713, -266, -863, -71, -863, -863, -863, -863, + 5453, -863, -863, -863, -863, -116, -863, -863, 933, -863, + -863, 7713, -35, -863, -863, -863, 5905, -54, -139, -138, + -137, -128, -124, -54, -123, -51, 12061, -863, -15, -347, + -44, -863, -295, -863, -9, -6, 7713, -863, -863, -863, + 7713, -39, -38, -863, -303, -863, -226, -863, -863, 10762, + -3, -863, -863, -863, 1, -32, 7713, -863, -5, -8, + -1, -863, -230, -863, -219, -2, 3, 4, 5, -215, + 6, 8, 10, 11, 12, 15, -214, 13, 16, 21, + -134, -863, 17, 7713, -863, 19, -863, -212, -863, -863, + -211, 9030, -863, -273, 1385, -863, -863, -863, -863, -863, + -3, -263, -863, 9463, -236, -863, -28, -863, -106, 10762, + 10762, -863, 10762, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -264, -863, -863, -863, 23, -203, 11195, 25, + -863, 10762, -863, -863, -311, 24, -6, 29, -863, -309, + -54, -863, -20, -863, -323, 28, -118, 10762, -112, -863, + -155, -111, 10762, -103, 35, -98, -54, -863, 11628, -863, + -94, 10762, 32, -51, -863, 7713, 18, 6357, -863, 7713, + 10762, -863, -347, -863, 33, -863, -863, -72, -254, -86, + -297, -68, -13, 26, 20, 50, 49, -300, 42, 9896, + -863, 43, -863, -863, 55, 58, 60, -863, 65, 71, + 62, 10329, 73, 10762, 66, 69, 70, 72, 74, -241, + -863, -863, -41, -863, -175, 83, 85, -863, -863, -863, + -863, -863, 1837, -863, -863, -863, -863, -863, -863, -863, + -863, -863, 5001, 24, 9463, -233, 8164, -863, -863, 9463, + 7713, -863, 51, -863, -863, -863, -194, -863, -863, 10762, + 52, -863, -863, 10762, 88, -863, -863, -863, 10762, -863, + -863, -863, -315, -863, -863, -191, 82, -863, -863, -863, + -863, -863, -863, -190, -863, -187, -863, -863, -186, 86, + -863, -863, -863, -863, -169, -863, -168, -863, -167, 89, + -863, -165, 91, -157, 82, -863, 85, -156, -863, 94, + 98, -863, -863, 18, -3, -40, -863, -863, -863, 6809, + -863, -863, -863, 10762, 10762, 10762, 10762, 10762, 10762, 10762, + 10762, 10762, 10762, 10762, 10762, 10762, 10762, 10762, 10762, 10762, + 10762, 10762, -863, -863, -863, 97, -863, 2289, -863, -863, + -863, 2289, -863, 10762, -863, -863, -34, 10762, -79, -863, + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, 10762, 10762, -863, -863, -863, + -863, -863, -863, -863, 9463, -863, -863, -208, -863, 7261, + -863, -863, 99, 96, -863, -863, -863, -863, -863, -132, + -131, -863, -307, -863, -323, -863, -323, -863, 10762, 10762, + -863, -155, -863, -155, -863, 10762, 10762, -863, 93, 35, + -863, 11628, -863, 10762, -863, -863, -33, 24, 18, -863, + -863, -863, -863, -863, -72, -72, -254, -254, -86, -86, + -86, -86, -297, -297, -68, -13, 26, 20, 50, 49, + 10762, -863, 2289, 4097, 57, 3645, -154, -863, -152, -863, + -863, -863, -863, -863, 8597, -863, -863, -863, 105, -863, + 75, -863, -145, -863, -144, -863, -143, -863, -142, -863, + -141, -140, -863, -863, -863, -27, 100, 96, 76, 106, + 109, -863, -863, 4097, 107, -863, -863, -863, -863, -863, + -863, -863, -863, -863, -863, -863, 10762, -863, 101, 2741, + 10762, -863, 103, 113, 67, 112, 3193, -863, 114, -863, + 9463, -863, -863, -863, -133, 10762, 2741, 107, -863, -863, + 2289, -863, 110, 96, -863, -863, 2289, 116, -863, -863 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int16 yydefact[] = +{ + 0, 166, 219, 217, 218, 216, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 220, 221, 222, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 345, 346, 347, 348, 349, 350, 351, 371, 372, 373, + 374, 375, 376, 377, 386, 399, 400, 387, 388, 390, + 389, 391, 392, 393, 394, 395, 396, 397, 398, 174, + 175, 245, 246, 244, 247, 254, 255, 252, 253, 250, + 251, 248, 249, 277, 278, 279, 289, 290, 291, 274, + 275, 276, 286, 287, 288, 271, 272, 273, 283, 284, + 285, 268, 269, 270, 280, 281, 282, 256, 257, 258, + 292, 293, 294, 259, 260, 261, 304, 305, 306, 262, + 263, 264, 316, 317, 318, 265, 266, 267, 328, 329, + 330, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 343, 340, 341, + 342, 524, 525, 526, 355, 356, 379, 382, 344, 353, + 354, 370, 352, 401, 402, 405, 406, 407, 409, 410, + 411, 413, 414, 415, 417, 418, 514, 515, 378, 380, + 381, 357, 358, 359, 403, 360, 364, 365, 368, 408, + 412, 416, 361, 362, 366, 367, 404, 363, 369, 448, + 450, 451, 452, 454, 455, 456, 458, 459, 460, 462, + 463, 464, 466, 467, 468, 470, 471, 472, 474, 475, + 476, 478, 479, 480, 482, 483, 484, 486, 487, 488, + 490, 491, 449, 453, 457, 461, 465, 473, 477, 481, + 469, 485, 489, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 383, 384, 385, 419, 428, + 430, 424, 429, 431, 432, 434, 435, 436, 438, 439, + 440, 442, 443, 444, 446, 447, 420, 421, 422, 433, + 423, 425, 426, 427, 437, 441, 445, 516, 517, 520, + 521, 522, 523, 518, 519, 0, 0, 0, 0, 0, + 0, 0, 0, 164, 165, 0, 620, 137, 530, 531, + 532, 0, 529, 170, 168, 169, 167, 0, 215, 171, + 172, 173, 139, 138, 0, 199, 180, 182, 178, 184, + 186, 181, 183, 179, 185, 187, 176, 177, 201, 188, + 195, 196, 197, 198, 189, 190, 191, 192, 193, 194, + 140, 141, 142, 143, 144, 145, 152, 619, 0, 621, + 0, 114, 113, 0, 125, 130, 159, 158, 156, 160, + 0, 153, 155, 161, 135, 211, 157, 528, 0, 616, + 618, 0, 0, 162, 163, 527, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, + 0, 99, 0, 94, 0, 109, 0, 121, 115, 123, + 0, 124, 0, 97, 131, 102, 0, 154, 136, 0, + 204, 210, 1, 617, 0, 0, 0, 96, 0, 0, + 0, 628, 0, 681, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 626, + 0, 624, 0, 0, 533, 149, 151, 0, 147, 202, + 0, 0, 100, 0, 0, 622, 110, 116, 120, 122, + 118, 126, 117, 0, 132, 105, 0, 103, 0, 0, + 0, 9, 0, 43, 42, 44, 41, 5, 6, 7, + 8, 2, 16, 14, 15, 17, 10, 11, 12, 13, + 3, 18, 37, 20, 25, 26, 0, 0, 30, 0, + 213, 0, 36, 34, 0, 205, 111, 0, 95, 0, + 0, 679, 0, 636, 0, 0, 0, 0, 0, 653, + 0, 0, 0, 0, 0, 0, 0, 673, 0, 651, + 0, 0, 0, 0, 98, 0, 0, 0, 537, 0, + 0, 146, 0, 200, 0, 206, 45, 49, 52, 55, + 60, 63, 65, 67, 69, 71, 73, 75, 0, 0, + 101, 564, 573, 577, 0, 0, 0, 598, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, + 78, 91, 0, 551, 0, 161, 135, 554, 575, 553, + 561, 552, 0, 555, 556, 579, 557, 586, 558, 559, + 594, 560, 0, 119, 0, 127, 0, 545, 134, 0, + 0, 107, 0, 104, 38, 39, 0, 22, 23, 0, + 0, 28, 27, 0, 215, 31, 33, 40, 0, 212, + 112, 683, 0, 684, 629, 0, 0, 682, 648, 644, + 645, 646, 647, 0, 642, 0, 93, 649, 0, 0, + 663, 664, 665, 666, 0, 661, 0, 667, 0, 0, + 669, 0, 0, 0, 2, 677, 678, 0, 675, 0, + 0, 623, 625, 0, 543, 0, 541, 536, 538, 0, + 150, 148, 203, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 76, 207, 208, 0, 563, 0, 596, 609, + 608, 0, 600, 0, 612, 610, 0, 0, 0, 593, + 613, 614, 615, 562, 81, 82, 84, 83, 86, 87, + 88, 89, 90, 85, 80, 0, 0, 578, 574, 576, + 580, 587, 595, 129, 0, 548, 549, 0, 133, 0, + 108, 4, 0, 24, 21, 32, 214, 632, 634, 0, + 0, 680, 0, 638, 0, 637, 0, 640, 0, 0, + 655, 0, 654, 0, 657, 0, 0, 659, 0, 0, + 674, 0, 671, 0, 652, 627, 0, 544, 0, 539, + 534, 46, 47, 48, 51, 50, 53, 54, 58, 59, + 56, 57, 61, 62, 64, 66, 68, 70, 72, 74, + 0, 209, 565, 0, 0, 0, 0, 611, 0, 592, + 79, 92, 128, 546, 0, 106, 19, 630, 0, 631, + 0, 643, 0, 650, 0, 662, 0, 668, 0, 670, + 0, 0, 676, 540, 542, 0, 0, 584, 0, 0, + 0, 603, 602, 605, 571, 588, 547, 550, 633, 635, + 639, 641, 656, 658, 660, 672, 0, 566, 0, 0, + 0, 604, 0, 0, 583, 0, 0, 581, 0, 77, + 0, 568, 597, 567, 0, 606, 0, 571, 570, 572, + 590, 585, 0, 607, 601, 582, 591, 0, 599, 589 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -863, -863, -863, -863, -863, -863, -863, -863, -863, -863, + -863, -863, -418, -863, -380, -379, -484, -382, -258, -256, + -253, -257, -252, -255, -863, -478, -863, -485, -863, -491, + -530, 14, -863, -863, -863, 7, -397, -863, -863, 44, + 53, 47, -863, -863, -400, -863, -863, -863, -863, -92, + -863, -377, -362, -863, 9, -863, 0, -414, -863, -863, + -863, -863, 150, -863, -863, -863, -546, -548, -218, -331, + -624, -863, -359, -609, -862, -863, -417, -863, -863, -427, + -426, -863, -863, 68, -719, -355, -863, -136, -863, -389, + -863, -135, -863, -863, -863, -863, -129, -863, -863, -863, + -863, -863, -863, -863, -863, 102, -863, -863, 2, -863, + -65, -234, -432, -863, -863, -863, -301, -293, -294, -863, + -863, -304, -299, -302, -298, -863, -296, -305, -863, -383, + -526 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 520, 521, 522, 782, 523, 524, 525, 526, 527, + 528, 529, 609, 531, 577, 578, 579, 580, 581, 582, + 583, 584, 585, 586, 587, 610, 840, 611, 765, 612, + 695, 613, 378, 640, 498, 614, 380, 381, 382, 427, + 428, 429, 383, 384, 385, 386, 387, 388, 477, 478, + 389, 390, 391, 392, 532, 480, 533, 483, 440, 441, + 534, 395, 396, 397, 569, 473, 567, 568, 705, 706, + 638, 777, 617, 618, 619, 620, 621, 737, 876, 912, + 904, 905, 906, 913, 622, 623, 624, 625, 907, 879, + 626, 627, 908, 927, 628, 629, 630, 843, 741, 845, + 883, 902, 903, 631, 398, 399, 400, 424, 632, 470, + 471, 450, 451, 789, 790, 402, 673, 674, 678, 403, + 404, 684, 685, 688, 691, 405, 697, 698, 406, 452, + 453 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 394, 445, 401, 588, 444, 430, 445, 379, 637, 393, + 773, 646, 776, 769, 377, 778, 667, 677, 842, 708, + 494, 530, 687, 709, 446, 668, 535, 421, 437, 446, + 466, 700, 667, 787, 720, 721, 731, 911, 475, 661, + 710, 661, 662, 655, 919, 658, 492, 417, 481, 430, + 328, 329, 330, 422, 911, 493, 481, 659, 669, 670, + 671, 672, 476, 576, 482, 647, 648, 788, 437, 676, + 722, 723, 732, 663, 676, 663, 633, 635, 589, 418, + 676, 644, 645, 676, 437, -35, 590, 649, 481, 407, + 432, 650, 676, 433, 779, 634, 565, 754, 755, 756, + 757, 758, 759, 760, 761, 762, 763, 716, 664, 717, + 746, 735, 748, 657, 664, 589, 664, 764, 589, 664, + 541, 664, 639, 664, 664, 774, 542, 495, 664, 576, + 496, 543, 844, 497, 576, 549, 557, 544, 571, 573, + 576, 550, 558, 576, 572, 574, 853, 652, 854, 637, + 852, 637, 576, 653, 637, 415, 781, 665, 783, 791, + 793, 708, 766, 795, 797, 542, 794, 408, 785, 796, + 798, 576, 409, 693, 456, 458, 460, 462, 464, 465, + 468, 800, 802, 804, 423, 807, 410, 801, 803, 805, + 565, 808, 565, 810, 812, 426, 884, 425, 885, 811, + 813, 926, 766, 437, 766, 890, 891, 892, 893, 894, + 895, 794, 798, 801, 805, 808, 813, 922, 562, 411, + 857, 859, 563, 766, 858, 860, 680, 681, 682, 683, + 887, 708, 445, 769, 412, 444, 828, 829, 830, 831, + 786, 718, 719, 454, 457, 459, 455, 455, 455, 413, + 642, 439, 846, 643, 461, 446, 848, 455, 463, 467, + 414, 455, 455, 565, 675, 724, 725, 455, 863, 677, + 679, 686, 419, 455, 455, 867, 687, 766, 849, 689, + 850, 851, 455, 420, 692, 667, 921, 455, 699, 637, + 817, 455, 713, 714, 715, 821, 822, 823, 576, 576, + 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, + 576, 576, 576, 576, 434, 766, 818, 769, 767, 819, + 676, 676, 766, 818, 447, 847, 873, 676, 676, 766, + 896, 449, 565, 676, 469, 676, 824, 825, 474, 826, + 827, 479, 832, 833, 484, 325, 490, 491, 481, 875, + 539, 536, 877, 537, 538, 540, 545, 641, 726, 546, + 547, 548, 551, 559, 552, 666, 553, 554, 555, 637, + 561, 556, 560, 651, 656, 589, 564, 570, 492, 662, + 576, 576, 431, 690, 701, 729, 730, 576, 576, 728, + 438, 393, 877, 576, 733, 576, 727, 736, 394, 393, + 401, 394, 565, 704, 738, 379, 394, 393, 401, 914, + 393, 909, 377, 448, 742, 393, 472, 739, 712, 740, + 743, 744, 747, 749, 923, 637, 431, 486, 750, 751, + 431, 752, -36, 753, -34, 393, 780, 784, -29, 393, + 792, 869, 799, 878, 814, 806, 438, 809, 815, 841, + 880, 856, 766, 888, 897, 393, 899, 889, 900, 910, + -569, 898, 915, 916, 917, 591, 446, 920, 834, 928, + 929, 835, 837, 566, 488, 836, 839, 489, 838, 487, + 711, 416, 393, 878, 616, 816, 881, 874, 918, 924, + 882, 925, 485, 615, 901, 862, 770, 771, 702, 866, + 443, 861, 865, 772, 868, 864, 446, 0, 872, 0, + 0, 870, 0, 0, 0, 871, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 660, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 696, 0, + 0, 0, 0, 0, 0, 703, 0, 566, 0, 566, + 0, 0, 0, 0, 393, 0, 393, 0, 393, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 616, 0, 0, 0, 0, 0, 0, 0, + 0, 615, 394, 0, 0, 0, 0, 0, 0, 0, + 566, 393, 0, 0, 0, 0, 0, 0, 0, 393, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 566, + 0, 0, 0, 0, 0, 0, 0, 0, 393, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 616, 0, 0, + 0, 616, 0, 0, 0, 0, 615, 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, 566, + 0, 0, 0, 0, 0, 0, 0, 0, 393, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 696, 0, 696, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 616, 616, 0, 616, 0, 401, 0, 0, + 0, 615, 615, 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, 616, 0, 0, 0, 0, 0, 0, + 0, 0, 615, 0, 0, 0, 0, 0, 0, 616, + 0, 0, 0, 0, 0, 0, 616, 0, 615, 0, + 0, 0, 0, 0, 0, 615, 616, 0, 0, 0, + 616, 0, 0, 0, 0, 615, 616, 0, 0, 615, + 0, 0, 0, 442, 0, 615, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, + 0, 0, 326, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 327, 328, 329, 330, + 331, 0, 0, 0, 0, 0, 0, 0, 0, 332, + 333, 334, 335, 336, 337, 338, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 340, 341, 342, 343, 344, 0, 0, 0, + 0, 0, 0, 0, 0, 345, 0, 346, 347, 348, + 349, 350, 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, 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 499, 500, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 501, 502, 0, 325, 0, 591, 592, + 0, 0, 0, 0, 593, 503, 504, 505, 506, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 327, 328, + 329, 330, 331, 0, 0, 0, 507, 508, 509, 510, + 511, 332, 333, 334, 335, 336, 337, 338, 594, 595, + 596, 597, 0, 598, 599, 600, 601, 602, 603, 604, + 605, 606, 607, 339, 340, 341, 342, 343, 344, 512, + 513, 514, 515, 516, 517, 518, 519, 345, 608, 346, + 347, 348, 349, 350, 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, + 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, 0, 0, 499, 500, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 501, 502, 0, 325, 0, + 591, 768, 0, 0, 0, 0, 593, 503, 504, 505, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 327, 328, 329, 330, 331, 0, 0, 0, 507, 508, + 509, 510, 511, 332, 333, 334, 335, 336, 337, 338, + 594, 595, 596, 597, 0, 598, 599, 600, 601, 602, + 603, 604, 605, 606, 607, 339, 340, 341, 342, 343, + 344, 512, 513, 514, 515, 516, 517, 518, 519, 345, + 608, 346, 347, 348, 349, 350, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, 0, 0, 499, 500, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 501, 502, 0, + 325, 0, 591, 0, 0, 0, 0, 0, 593, 503, + 504, 505, 506, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 327, 328, 329, 330, 331, 0, 0, 0, + 507, 508, 509, 510, 511, 332, 333, 334, 335, 336, + 337, 338, 594, 595, 596, 597, 0, 598, 599, 600, + 601, 602, 603, 604, 605, 606, 607, 339, 340, 341, + 342, 343, 344, 512, 513, 514, 515, 516, 517, 518, + 519, 345, 608, 346, 347, 348, 349, 350, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, 0, 0, + 499, 500, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, + 502, 0, 325, 0, 484, 0, 0, 0, 0, 0, + 593, 503, 504, 505, 506, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 327, 328, 329, 330, 331, 0, + 0, 0, 507, 508, 509, 510, 511, 332, 333, 334, + 335, 336, 337, 338, 594, 595, 596, 597, 0, 598, + 599, 600, 601, 602, 603, 604, 605, 606, 607, 339, + 340, 341, 342, 343, 344, 512, 513, 514, 515, 516, + 517, 518, 519, 345, 608, 346, 347, 348, 349, 350, + 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, + 0, 0, 499, 500, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 501, 502, 0, 325, 0, 0, 0, 0, 0, + 0, 0, 593, 503, 504, 505, 506, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 327, 328, 329, 330, + 331, 0, 0, 0, 507, 508, 509, 510, 511, 332, + 333, 334, 335, 336, 337, 338, 594, 595, 596, 597, + 0, 598, 599, 600, 601, 602, 603, 604, 605, 606, + 607, 339, 340, 341, 342, 343, 344, 512, 513, 514, + 515, 516, 517, 518, 519, 345, 608, 346, 347, 348, + 349, 350, 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, 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 499, 500, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 501, 502, 0, 325, 0, 0, 0, + 0, 0, 0, 0, 593, 503, 504, 505, 506, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 327, 328, + 329, 330, 331, 0, 0, 0, 507, 508, 509, 510, + 511, 332, 333, 334, 335, 336, 337, 338, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 339, 340, 341, 342, 343, 344, 512, + 513, 514, 515, 516, 517, 518, 519, 345, 0, 346, + 347, 348, 349, 350, 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, + 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, 0, 0, 0, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 499, 500, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 501, 502, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 503, 504, 505, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 327, 328, 329, 330, 0, 0, 0, 0, 507, 508, + 509, 510, 511, 332, 333, 334, 335, 336, 337, 338, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 339, 340, 341, 342, 343, + 344, 512, 513, 514, 515, 516, 517, 518, 519, 345, + 0, 346, 347, 348, 349, 350, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 325, 0, 0, 0, 0, 0, 0, 0, 326, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 327, 328, 329, 330, 331, 0, 0, 0, + 0, 0, 0, 0, 0, 332, 333, 334, 335, 336, + 337, 338, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 340, 341, + 342, 343, 344, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 0, 346, 347, 348, 349, 350, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, 0, 0, + 0, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 327, 328, 329, 330, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 332, 333, 334, + 335, 336, 337, 338, 594, 0, 0, 597, 0, 598, + 599, 0, 0, 602, 0, 0, 0, 0, 0, 339, + 340, 341, 342, 343, 344, 0, 0, 0, 0, 0, + 0, 0, 0, 345, 0, 346, 347, 348, 349, 350, + 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, + 0, 0, 0, 318, 319, 320, 321, 322, 323, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 435, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 327, 328, 329, 330, + 0, 0, 0, 0, 0, 0, 0, 0, 436, 332, + 333, 334, 335, 336, 337, 338, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 340, 341, 342, 343, 344, 0, 0, 0, + 0, 0, 0, 0, 0, 345, 0, 346, 347, 348, + 349, 350, 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, 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 327, 328, + 329, 330, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 332, 333, 334, 335, 336, 337, 338, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 339, 340, 341, 342, 343, 344, 0, + 0, 0, 0, 0, 0, 0, 0, 345, 0, 346, + 347, 348, 349, 350, 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, + 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, 0, 0, 0, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 707, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 327, 328, 329, 330, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 332, 333, 334, 335, 336, 337, 338, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 339, 340, 341, 342, 343, + 344, 0, 0, 0, 0, 0, 0, 0, 0, 345, + 0, 346, 347, 348, 349, 350, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, 0, 0, 0, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 820, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 327, 328, 329, 330, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 332, 333, 334, 335, 336, + 337, 338, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 340, 341, + 342, 343, 344, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 0, 346, 347, 348, 349, 350, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, 0, 0, + 0, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 855, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 327, 328, 329, 330, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 332, 333, 334, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, + 340, 341, 342, 343, 344, 0, 0, 0, 0, 0, + 0, 0, 0, 345, 0, 346, 347, 348, 349, 350, + 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, + 0, 0, 0, 318, 319, 320, 321, 322, 323, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 327, 328, 329, 330, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, + 333, 334, 335, 336, 337, 338, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 339, 340, 341, 342, 343, 344, 0, 0, 0, + 0, 0, 0, 0, 0, 345, 0, 346, 347, 348, + 349, 350, 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, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, 0, 0, 0, 321, 0, 0, + 0, 0, 0, 499, 500, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 501, 502, 0, 0, 0, 636, 775, 0, + 0, 0, 0, 0, 503, 504, 505, 506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 507, 508, 509, 510, 511, + 332, 0, 0, 0, 0, 337, 338, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 512, 513, + 514, 515, 516, 517, 518, 519, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 358, 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, 0, 0, + 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, 0, 0, 0, 0, 0, 0, + 321, 0, 0, 0, 0, 0, 499, 500, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 501, 502, 0, 0, 0, + 636, 886, 0, 0, 0, 0, 0, 503, 504, 505, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 507, 508, + 509, 510, 511, 332, 0, 0, 0, 0, 337, 338, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 512, 513, 514, 515, 516, 517, 518, 519, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 358, 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, 0, 0, 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, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 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, 0, 0, 0, + 0, 0, 0, 321, 0, 0, 0, 0, 0, 499, + 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 501, 502, + 0, 0, 575, 0, 0, 0, 0, 0, 0, 0, + 503, 504, 505, 506, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 507, 508, 509, 510, 511, 332, 0, 0, 0, + 0, 337, 338, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 512, 513, 514, 515, 516, 517, + 518, 519, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 358, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, + 0, 0, 0, 0, 0, 0, 321, 0, 0, 0, + 0, 0, 499, 500, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 501, 502, 0, 0, 0, 636, 0, 0, 0, + 0, 0, 0, 503, 504, 505, 506, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 507, 508, 509, 510, 511, 332, + 0, 0, 0, 0, 337, 338, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 512, 513, 514, + 515, 516, 517, 518, 519, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 358, + 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, 0, 0, 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, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, 0, 0, 0, 321, + 0, 0, 0, 0, 0, 499, 500, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 501, 502, 0, 0, 734, 0, + 0, 0, 0, 0, 0, 0, 503, 504, 505, 506, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 507, 508, 509, + 510, 511, 332, 0, 0, 0, 0, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 512, 513, 514, 515, 516, 517, 518, 519, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 358, 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, + 0, 0, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, 0, 0, 0, 0, + 0, 0, 321, 0, 0, 0, 0, 0, 499, 500, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 501, 502, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 745, 503, + 504, 505, 506, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 507, 508, 509, 510, 511, 332, 0, 0, 0, 0, + 337, 338, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 512, 513, 514, 515, 516, 517, 518, + 519, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 358, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 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, 0, + 0, 0, 0, 0, 0, 321, 0, 0, 0, 0, + 0, 499, 500, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 501, 502, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 503, 504, 505, 506, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 507, 508, 509, 510, 511, 332, 0, + 0, 0, 0, 337, 338, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 512, 513, 514, 515, + 516, 517, 518, 519, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 358, 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, 0, 0, 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, 0, 0, 0, 321, 0, + 0, 0, 0, 0, 499, 500, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 501, 502, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 503, 504, 505, 506, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 507, 508, 509, 510, + 511, 332, 0, 0, 0, 0, 337, 654, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, + 513, 514, 515, 516, 517, 518, 519, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 358, 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, 0, + 0, 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, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 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, 0, 0, 0, 0, 0, + 0, 321, 0, 0, 0, 0, 0, 499, 500, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 501, 502, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 503, 504, + 505, 506, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 507, + 508, 509, 510, 694, 332, 0, 0, 0, 0, 337, + 338, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 512, 513, 514, 515, 516, 517, 518, 519, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 358, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, 0, 0, + 0, 0, 0, 0, 321, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 332, 0, 0, + 0, 0, 337, 338 +}; + +static const yytype_int16 yycheck[] = +{ + 0, 401, 0, 481, 401, 382, 406, 0, 493, 0, + 634, 502, 636, 622, 0, 639, 542, 547, 737, 567, + 434, 439, 552, 569, 401, 348, 440, 359, 390, 406, + 413, 561, 558, 348, 331, 332, 336, 899, 385, 348, + 570, 348, 351, 528, 906, 356, 349, 353, 351, 426, + 374, 375, 376, 385, 916, 358, 351, 368, 381, 382, + 383, 384, 409, 481, 359, 329, 330, 382, 430, 547, + 367, 368, 372, 382, 552, 382, 490, 491, 351, 385, + 558, 499, 500, 561, 446, 349, 359, 351, 351, 349, + 356, 355, 570, 359, 640, 358, 473, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 361, 540, 363, + 601, 589, 603, 531, 546, 351, 548, 358, 351, 551, + 350, 553, 358, 555, 556, 358, 356, 353, 560, 547, + 356, 350, 741, 359, 552, 350, 350, 356, 350, 350, + 558, 356, 356, 561, 356, 356, 354, 350, 356, 634, + 774, 636, 570, 356, 639, 351, 350, 540, 649, 350, + 350, 709, 356, 350, 350, 356, 356, 349, 653, 356, + 356, 589, 349, 556, 408, 409, 410, 411, 412, 413, + 414, 350, 350, 350, 359, 350, 349, 356, 356, 356, + 567, 356, 569, 350, 350, 356, 350, 350, 350, 356, + 356, 920, 356, 565, 356, 350, 350, 350, 350, 350, + 350, 356, 356, 356, 356, 356, 356, 350, 352, 349, + 352, 352, 356, 356, 356, 356, 381, 382, 383, 384, + 854, 779, 632, 842, 349, 632, 720, 721, 722, 723, + 658, 327, 328, 382, 382, 382, 385, 385, 385, 349, + 356, 367, 743, 359, 382, 632, 747, 385, 382, 382, + 349, 385, 385, 640, 382, 333, 334, 385, 798, 799, + 382, 382, 349, 385, 385, 805, 806, 356, 357, 382, + 765, 766, 385, 349, 382, 811, 910, 385, 382, 774, + 704, 385, 364, 365, 366, 713, 714, 715, 716, 717, + 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, + 728, 729, 730, 731, 385, 356, 356, 926, 359, 359, + 798, 799, 356, 356, 359, 359, 359, 805, 806, 356, + 357, 385, 709, 811, 385, 813, 716, 717, 353, 718, + 719, 385, 724, 725, 353, 351, 385, 385, 351, 840, + 358, 350, 843, 385, 359, 356, 358, 385, 371, 356, + 356, 356, 356, 350, 356, 385, 356, 356, 356, 854, + 349, 356, 356, 350, 349, 351, 359, 358, 349, 351, + 798, 799, 382, 348, 352, 335, 337, 805, 806, 369, + 390, 382, 883, 811, 352, 813, 370, 354, 398, 390, + 398, 401, 779, 385, 349, 398, 406, 398, 406, 900, + 401, 896, 398, 406, 349, 406, 416, 359, 385, 359, + 349, 359, 349, 357, 915, 910, 426, 425, 359, 359, + 430, 359, 349, 359, 349, 426, 385, 385, 350, 430, + 358, 348, 356, 843, 350, 356, 446, 356, 350, 352, + 393, 352, 356, 348, 354, 446, 350, 382, 349, 358, + 353, 385, 359, 350, 397, 353, 843, 353, 726, 359, + 354, 727, 729, 473, 430, 728, 731, 430, 730, 426, + 572, 331, 473, 883, 484, 703, 845, 818, 905, 916, + 845, 917, 424, 484, 883, 796, 632, 632, 563, 803, + 398, 794, 801, 632, 806, 799, 883, -1, 813, -1, + -1, 809, -1, -1, -1, 811, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 536, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 558, -1, + -1, -1, -1, -1, -1, 565, -1, 567, -1, 569, + -1, -1, -1, -1, 565, -1, 567, -1, 569, -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, 622, -1, -1, -1, -1, -1, -1, -1, + -1, 622, 632, -1, -1, -1, -1, -1, -1, -1, + 640, 632, -1, -1, -1, -1, -1, -1, -1, 640, + -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, 709, + -1, -1, -1, -1, -1, -1, -1, -1, 709, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 737, -1, -1, + -1, 741, -1, -1, -1, -1, 737, -1, -1, -1, + 741, -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, 779, + -1, -1, -1, -1, -1, -1, -1, -1, 779, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 811, -1, 813, -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, 842, 843, -1, 845, -1, 845, -1, -1, + -1, 842, 843, -1, 845, -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, 883, -1, -1, -1, -1, -1, -1, + -1, -1, 883, -1, -1, -1, -1, -1, -1, 899, + -1, -1, -1, -1, -1, -1, 906, -1, 899, -1, + -1, -1, -1, -1, -1, 906, 916, -1, -1, -1, + 920, -1, -1, -1, -1, 916, 926, -1, -1, 920, + -1, -1, -1, 0, -1, 926, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 351, -1, -1, -1, -1, -1, + -1, -1, 359, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 373, 374, 375, 376, + 377, -1, -1, -1, -1, -1, -1, -1, -1, 386, + 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 408, 409, 410, 411, 412, 413, -1, -1, -1, + -1, -1, -1, -1, -1, 422, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, -1, -1, 329, 330, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 348, 349, -1, 351, -1, 353, 354, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 373, 374, + 375, 376, 377, -1, -1, -1, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, -1, 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, + 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, 329, 330, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 348, 349, -1, 351, -1, + 353, 354, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 373, 374, 375, 376, 377, -1, -1, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, -1, 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, 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, -1, -1, 329, 330, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 348, 349, -1, + 351, -1, 353, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 373, 374, 375, 376, 377, -1, -1, -1, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, -1, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, -1, -1, + 329, 330, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 348, + 349, -1, 351, -1, 353, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 373, 374, 375, 376, 377, -1, + -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, 391, 392, 393, 394, 395, 396, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, + -1, -1, 329, 330, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 348, 349, -1, 351, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 373, 374, 375, 376, + 377, -1, -1, -1, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, -1, -1, 329, 330, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 348, 349, -1, 351, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 373, 374, + 375, 376, 377, -1, -1, -1, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 421, 422, -1, 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, + 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, 320, 321, 322, + 323, 324, 325, 326, -1, -1, 329, 330, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 348, 349, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 373, 374, 375, 376, -1, -1, -1, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, + -1, 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, 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 351, -1, -1, -1, -1, -1, -1, -1, 359, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 373, 374, 375, 376, 377, -1, -1, -1, + -1, -1, -1, -1, -1, 386, 387, 388, 389, 390, + 391, 392, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 408, 409, 410, + 411, 412, 413, -1, -1, -1, -1, -1, -1, -1, + -1, 422, -1, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, -1, -1, + -1, 320, 321, 322, 323, 324, 325, 326, -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, 373, 374, 375, 376, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 386, 387, 388, + 389, 390, 391, 392, 393, -1, -1, 396, -1, 398, + 399, -1, -1, 402, -1, -1, -1, -1, -1, 408, + 409, 410, 411, 412, 413, -1, -1, -1, -1, -1, + -1, -1, -1, 422, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, + -1, -1, -1, 320, 321, 322, 323, 324, 325, 326, + -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, 359, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 373, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, -1, 385, 386, + 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 408, 409, 410, 411, 412, 413, -1, -1, -1, + -1, -1, -1, -1, -1, 422, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, 320, 321, 322, 323, 324, + 325, 326, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 351, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 373, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 386, 387, 388, 389, 390, 391, 392, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 408, 409, 410, 411, 412, 413, -1, + -1, -1, -1, -1, -1, -1, -1, 422, -1, 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, + 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, 320, 321, 322, + 323, 324, 325, 326, -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, 354, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 373, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 386, 387, 388, 389, 390, 391, 392, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 408, 409, 410, 411, 412, + 413, -1, -1, -1, -1, -1, -1, -1, -1, 422, + -1, 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, 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, -1, -1, -1, 320, + 321, 322, 323, 324, 325, 326, -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, 354, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 373, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 386, 387, 388, 389, 390, + 391, 392, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 408, 409, 410, + 411, 412, 413, -1, -1, -1, -1, -1, -1, -1, + -1, 422, -1, 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, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, -1, -1, + -1, 320, 321, 322, 323, 324, 325, 326, -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, 354, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 373, 374, 375, 376, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 386, 387, 388, + 389, 390, 391, 392, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, + 409, 410, 411, 412, 413, -1, -1, -1, -1, -1, + -1, -1, -1, 422, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, + -1, -1, -1, 320, 321, 322, 323, 324, 325, 326, + -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, 373, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 386, + 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 408, 409, 410, 411, 412, 413, -1, -1, -1, + -1, -1, -1, -1, -1, 422, -1, 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, 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, -1, -1, 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, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 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, -1, -1, -1, -1, -1, -1, 323, -1, -1, + -1, -1, -1, 329, 330, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 348, 349, -1, -1, -1, 353, 354, -1, + -1, -1, -1, -1, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 381, 382, 383, 384, 385, + 386, -1, -1, -1, -1, 391, 392, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 414, 415, + 416, 417, 418, 419, 420, 421, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 436, 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, -1, -1, + 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, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, -1, -1, -1, + 323, -1, -1, -1, -1, -1, 329, 330, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 348, 349, -1, -1, -1, + 353, 354, -1, -1, -1, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 381, 382, + 383, 384, 385, 386, -1, -1, -1, -1, 391, 392, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 414, 415, 416, 417, 418, 419, 420, 421, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 436, 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, -1, -1, 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, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 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, -1, -1, -1, + -1, -1, -1, 323, -1, -1, -1, -1, -1, 329, + 330, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 348, 349, + -1, -1, 352, -1, -1, -1, -1, -1, -1, -1, + 360, 361, 362, 363, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 381, 382, 383, 384, 385, 386, -1, -1, -1, + -1, 391, 392, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 414, 415, 416, 417, 418, 419, + 420, 421, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 436, 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, -1, -1, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 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, + -1, -1, -1, -1, -1, -1, 323, -1, -1, -1, + -1, -1, 329, 330, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 348, 349, -1, -1, -1, 353, -1, -1, -1, + -1, -1, -1, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 381, 382, 383, 384, 385, 386, + -1, -1, -1, -1, 391, 392, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 414, 415, 416, + 417, 418, 419, 420, 421, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 436, + 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, -1, -1, 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, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, -1, -1, -1, 323, + -1, -1, -1, -1, -1, 329, 330, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 348, 349, -1, -1, 352, -1, + -1, -1, -1, -1, -1, -1, 360, 361, 362, 363, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 381, 382, 383, + 384, 385, 386, -1, -1, -1, -1, 391, 392, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 414, 415, 416, 417, 418, 419, 420, 421, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 436, 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, + -1, -1, 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, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 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, -1, -1, -1, -1, + -1, -1, 323, -1, -1, -1, -1, -1, 329, 330, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 348, 349, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 381, 382, 383, 384, 385, 386, -1, -1, -1, -1, + 391, 392, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 414, 415, 416, 417, 418, 419, 420, + 421, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 436, 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, -1, -1, 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, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 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, -1, + -1, -1, -1, -1, -1, 323, -1, -1, -1, -1, + -1, 329, 330, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 348, 349, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 360, 361, 362, 363, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 381, 382, 383, 384, 385, 386, -1, + -1, -1, -1, 391, 392, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 414, 415, 416, 417, + 418, 419, 420, 421, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 436, 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, -1, -1, 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, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, -1, -1, -1, 323, -1, + -1, -1, -1, -1, 329, 330, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 348, 349, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 381, 382, 383, 384, + 385, 386, -1, -1, -1, -1, 391, 392, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 414, + 415, 416, 417, 418, 419, 420, 421, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 436, 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, -1, + -1, 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, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, -1, -1, -1, + -1, 323, -1, -1, -1, -1, -1, 329, 330, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 348, 349, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 360, 361, + 362, 363, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 381, + 382, 383, 384, 385, 386, -1, -1, -1, -1, 391, + 392, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 414, 415, 416, 417, 418, 419, 420, 421, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 436, 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, -1, -1, 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, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 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, -1, -1, + -1, -1, -1, -1, 323, -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, 386, -1, -1, + -1, -1, 391, 392 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_int16 yystos[] = +{ + 0, 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, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 351, 359, 373, 374, 375, + 376, 377, 386, 387, 388, 389, 390, 391, 392, 408, + 409, 410, 411, 412, 413, 422, 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, 486, 487, 490, + 491, 492, 493, 497, 498, 499, 500, 501, 502, 505, + 506, 507, 508, 509, 511, 516, 517, 518, 559, 560, + 561, 563, 570, 574, 575, 580, 583, 349, 349, 349, + 349, 349, 349, 349, 349, 351, 517, 353, 385, 349, + 349, 359, 385, 359, 562, 350, 356, 494, 495, 496, + 506, 511, 356, 359, 385, 359, 385, 507, 511, 367, + 513, 514, 0, 560, 491, 499, 506, 359, 490, 385, + 566, 567, 584, 585, 382, 385, 566, 382, 566, 382, + 566, 382, 566, 382, 566, 566, 584, 382, 566, 385, + 564, 565, 511, 520, 353, 385, 409, 503, 504, 385, + 510, 351, 359, 512, 353, 538, 563, 495, 494, 496, + 385, 385, 349, 358, 512, 353, 356, 359, 489, 329, + 330, 348, 349, 360, 361, 362, 363, 381, 382, 383, + 384, 385, 414, 415, 416, 417, 418, 419, 420, 421, + 456, 457, 458, 460, 461, 462, 463, 464, 465, 466, + 467, 468, 509, 511, 515, 512, 350, 385, 359, 358, + 356, 350, 356, 350, 356, 358, 356, 356, 356, 350, + 356, 356, 356, 356, 356, 356, 356, 350, 356, 350, + 356, 349, 352, 356, 359, 506, 511, 521, 522, 519, + 358, 350, 356, 350, 356, 352, 467, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 351, + 359, 353, 354, 359, 393, 394, 395, 396, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 423, 467, + 480, 482, 484, 486, 490, 509, 511, 527, 528, 529, + 530, 531, 539, 540, 541, 542, 545, 546, 549, 550, + 551, 558, 563, 512, 358, 512, 353, 482, 525, 358, + 488, 385, 356, 359, 467, 467, 484, 329, 330, 351, + 355, 350, 350, 356, 392, 482, 349, 467, 356, 368, + 563, 348, 351, 382, 567, 584, 385, 585, 348, 381, + 382, 383, 384, 571, 572, 382, 480, 485, 573, 382, + 381, 382, 383, 384, 576, 577, 382, 485, 578, 382, + 348, 579, 382, 584, 385, 485, 511, 581, 582, 382, + 485, 352, 565, 511, 385, 523, 524, 354, 522, 521, + 485, 504, 385, 364, 365, 366, 361, 363, 327, 328, + 331, 332, 367, 368, 333, 334, 371, 370, 369, 335, + 337, 336, 372, 352, 352, 480, 354, 532, 349, 359, + 359, 553, 349, 349, 359, 359, 484, 349, 484, 357, + 359, 359, 359, 359, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 358, 483, 356, 359, 354, 528, + 542, 546, 551, 525, 358, 354, 525, 526, 525, 521, + 385, 350, 459, 484, 385, 482, 467, 348, 382, 568, + 569, 350, 358, 350, 356, 350, 356, 350, 356, 356, + 350, 356, 350, 356, 350, 356, 356, 350, 356, 356, + 350, 356, 350, 356, 350, 350, 523, 512, 356, 359, + 354, 467, 467, 467, 469, 469, 470, 470, 471, 471, + 471, 471, 472, 472, 473, 474, 475, 476, 477, 478, + 481, 352, 539, 552, 528, 554, 484, 359, 484, 357, + 482, 482, 525, 354, 356, 354, 352, 352, 356, 352, + 356, 572, 571, 485, 573, 577, 576, 485, 578, 348, + 579, 581, 582, 359, 524, 484, 533, 484, 499, 544, + 393, 527, 540, 555, 350, 350, 354, 525, 348, 382, + 350, 350, 350, 350, 350, 350, 357, 354, 385, 350, + 349, 544, 556, 557, 535, 536, 537, 543, 547, 482, + 358, 529, 534, 538, 484, 359, 350, 397, 531, 529, + 353, 525, 350, 484, 534, 535, 539, 548, 359, 354 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_int16 yyr1[] = +{ + 0, 455, 456, 457, 457, 457, 457, 457, 457, 457, + 457, 457, 457, 457, 457, 457, 457, 457, 458, 458, + 458, 458, 458, 458, 459, 460, 461, 462, 462, 463, + 463, 464, 464, 465, 466, 466, 466, 467, 467, 467, + 467, 468, 468, 468, 468, 469, 469, 469, 469, 470, + 470, 470, 471, 471, 471, 472, 472, 472, 472, 472, + 473, 473, 473, 474, 474, 475, 475, 476, 476, 477, + 477, 478, 478, 479, 479, 480, 481, 480, 482, 482, + 483, 483, 483, 483, 483, 483, 483, 483, 483, 483, + 483, 484, 484, 485, 486, 486, 486, 486, 486, 486, + 486, 486, 486, 486, 486, 488, 487, 489, 489, 490, + 490, 490, 490, 491, 491, 492, 492, 493, 494, 494, + 495, 495, 495, 495, 496, 497, 497, 497, 497, 497, + 498, 498, 498, 498, 498, 499, 499, 500, 501, 501, + 501, 501, 501, 501, 501, 501, 502, 503, 503, 504, + 504, 504, 505, 506, 506, 507, 507, 507, 507, 507, + 507, 507, 507, 507, 507, 507, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 508, 508, 508, 508, + 508, 509, 510, 510, 511, 511, 512, 512, 512, 512, + 513, 513, 514, 515, 515, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 517, 517, 517, 519, 518, 520, 518, 521, 521, 522, + 522, 523, 523, 524, 524, 525, 525, 525, 525, 526, + 526, 527, 528, 528, 529, 529, 529, 529, 529, 529, + 529, 529, 530, 531, 532, 533, 531, 534, 534, 536, + 535, 537, 535, 538, 538, 539, 539, 540, 540, 541, + 541, 542, 543, 543, 544, 544, 545, 545, 547, 546, + 548, 548, 549, 549, 550, 550, 552, 551, 553, 551, + 554, 551, 555, 555, 556, 556, 557, 557, 558, 558, + 558, 558, 558, 558, 558, 558, 559, 559, 560, 560, + 560, 562, 561, 563, 564, 564, 565, 565, 566, 566, + 567, 567, 568, 568, 569, 569, 570, 570, 570, 570, + 570, 570, 571, 571, 572, 572, 572, 572, 572, 573, + 573, 574, 574, 575, 575, 575, 575, 575, 575, 575, + 575, 576, 576, 577, 577, 577, 577, 578, 578, 579, + 579, 580, 580, 580, 580, 581, 581, 582, 582, 583, + 583, 584, 584, 585, 585 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 1, 1, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 1, 3, 2, 2, 1, 1, 1, 2, 2, 2, + 1, 2, 3, 2, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, + 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, + 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 0, 6, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 2, 3, 2, 2, 4, 2, + 3, 4, 2, 3, 4, 0, 6, 2, 3, 2, + 3, 3, 4, 1, 1, 2, 3, 3, 2, 3, + 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, + 1, 2, 3, 5, 4, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 1, 3, 1, + 3, 1, 1, 1, 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, + 4, 1, 1, 3, 2, 3, 2, 3, 3, 4, + 1, 0, 3, 1, 3, 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, 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, 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, 6, 0, 5, 1, 2, 3, + 4, 1, 3, 1, 2, 1, 3, 4, 2, 1, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 0, 0, 5, 1, 1, 0, + 2, 0, 2, 2, 3, 1, 2, 1, 2, 1, + 2, 5, 3, 1, 1, 4, 1, 2, 0, 8, + 0, 1, 3, 2, 1, 2, 0, 6, 0, 8, + 0, 7, 1, 1, 1, 0, 2, 3, 2, 2, + 2, 3, 2, 2, 2, 2, 1, 2, 1, 1, + 1, 0, 3, 5, 1, 3, 1, 4, 1, 3, + 5, 5, 1, 3, 1, 3, 4, 6, 6, 8, + 6, 8, 1, 3, 1, 1, 1, 1, 1, 1, + 3, 4, 6, 4, 6, 6, 8, 6, 8, 6, + 8, 1, 3, 1, 1, 1, 1, 1, 3, 1, + 3, 6, 8, 4, 6, 1, 3, 1, 1, 4, + 6, 1, 3, 3, 3 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (pParseContext, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +# ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value, pParseContext); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) +{ + FILE *yyoutput = yyo; + YYUSE (yyoutput); + YYUSE (pParseContext); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yykind < YYNTOKENS) + YYPRINT (yyo, yytoknum[yykind], *yyvaluep); +# endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) +{ + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + + yy_symbol_value_print (yyo, yykind, yyvaluep, pParseContext); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule, glslang::TParseContext* pParseContext) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], pParseContext); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +/* Context of a parse error. */ +typedef struct +{ + yy_state_t *yyssp; + yysymbol_kind_t yytoken; +} yypcontext_t; + +/* Put in YYARG at most YYARGN of the expected tokens given the + current YYCTX, and return the number of tokens stored in YYARG. If + YYARG is null, return the number of expected tokens (guaranteed to + be less than YYNTOKENS). Return YYENOMEM on memory exhaustion. + Return 0 if there are more than YYARGN expected tokens, yet fill + YYARG up to YYARGN. */ +static int +yypcontext_expected_tokens (const yypcontext_t *yyctx, + yysymbol_kind_t yyarg[], int yyargn) +{ + /* Actual size of YYARG. */ + int yycount = 0; + int yyn = yypact[+*yyctx->yyssp]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (!yyarg) + ++yycount; + else if (yycount == yyargn) + return 0; + else + yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); + } + } + if (yyarg && yycount == 0 && 0 < yyargn) + yyarg[0] = YYSYMBOL_YYEMPTY; + return yycount; +} + + + + +#ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) +# else +/* Return the length of YYSTR. */ +static YYPTRDIFF_T +yystrlen (const char *yystr) +{ + YYPTRDIFF_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +#endif + +#ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +#endif + +#ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYPTRDIFF_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYPTRDIFF_T yyn = 0; + char const *yyp = yystr; + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + else + goto append; + + append: + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (yyres) + return yystpcpy (yyres, yystr) - yyres; + else + return yystrlen (yystr); +} +#endif + + +static int +yy_syntax_error_arguments (const yypcontext_t *yyctx, + yysymbol_kind_t yyarg[], int yyargn) +{ + /* Actual size of YYARG. */ + int yycount = 0; + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yyctx->yytoken != YYSYMBOL_YYEMPTY) + { + int yyn; + if (yyarg) + yyarg[yycount] = yyctx->yytoken; + ++yycount; + yyn = yypcontext_expected_tokens (yyctx, + yyarg ? yyarg + 1 : yyarg, yyargn - 1); + if (yyn == YYENOMEM) + return YYENOMEM; + else + yycount += yyn; + } + return yycount; +} + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, + const yypcontext_t *yyctx) +{ + enum { YYARGS_MAX = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat: reported tokens (one for the "unexpected", + one per "expected"). */ + yysymbol_kind_t yyarg[YYARGS_MAX]; + /* Cumulated lengths of YYARG. */ + YYPTRDIFF_T yysize = 0; + + /* Actual size of YYARG. */ + int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX); + if (yycount == YYENOMEM) + return YYENOMEM; + + switch (yycount) + { +#define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + default: /* Avoid compiler warnings. */ + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +#undef YYCASE_ + } + + /* Compute error message size. Don't count the "%s"s, but reserve + room for the terminator. */ + yysize = yystrlen (yyformat) - 2 * yycount + 1; + { + int yyi; + for (yyi = 0; yyi < yycount; ++yyi) + { + YYPTRDIFF_T yysize1 + = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]); + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else + return YYENOMEM; + } + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return -1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]); + yyformat += 2; + } + else + { + ++yyp; + ++yyformat; + } + } + return 0; +} + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext) +{ + YYUSE (yyvaluep); + YYUSE (pParseContext); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (glslang::TParseContext* pParseContext) +{ +/* Lookahead token kind. */ +int yychar; + + +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + + /* Number of syntax errors so far. */ + int yynerrs = 0; + + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (&yylval, parseContext); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: /* variable_identifier: IDENTIFIER */ +#line 392 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); + } +#line 5181 "MachineIndependent/glslang_tab.cpp" + break; + + case 3: /* primary_expression: variable_identifier */ +#line 398 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 5189 "MachineIndependent/glslang_tab.cpp" + break; + + case 4: /* primary_expression: LEFT_PAREN expression RIGHT_PAREN */ +#line 401 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); + if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) + (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); + } +#line 5199 "MachineIndependent/glslang_tab.cpp" + break; + + case 5: /* primary_expression: FLOATCONSTANT */ +#line 406 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); + } +#line 5207 "MachineIndependent/glslang_tab.cpp" + break; + + case 6: /* primary_expression: INTCONSTANT */ +#line 409 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); + } +#line 5215 "MachineIndependent/glslang_tab.cpp" + break; + + case 7: /* primary_expression: UINTCONSTANT */ +#line 412 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); + } +#line 5224 "MachineIndependent/glslang_tab.cpp" + break; + + case 8: /* primary_expression: BOOLCONSTANT */ +#line 416 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); + } +#line 5232 "MachineIndependent/glslang_tab.cpp" + break; + + case 9: /* primary_expression: STRING_LITERAL */ +#line 420 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); + } +#line 5240 "MachineIndependent/glslang_tab.cpp" + break; + + case 10: /* primary_expression: INT32CONSTANT */ +#line 423 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); + } +#line 5249 "MachineIndependent/glslang_tab.cpp" + break; + + case 11: /* primary_expression: UINT32CONSTANT */ +#line 427 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); + } +#line 5258 "MachineIndependent/glslang_tab.cpp" + break; + + case 12: /* primary_expression: INT64CONSTANT */ +#line 431 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); + } +#line 5267 "MachineIndependent/glslang_tab.cpp" + break; + + case 13: /* primary_expression: UINT64CONSTANT */ +#line 435 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); + } +#line 5276 "MachineIndependent/glslang_tab.cpp" + break; + + case 14: /* primary_expression: INT16CONSTANT */ +#line 439 "MachineIndependent/glslang.y" + { + parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); + } +#line 5285 "MachineIndependent/glslang_tab.cpp" + break; + + case 15: /* primary_expression: UINT16CONSTANT */ +#line 443 "MachineIndependent/glslang.y" + { + parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); + } +#line 5294 "MachineIndependent/glslang_tab.cpp" + break; + + case 16: /* primary_expression: DOUBLECONSTANT */ +#line 447 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true); + } +#line 5305 "MachineIndependent/glslang_tab.cpp" + break; + + case 17: /* primary_expression: FLOAT16CONSTANT */ +#line 453 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); + } +#line 5314 "MachineIndependent/glslang_tab.cpp" + break; + + case 18: /* postfix_expression: primary_expression */ +#line 461 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 5322 "MachineIndependent/glslang_tab.cpp" + break; + + case 19: /* postfix_expression: postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET */ +#line 464 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); + } +#line 5330 "MachineIndependent/glslang_tab.cpp" + break; + + case 20: /* postfix_expression: function_call */ +#line 467 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 5338 "MachineIndependent/glslang_tab.cpp" + break; + + case 21: /* postfix_expression: postfix_expression DOT IDENTIFIER */ +#line 470 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); + } +#line 5346 "MachineIndependent/glslang_tab.cpp" + break; + + case 22: /* postfix_expression: postfix_expression INC_OP */ +#line 473 "MachineIndependent/glslang.y" + { + parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); + parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode)); + } +#line 5356 "MachineIndependent/glslang_tab.cpp" + break; + + case 23: /* postfix_expression: postfix_expression DEC_OP */ +#line 478 "MachineIndependent/glslang.y" + { + parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); + parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode)); + } +#line 5366 "MachineIndependent/glslang_tab.cpp" + break; + + case 24: /* integer_expression: expression */ +#line 486 "MachineIndependent/glslang.y" + { + parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 5375 "MachineIndependent/glslang_tab.cpp" + break; + + case 25: /* function_call: function_call_or_method */ +#line 493 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); + delete (yyvsp[0].interm).function; + } +#line 5384 "MachineIndependent/glslang_tab.cpp" + break; + + case 26: /* function_call_or_method: function_call_generic */ +#line 500 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + } +#line 5392 "MachineIndependent/glslang_tab.cpp" + break; + + case 27: /* function_call_generic: function_call_header_with_parameters RIGHT_PAREN */ +#line 506 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-1].interm); + (yyval.interm).loc = (yyvsp[0].lex).loc; + } +#line 5401 "MachineIndependent/glslang_tab.cpp" + break; + + case 28: /* function_call_generic: function_call_header_no_parameters RIGHT_PAREN */ +#line 510 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-1].interm); + (yyval.interm).loc = (yyvsp[0].lex).loc; + } +#line 5410 "MachineIndependent/glslang_tab.cpp" + break; + + case 29: /* function_call_header_no_parameters: function_call_header VOID */ +#line 517 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-1].interm); + } +#line 5418 "MachineIndependent/glslang_tab.cpp" + break; + + case 30: /* function_call_header_no_parameters: function_call_header */ +#line 520 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + } +#line 5426 "MachineIndependent/glslang_tab.cpp" + break; + + case 31: /* function_call_header_with_parameters: function_call_header assignment_expression */ +#line 526 "MachineIndependent/glslang.y" + { + TParameter param = { 0, new TType }; + param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); + (yyvsp[-1].interm).function->addParameter(param); + (yyval.interm).function = (yyvsp[-1].interm).function; + (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode); + } +#line 5438 "MachineIndependent/glslang_tab.cpp" + break; + + case 32: /* function_call_header_with_parameters: function_call_header_with_parameters COMMA assignment_expression */ +#line 533 "MachineIndependent/glslang.y" + { + TParameter param = { 0, new TType }; + param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); + (yyvsp[-2].interm).function->addParameter(param); + (yyval.interm).function = (yyvsp[-2].interm).function; + (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); + } +#line 5450 "MachineIndependent/glslang_tab.cpp" + break; + + case 33: /* function_call_header: function_identifier LEFT_PAREN */ +#line 543 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-1].interm); + } +#line 5458 "MachineIndependent/glslang_tab.cpp" + break; + + case 34: /* function_identifier: type_specifier */ +#line 551 "MachineIndependent/glslang.y" + { + // Constructor + (yyval.interm).intermNode = 0; + (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); + } +#line 5468 "MachineIndependent/glslang_tab.cpp" + break; + + case 35: /* function_identifier: postfix_expression */ +#line 556 "MachineIndependent/glslang.y" + { + // + // Should be a method or subroutine call, but we haven't recognized the arguments yet. + // + (yyval.interm).function = 0; + (yyval.interm).intermNode = 0; + + TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode(); + if (method) { + (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); + (yyval.interm).intermNode = method->getObject(); + } else { + TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode(); + if (symbol) { + parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); + TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); + (yyval.interm).function = function; + } else + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", ""); + } + + if ((yyval.interm).function == 0) { + // error recover + TString* empty = NewPoolTString(""); + (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull); + } + } +#line 5500 "MachineIndependent/glslang_tab.cpp" + break; + + case 36: /* function_identifier: non_uniform_qualifier */ +#line 584 "MachineIndependent/glslang.y" + { + // Constructor + (yyval.interm).intermNode = 0; + (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); + } +#line 5510 "MachineIndependent/glslang_tab.cpp" + break; + + case 37: /* unary_expression: postfix_expression */ +#line 593 "MachineIndependent/glslang.y" + { + parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode()) + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); + } +#line 5521 "MachineIndependent/glslang_tab.cpp" + break; + + case 38: /* unary_expression: INC_OP unary_expression */ +#line 599 "MachineIndependent/glslang.y" + { + parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); + } +#line 5530 "MachineIndependent/glslang_tab.cpp" + break; + + case 39: /* unary_expression: DEC_OP unary_expression */ +#line 603 "MachineIndependent/glslang.y" + { + parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); + } +#line 5539 "MachineIndependent/glslang_tab.cpp" + break; + + case 40: /* unary_expression: unary_operator unary_expression */ +#line 607 "MachineIndependent/glslang.y" + { + if ((yyvsp[-1].interm).op != EOpNull) { + char errorOp[2] = {0, 0}; + switch((yyvsp[-1].interm).op) { + case EOpNegative: errorOp[0] = '-'; break; + case EOpLogicalNot: errorOp[0] = '!'; break; + case EOpBitwiseNot: errorOp[0] = '~'; break; + default: break; // some compilers want this + } + (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode)); + } else { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) + (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); + } + } +#line 5560 "MachineIndependent/glslang_tab.cpp" + break; + + case 41: /* unary_operator: PLUS */ +#line 627 "MachineIndependent/glslang.y" + { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } +#line 5566 "MachineIndependent/glslang_tab.cpp" + break; + + case 42: /* unary_operator: DASH */ +#line 628 "MachineIndependent/glslang.y" + { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } +#line 5572 "MachineIndependent/glslang_tab.cpp" + break; + + case 43: /* unary_operator: BANG */ +#line 629 "MachineIndependent/glslang.y" + { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } +#line 5578 "MachineIndependent/glslang_tab.cpp" + break; + + case 44: /* unary_operator: TILDE */ +#line 630 "MachineIndependent/glslang.y" + { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } +#line 5585 "MachineIndependent/glslang_tab.cpp" + break; + + case 45: /* multiplicative_expression: unary_expression */ +#line 636 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5591 "MachineIndependent/glslang_tab.cpp" + break; + + case 46: /* multiplicative_expression: multiplicative_expression STAR unary_expression */ +#line 637 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5601 "MachineIndependent/glslang_tab.cpp" + break; + + case 47: /* multiplicative_expression: multiplicative_expression SLASH unary_expression */ +#line 642 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5611 "MachineIndependent/glslang_tab.cpp" + break; + + case 48: /* multiplicative_expression: multiplicative_expression PERCENT unary_expression */ +#line 647 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5622 "MachineIndependent/glslang_tab.cpp" + break; + + case 49: /* additive_expression: multiplicative_expression */ +#line 656 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5628 "MachineIndependent/glslang_tab.cpp" + break; + + case 50: /* additive_expression: additive_expression PLUS multiplicative_expression */ +#line 657 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5638 "MachineIndependent/glslang_tab.cpp" + break; + + case 51: /* additive_expression: additive_expression DASH multiplicative_expression */ +#line 662 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5648 "MachineIndependent/glslang_tab.cpp" + break; + + case 52: /* shift_expression: additive_expression */ +#line 670 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5654 "MachineIndependent/glslang_tab.cpp" + break; + + case 53: /* shift_expression: shift_expression LEFT_OP additive_expression */ +#line 671 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5665 "MachineIndependent/glslang_tab.cpp" + break; + + case 54: /* shift_expression: shift_expression RIGHT_OP additive_expression */ +#line 677 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5676 "MachineIndependent/glslang_tab.cpp" + break; + + case 55: /* relational_expression: shift_expression */ +#line 686 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5682 "MachineIndependent/glslang_tab.cpp" + break; + + case 56: /* relational_expression: relational_expression LEFT_ANGLE shift_expression */ +#line 687 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5692 "MachineIndependent/glslang_tab.cpp" + break; + + case 57: /* relational_expression: relational_expression RIGHT_ANGLE shift_expression */ +#line 692 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5702 "MachineIndependent/glslang_tab.cpp" + break; + + case 58: /* relational_expression: relational_expression LE_OP shift_expression */ +#line 697 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5712 "MachineIndependent/glslang_tab.cpp" + break; + + case 59: /* relational_expression: relational_expression GE_OP shift_expression */ +#line 702 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5722 "MachineIndependent/glslang_tab.cpp" + break; + + case 60: /* equality_expression: relational_expression */ +#line 710 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5728 "MachineIndependent/glslang_tab.cpp" + break; + + case 61: /* equality_expression: equality_expression EQ_OP relational_expression */ +#line 711 "MachineIndependent/glslang.y" + { + parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); + parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); + parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); + parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5742 "MachineIndependent/glslang_tab.cpp" + break; + + case 62: /* equality_expression: equality_expression NE_OP relational_expression */ +#line 720 "MachineIndependent/glslang.y" + { + parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); + parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); + parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); + parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5756 "MachineIndependent/glslang_tab.cpp" + break; + + case 63: /* and_expression: equality_expression */ +#line 732 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5762 "MachineIndependent/glslang_tab.cpp" + break; + + case 64: /* and_expression: and_expression AMPERSAND equality_expression */ +#line 733 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5773 "MachineIndependent/glslang_tab.cpp" + break; + + case 65: /* exclusive_or_expression: and_expression */ +#line 742 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5779 "MachineIndependent/glslang_tab.cpp" + break; + + case 66: /* exclusive_or_expression: exclusive_or_expression CARET and_expression */ +#line 743 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5790 "MachineIndependent/glslang_tab.cpp" + break; + + case 67: /* inclusive_or_expression: exclusive_or_expression */ +#line 752 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5796 "MachineIndependent/glslang_tab.cpp" + break; + + case 68: /* inclusive_or_expression: inclusive_or_expression VERTICAL_BAR exclusive_or_expression */ +#line 753 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 5807 "MachineIndependent/glslang_tab.cpp" + break; + + case 69: /* logical_and_expression: inclusive_or_expression */ +#line 762 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5813 "MachineIndependent/glslang_tab.cpp" + break; + + case 70: /* logical_and_expression: logical_and_expression AND_OP inclusive_or_expression */ +#line 763 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5823 "MachineIndependent/glslang_tab.cpp" + break; + + case 71: /* logical_xor_expression: logical_and_expression */ +#line 771 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5829 "MachineIndependent/glslang_tab.cpp" + break; + + case 72: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ +#line 772 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5839 "MachineIndependent/glslang_tab.cpp" + break; + + case 73: /* logical_or_expression: logical_xor_expression */ +#line 780 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5845 "MachineIndependent/glslang_tab.cpp" + break; + + case 74: /* logical_or_expression: logical_or_expression OR_OP logical_xor_expression */ +#line 781 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); + } +#line 5855 "MachineIndependent/glslang_tab.cpp" + break; + + case 75: /* conditional_expression: logical_or_expression */ +#line 789 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5861 "MachineIndependent/glslang_tab.cpp" + break; + + case 76: /* $@1: %empty */ +#line 790 "MachineIndependent/glslang.y" + { + ++parseContext.controlFlowNestingLevel; + } +#line 5869 "MachineIndependent/glslang_tab.cpp" + break; + + case 77: /* conditional_expression: logical_or_expression QUESTION $@1 expression COLON assignment_expression */ +#line 793 "MachineIndependent/glslang.y" + { + --parseContext.controlFlowNestingLevel; + parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); + parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode)); + parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)); + parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc); + if ((yyval.interm.intermTypedNode) == 0) { + parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + } +#line 5886 "MachineIndependent/glslang_tab.cpp" + break; + + case 78: /* assignment_expression: conditional_expression */ +#line 808 "MachineIndependent/glslang.y" + { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } +#line 5892 "MachineIndependent/glslang_tab.cpp" + break; + + case 79: /* assignment_expression: unary_expression assignment_operator assignment_expression */ +#line 809 "MachineIndependent/glslang.y" + { + parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); + parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); + parseContext.storage16BitAssignmentCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); + parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); + parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)); + parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.addAssign((yyvsp[-1].interm).loc, (yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + if ((yyval.interm.intermTypedNode) == 0) { + parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } + } +#line 5910 "MachineIndependent/glslang_tab.cpp" + break; + + case 80: /* assignment_operator: EQUAL */ +#line 825 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpAssign; + } +#line 5919 "MachineIndependent/glslang_tab.cpp" + break; + + case 81: /* assignment_operator: MUL_ASSIGN */ +#line 829 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpMulAssign; + } +#line 5928 "MachineIndependent/glslang_tab.cpp" + break; + + case 82: /* assignment_operator: DIV_ASSIGN */ +#line 833 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpDivAssign; + } +#line 5937 "MachineIndependent/glslang_tab.cpp" + break; + + case 83: /* assignment_operator: MOD_ASSIGN */ +#line 837 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpModAssign; + } +#line 5947 "MachineIndependent/glslang_tab.cpp" + break; + + case 84: /* assignment_operator: ADD_ASSIGN */ +#line 842 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpAddAssign; + } +#line 5956 "MachineIndependent/glslang_tab.cpp" + break; + + case 85: /* assignment_operator: SUB_ASSIGN */ +#line 846 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).op = EOpSubAssign; + } +#line 5965 "MachineIndependent/glslang_tab.cpp" + break; + + case 86: /* assignment_operator: LEFT_ASSIGN */ +#line 850 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); + (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; + } +#line 5974 "MachineIndependent/glslang_tab.cpp" + break; + + case 87: /* assignment_operator: RIGHT_ASSIGN */ +#line 854 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); + (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; + } +#line 5983 "MachineIndependent/glslang_tab.cpp" + break; + + case 88: /* assignment_operator: AND_ASSIGN */ +#line 858 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); + (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; + } +#line 5992 "MachineIndependent/glslang_tab.cpp" + break; + + case 89: /* assignment_operator: XOR_ASSIGN */ +#line 862 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); + (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; + } +#line 6001 "MachineIndependent/glslang_tab.cpp" + break; + + case 90: /* assignment_operator: OR_ASSIGN */ +#line 866 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); + (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; + } +#line 6010 "MachineIndependent/glslang_tab.cpp" + break; + + case 91: /* expression: assignment_expression */ +#line 873 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 6018 "MachineIndependent/glslang_tab.cpp" + break; + + case 92: /* expression: expression COMMA assignment_expression */ +#line 876 "MachineIndependent/glslang.y" + { + parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); + (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); + if ((yyval.interm.intermTypedNode) == 0) { + parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } + } +#line 6031 "MachineIndependent/glslang_tab.cpp" + break; + + case 93: /* constant_expression: conditional_expression */ +#line 887 "MachineIndependent/glslang.y" + { + parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 6040 "MachineIndependent/glslang_tab.cpp" + break; + + case 94: /* declaration: function_prototype SEMICOLON */ +#line 894 "MachineIndependent/glslang.y" + { + parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); + (yyval.interm.intermNode) = 0; + // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature + } +#line 6050 "MachineIndependent/glslang_tab.cpp" + break; + + case 95: /* declaration: spirv_instruction_qualifier function_prototype SEMICOLON */ +#line 900 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[-1].interm).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); + (yyvsp[-1].interm).function->setSpirvInstruction(*(yyvsp[-2].interm.spirvInst)); // Attach SPIR-V intruction qualifier + parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); + (yyval.interm.intermNode) = 0; + // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature + } +#line 6062 "MachineIndependent/glslang_tab.cpp" + break; + + case 96: /* declaration: spirv_execution_mode_qualifier SEMICOLON */ +#line 907 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "SPIR-V execution mode qualifier"); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); + (yyval.interm.intermNode) = 0; + } +#line 6072 "MachineIndependent/glslang_tab.cpp" + break; + + case 97: /* declaration: init_declarator_list SEMICOLON */ +#line 913 "MachineIndependent/glslang.y" + { + if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) + (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); + (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode; + } +#line 6082 "MachineIndependent/glslang_tab.cpp" + break; + + case 98: /* declaration: PRECISION precision_qualifier type_specifier SEMICOLON */ +#line 918 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); + // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope + parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); + parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision); + (yyval.interm.intermNode) = 0; + } +#line 6094 "MachineIndependent/glslang_tab.cpp" + break; + + case 99: /* declaration: block_structure SEMICOLON */ +#line 925 "MachineIndependent/glslang.y" + { + parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); + (yyval.interm.intermNode) = 0; + } +#line 6103 "MachineIndependent/glslang_tab.cpp" + break; + + case 100: /* declaration: block_structure IDENTIFIER SEMICOLON */ +#line 929 "MachineIndependent/glslang.y" + { + parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); + (yyval.interm.intermNode) = 0; + } +#line 6112 "MachineIndependent/glslang_tab.cpp" + break; + + case 101: /* declaration: block_structure IDENTIFIER array_specifier SEMICOLON */ +#line 933 "MachineIndependent/glslang.y" + { + parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); + (yyval.interm.intermNode) = 0; + } +#line 6121 "MachineIndependent/glslang_tab.cpp" + break; + + case 102: /* declaration: type_qualifier SEMICOLON */ +#line 937 "MachineIndependent/glslang.y" + { + parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); + parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); + (yyval.interm.intermNode) = 0; + } +#line 6131 "MachineIndependent/glslang_tab.cpp" + break; + + case 103: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ +#line 942 "MachineIndependent/glslang.y" + { + parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); + parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); + (yyval.interm.intermNode) = 0; + } +#line 6141 "MachineIndependent/glslang_tab.cpp" + break; + + case 104: /* declaration: type_qualifier IDENTIFIER identifier_list SEMICOLON */ +#line 947 "MachineIndependent/glslang.y" + { + parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); + (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); + parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList)); + (yyval.interm.intermNode) = 0; + } +#line 6152 "MachineIndependent/glslang_tab.cpp" + break; + + case 105: /* $@2: %empty */ +#line 956 "MachineIndependent/glslang.y" + { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } +#line 6158 "MachineIndependent/glslang_tab.cpp" + break; + + case 106: /* block_structure: type_qualifier IDENTIFIER LEFT_BRACE $@2 struct_declaration_list RIGHT_BRACE */ +#line 956 "MachineIndependent/glslang.y" + { + --parseContext.blockNestingLevel; + parseContext.blockName = (yyvsp[-4].lex).string; + parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier); + parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers); + parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier; + (yyval.interm).loc = (yyvsp[-5].interm.type).loc; + (yyval.interm).typeList = (yyvsp[-1].interm.typeList); + } +#line 6172 "MachineIndependent/glslang_tab.cpp" + break; + + case 107: /* identifier_list: COMMA IDENTIFIER */ +#line 967 "MachineIndependent/glslang.y" + { + (yyval.interm.identifierList) = new TIdentifierList; + (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); + } +#line 6181 "MachineIndependent/glslang_tab.cpp" + break; + + case 108: /* identifier_list: identifier_list COMMA IDENTIFIER */ +#line 971 "MachineIndependent/glslang.y" + { + (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); + (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); + } +#line 6190 "MachineIndependent/glslang_tab.cpp" + break; + + case 109: /* function_prototype: function_declarator RIGHT_PAREN */ +#line 978 "MachineIndependent/glslang.y" + { + (yyval.interm).function = (yyvsp[-1].interm.function); + (yyval.interm).loc = (yyvsp[0].lex).loc; + } +#line 6199 "MachineIndependent/glslang_tab.cpp" + break; + + case 110: /* function_prototype: function_declarator RIGHT_PAREN attribute */ +#line 982 "MachineIndependent/glslang.y" + { + (yyval.interm).function = (yyvsp[-2].interm.function); + (yyval.interm).loc = (yyvsp[-1].lex).loc; + parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes), (yyval.interm).function); + } +#line 6210 "MachineIndependent/glslang_tab.cpp" + break; + + case 111: /* function_prototype: attribute function_declarator RIGHT_PAREN */ +#line 988 "MachineIndependent/glslang.y" + { + (yyval.interm).function = (yyvsp[-1].interm.function); + (yyval.interm).loc = (yyvsp[0].lex).loc; + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes((yyvsp[0].lex).loc, *(yyvsp[-2].interm.attributes), (yyval.interm).function); + } +#line 6221 "MachineIndependent/glslang_tab.cpp" + break; + + case 112: /* function_prototype: attribute function_declarator RIGHT_PAREN attribute */ +#line 994 "MachineIndependent/glslang.y" + { + (yyval.interm).function = (yyvsp[-2].interm.function); + (yyval.interm).loc = (yyvsp[-1].lex).loc; + parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); + parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[-3].interm.attributes), (yyval.interm).function); + parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes), (yyval.interm).function); + } +#line 6233 "MachineIndependent/glslang_tab.cpp" + break; + + case 113: /* function_declarator: function_header */ +#line 1004 "MachineIndependent/glslang.y" + { + (yyval.interm.function) = (yyvsp[0].interm.function); + } +#line 6241 "MachineIndependent/glslang_tab.cpp" + break; + + case 114: /* function_declarator: function_header_with_parameters */ +#line 1007 "MachineIndependent/glslang.y" + { + (yyval.interm.function) = (yyvsp[0].interm.function); + } +#line 6249 "MachineIndependent/glslang_tab.cpp" + break; + + case 115: /* function_header_with_parameters: function_header parameter_declaration */ +#line 1014 "MachineIndependent/glslang.y" + { + // Add the parameter + (yyval.interm.function) = (yyvsp[-1].interm.function); + if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid) + (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param); + else + delete (yyvsp[0].interm).param.type; + } +#line 6262 "MachineIndependent/glslang_tab.cpp" + break; + + case 116: /* function_header_with_parameters: function_header_with_parameters COMMA parameter_declaration */ +#line 1022 "MachineIndependent/glslang.y" + { + // + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + // + if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) { + // + // This parameter > first is void + // + parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", ""); + delete (yyvsp[0].interm).param.type; + } else { + // Add the parameter + (yyval.interm.function) = (yyvsp[-2].interm.function); + (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); + } + } +#line 6284 "MachineIndependent/glslang_tab.cpp" + break; + + case 117: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ +#line 1042 "MachineIndependent/glslang.y" + { + if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { + parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", + GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), ""); + } + if ((yyvsp[-2].interm.type).arraySizes) + parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type((yyvsp[-2].interm.type)); + + // Potentially rename shader entry point function. No-op most of the time. + parseContext.renameShaderFunction((yyvsp[-1].lex).string); + + // Make the function + function = new TFunction((yyvsp[-1].lex).string, type); + (yyval.interm.function) = function; + } +#line 6308 "MachineIndependent/glslang_tab.cpp" + break; + + case 118: /* parameter_declarator: type_specifier IDENTIFIER */ +#line 1065 "MachineIndependent/glslang.y" + { + if ((yyvsp[-1].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes); + } + if ((yyvsp[-1].interm.type).basicType == EbtVoid) { + parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), ""); + } + parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string); + + TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))}; + (yyval.interm).loc = (yyvsp[0].lex).loc; + (yyval.interm).param = param; + } +#line 6328 "MachineIndependent/glslang_tab.cpp" + break; + + case 119: /* parameter_declarator: type_specifier IDENTIFIER array_specifier */ +#line 1080 "MachineIndependent/glslang.y" + { + if ((yyvsp[-2].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); + } + TType* type = new TType((yyvsp[-2].interm.type)); + type->transferArraySizes((yyvsp[0].interm).arraySizes); + type->copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); + + parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, type->getArraySizes()); + parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes); + parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string); + + TParameter param = { (yyvsp[-1].lex).string, type }; + + (yyval.interm).loc = (yyvsp[-1].lex).loc; + (yyval.interm).param = param; + } +#line 6352 "MachineIndependent/glslang_tab.cpp" + break; + + case 120: /* parameter_declaration: type_qualifier parameter_declarator */ +#line 1105 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) + (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; + parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); + + parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); + parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); + parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); + + } +#line 6368 "MachineIndependent/glslang_tab.cpp" + break; + + case 121: /* parameter_declaration: parameter_declarator */ +#line 1116 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + + parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); + parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); + parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); + } +#line 6380 "MachineIndependent/glslang_tab.cpp" + break; + + case 122: /* parameter_declaration: type_qualifier parameter_type_specifier */ +#line 1126 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) + (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; + parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); + + parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); + parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); + parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); + } +#line 6395 "MachineIndependent/glslang_tab.cpp" + break; + + case 123: /* parameter_declaration: parameter_type_specifier */ +#line 1136 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + + parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); + parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); + parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); + } +#line 6407 "MachineIndependent/glslang_tab.cpp" + break; + + case 124: /* parameter_type_specifier: type_specifier */ +#line 1146 "MachineIndependent/glslang.y" + { + TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; + (yyval.interm).param = param; + if ((yyvsp[0].interm.type).arraySizes) + parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); + } +#line 6418 "MachineIndependent/glslang_tab.cpp" + break; + + case 125: /* init_declarator_list: single_declaration */ +#line 1155 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[0].interm); + } +#line 6426 "MachineIndependent/glslang_tab.cpp" + break; + + case 126: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER */ +#line 1158 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-2].interm); + parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); + } +#line 6435 "MachineIndependent/glslang_tab.cpp" + break; + + case 127: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier */ +#line 1162 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-3].interm); + parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); + } +#line 6444 "MachineIndependent/glslang_tab.cpp" + break; + + case 128: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer */ +#line 1166 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-5].interm).type; + TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); + } +#line 6454 "MachineIndependent/glslang_tab.cpp" + break; + + case 129: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER EQUAL initializer */ +#line 1171 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-4].interm).type; + TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); + } +#line 6464 "MachineIndependent/glslang_tab.cpp" + break; + + case 130: /* single_declaration: fully_specified_type */ +#line 1179 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[0].interm.type); + (yyval.interm).intermNode = 0; + + parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); + + } +#line 6476 "MachineIndependent/glslang_tab.cpp" + break; + + case 131: /* single_declaration: fully_specified_type IDENTIFIER */ +#line 1186 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-1].interm.type); + (yyval.interm).intermNode = 0; + parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); + } +#line 6486 "MachineIndependent/glslang_tab.cpp" + break; + + case 132: /* single_declaration: fully_specified_type IDENTIFIER array_specifier */ +#line 1191 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-2].interm.type); + (yyval.interm).intermNode = 0; + parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); + } +#line 6496 "MachineIndependent/glslang_tab.cpp" + break; + + case 133: /* single_declaration: fully_specified_type IDENTIFIER array_specifier EQUAL initializer */ +#line 1196 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-4].interm.type); + TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); + } +#line 6506 "MachineIndependent/glslang_tab.cpp" + break; + + case 134: /* single_declaration: fully_specified_type IDENTIFIER EQUAL initializer */ +#line 1201 "MachineIndependent/glslang.y" + { + (yyval.interm).type = (yyvsp[-3].interm.type); + TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); + } +#line 6516 "MachineIndependent/glslang_tab.cpp" + break; + + case 135: /* fully_specified_type: type_specifier */ +#line 1210 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + + parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type)); + if ((yyvsp[0].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + } + parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier); + } +#line 6531 "MachineIndependent/glslang_tab.cpp" + break; + + case 136: /* fully_specified_type: type_qualifier type_specifier */ +#line 1220 "MachineIndependent/glslang.y" + { + parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); + parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); + + if ((yyvsp[0].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + } + + if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier)) + (yyvsp[0].interm.type).arraySizes = nullptr; + + parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); + (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers); + parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true); + parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier); + + (yyval.interm.type) = (yyvsp[0].interm.type); + + if (! (yyval.interm.type).qualifier.isInterpolation() && + ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) || + (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) + (yyval.interm.type).qualifier.smooth = true; + } +#line 6560 "MachineIndependent/glslang_tab.cpp" + break; + + case 137: /* invariant_qualifier: INVARIANT */ +#line 1247 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); + parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.invariant = true; + } +#line 6571 "MachineIndependent/glslang_tab.cpp" + break; + + case 138: /* interpolation_qualifier: SMOOTH */ +#line 1256 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.smooth = true; + } +#line 6583 "MachineIndependent/glslang_tab.cpp" + break; + + case 139: /* interpolation_qualifier: FLAT */ +#line 1263 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.flat = true; + } +#line 6595 "MachineIndependent/glslang_tab.cpp" + break; + + case 140: /* interpolation_qualifier: NOPERSPECTIVE */ +#line 1271 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.nopersp = true; + } +#line 6607 "MachineIndependent/glslang_tab.cpp" + break; + + case 141: /* interpolation_qualifier: EXPLICITINTERPAMD */ +#line 1278 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.explicitInterp = true; + } +#line 6619 "MachineIndependent/glslang_tab.cpp" + break; + + case 142: /* interpolation_qualifier: PERVERTEXNV */ +#line 1285 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.pervertexNV = true; + } +#line 6632 "MachineIndependent/glslang_tab.cpp" + break; + + case 143: /* interpolation_qualifier: PERPRIMITIVENV */ +#line 1293 "MachineIndependent/glslang.y" + { + // No need for profile version or extension check. Shader stage already checks both. + parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV"); + // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. + if (parseContext.language == EShLangFragment) + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.perPrimitiveNV = true; + } +#line 6647 "MachineIndependent/glslang_tab.cpp" + break; + + case 144: /* interpolation_qualifier: PERVIEWNV */ +#line 1303 "MachineIndependent/glslang.y" + { + // No need for profile version or extension check. Shader stage already checks both. + parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV"); + parseContext.requireStage((yyvsp[0].lex).loc, EShLangMeshNV, "perviewNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.perViewNV = true; + } +#line 6659 "MachineIndependent/glslang_tab.cpp" + break; + + case 145: /* interpolation_qualifier: PERTASKNV */ +#line 1310 "MachineIndependent/glslang.y" + { + // No need for profile version or extension check. Shader stage already checks both. + parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.perTaskNV = true; + } +#line 6671 "MachineIndependent/glslang_tab.cpp" + break; + + case 146: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ +#line 1321 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[-1].interm.type); + } +#line 6679 "MachineIndependent/glslang_tab.cpp" + break; + + case 147: /* layout_qualifier_id_list: layout_qualifier_id */ +#line 1327 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6687 "MachineIndependent/glslang_tab.cpp" + break; + + case 148: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ +#line 1330 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[-2].interm.type); + (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); + parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); + } +#line 6697 "MachineIndependent/glslang_tab.cpp" + break; + + case 149: /* layout_qualifier_id: IDENTIFIER */ +#line 1337 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); + } +#line 6706 "MachineIndependent/glslang_tab.cpp" + break; + + case 150: /* layout_qualifier_id: IDENTIFIER EQUAL constant_expression */ +#line 1341 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-2].lex).loc); + parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); + } +#line 6715 "MachineIndependent/glslang_tab.cpp" + break; + + case 151: /* layout_qualifier_id: SHARED */ +#line 1345 "MachineIndependent/glslang.y" + { // because "shared" is both an identifier and a keyword + (yyval.interm.type).init((yyvsp[0].lex).loc); + TString strShared("shared"); + parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); + } +#line 6725 "MachineIndependent/glslang_tab.cpp" + break; + + case 152: /* precise_qualifier: PRECISE */ +#line 1354 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.noContraction = true; + } +#line 6736 "MachineIndependent/glslang_tab.cpp" + break; + + case 153: /* type_qualifier: single_type_qualifier */ +#line 1364 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6744 "MachineIndependent/glslang_tab.cpp" + break; + + case 154: /* type_qualifier: type_qualifier single_type_qualifier */ +#line 1367 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[-1].interm.type); + if ((yyval.interm.type).basicType == EbtVoid) + (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType; + + (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); + parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); + } +#line 6757 "MachineIndependent/glslang_tab.cpp" + break; + + case 155: /* single_type_qualifier: storage_qualifier */ +#line 1378 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6765 "MachineIndependent/glslang_tab.cpp" + break; + + case 156: /* single_type_qualifier: layout_qualifier */ +#line 1381 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6773 "MachineIndependent/glslang_tab.cpp" + break; + + case 157: /* single_type_qualifier: precision_qualifier */ +#line 1384 "MachineIndependent/glslang.y" + { + parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6782 "MachineIndependent/glslang_tab.cpp" + break; + + case 158: /* single_type_qualifier: interpolation_qualifier */ +#line 1388 "MachineIndependent/glslang.y" + { + // allow inheritance of storage qualifier from block declaration + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6791 "MachineIndependent/glslang_tab.cpp" + break; + + case 159: /* single_type_qualifier: invariant_qualifier */ +#line 1392 "MachineIndependent/glslang.y" + { + // allow inheritance of storage qualifier from block declaration + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6800 "MachineIndependent/glslang_tab.cpp" + break; + + case 160: /* single_type_qualifier: precise_qualifier */ +#line 1397 "MachineIndependent/glslang.y" + { + // allow inheritance of storage qualifier from block declaration + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6809 "MachineIndependent/glslang_tab.cpp" + break; + + case 161: /* single_type_qualifier: non_uniform_qualifier */ +#line 1401 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6817 "MachineIndependent/glslang_tab.cpp" + break; + + case 162: /* single_type_qualifier: spirv_storage_class_qualifier */ +#line 1404 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].interm.type).loc, "spirv_storage_class"); + parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6827 "MachineIndependent/glslang_tab.cpp" + break; + + case 163: /* single_type_qualifier: spirv_decorate_qualifier */ +#line 1409 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 6836 "MachineIndependent/glslang_tab.cpp" + break; + + case 164: /* single_type_qualifier: SPIRV_BY_REFERENCE */ +#line 1413 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.setSpirvByReference(); + } +#line 6846 "MachineIndependent/glslang_tab.cpp" + break; + + case 165: /* single_type_qualifier: SPIRV_LITERAL */ +#line 1418 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.setSpirvLiteral(); + } +#line 6856 "MachineIndependent/glslang_tab.cpp" + break; + + case 166: /* storage_qualifier: CONST */ +#line 1427 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant + } +#line 6865 "MachineIndependent/glslang_tab.cpp" + break; + + case 167: /* storage_qualifier: INOUT */ +#line 1431 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqInOut; + } +#line 6875 "MachineIndependent/glslang_tab.cpp" + break; + + case 168: /* storage_qualifier: IN */ +#line 1436 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "in"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later + (yyval.interm.type).qualifier.storage = EvqIn; + } +#line 6886 "MachineIndependent/glslang_tab.cpp" + break; + + case 169: /* storage_qualifier: OUT */ +#line 1442 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "out"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later + (yyval.interm.type).qualifier.storage = EvqOut; + } +#line 6897 "MachineIndependent/glslang_tab.cpp" + break; + + case 170: /* storage_qualifier: CENTROID */ +#line 1448 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); + parseContext.globalCheck((yyvsp[0].lex).loc, "centroid"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.centroid = true; + } +#line 6909 "MachineIndependent/glslang_tab.cpp" + break; + + case 171: /* storage_qualifier: UNIFORM */ +#line 1455 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqUniform; + } +#line 6919 "MachineIndependent/glslang_tab.cpp" + break; + + case 172: /* storage_qualifier: SHARED */ +#line 1460 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); + parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshNVMask | EShLangTaskNVMask), "shared"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqShared; + } +#line 6932 "MachineIndependent/glslang_tab.cpp" + break; + + case 173: /* storage_qualifier: BUFFER */ +#line 1468 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqBuffer; + } +#line 6942 "MachineIndependent/glslang_tab.cpp" + break; + + case 174: /* storage_qualifier: ATTRIBUTE */ +#line 1474 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); + parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); + parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute"); + parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute"); + parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute"); + + parseContext.globalCheck((yyvsp[0].lex).loc, "attribute"); + + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqVaryingIn; + } +#line 6959 "MachineIndependent/glslang_tab.cpp" + break; + + case 175: /* storage_qualifier: VARYING */ +#line 1486 "MachineIndependent/glslang.y" + { + parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); + parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); + parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying"); + parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying"); + + parseContext.globalCheck((yyvsp[0].lex).loc, "varying"); + + (yyval.interm.type).init((yyvsp[0].lex).loc); + if (parseContext.language == EShLangVertex) + (yyval.interm.type).qualifier.storage = EvqVaryingOut; + else + (yyval.interm.type).qualifier.storage = EvqVaryingIn; + } +#line 6978 "MachineIndependent/glslang_tab.cpp" + break; + + case 176: /* storage_qualifier: PATCH */ +#line 1500 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.patch = true; + } +#line 6989 "MachineIndependent/glslang_tab.cpp" + break; + + case 177: /* storage_qualifier: SAMPLE */ +#line 1506 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.sample = true; + } +#line 6999 "MachineIndependent/glslang_tab.cpp" + break; + + case 178: /* storage_qualifier: HITATTRNV */ +#line 1511 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqHitAttr; + } +#line 7012 "MachineIndependent/glslang_tab.cpp" + break; + + case 179: /* storage_qualifier: HITATTREXT */ +#line 1519 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqHitAttr; + } +#line 7025 "MachineIndependent/glslang_tab.cpp" + break; + + case 180: /* storage_qualifier: PAYLOADNV */ +#line 1527 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayload; + } +#line 7038 "MachineIndependent/glslang_tab.cpp" + break; + + case 181: /* storage_qualifier: PAYLOADEXT */ +#line 1535 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayload; + } +#line 7051 "MachineIndependent/glslang_tab.cpp" + break; + + case 182: /* storage_qualifier: PAYLOADINNV */ +#line 1543 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayloadIn; + } +#line 7064 "MachineIndependent/glslang_tab.cpp" + break; + + case 183: /* storage_qualifier: PAYLOADINEXT */ +#line 1551 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayloadIn; + } +#line 7077 "MachineIndependent/glslang_tab.cpp" + break; + + case 184: /* storage_qualifier: CALLDATANV */ +#line 1559 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableData; + } +#line 7090 "MachineIndependent/glslang_tab.cpp" + break; + + case 185: /* storage_qualifier: CALLDATAEXT */ +#line 1567 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableData; + } +#line 7103 "MachineIndependent/glslang_tab.cpp" + break; + + case 186: /* storage_qualifier: CALLDATAINNV */ +#line 1575 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableDataIn; + } +#line 7115 "MachineIndependent/glslang_tab.cpp" + break; + + case 187: /* storage_qualifier: CALLDATAINEXT */ +#line 1582 "MachineIndependent/glslang.y" + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableDataIn; + } +#line 7127 "MachineIndependent/glslang_tab.cpp" + break; + + case 188: /* storage_qualifier: COHERENT */ +#line 1589 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.coherent = true; + } +#line 7136 "MachineIndependent/glslang_tab.cpp" + break; + + case 189: /* storage_qualifier: DEVICECOHERENT */ +#line 1593 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); + (yyval.interm.type).qualifier.devicecoherent = true; + } +#line 7146 "MachineIndependent/glslang_tab.cpp" + break; + + case 190: /* storage_qualifier: QUEUEFAMILYCOHERENT */ +#line 1598 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); + (yyval.interm.type).qualifier.queuefamilycoherent = true; + } +#line 7156 "MachineIndependent/glslang_tab.cpp" + break; + + case 191: /* storage_qualifier: WORKGROUPCOHERENT */ +#line 1603 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); + (yyval.interm.type).qualifier.workgroupcoherent = true; + } +#line 7166 "MachineIndependent/glslang_tab.cpp" + break; + + case 192: /* storage_qualifier: SUBGROUPCOHERENT */ +#line 1608 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); + (yyval.interm.type).qualifier.subgroupcoherent = true; + } +#line 7176 "MachineIndependent/glslang_tab.cpp" + break; + + case 193: /* storage_qualifier: NONPRIVATE */ +#line 1613 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); + (yyval.interm.type).qualifier.nonprivate = true; + } +#line 7186 "MachineIndependent/glslang_tab.cpp" + break; + + case 194: /* storage_qualifier: SHADERCALLCOHERENT */ +#line 1618 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + (yyval.interm.type).qualifier.shadercallcoherent = true; + } +#line 7196 "MachineIndependent/glslang_tab.cpp" + break; + + case 195: /* storage_qualifier: VOLATILE */ +#line 1623 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.volatil = true; + } +#line 7205 "MachineIndependent/glslang_tab.cpp" + break; + + case 196: /* storage_qualifier: RESTRICT */ +#line 1627 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.restrict = true; + } +#line 7214 "MachineIndependent/glslang_tab.cpp" + break; + + case 197: /* storage_qualifier: READONLY */ +#line 1631 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.readonly = true; + } +#line 7223 "MachineIndependent/glslang_tab.cpp" + break; + + case 198: /* storage_qualifier: WRITEONLY */ +#line 1635 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.writeonly = true; + } +#line 7232 "MachineIndependent/glslang_tab.cpp" + break; + + case 199: /* storage_qualifier: SUBROUTINE */ +#line 1639 "MachineIndependent/glslang.y" + { + parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); + parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); + parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + } +#line 7243 "MachineIndependent/glslang_tab.cpp" + break; + + case 200: /* storage_qualifier: SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN */ +#line 1645 "MachineIndependent/glslang.y" + { + parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); + parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); + parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); + (yyval.interm.type).init((yyvsp[-3].lex).loc); + } +#line 7254 "MachineIndependent/glslang_tab.cpp" + break; + + case 201: /* non_uniform_qualifier: NONUNIFORM */ +#line 1656 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.nonUniform = true; + } +#line 7263 "MachineIndependent/glslang_tab.cpp" + break; + + case 202: /* type_name_list: IDENTIFIER */ +#line 1663 "MachineIndependent/glslang.y" + { + // TODO + } +#line 7271 "MachineIndependent/glslang_tab.cpp" + break; + + case 203: /* type_name_list: type_name_list COMMA IDENTIFIER */ +#line 1666 "MachineIndependent/glslang.y" + { + // TODO: 4.0 semantics: subroutines + // 1) make sure each identifier is a type declared earlier with SUBROUTINE + // 2) save all of the identifiers for future comparison with the declared function + } +#line 7281 "MachineIndependent/glslang_tab.cpp" + break; + + case 204: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt */ +#line 1675 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[-1].interm.type); + (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); + (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters); + } +#line 7291 "MachineIndependent/glslang_tab.cpp" + break; + + case 205: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt array_specifier */ +#line 1680 "MachineIndependent/glslang.y" + { + parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); + (yyval.interm.type) = (yyvsp[-2].interm.type); + (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); + (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters); + (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; + } +#line 7303 "MachineIndependent/glslang_tab.cpp" + break; + + case 206: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ +#line 1690 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[-1].lex).loc; + (yyval.interm).arraySizes = new TArraySizes; + (yyval.interm).arraySizes->addInnerSize(); + } +#line 7313 "MachineIndependent/glslang_tab.cpp" + break; + + case 207: /* array_specifier: LEFT_BRACKET conditional_expression RIGHT_BRACKET */ +#line 1695 "MachineIndependent/glslang.y" + { + (yyval.interm).loc = (yyvsp[-2].lex).loc; + (yyval.interm).arraySizes = new TArraySizes; + + TArraySize size; + parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); + (yyval.interm).arraySizes->addInnerSize(size); + } +#line 7326 "MachineIndependent/glslang_tab.cpp" + break; + + case 208: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ +#line 1703 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-2].interm); + (yyval.interm).arraySizes->addInnerSize(); + } +#line 7335 "MachineIndependent/glslang_tab.cpp" + break; + + case 209: /* array_specifier: array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET */ +#line 1707 "MachineIndependent/glslang.y" + { + (yyval.interm) = (yyvsp[-3].interm); + + TArraySize size; + parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); + (yyval.interm).arraySizes->addInnerSize(size); + } +#line 7347 "MachineIndependent/glslang_tab.cpp" + break; + + case 210: /* type_parameter_specifier_opt: type_parameter_specifier */ +#line 1717 "MachineIndependent/glslang.y" + { + (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters); + } +#line 7355 "MachineIndependent/glslang_tab.cpp" + break; + + case 211: /* type_parameter_specifier_opt: %empty */ +#line 1720 "MachineIndependent/glslang.y" + { + (yyval.interm.typeParameters) = 0; + } +#line 7363 "MachineIndependent/glslang_tab.cpp" + break; + + case 212: /* type_parameter_specifier: LEFT_ANGLE type_parameter_specifier_list RIGHT_ANGLE */ +#line 1726 "MachineIndependent/glslang.y" + { + (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters); + } +#line 7371 "MachineIndependent/glslang_tab.cpp" + break; + + case 213: /* type_parameter_specifier_list: unary_expression */ +#line 1732 "MachineIndependent/glslang.y" + { + (yyval.interm.typeParameters) = new TArraySizes; + + TArraySize size; + parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); + (yyval.interm.typeParameters)->addInnerSize(size); + } +#line 7383 "MachineIndependent/glslang_tab.cpp" + break; + + case 214: /* type_parameter_specifier_list: type_parameter_specifier_list COMMA unary_expression */ +#line 1739 "MachineIndependent/glslang.y" + { + (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters); + + TArraySize size; + parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); + (yyval.interm.typeParameters)->addInnerSize(size); + } +#line 7395 "MachineIndependent/glslang_tab.cpp" + break; + + case 215: /* type_specifier_nonarray: VOID */ +#line 1749 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtVoid; + } +#line 7404 "MachineIndependent/glslang_tab.cpp" + break; + + case 216: /* type_specifier_nonarray: FLOAT */ +#line 1753 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + } +#line 7413 "MachineIndependent/glslang_tab.cpp" + break; + + case 217: /* type_specifier_nonarray: INT */ +#line 1757 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + } +#line 7422 "MachineIndependent/glslang_tab.cpp" + break; + + case 218: /* type_specifier_nonarray: UINT */ +#line 1761 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + } +#line 7432 "MachineIndependent/glslang_tab.cpp" + break; + + case 219: /* type_specifier_nonarray: BOOL */ +#line 1766 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtBool; + } +#line 7441 "MachineIndependent/glslang_tab.cpp" + break; + + case 220: /* type_specifier_nonarray: VEC2 */ +#line 1770 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(2); + } +#line 7451 "MachineIndependent/glslang_tab.cpp" + break; + + case 221: /* type_specifier_nonarray: VEC3 */ +#line 1775 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(3); + } +#line 7461 "MachineIndependent/glslang_tab.cpp" + break; + + case 222: /* type_specifier_nonarray: VEC4 */ +#line 1780 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(4); + } +#line 7471 "MachineIndependent/glslang_tab.cpp" + break; + + case 223: /* type_specifier_nonarray: BVEC2 */ +#line 1785 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtBool; + (yyval.interm.type).setVector(2); + } +#line 7481 "MachineIndependent/glslang_tab.cpp" + break; + + case 224: /* type_specifier_nonarray: BVEC3 */ +#line 1790 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtBool; + (yyval.interm.type).setVector(3); + } +#line 7491 "MachineIndependent/glslang_tab.cpp" + break; + + case 225: /* type_specifier_nonarray: BVEC4 */ +#line 1795 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtBool; + (yyval.interm.type).setVector(4); + } +#line 7501 "MachineIndependent/glslang_tab.cpp" + break; + + case 226: /* type_specifier_nonarray: IVEC2 */ +#line 1800 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(2); + } +#line 7511 "MachineIndependent/glslang_tab.cpp" + break; + + case 227: /* type_specifier_nonarray: IVEC3 */ +#line 1805 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(3); + } +#line 7521 "MachineIndependent/glslang_tab.cpp" + break; + + case 228: /* type_specifier_nonarray: IVEC4 */ +#line 1810 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(4); + } +#line 7531 "MachineIndependent/glslang_tab.cpp" + break; + + case 229: /* type_specifier_nonarray: UVEC2 */ +#line 1815 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(2); + } +#line 7542 "MachineIndependent/glslang_tab.cpp" + break; + + case 230: /* type_specifier_nonarray: UVEC3 */ +#line 1821 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(3); + } +#line 7553 "MachineIndependent/glslang_tab.cpp" + break; + + case 231: /* type_specifier_nonarray: UVEC4 */ +#line 1827 "MachineIndependent/glslang.y" + { + parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(4); + } +#line 7564 "MachineIndependent/glslang_tab.cpp" + break; + + case 232: /* type_specifier_nonarray: MAT2 */ +#line 1833 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 2); + } +#line 7574 "MachineIndependent/glslang_tab.cpp" + break; + + case 233: /* type_specifier_nonarray: MAT3 */ +#line 1838 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 3); + } +#line 7584 "MachineIndependent/glslang_tab.cpp" + break; + + case 234: /* type_specifier_nonarray: MAT4 */ +#line 1843 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 4); + } +#line 7594 "MachineIndependent/glslang_tab.cpp" + break; + + case 235: /* type_specifier_nonarray: MAT2X2 */ +#line 1848 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 2); + } +#line 7604 "MachineIndependent/glslang_tab.cpp" + break; + + case 236: /* type_specifier_nonarray: MAT2X3 */ +#line 1853 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 3); + } +#line 7614 "MachineIndependent/glslang_tab.cpp" + break; + + case 237: /* type_specifier_nonarray: MAT2X4 */ +#line 1858 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 4); + } +#line 7624 "MachineIndependent/glslang_tab.cpp" + break; + + case 238: /* type_specifier_nonarray: MAT3X2 */ +#line 1863 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 2); + } +#line 7634 "MachineIndependent/glslang_tab.cpp" + break; + + case 239: /* type_specifier_nonarray: MAT3X3 */ +#line 1868 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 3); + } +#line 7644 "MachineIndependent/glslang_tab.cpp" + break; + + case 240: /* type_specifier_nonarray: MAT3X4 */ +#line 1873 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 4); + } +#line 7654 "MachineIndependent/glslang_tab.cpp" + break; + + case 241: /* type_specifier_nonarray: MAT4X2 */ +#line 1878 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 2); + } +#line 7664 "MachineIndependent/glslang_tab.cpp" + break; + + case 242: /* type_specifier_nonarray: MAT4X3 */ +#line 1883 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 3); + } +#line 7674 "MachineIndependent/glslang_tab.cpp" + break; + + case 243: /* type_specifier_nonarray: MAT4X4 */ +#line 1888 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 4); + } +#line 7684 "MachineIndependent/glslang_tab.cpp" + break; + + case 244: /* type_specifier_nonarray: DOUBLE */ +#line 1894 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + } +#line 7696 "MachineIndependent/glslang_tab.cpp" + break; + + case 245: /* type_specifier_nonarray: FLOAT16_T */ +#line 1901 "MachineIndependent/glslang.y" + { + parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + } +#line 7706 "MachineIndependent/glslang_tab.cpp" + break; + + case 246: /* type_specifier_nonarray: FLOAT32_T */ +#line 1906 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + } +#line 7716 "MachineIndependent/glslang_tab.cpp" + break; + + case 247: /* type_specifier_nonarray: FLOAT64_T */ +#line 1911 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + } +#line 7726 "MachineIndependent/glslang_tab.cpp" + break; + + case 248: /* type_specifier_nonarray: INT8_T */ +#line 1916 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt8; + } +#line 7736 "MachineIndependent/glslang_tab.cpp" + break; + + case 249: /* type_specifier_nonarray: UINT8_T */ +#line 1921 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint8; + } +#line 7746 "MachineIndependent/glslang_tab.cpp" + break; + + case 250: /* type_specifier_nonarray: INT16_T */ +#line 1926 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt16; + } +#line 7756 "MachineIndependent/glslang_tab.cpp" + break; + + case 251: /* type_specifier_nonarray: UINT16_T */ +#line 1931 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint16; + } +#line 7766 "MachineIndependent/glslang_tab.cpp" + break; + + case 252: /* type_specifier_nonarray: INT32_T */ +#line 1936 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + } +#line 7776 "MachineIndependent/glslang_tab.cpp" + break; + + case 253: /* type_specifier_nonarray: UINT32_T */ +#line 1941 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + } +#line 7786 "MachineIndependent/glslang_tab.cpp" + break; + + case 254: /* type_specifier_nonarray: INT64_T */ +#line 1946 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt64; + } +#line 7796 "MachineIndependent/glslang_tab.cpp" + break; + + case 255: /* type_specifier_nonarray: UINT64_T */ +#line 1951 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint64; + } +#line 7806 "MachineIndependent/glslang_tab.cpp" + break; + + case 256: /* type_specifier_nonarray: DVEC2 */ +#line 1956 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(2); + } +#line 7819 "MachineIndependent/glslang_tab.cpp" + break; + + case 257: /* type_specifier_nonarray: DVEC3 */ +#line 1964 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(3); + } +#line 7832 "MachineIndependent/glslang_tab.cpp" + break; + + case 258: /* type_specifier_nonarray: DVEC4 */ +#line 1972 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(4); + } +#line 7845 "MachineIndependent/glslang_tab.cpp" + break; + + case 259: /* type_specifier_nonarray: F16VEC2 */ +#line 1980 "MachineIndependent/glslang.y" + { + parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setVector(2); + } +#line 7856 "MachineIndependent/glslang_tab.cpp" + break; + + case 260: /* type_specifier_nonarray: F16VEC3 */ +#line 1986 "MachineIndependent/glslang.y" + { + parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setVector(3); + } +#line 7867 "MachineIndependent/glslang_tab.cpp" + break; + + case 261: /* type_specifier_nonarray: F16VEC4 */ +#line 1992 "MachineIndependent/glslang.y" + { + parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setVector(4); + } +#line 7878 "MachineIndependent/glslang_tab.cpp" + break; + + case 262: /* type_specifier_nonarray: F32VEC2 */ +#line 1998 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(2); + } +#line 7889 "MachineIndependent/glslang_tab.cpp" + break; + + case 263: /* type_specifier_nonarray: F32VEC3 */ +#line 2004 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(3); + } +#line 7900 "MachineIndependent/glslang_tab.cpp" + break; + + case 264: /* type_specifier_nonarray: F32VEC4 */ +#line 2010 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setVector(4); + } +#line 7911 "MachineIndependent/glslang_tab.cpp" + break; + + case 265: /* type_specifier_nonarray: F64VEC2 */ +#line 2016 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(2); + } +#line 7922 "MachineIndependent/glslang_tab.cpp" + break; + + case 266: /* type_specifier_nonarray: F64VEC3 */ +#line 2022 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(3); + } +#line 7933 "MachineIndependent/glslang_tab.cpp" + break; + + case 267: /* type_specifier_nonarray: F64VEC4 */ +#line 2028 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setVector(4); + } +#line 7944 "MachineIndependent/glslang_tab.cpp" + break; + + case 268: /* type_specifier_nonarray: I8VEC2 */ +#line 2034 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt8; + (yyval.interm.type).setVector(2); + } +#line 7955 "MachineIndependent/glslang_tab.cpp" + break; + + case 269: /* type_specifier_nonarray: I8VEC3 */ +#line 2040 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt8; + (yyval.interm.type).setVector(3); + } +#line 7966 "MachineIndependent/glslang_tab.cpp" + break; + + case 270: /* type_specifier_nonarray: I8VEC4 */ +#line 2046 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt8; + (yyval.interm.type).setVector(4); + } +#line 7977 "MachineIndependent/glslang_tab.cpp" + break; + + case 271: /* type_specifier_nonarray: I16VEC2 */ +#line 2052 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt16; + (yyval.interm.type).setVector(2); + } +#line 7988 "MachineIndependent/glslang_tab.cpp" + break; + + case 272: /* type_specifier_nonarray: I16VEC3 */ +#line 2058 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt16; + (yyval.interm.type).setVector(3); + } +#line 7999 "MachineIndependent/glslang_tab.cpp" + break; + + case 273: /* type_specifier_nonarray: I16VEC4 */ +#line 2064 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt16; + (yyval.interm.type).setVector(4); + } +#line 8010 "MachineIndependent/glslang_tab.cpp" + break; + + case 274: /* type_specifier_nonarray: I32VEC2 */ +#line 2070 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(2); + } +#line 8021 "MachineIndependent/glslang_tab.cpp" + break; + + case 275: /* type_specifier_nonarray: I32VEC3 */ +#line 2076 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(3); + } +#line 8032 "MachineIndependent/glslang_tab.cpp" + break; + + case 276: /* type_specifier_nonarray: I32VEC4 */ +#line 2082 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).setVector(4); + } +#line 8043 "MachineIndependent/glslang_tab.cpp" + break; + + case 277: /* type_specifier_nonarray: I64VEC2 */ +#line 2088 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt64; + (yyval.interm.type).setVector(2); + } +#line 8054 "MachineIndependent/glslang_tab.cpp" + break; + + case 278: /* type_specifier_nonarray: I64VEC3 */ +#line 2094 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt64; + (yyval.interm.type).setVector(3); + } +#line 8065 "MachineIndependent/glslang_tab.cpp" + break; + + case 279: /* type_specifier_nonarray: I64VEC4 */ +#line 2100 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt64; + (yyval.interm.type).setVector(4); + } +#line 8076 "MachineIndependent/glslang_tab.cpp" + break; + + case 280: /* type_specifier_nonarray: U8VEC2 */ +#line 2106 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint8; + (yyval.interm.type).setVector(2); + } +#line 8087 "MachineIndependent/glslang_tab.cpp" + break; + + case 281: /* type_specifier_nonarray: U8VEC3 */ +#line 2112 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint8; + (yyval.interm.type).setVector(3); + } +#line 8098 "MachineIndependent/glslang_tab.cpp" + break; + + case 282: /* type_specifier_nonarray: U8VEC4 */ +#line 2118 "MachineIndependent/glslang.y" + { + parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint8; + (yyval.interm.type).setVector(4); + } +#line 8109 "MachineIndependent/glslang_tab.cpp" + break; + + case 283: /* type_specifier_nonarray: U16VEC2 */ +#line 2124 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint16; + (yyval.interm.type).setVector(2); + } +#line 8120 "MachineIndependent/glslang_tab.cpp" + break; + + case 284: /* type_specifier_nonarray: U16VEC3 */ +#line 2130 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint16; + (yyval.interm.type).setVector(3); + } +#line 8131 "MachineIndependent/glslang_tab.cpp" + break; + + case 285: /* type_specifier_nonarray: U16VEC4 */ +#line 2136 "MachineIndependent/glslang.y" + { + parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint16; + (yyval.interm.type).setVector(4); + } +#line 8142 "MachineIndependent/glslang_tab.cpp" + break; + + case 286: /* type_specifier_nonarray: U32VEC2 */ +#line 2142 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(2); + } +#line 8153 "MachineIndependent/glslang_tab.cpp" + break; + + case 287: /* type_specifier_nonarray: U32VEC3 */ +#line 2148 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(3); + } +#line 8164 "MachineIndependent/glslang_tab.cpp" + break; + + case 288: /* type_specifier_nonarray: U32VEC4 */ +#line 2154 "MachineIndependent/glslang.y" + { + parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).setVector(4); + } +#line 8175 "MachineIndependent/glslang_tab.cpp" + break; + + case 289: /* type_specifier_nonarray: U64VEC2 */ +#line 2160 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint64; + (yyval.interm.type).setVector(2); + } +#line 8186 "MachineIndependent/glslang_tab.cpp" + break; + + case 290: /* type_specifier_nonarray: U64VEC3 */ +#line 2166 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint64; + (yyval.interm.type).setVector(3); + } +#line 8197 "MachineIndependent/glslang_tab.cpp" + break; + + case 291: /* type_specifier_nonarray: U64VEC4 */ +#line 2172 "MachineIndependent/glslang.y" + { + parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint64; + (yyval.interm.type).setVector(4); + } +#line 8208 "MachineIndependent/glslang_tab.cpp" + break; + + case 292: /* type_specifier_nonarray: DMAT2 */ +#line 2178 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8221 "MachineIndependent/glslang_tab.cpp" + break; + + case 293: /* type_specifier_nonarray: DMAT3 */ +#line 2186 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8234 "MachineIndependent/glslang_tab.cpp" + break; + + case 294: /* type_specifier_nonarray: DMAT4 */ +#line 2194 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8247 "MachineIndependent/glslang_tab.cpp" + break; + + case 295: /* type_specifier_nonarray: DMAT2X2 */ +#line 2202 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8260 "MachineIndependent/glslang_tab.cpp" + break; + + case 296: /* type_specifier_nonarray: DMAT2X3 */ +#line 2210 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 3); + } +#line 8273 "MachineIndependent/glslang_tab.cpp" + break; + + case 297: /* type_specifier_nonarray: DMAT2X4 */ +#line 2218 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 4); + } +#line 8286 "MachineIndependent/glslang_tab.cpp" + break; + + case 298: /* type_specifier_nonarray: DMAT3X2 */ +#line 2226 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 2); + } +#line 8299 "MachineIndependent/glslang_tab.cpp" + break; + + case 299: /* type_specifier_nonarray: DMAT3X3 */ +#line 2234 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8312 "MachineIndependent/glslang_tab.cpp" + break; + + case 300: /* type_specifier_nonarray: DMAT3X4 */ +#line 2242 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 4); + } +#line 8325 "MachineIndependent/glslang_tab.cpp" + break; + + case 301: /* type_specifier_nonarray: DMAT4X2 */ +#line 2250 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 2); + } +#line 8338 "MachineIndependent/glslang_tab.cpp" + break; + + case 302: /* type_specifier_nonarray: DMAT4X3 */ +#line 2258 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 3); + } +#line 8351 "MachineIndependent/glslang_tab.cpp" + break; + + case 303: /* type_specifier_nonarray: DMAT4X4 */ +#line 2266 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8364 "MachineIndependent/glslang_tab.cpp" + break; + + case 304: /* type_specifier_nonarray: F16MAT2 */ +#line 2274 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8375 "MachineIndependent/glslang_tab.cpp" + break; + + case 305: /* type_specifier_nonarray: F16MAT3 */ +#line 2280 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8386 "MachineIndependent/glslang_tab.cpp" + break; + + case 306: /* type_specifier_nonarray: F16MAT4 */ +#line 2286 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8397 "MachineIndependent/glslang_tab.cpp" + break; + + case 307: /* type_specifier_nonarray: F16MAT2X2 */ +#line 2292 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8408 "MachineIndependent/glslang_tab.cpp" + break; + + case 308: /* type_specifier_nonarray: F16MAT2X3 */ +#line 2298 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(2, 3); + } +#line 8419 "MachineIndependent/glslang_tab.cpp" + break; + + case 309: /* type_specifier_nonarray: F16MAT2X4 */ +#line 2304 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(2, 4); + } +#line 8430 "MachineIndependent/glslang_tab.cpp" + break; + + case 310: /* type_specifier_nonarray: F16MAT3X2 */ +#line 2310 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(3, 2); + } +#line 8441 "MachineIndependent/glslang_tab.cpp" + break; + + case 311: /* type_specifier_nonarray: F16MAT3X3 */ +#line 2316 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8452 "MachineIndependent/glslang_tab.cpp" + break; + + case 312: /* type_specifier_nonarray: F16MAT3X4 */ +#line 2322 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(3, 4); + } +#line 8463 "MachineIndependent/glslang_tab.cpp" + break; + + case 313: /* type_specifier_nonarray: F16MAT4X2 */ +#line 2328 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(4, 2); + } +#line 8474 "MachineIndependent/glslang_tab.cpp" + break; + + case 314: /* type_specifier_nonarray: F16MAT4X3 */ +#line 2334 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(4, 3); + } +#line 8485 "MachineIndependent/glslang_tab.cpp" + break; + + case 315: /* type_specifier_nonarray: F16MAT4X4 */ +#line 2340 "MachineIndependent/glslang.y" + { + parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat16; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8496 "MachineIndependent/glslang_tab.cpp" + break; + + case 316: /* type_specifier_nonarray: F32MAT2 */ +#line 2346 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8507 "MachineIndependent/glslang_tab.cpp" + break; + + case 317: /* type_specifier_nonarray: F32MAT3 */ +#line 2352 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8518 "MachineIndependent/glslang_tab.cpp" + break; + + case 318: /* type_specifier_nonarray: F32MAT4 */ +#line 2358 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8529 "MachineIndependent/glslang_tab.cpp" + break; + + case 319: /* type_specifier_nonarray: F32MAT2X2 */ +#line 2364 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8540 "MachineIndependent/glslang_tab.cpp" + break; + + case 320: /* type_specifier_nonarray: F32MAT2X3 */ +#line 2370 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 3); + } +#line 8551 "MachineIndependent/glslang_tab.cpp" + break; + + case 321: /* type_specifier_nonarray: F32MAT2X4 */ +#line 2376 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(2, 4); + } +#line 8562 "MachineIndependent/glslang_tab.cpp" + break; + + case 322: /* type_specifier_nonarray: F32MAT3X2 */ +#line 2382 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 2); + } +#line 8573 "MachineIndependent/glslang_tab.cpp" + break; + + case 323: /* type_specifier_nonarray: F32MAT3X3 */ +#line 2388 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8584 "MachineIndependent/glslang_tab.cpp" + break; + + case 324: /* type_specifier_nonarray: F32MAT3X4 */ +#line 2394 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(3, 4); + } +#line 8595 "MachineIndependent/glslang_tab.cpp" + break; + + case 325: /* type_specifier_nonarray: F32MAT4X2 */ +#line 2400 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 2); + } +#line 8606 "MachineIndependent/glslang_tab.cpp" + break; + + case 326: /* type_specifier_nonarray: F32MAT4X3 */ +#line 2406 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 3); + } +#line 8617 "MachineIndependent/glslang_tab.cpp" + break; + + case 327: /* type_specifier_nonarray: F32MAT4X4 */ +#line 2412 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8628 "MachineIndependent/glslang_tab.cpp" + break; + + case 328: /* type_specifier_nonarray: F64MAT2 */ +#line 2418 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8639 "MachineIndependent/glslang_tab.cpp" + break; + + case 329: /* type_specifier_nonarray: F64MAT3 */ +#line 2424 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8650 "MachineIndependent/glslang_tab.cpp" + break; + + case 330: /* type_specifier_nonarray: F64MAT4 */ +#line 2430 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8661 "MachineIndependent/glslang_tab.cpp" + break; + + case 331: /* type_specifier_nonarray: F64MAT2X2 */ +#line 2436 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 2); + } +#line 8672 "MachineIndependent/glslang_tab.cpp" + break; + + case 332: /* type_specifier_nonarray: F64MAT2X3 */ +#line 2442 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 3); + } +#line 8683 "MachineIndependent/glslang_tab.cpp" + break; + + case 333: /* type_specifier_nonarray: F64MAT2X4 */ +#line 2448 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(2, 4); + } +#line 8694 "MachineIndependent/glslang_tab.cpp" + break; + + case 334: /* type_specifier_nonarray: F64MAT3X2 */ +#line 2454 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 2); + } +#line 8705 "MachineIndependent/glslang_tab.cpp" + break; + + case 335: /* type_specifier_nonarray: F64MAT3X3 */ +#line 2460 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 3); + } +#line 8716 "MachineIndependent/glslang_tab.cpp" + break; + + case 336: /* type_specifier_nonarray: F64MAT3X4 */ +#line 2466 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(3, 4); + } +#line 8727 "MachineIndependent/glslang_tab.cpp" + break; + + case 337: /* type_specifier_nonarray: F64MAT4X2 */ +#line 2472 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 2); + } +#line 8738 "MachineIndependent/glslang_tab.cpp" + break; + + case 338: /* type_specifier_nonarray: F64MAT4X3 */ +#line 2478 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 3); + } +#line 8749 "MachineIndependent/glslang_tab.cpp" + break; + + case 339: /* type_specifier_nonarray: F64MAT4X4 */ +#line 2484 "MachineIndependent/glslang.y" + { + parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtDouble; + (yyval.interm.type).setMatrix(4, 4); + } +#line 8760 "MachineIndependent/glslang_tab.cpp" + break; + + case 340: /* type_specifier_nonarray: ACCSTRUCTNV */ +#line 2490 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtAccStruct; + } +#line 8769 "MachineIndependent/glslang_tab.cpp" + break; + + case 341: /* type_specifier_nonarray: ACCSTRUCTEXT */ +#line 2494 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtAccStruct; + } +#line 8778 "MachineIndependent/glslang_tab.cpp" + break; + + case 342: /* type_specifier_nonarray: RAYQUERYEXT */ +#line 2498 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtRayQuery; + } +#line 8787 "MachineIndependent/glslang_tab.cpp" + break; + + case 343: /* type_specifier_nonarray: ATOMIC_UINT */ +#line 2502 "MachineIndependent/glslang.y" + { + parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtAtomicUint; + } +#line 8797 "MachineIndependent/glslang_tab.cpp" + break; + + case 344: /* type_specifier_nonarray: SAMPLER1D */ +#line 2507 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd1D); + } +#line 8807 "MachineIndependent/glslang_tab.cpp" + break; + + case 345: /* type_specifier_nonarray: SAMPLER2D */ +#line 2513 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D); + } +#line 8817 "MachineIndependent/glslang_tab.cpp" + break; + + case 346: /* type_specifier_nonarray: SAMPLER3D */ +#line 2518 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd3D); + } +#line 8827 "MachineIndependent/glslang_tab.cpp" + break; + + case 347: /* type_specifier_nonarray: SAMPLERCUBE */ +#line 2523 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdCube); + } +#line 8837 "MachineIndependent/glslang_tab.cpp" + break; + + case 348: /* type_specifier_nonarray: SAMPLER2DSHADOW */ +#line 2528 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); + } +#line 8847 "MachineIndependent/glslang_tab.cpp" + break; + + case 349: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ +#line 2533 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); + } +#line 8857 "MachineIndependent/glslang_tab.cpp" + break; + + case 350: /* type_specifier_nonarray: SAMPLER2DARRAY */ +#line 2538 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); + } +#line 8867 "MachineIndependent/glslang_tab.cpp" + break; + + case 351: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ +#line 2543 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); + } +#line 8877 "MachineIndependent/glslang_tab.cpp" + break; + + case 352: /* type_specifier_nonarray: SAMPLER1DSHADOW */ +#line 2549 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); + } +#line 8887 "MachineIndependent/glslang_tab.cpp" + break; + + case 353: /* type_specifier_nonarray: SAMPLER1DARRAY */ +#line 2554 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); + } +#line 8897 "MachineIndependent/glslang_tab.cpp" + break; + + case 354: /* type_specifier_nonarray: SAMPLER1DARRAYSHADOW */ +#line 2559 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); + } +#line 8907 "MachineIndependent/glslang_tab.cpp" + break; + + case 355: /* type_specifier_nonarray: SAMPLERCUBEARRAY */ +#line 2564 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); + } +#line 8917 "MachineIndependent/glslang_tab.cpp" + break; + + case 356: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOW */ +#line 2569 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); + } +#line 8927 "MachineIndependent/glslang_tab.cpp" + break; + + case 357: /* type_specifier_nonarray: F16SAMPLER1D */ +#line 2574 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); + } +#line 8938 "MachineIndependent/glslang_tab.cpp" + break; + + case 358: /* type_specifier_nonarray: F16SAMPLER2D */ +#line 2580 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); + } +#line 8949 "MachineIndependent/glslang_tab.cpp" + break; + + case 359: /* type_specifier_nonarray: F16SAMPLER3D */ +#line 2586 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); + } +#line 8960 "MachineIndependent/glslang_tab.cpp" + break; + + case 360: /* type_specifier_nonarray: F16SAMPLERCUBE */ +#line 2592 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); + } +#line 8971 "MachineIndependent/glslang_tab.cpp" + break; + + case 361: /* type_specifier_nonarray: F16SAMPLER1DSHADOW */ +#line 2598 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); + } +#line 8982 "MachineIndependent/glslang_tab.cpp" + break; + + case 362: /* type_specifier_nonarray: F16SAMPLER2DSHADOW */ +#line 2604 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); + } +#line 8993 "MachineIndependent/glslang_tab.cpp" + break; + + case 363: /* type_specifier_nonarray: F16SAMPLERCUBESHADOW */ +#line 2610 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); + } +#line 9004 "MachineIndependent/glslang_tab.cpp" + break; + + case 364: /* type_specifier_nonarray: F16SAMPLER1DARRAY */ +#line 2616 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); + } +#line 9015 "MachineIndependent/glslang_tab.cpp" + break; + + case 365: /* type_specifier_nonarray: F16SAMPLER2DARRAY */ +#line 2622 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); + } +#line 9026 "MachineIndependent/glslang_tab.cpp" + break; + + case 366: /* type_specifier_nonarray: F16SAMPLER1DARRAYSHADOW */ +#line 2628 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); + } +#line 9037 "MachineIndependent/glslang_tab.cpp" + break; + + case 367: /* type_specifier_nonarray: F16SAMPLER2DARRAYSHADOW */ +#line 2634 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); + } +#line 9048 "MachineIndependent/glslang_tab.cpp" + break; + + case 368: /* type_specifier_nonarray: F16SAMPLERCUBEARRAY */ +#line 2640 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); + } +#line 9059 "MachineIndependent/glslang_tab.cpp" + break; + + case 369: /* type_specifier_nonarray: F16SAMPLERCUBEARRAYSHADOW */ +#line 2646 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); + } +#line 9070 "MachineIndependent/glslang_tab.cpp" + break; + + case 370: /* type_specifier_nonarray: ISAMPLER1D */ +#line 2652 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd1D); + } +#line 9080 "MachineIndependent/glslang_tab.cpp" + break; + + case 371: /* type_specifier_nonarray: ISAMPLER2D */ +#line 2658 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd2D); + } +#line 9090 "MachineIndependent/glslang_tab.cpp" + break; + + case 372: /* type_specifier_nonarray: ISAMPLER3D */ +#line 2663 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd3D); + } +#line 9100 "MachineIndependent/glslang_tab.cpp" + break; + + case 373: /* type_specifier_nonarray: ISAMPLERCUBE */ +#line 2668 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, EsdCube); + } +#line 9110 "MachineIndependent/glslang_tab.cpp" + break; + + case 374: /* type_specifier_nonarray: ISAMPLER2DARRAY */ +#line 2673 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); + } +#line 9120 "MachineIndependent/glslang_tab.cpp" + break; + + case 375: /* type_specifier_nonarray: USAMPLER2D */ +#line 2678 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd2D); + } +#line 9130 "MachineIndependent/glslang_tab.cpp" + break; + + case 376: /* type_specifier_nonarray: USAMPLER3D */ +#line 2683 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd3D); + } +#line 9140 "MachineIndependent/glslang_tab.cpp" + break; + + case 377: /* type_specifier_nonarray: USAMPLERCUBE */ +#line 2688 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, EsdCube); + } +#line 9150 "MachineIndependent/glslang_tab.cpp" + break; + + case 378: /* type_specifier_nonarray: ISAMPLER1DARRAY */ +#line 2694 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); + } +#line 9160 "MachineIndependent/glslang_tab.cpp" + break; + + case 379: /* type_specifier_nonarray: ISAMPLERCUBEARRAY */ +#line 2699 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); + } +#line 9170 "MachineIndependent/glslang_tab.cpp" + break; + + case 380: /* type_specifier_nonarray: USAMPLER1D */ +#line 2704 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd1D); + } +#line 9180 "MachineIndependent/glslang_tab.cpp" + break; + + case 381: /* type_specifier_nonarray: USAMPLER1DARRAY */ +#line 2709 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); + } +#line 9190 "MachineIndependent/glslang_tab.cpp" + break; + + case 382: /* type_specifier_nonarray: USAMPLERCUBEARRAY */ +#line 2714 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); + } +#line 9200 "MachineIndependent/glslang_tab.cpp" + break; + + case 383: /* type_specifier_nonarray: TEXTURECUBEARRAY */ +#line 2719 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); + } +#line 9210 "MachineIndependent/glslang_tab.cpp" + break; + + case 384: /* type_specifier_nonarray: ITEXTURECUBEARRAY */ +#line 2724 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); + } +#line 9220 "MachineIndependent/glslang_tab.cpp" + break; + + case 385: /* type_specifier_nonarray: UTEXTURECUBEARRAY */ +#line 2729 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); + } +#line 9230 "MachineIndependent/glslang_tab.cpp" + break; + + case 386: /* type_specifier_nonarray: USAMPLER2DARRAY */ +#line 2735 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); + } +#line 9240 "MachineIndependent/glslang_tab.cpp" + break; + + case 387: /* type_specifier_nonarray: TEXTURE2D */ +#line 2740 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); + } +#line 9250 "MachineIndependent/glslang_tab.cpp" + break; + + case 388: /* type_specifier_nonarray: TEXTURE3D */ +#line 2745 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); + } +#line 9260 "MachineIndependent/glslang_tab.cpp" + break; + + case 389: /* type_specifier_nonarray: TEXTURE2DARRAY */ +#line 2750 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); + } +#line 9270 "MachineIndependent/glslang_tab.cpp" + break; + + case 390: /* type_specifier_nonarray: TEXTURECUBE */ +#line 2755 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); + } +#line 9280 "MachineIndependent/glslang_tab.cpp" + break; + + case 391: /* type_specifier_nonarray: ITEXTURE2D */ +#line 2760 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); + } +#line 9290 "MachineIndependent/glslang_tab.cpp" + break; + + case 392: /* type_specifier_nonarray: ITEXTURE3D */ +#line 2765 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); + } +#line 9300 "MachineIndependent/glslang_tab.cpp" + break; + + case 393: /* type_specifier_nonarray: ITEXTURECUBE */ +#line 2770 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); + } +#line 9310 "MachineIndependent/glslang_tab.cpp" + break; + + case 394: /* type_specifier_nonarray: ITEXTURE2DARRAY */ +#line 2775 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); + } +#line 9320 "MachineIndependent/glslang_tab.cpp" + break; + + case 395: /* type_specifier_nonarray: UTEXTURE2D */ +#line 2780 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); + } +#line 9330 "MachineIndependent/glslang_tab.cpp" + break; + + case 396: /* type_specifier_nonarray: UTEXTURE3D */ +#line 2785 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); + } +#line 9340 "MachineIndependent/glslang_tab.cpp" + break; + + case 397: /* type_specifier_nonarray: UTEXTURECUBE */ +#line 2790 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); + } +#line 9350 "MachineIndependent/glslang_tab.cpp" + break; + + case 398: /* type_specifier_nonarray: UTEXTURE2DARRAY */ +#line 2795 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); + } +#line 9360 "MachineIndependent/glslang_tab.cpp" + break; + + case 399: /* type_specifier_nonarray: SAMPLER */ +#line 2800 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setPureSampler(false); + } +#line 9370 "MachineIndependent/glslang_tab.cpp" + break; + + case 400: /* type_specifier_nonarray: SAMPLERSHADOW */ +#line 2805 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setPureSampler(true); + } +#line 9380 "MachineIndependent/glslang_tab.cpp" + break; + + case 401: /* type_specifier_nonarray: SAMPLER2DRECT */ +#line 2811 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdRect); + } +#line 9390 "MachineIndependent/glslang_tab.cpp" + break; + + case 402: /* type_specifier_nonarray: SAMPLER2DRECTSHADOW */ +#line 2816 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); + } +#line 9400 "MachineIndependent/glslang_tab.cpp" + break; + + case 403: /* type_specifier_nonarray: F16SAMPLER2DRECT */ +#line 2821 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); + } +#line 9411 "MachineIndependent/glslang_tab.cpp" + break; + + case 404: /* type_specifier_nonarray: F16SAMPLER2DRECTSHADOW */ +#line 2827 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); + } +#line 9422 "MachineIndependent/glslang_tab.cpp" + break; + + case 405: /* type_specifier_nonarray: ISAMPLER2DRECT */ +#line 2833 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, EsdRect); + } +#line 9432 "MachineIndependent/glslang_tab.cpp" + break; + + case 406: /* type_specifier_nonarray: USAMPLER2DRECT */ +#line 2838 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, EsdRect); + } +#line 9442 "MachineIndependent/glslang_tab.cpp" + break; + + case 407: /* type_specifier_nonarray: SAMPLERBUFFER */ +#line 2843 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); + } +#line 9452 "MachineIndependent/glslang_tab.cpp" + break; + + case 408: /* type_specifier_nonarray: F16SAMPLERBUFFER */ +#line 2848 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); + } +#line 9463 "MachineIndependent/glslang_tab.cpp" + break; + + case 409: /* type_specifier_nonarray: ISAMPLERBUFFER */ +#line 2854 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); + } +#line 9473 "MachineIndependent/glslang_tab.cpp" + break; + + case 410: /* type_specifier_nonarray: USAMPLERBUFFER */ +#line 2859 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); + } +#line 9483 "MachineIndependent/glslang_tab.cpp" + break; + + case 411: /* type_specifier_nonarray: SAMPLER2DMS */ +#line 2864 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); + } +#line 9493 "MachineIndependent/glslang_tab.cpp" + break; + + case 412: /* type_specifier_nonarray: F16SAMPLER2DMS */ +#line 2869 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); + } +#line 9504 "MachineIndependent/glslang_tab.cpp" + break; + + case 413: /* type_specifier_nonarray: ISAMPLER2DMS */ +#line 2875 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); + } +#line 9514 "MachineIndependent/glslang_tab.cpp" + break; + + case 414: /* type_specifier_nonarray: USAMPLER2DMS */ +#line 2880 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); + } +#line 9524 "MachineIndependent/glslang_tab.cpp" + break; + + case 415: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ +#line 2885 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); + } +#line 9534 "MachineIndependent/glslang_tab.cpp" + break; + + case 416: /* type_specifier_nonarray: F16SAMPLER2DMSARRAY */ +#line 2890 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); + } +#line 9545 "MachineIndependent/glslang_tab.cpp" + break; + + case 417: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ +#line 2896 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); + } +#line 9555 "MachineIndependent/glslang_tab.cpp" + break; + + case 418: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ +#line 2901 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); + } +#line 9565 "MachineIndependent/glslang_tab.cpp" + break; + + case 419: /* type_specifier_nonarray: TEXTURE1D */ +#line 2906 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); + } +#line 9575 "MachineIndependent/glslang_tab.cpp" + break; + + case 420: /* type_specifier_nonarray: F16TEXTURE1D */ +#line 2911 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); + } +#line 9586 "MachineIndependent/glslang_tab.cpp" + break; + + case 421: /* type_specifier_nonarray: F16TEXTURE2D */ +#line 2917 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); + } +#line 9597 "MachineIndependent/glslang_tab.cpp" + break; + + case 422: /* type_specifier_nonarray: F16TEXTURE3D */ +#line 2923 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); + } +#line 9608 "MachineIndependent/glslang_tab.cpp" + break; + + case 423: /* type_specifier_nonarray: F16TEXTURECUBE */ +#line 2929 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); + } +#line 9619 "MachineIndependent/glslang_tab.cpp" + break; + + case 424: /* type_specifier_nonarray: TEXTURE1DARRAY */ +#line 2935 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); + } +#line 9629 "MachineIndependent/glslang_tab.cpp" + break; + + case 425: /* type_specifier_nonarray: F16TEXTURE1DARRAY */ +#line 2940 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); + } +#line 9640 "MachineIndependent/glslang_tab.cpp" + break; + + case 426: /* type_specifier_nonarray: F16TEXTURE2DARRAY */ +#line 2946 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); + } +#line 9651 "MachineIndependent/glslang_tab.cpp" + break; + + case 427: /* type_specifier_nonarray: F16TEXTURECUBEARRAY */ +#line 2952 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); + } +#line 9662 "MachineIndependent/glslang_tab.cpp" + break; + + case 428: /* type_specifier_nonarray: ITEXTURE1D */ +#line 2958 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); + } +#line 9672 "MachineIndependent/glslang_tab.cpp" + break; + + case 429: /* type_specifier_nonarray: ITEXTURE1DARRAY */ +#line 2963 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); + } +#line 9682 "MachineIndependent/glslang_tab.cpp" + break; + + case 430: /* type_specifier_nonarray: UTEXTURE1D */ +#line 2968 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); + } +#line 9692 "MachineIndependent/glslang_tab.cpp" + break; + + case 431: /* type_specifier_nonarray: UTEXTURE1DARRAY */ +#line 2973 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); + } +#line 9702 "MachineIndependent/glslang_tab.cpp" + break; + + case 432: /* type_specifier_nonarray: TEXTURE2DRECT */ +#line 2978 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); + } +#line 9712 "MachineIndependent/glslang_tab.cpp" + break; + + case 433: /* type_specifier_nonarray: F16TEXTURE2DRECT */ +#line 2983 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); + } +#line 9723 "MachineIndependent/glslang_tab.cpp" + break; + + case 434: /* type_specifier_nonarray: ITEXTURE2DRECT */ +#line 2989 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); + } +#line 9733 "MachineIndependent/glslang_tab.cpp" + break; + + case 435: /* type_specifier_nonarray: UTEXTURE2DRECT */ +#line 2994 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); + } +#line 9743 "MachineIndependent/glslang_tab.cpp" + break; + + case 436: /* type_specifier_nonarray: TEXTUREBUFFER */ +#line 2999 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); + } +#line 9753 "MachineIndependent/glslang_tab.cpp" + break; + + case 437: /* type_specifier_nonarray: F16TEXTUREBUFFER */ +#line 3004 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); + } +#line 9764 "MachineIndependent/glslang_tab.cpp" + break; + + case 438: /* type_specifier_nonarray: ITEXTUREBUFFER */ +#line 3010 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); + } +#line 9774 "MachineIndependent/glslang_tab.cpp" + break; + + case 439: /* type_specifier_nonarray: UTEXTUREBUFFER */ +#line 3015 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); + } +#line 9784 "MachineIndependent/glslang_tab.cpp" + break; + + case 440: /* type_specifier_nonarray: TEXTURE2DMS */ +#line 3020 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); + } +#line 9794 "MachineIndependent/glslang_tab.cpp" + break; + + case 441: /* type_specifier_nonarray: F16TEXTURE2DMS */ +#line 3025 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); + } +#line 9805 "MachineIndependent/glslang_tab.cpp" + break; + + case 442: /* type_specifier_nonarray: ITEXTURE2DMS */ +#line 3031 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); + } +#line 9815 "MachineIndependent/glslang_tab.cpp" + break; + + case 443: /* type_specifier_nonarray: UTEXTURE2DMS */ +#line 3036 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); + } +#line 9825 "MachineIndependent/glslang_tab.cpp" + break; + + case 444: /* type_specifier_nonarray: TEXTURE2DMSARRAY */ +#line 3041 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); + } +#line 9835 "MachineIndependent/glslang_tab.cpp" + break; + + case 445: /* type_specifier_nonarray: F16TEXTURE2DMSARRAY */ +#line 3046 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); + } +#line 9846 "MachineIndependent/glslang_tab.cpp" + break; + + case 446: /* type_specifier_nonarray: ITEXTURE2DMSARRAY */ +#line 3052 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); + } +#line 9856 "MachineIndependent/glslang_tab.cpp" + break; + + case 447: /* type_specifier_nonarray: UTEXTURE2DMSARRAY */ +#line 3057 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); + } +#line 9866 "MachineIndependent/glslang_tab.cpp" + break; + + case 448: /* type_specifier_nonarray: IMAGE1D */ +#line 3062 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); + } +#line 9876 "MachineIndependent/glslang_tab.cpp" + break; + + case 449: /* type_specifier_nonarray: F16IMAGE1D */ +#line 3067 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); + } +#line 9887 "MachineIndependent/glslang_tab.cpp" + break; + + case 450: /* type_specifier_nonarray: IIMAGE1D */ +#line 3073 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); + } +#line 9897 "MachineIndependent/glslang_tab.cpp" + break; + + case 451: /* type_specifier_nonarray: UIMAGE1D */ +#line 3078 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); + } +#line 9907 "MachineIndependent/glslang_tab.cpp" + break; + + case 452: /* type_specifier_nonarray: IMAGE2D */ +#line 3083 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); + } +#line 9917 "MachineIndependent/glslang_tab.cpp" + break; + + case 453: /* type_specifier_nonarray: F16IMAGE2D */ +#line 3088 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); + } +#line 9928 "MachineIndependent/glslang_tab.cpp" + break; + + case 454: /* type_specifier_nonarray: IIMAGE2D */ +#line 3094 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); + } +#line 9938 "MachineIndependent/glslang_tab.cpp" + break; + + case 455: /* type_specifier_nonarray: UIMAGE2D */ +#line 3099 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); + } +#line 9948 "MachineIndependent/glslang_tab.cpp" + break; + + case 456: /* type_specifier_nonarray: IMAGE3D */ +#line 3104 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); + } +#line 9958 "MachineIndependent/glslang_tab.cpp" + break; + + case 457: /* type_specifier_nonarray: F16IMAGE3D */ +#line 3109 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); + } +#line 9969 "MachineIndependent/glslang_tab.cpp" + break; + + case 458: /* type_specifier_nonarray: IIMAGE3D */ +#line 3115 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); + } +#line 9979 "MachineIndependent/glslang_tab.cpp" + break; + + case 459: /* type_specifier_nonarray: UIMAGE3D */ +#line 3120 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); + } +#line 9989 "MachineIndependent/glslang_tab.cpp" + break; + + case 460: /* type_specifier_nonarray: IMAGE2DRECT */ +#line 3125 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); + } +#line 9999 "MachineIndependent/glslang_tab.cpp" + break; + + case 461: /* type_specifier_nonarray: F16IMAGE2DRECT */ +#line 3130 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); + } +#line 10010 "MachineIndependent/glslang_tab.cpp" + break; + + case 462: /* type_specifier_nonarray: IIMAGE2DRECT */ +#line 3136 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); + } +#line 10020 "MachineIndependent/glslang_tab.cpp" + break; + + case 463: /* type_specifier_nonarray: UIMAGE2DRECT */ +#line 3141 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); + } +#line 10030 "MachineIndependent/glslang_tab.cpp" + break; + + case 464: /* type_specifier_nonarray: IMAGECUBE */ +#line 3146 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); + } +#line 10040 "MachineIndependent/glslang_tab.cpp" + break; + + case 465: /* type_specifier_nonarray: F16IMAGECUBE */ +#line 3151 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); + } +#line 10051 "MachineIndependent/glslang_tab.cpp" + break; + + case 466: /* type_specifier_nonarray: IIMAGECUBE */ +#line 3157 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); + } +#line 10061 "MachineIndependent/glslang_tab.cpp" + break; + + case 467: /* type_specifier_nonarray: UIMAGECUBE */ +#line 3162 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); + } +#line 10071 "MachineIndependent/glslang_tab.cpp" + break; + + case 468: /* type_specifier_nonarray: IMAGEBUFFER */ +#line 3167 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); + } +#line 10081 "MachineIndependent/glslang_tab.cpp" + break; + + case 469: /* type_specifier_nonarray: F16IMAGEBUFFER */ +#line 3172 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); + } +#line 10092 "MachineIndependent/glslang_tab.cpp" + break; + + case 470: /* type_specifier_nonarray: IIMAGEBUFFER */ +#line 3178 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); + } +#line 10102 "MachineIndependent/glslang_tab.cpp" + break; + + case 471: /* type_specifier_nonarray: UIMAGEBUFFER */ +#line 3183 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); + } +#line 10112 "MachineIndependent/glslang_tab.cpp" + break; + + case 472: /* type_specifier_nonarray: IMAGE1DARRAY */ +#line 3188 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); + } +#line 10122 "MachineIndependent/glslang_tab.cpp" + break; + + case 473: /* type_specifier_nonarray: F16IMAGE1DARRAY */ +#line 3193 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); + } +#line 10133 "MachineIndependent/glslang_tab.cpp" + break; + + case 474: /* type_specifier_nonarray: IIMAGE1DARRAY */ +#line 3199 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); + } +#line 10143 "MachineIndependent/glslang_tab.cpp" + break; + + case 475: /* type_specifier_nonarray: UIMAGE1DARRAY */ +#line 3204 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); + } +#line 10153 "MachineIndependent/glslang_tab.cpp" + break; + + case 476: /* type_specifier_nonarray: IMAGE2DARRAY */ +#line 3209 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); + } +#line 10163 "MachineIndependent/glslang_tab.cpp" + break; + + case 477: /* type_specifier_nonarray: F16IMAGE2DARRAY */ +#line 3214 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); + } +#line 10174 "MachineIndependent/glslang_tab.cpp" + break; + + case 478: /* type_specifier_nonarray: IIMAGE2DARRAY */ +#line 3220 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); + } +#line 10184 "MachineIndependent/glslang_tab.cpp" + break; + + case 479: /* type_specifier_nonarray: UIMAGE2DARRAY */ +#line 3225 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); + } +#line 10194 "MachineIndependent/glslang_tab.cpp" + break; + + case 480: /* type_specifier_nonarray: IMAGECUBEARRAY */ +#line 3230 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); + } +#line 10204 "MachineIndependent/glslang_tab.cpp" + break; + + case 481: /* type_specifier_nonarray: F16IMAGECUBEARRAY */ +#line 3235 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); + } +#line 10215 "MachineIndependent/glslang_tab.cpp" + break; + + case 482: /* type_specifier_nonarray: IIMAGECUBEARRAY */ +#line 3241 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); + } +#line 10225 "MachineIndependent/glslang_tab.cpp" + break; + + case 483: /* type_specifier_nonarray: UIMAGECUBEARRAY */ +#line 3246 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); + } +#line 10235 "MachineIndependent/glslang_tab.cpp" + break; + + case 484: /* type_specifier_nonarray: IMAGE2DMS */ +#line 3251 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); + } +#line 10245 "MachineIndependent/glslang_tab.cpp" + break; + + case 485: /* type_specifier_nonarray: F16IMAGE2DMS */ +#line 3256 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); + } +#line 10256 "MachineIndependent/glslang_tab.cpp" + break; + + case 486: /* type_specifier_nonarray: IIMAGE2DMS */ +#line 3262 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); + } +#line 10266 "MachineIndependent/glslang_tab.cpp" + break; + + case 487: /* type_specifier_nonarray: UIMAGE2DMS */ +#line 3267 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); + } +#line 10276 "MachineIndependent/glslang_tab.cpp" + break; + + case 488: /* type_specifier_nonarray: IMAGE2DMSARRAY */ +#line 3272 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); + } +#line 10286 "MachineIndependent/glslang_tab.cpp" + break; + + case 489: /* type_specifier_nonarray: F16IMAGE2DMSARRAY */ +#line 3277 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); + } +#line 10297 "MachineIndependent/glslang_tab.cpp" + break; + + case 490: /* type_specifier_nonarray: IIMAGE2DMSARRAY */ +#line 3283 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); + } +#line 10307 "MachineIndependent/glslang_tab.cpp" + break; + + case 491: /* type_specifier_nonarray: UIMAGE2DMSARRAY */ +#line 3288 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); + } +#line 10317 "MachineIndependent/glslang_tab.cpp" + break; + + case 492: /* type_specifier_nonarray: I64IMAGE1D */ +#line 3293 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D); + } +#line 10327 "MachineIndependent/glslang_tab.cpp" + break; + + case 493: /* type_specifier_nonarray: U64IMAGE1D */ +#line 3298 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D); + } +#line 10337 "MachineIndependent/glslang_tab.cpp" + break; + + case 494: /* type_specifier_nonarray: I64IMAGE2D */ +#line 3303 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D); + } +#line 10347 "MachineIndependent/glslang_tab.cpp" + break; + + case 495: /* type_specifier_nonarray: U64IMAGE2D */ +#line 3308 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D); + } +#line 10357 "MachineIndependent/glslang_tab.cpp" + break; + + case 496: /* type_specifier_nonarray: I64IMAGE3D */ +#line 3313 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd3D); + } +#line 10367 "MachineIndependent/glslang_tab.cpp" + break; + + case 497: /* type_specifier_nonarray: U64IMAGE3D */ +#line 3318 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd3D); + } +#line 10377 "MachineIndependent/glslang_tab.cpp" + break; + + case 498: /* type_specifier_nonarray: I64IMAGE2DRECT */ +#line 3323 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, EsdRect); + } +#line 10387 "MachineIndependent/glslang_tab.cpp" + break; + + case 499: /* type_specifier_nonarray: U64IMAGE2DRECT */ +#line 3328 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, EsdRect); + } +#line 10397 "MachineIndependent/glslang_tab.cpp" + break; + + case 500: /* type_specifier_nonarray: I64IMAGECUBE */ +#line 3333 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube); + } +#line 10407 "MachineIndependent/glslang_tab.cpp" + break; + + case 501: /* type_specifier_nonarray: U64IMAGECUBE */ +#line 3338 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube); + } +#line 10417 "MachineIndependent/glslang_tab.cpp" + break; + + case 502: /* type_specifier_nonarray: I64IMAGEBUFFER */ +#line 3343 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, EsdBuffer); + } +#line 10427 "MachineIndependent/glslang_tab.cpp" + break; + + case 503: /* type_specifier_nonarray: U64IMAGEBUFFER */ +#line 3348 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, EsdBuffer); + } +#line 10437 "MachineIndependent/glslang_tab.cpp" + break; + + case 504: /* type_specifier_nonarray: I64IMAGE1DARRAY */ +#line 3353 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D, true); + } +#line 10447 "MachineIndependent/glslang_tab.cpp" + break; + + case 505: /* type_specifier_nonarray: U64IMAGE1DARRAY */ +#line 3358 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D, true); + } +#line 10457 "MachineIndependent/glslang_tab.cpp" + break; + + case 506: /* type_specifier_nonarray: I64IMAGE2DARRAY */ +#line 3363 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true); + } +#line 10467 "MachineIndependent/glslang_tab.cpp" + break; + + case 507: /* type_specifier_nonarray: U64IMAGE2DARRAY */ +#line 3368 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true); + } +#line 10477 "MachineIndependent/glslang_tab.cpp" + break; + + case 508: /* type_specifier_nonarray: I64IMAGECUBEARRAY */ +#line 3373 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube, true); + } +#line 10487 "MachineIndependent/glslang_tab.cpp" + break; + + case 509: /* type_specifier_nonarray: U64IMAGECUBEARRAY */ +#line 3378 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube, true); + } +#line 10497 "MachineIndependent/glslang_tab.cpp" + break; + + case 510: /* type_specifier_nonarray: I64IMAGE2DMS */ +#line 3383 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, false, false, true); + } +#line 10507 "MachineIndependent/glslang_tab.cpp" + break; + + case 511: /* type_specifier_nonarray: U64IMAGE2DMS */ +#line 3388 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, false, false, true); + } +#line 10517 "MachineIndependent/glslang_tab.cpp" + break; + + case 512: /* type_specifier_nonarray: I64IMAGE2DMSARRAY */ +#line 3393 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true, false, true); + } +#line 10527 "MachineIndependent/glslang_tab.cpp" + break; + + case 513: /* type_specifier_nonarray: U64IMAGE2DMSARRAY */ +#line 3398 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true, false, true); + } +#line 10537 "MachineIndependent/glslang_tab.cpp" + break; + + case 514: /* type_specifier_nonarray: SAMPLEREXTERNALOES */ +#line 3403 "MachineIndependent/glslang.y" + { // GL_OES_EGL_image_external + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D); + (yyval.interm.type).sampler.external = true; + } +#line 10548 "MachineIndependent/glslang_tab.cpp" + break; + + case 515: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ +#line 3409 "MachineIndependent/glslang.y" + { // GL_EXT_YUV_target + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.set(EbtFloat, Esd2D); + (yyval.interm.type).sampler.yuv = true; + } +#line 10559 "MachineIndependent/glslang_tab.cpp" + break; + + case 516: /* type_specifier_nonarray: SUBPASSINPUT */ +#line 3415 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtFloat); + } +#line 10570 "MachineIndependent/glslang_tab.cpp" + break; + + case 517: /* type_specifier_nonarray: SUBPASSINPUTMS */ +#line 3421 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtFloat, true); + } +#line 10581 "MachineIndependent/glslang_tab.cpp" + break; + + case 518: /* type_specifier_nonarray: F16SUBPASSINPUT */ +#line 3427 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtFloat16); + } +#line 10593 "MachineIndependent/glslang_tab.cpp" + break; + + case 519: /* type_specifier_nonarray: F16SUBPASSINPUTMS */ +#line 3434 "MachineIndependent/glslang.y" + { + parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); + } +#line 10605 "MachineIndependent/glslang_tab.cpp" + break; + + case 520: /* type_specifier_nonarray: ISUBPASSINPUT */ +#line 3441 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtInt); + } +#line 10616 "MachineIndependent/glslang_tab.cpp" + break; + + case 521: /* type_specifier_nonarray: ISUBPASSINPUTMS */ +#line 3447 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtInt, true); + } +#line 10627 "MachineIndependent/glslang_tab.cpp" + break; + + case 522: /* type_specifier_nonarray: USUBPASSINPUT */ +#line 3453 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtUint); + } +#line 10638 "MachineIndependent/glslang_tab.cpp" + break; + + case 523: /* type_specifier_nonarray: USUBPASSINPUTMS */ +#line 3459 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtSampler; + (yyval.interm.type).sampler.setSubpass(EbtUint, true); + } +#line 10649 "MachineIndependent/glslang_tab.cpp" + break; + + case 524: /* type_specifier_nonarray: FCOOPMATNV */ +#line 3465 "MachineIndependent/glslang.y" + { + parseContext.fcoopmatCheck((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtFloat; + (yyval.interm.type).coopmat = true; + } +#line 10660 "MachineIndependent/glslang_tab.cpp" + break; + + case 525: /* type_specifier_nonarray: ICOOPMATNV */ +#line 3471 "MachineIndependent/glslang.y" + { + parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtInt; + (yyval.interm.type).coopmat = true; + } +#line 10671 "MachineIndependent/glslang_tab.cpp" + break; + + case 526: /* type_specifier_nonarray: UCOOPMATNV */ +#line 3477 "MachineIndependent/glslang.y" + { + parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtUint; + (yyval.interm.type).coopmat = true; + } +#line 10682 "MachineIndependent/glslang_tab.cpp" + break; + + case 527: /* type_specifier_nonarray: spirv_type_specifier */ +#line 3483 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 10691 "MachineIndependent/glslang_tab.cpp" + break; + + case 528: /* type_specifier_nonarray: struct_specifier */ +#line 3488 "MachineIndependent/glslang.y" + { + (yyval.interm.type) = (yyvsp[0].interm.type); + (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); + } +#line 10701 "MachineIndependent/glslang_tab.cpp" + break; + + case 529: /* type_specifier_nonarray: TYPE_NAME */ +#line 3493 "MachineIndependent/glslang.y" + { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) { + const TType& structure = variable->getType(); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtStruct; + (yyval.interm.type).userDef = &structure; + } else + parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); + } +#line 10719 "MachineIndependent/glslang_tab.cpp" + break; + + case 530: /* precision_qualifier: HIGH_PRECISION */ +#line 3509 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); + } +#line 10729 "MachineIndependent/glslang_tab.cpp" + break; + + case 531: /* precision_qualifier: MEDIUM_PRECISION */ +#line 3514 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); + } +#line 10739 "MachineIndependent/glslang_tab.cpp" + break; + + case 532: /* precision_qualifier: LOW_PRECISION */ +#line 3519 "MachineIndependent/glslang.y" + { + parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); + } +#line 10749 "MachineIndependent/glslang_tab.cpp" + break; + + case 533: /* $@3: %empty */ +#line 3527 "MachineIndependent/glslang.y" + { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } +#line 10755 "MachineIndependent/glslang_tab.cpp" + break; + + case 534: /* struct_specifier: STRUCT IDENTIFIER LEFT_BRACE $@3 struct_declaration_list RIGHT_BRACE */ +#line 3527 "MachineIndependent/glslang.y" + { + TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); + parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); + TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true); + if (! parseContext.symbolTable.insert(*userTypeDef)) + parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct"); + (yyval.interm.type).init((yyvsp[-5].lex).loc); + (yyval.interm.type).basicType = EbtStruct; + (yyval.interm.type).userDef = structure; + --parseContext.structNestingLevel; + } +#line 10771 "MachineIndependent/glslang_tab.cpp" + break; + + case 535: /* $@4: %empty */ +#line 3538 "MachineIndependent/glslang.y" + { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } +#line 10777 "MachineIndependent/glslang_tab.cpp" + break; + + case 536: /* struct_specifier: STRUCT LEFT_BRACE $@4 struct_declaration_list RIGHT_BRACE */ +#line 3538 "MachineIndependent/glslang.y" + { + TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); + (yyval.interm.type).init((yyvsp[-4].lex).loc); + (yyval.interm.type).basicType = EbtStruct; + (yyval.interm.type).userDef = structure; + --parseContext.structNestingLevel; + } +#line 10789 "MachineIndependent/glslang_tab.cpp" + break; + + case 537: /* struct_declaration_list: struct_declaration */ +#line 3548 "MachineIndependent/glslang.y" + { + (yyval.interm.typeList) = (yyvsp[0].interm.typeList); + } +#line 10797 "MachineIndependent/glslang_tab.cpp" + break; + + case 538: /* struct_declaration_list: struct_declaration_list struct_declaration */ +#line 3551 "MachineIndependent/glslang.y" + { + (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); + for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { + for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { + if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName()) + parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str()); + } + (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); + } + } +#line 10812 "MachineIndependent/glslang_tab.cpp" + break; + + case 539: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ +#line 3564 "MachineIndependent/glslang.y" + { + if ((yyvsp[-2].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + if (parseContext.isEsProfile()) + parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); + } + + (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); + + parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); + parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); + + for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { + TType type((yyvsp[-2].interm.type)); + type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); + type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); + type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); + parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); + (*(yyval.interm.typeList))[i].type->shallowCopy(type); + } + } +#line 10839 "MachineIndependent/glslang_tab.cpp" + break; + + case 540: /* struct_declaration: type_qualifier type_specifier struct_declarator_list SEMICOLON */ +#line 3586 "MachineIndependent/glslang.y" + { + if ((yyvsp[-2].interm.type).arraySizes) { + parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); + parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); + if (parseContext.isEsProfile()) + parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); + } + + (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); + + parseContext.memberQualifierCheck((yyvsp[-3].interm.type)); + parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); + parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true); + parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); + + for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { + TType type((yyvsp[-2].interm.type)); + type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); + type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); + type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); + parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); + (*(yyval.interm.typeList))[i].type->shallowCopy(type); + } + } +#line 10868 "MachineIndependent/glslang_tab.cpp" + break; + + case 541: /* struct_declarator_list: struct_declarator */ +#line 3613 "MachineIndependent/glslang.y" + { + (yyval.interm.typeList) = new TTypeList; + (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); + } +#line 10877 "MachineIndependent/glslang_tab.cpp" + break; + + case 542: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ +#line 3617 "MachineIndependent/glslang.y" + { + (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); + } +#line 10885 "MachineIndependent/glslang_tab.cpp" + break; + + case 543: /* struct_declarator: IDENTIFIER */ +#line 3623 "MachineIndependent/glslang.y" + { + (yyval.interm.typeLine).type = new TType(EbtVoid); + (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; + (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); + } +#line 10895 "MachineIndependent/glslang_tab.cpp" + break; + + case 544: /* struct_declarator: IDENTIFIER array_specifier */ +#line 3628 "MachineIndependent/glslang.y" + { + parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); + + (yyval.interm.typeLine).type = new TType(EbtVoid); + (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc; + (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); + (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); + } +#line 10908 "MachineIndependent/glslang_tab.cpp" + break; + + case 545: /* initializer: assignment_expression */ +#line 3639 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 10916 "MachineIndependent/glslang_tab.cpp" + break; + + case 546: /* initializer: LEFT_BRACE initializer_list RIGHT_BRACE */ +#line 3643 "MachineIndependent/glslang.y" + { + const char* initFeature = "{ } style initializers"; + parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); + parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); + (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); + } +#line 10927 "MachineIndependent/glslang_tab.cpp" + break; + + case 547: /* initializer: LEFT_BRACE initializer_list COMMA RIGHT_BRACE */ +#line 3649 "MachineIndependent/glslang.y" + { + const char* initFeature = "{ } style initializers"; + parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); + parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); + (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); + } +#line 10938 "MachineIndependent/glslang_tab.cpp" + break; + + case 548: /* initializer: LEFT_BRACE RIGHT_BRACE */ +#line 3655 "MachineIndependent/glslang.y" + { + const char* initFeature = "empty { } initializer"; + parseContext.profileRequires((yyvsp[-1].lex).loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + parseContext.profileRequires((yyvsp[-1].lex).loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); + (yyval.interm.intermTypedNode) = parseContext.intermediate.makeAggregate((yyvsp[-1].lex).loc); + } +#line 10949 "MachineIndependent/glslang_tab.cpp" + break; + + case 549: /* initializer_list: initializer */ +#line 3666 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); + } +#line 10957 "MachineIndependent/glslang_tab.cpp" + break; + + case 550: /* initializer_list: initializer_list COMMA initializer */ +#line 3669 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); + } +#line 10965 "MachineIndependent/glslang_tab.cpp" + break; + + case 551: /* declaration_statement: declaration */ +#line 3676 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 10971 "MachineIndependent/glslang_tab.cpp" + break; + + case 552: /* statement: compound_statement */ +#line 3680 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 10977 "MachineIndependent/glslang_tab.cpp" + break; + + case 553: /* statement: simple_statement */ +#line 3681 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 10983 "MachineIndependent/glslang_tab.cpp" + break; + + case 554: /* simple_statement: declaration_statement */ +#line 3687 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 10989 "MachineIndependent/glslang_tab.cpp" + break; + + case 555: /* simple_statement: expression_statement */ +#line 3688 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 10995 "MachineIndependent/glslang_tab.cpp" + break; + + case 556: /* simple_statement: selection_statement */ +#line 3689 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11001 "MachineIndependent/glslang_tab.cpp" + break; + + case 557: /* simple_statement: switch_statement */ +#line 3690 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11007 "MachineIndependent/glslang_tab.cpp" + break; + + case 558: /* simple_statement: case_label */ +#line 3691 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11013 "MachineIndependent/glslang_tab.cpp" + break; + + case 559: /* simple_statement: iteration_statement */ +#line 3692 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11019 "MachineIndependent/glslang_tab.cpp" + break; + + case 560: /* simple_statement: jump_statement */ +#line 3693 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11025 "MachineIndependent/glslang_tab.cpp" + break; + + case 561: /* simple_statement: demote_statement */ +#line 3695 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11031 "MachineIndependent/glslang_tab.cpp" + break; + + case 562: /* demote_statement: DEMOTE SEMICOLON */ +#line 3701 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote"); + parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc); + } +#line 11041 "MachineIndependent/glslang_tab.cpp" + break; + + case 563: /* compound_statement: LEFT_BRACE RIGHT_BRACE */ +#line 3710 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = 0; } +#line 11047 "MachineIndependent/glslang_tab.cpp" + break; + + case 564: /* $@5: %empty */ +#line 3711 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.push(); + ++parseContext.statementNestingLevel; + } +#line 11056 "MachineIndependent/glslang_tab.cpp" + break; + + case 565: /* $@6: %empty */ +#line 3715 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + } +#line 11065 "MachineIndependent/glslang_tab.cpp" + break; + + case 566: /* compound_statement: LEFT_BRACE $@5 statement_list $@6 RIGHT_BRACE */ +#line 3719 "MachineIndependent/glslang.y" + { + if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) + (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); + (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); + } +#line 11075 "MachineIndependent/glslang_tab.cpp" + break; + + case 567: /* statement_no_new_scope: compound_statement_no_new_scope */ +#line 3727 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11081 "MachineIndependent/glslang_tab.cpp" + break; + + case 568: /* statement_no_new_scope: simple_statement */ +#line 3728 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } +#line 11087 "MachineIndependent/glslang_tab.cpp" + break; + + case 569: /* $@7: %empty */ +#line 3732 "MachineIndependent/glslang.y" + { + ++parseContext.controlFlowNestingLevel; + } +#line 11095 "MachineIndependent/glslang_tab.cpp" + break; + + case 570: /* statement_scoped: $@7 compound_statement */ +#line 3735 "MachineIndependent/glslang.y" + { + --parseContext.controlFlowNestingLevel; + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11104 "MachineIndependent/glslang_tab.cpp" + break; + + case 571: /* $@8: %empty */ +#line 3739 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.push(); + ++parseContext.statementNestingLevel; + ++parseContext.controlFlowNestingLevel; + } +#line 11114 "MachineIndependent/glslang_tab.cpp" + break; + + case 572: /* statement_scoped: $@8 simple_statement */ +#line 3744 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + --parseContext.controlFlowNestingLevel; + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11125 "MachineIndependent/glslang_tab.cpp" + break; + + case 573: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ +#line 3753 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = 0; + } +#line 11133 "MachineIndependent/glslang_tab.cpp" + break; + + case 574: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ +#line 3756 "MachineIndependent/glslang.y" + { + if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) + (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); + (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); + } +#line 11143 "MachineIndependent/glslang_tab.cpp" + break; + + case 575: /* statement_list: statement */ +#line 3764 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); + if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || + (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { + parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case + } + } +#line 11156 "MachineIndependent/glslang_tab.cpp" + break; + + case 576: /* statement_list: statement_list statement */ +#line 3772 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || + (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { + parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case + } else + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); + } +#line 11169 "MachineIndependent/glslang_tab.cpp" + break; + + case 577: /* expression_statement: SEMICOLON */ +#line 3783 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = 0; } +#line 11175 "MachineIndependent/glslang_tab.cpp" + break; + + case 578: /* expression_statement: expression SEMICOLON */ +#line 3784 "MachineIndependent/glslang.y" + { (yyval.interm.intermNode) = static_cast((yyvsp[-1].interm.intermTypedNode)); } +#line 11181 "MachineIndependent/glslang_tab.cpp" + break; + + case 579: /* selection_statement: selection_statement_nonattributed */ +#line 3788 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11189 "MachineIndependent/glslang_tab.cpp" + break; + + case 580: /* selection_statement: attribute selection_statement_nonattributed */ +#line 3792 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); + parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11199 "MachineIndependent/glslang_tab.cpp" + break; + + case 581: /* selection_statement_nonattributed: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement */ +#line 3800 "MachineIndependent/glslang.y" + { + parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); + (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); + } +#line 11208 "MachineIndependent/glslang_tab.cpp" + break; + + case 582: /* selection_rest_statement: statement_scoped ELSE statement_scoped */ +#line 3807 "MachineIndependent/glslang.y" + { + (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); + (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); + } +#line 11217 "MachineIndependent/glslang_tab.cpp" + break; + + case 583: /* selection_rest_statement: statement_scoped */ +#line 3811 "MachineIndependent/glslang.y" + { + (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); + (yyval.interm.nodePair).node2 = 0; + } +#line 11226 "MachineIndependent/glslang_tab.cpp" + break; + + case 584: /* condition: expression */ +#line 3819 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); + } +#line 11235 "MachineIndependent/glslang_tab.cpp" + break; + + case 585: /* condition: fully_specified_type IDENTIFIER EQUAL initializer */ +#line 3823 "MachineIndependent/glslang.y" + { + parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); + + TType type((yyvsp[-3].interm.type)); + TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); + if (initNode) + (yyval.interm.intermTypedNode) = initNode->getAsTyped(); + else + (yyval.interm.intermTypedNode) = 0; + } +#line 11250 "MachineIndependent/glslang_tab.cpp" + break; + + case 586: /* switch_statement: switch_statement_nonattributed */ +#line 3836 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11258 "MachineIndependent/glslang_tab.cpp" + break; + + case 587: /* switch_statement: attribute switch_statement_nonattributed */ +#line 3840 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); + parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11268 "MachineIndependent/glslang_tab.cpp" + break; + + case 588: /* $@9: %empty */ +#line 3848 "MachineIndependent/glslang.y" + { + // start new switch sequence on the switch stack + ++parseContext.controlFlowNestingLevel; + ++parseContext.statementNestingLevel; + parseContext.switchSequenceStack.push_back(new TIntermSequence); + parseContext.switchLevel.push_back(parseContext.statementNestingLevel); + parseContext.symbolTable.push(); + } +#line 11281 "MachineIndependent/glslang_tab.cpp" + break; + + case 589: /* switch_statement_nonattributed: SWITCH LEFT_PAREN expression RIGHT_PAREN $@9 LEFT_BRACE switch_statement_list RIGHT_BRACE */ +#line 3856 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); + delete parseContext.switchSequenceStack.back(); + parseContext.switchSequenceStack.pop_back(); + parseContext.switchLevel.pop_back(); + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + --parseContext.controlFlowNestingLevel; + } +#line 11295 "MachineIndependent/glslang_tab.cpp" + break; + + case 590: /* switch_statement_list: %empty */ +#line 3868 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = 0; + } +#line 11303 "MachineIndependent/glslang_tab.cpp" + break; + + case 591: /* switch_statement_list: statement_list */ +#line 3871 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11311 "MachineIndependent/glslang_tab.cpp" + break; + + case 592: /* case_label: CASE expression COLON */ +#line 3877 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = 0; + if (parseContext.switchLevel.size() == 0) + parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", ""); + else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) + parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", ""); + else { + parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case"); + parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); + } + } +#line 11328 "MachineIndependent/glslang_tab.cpp" + break; + + case 593: /* case_label: DEFAULT COLON */ +#line 3889 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = 0; + if (parseContext.switchLevel.size() == 0) + parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", ""); + else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) + parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", ""); + else + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); + } +#line 11342 "MachineIndependent/glslang_tab.cpp" + break; + + case 594: /* iteration_statement: iteration_statement_nonattributed */ +#line 3901 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11350 "MachineIndependent/glslang_tab.cpp" + break; + + case 595: /* iteration_statement: attribute iteration_statement_nonattributed */ +#line 3905 "MachineIndependent/glslang.y" + { + parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); + parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11360 "MachineIndependent/glslang_tab.cpp" + break; + + case 596: /* $@10: %empty */ +#line 3913 "MachineIndependent/glslang.y" + { + if (! parseContext.limits.whileLoops) + parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); + parseContext.symbolTable.push(); + ++parseContext.loopNestingLevel; + ++parseContext.statementNestingLevel; + ++parseContext.controlFlowNestingLevel; + } +#line 11373 "MachineIndependent/glslang_tab.cpp" + break; + + case 597: /* iteration_statement_nonattributed: WHILE LEFT_PAREN $@10 condition RIGHT_PAREN statement_no_new_scope */ +#line 3921 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); + --parseContext.loopNestingLevel; + --parseContext.statementNestingLevel; + --parseContext.controlFlowNestingLevel; + } +#line 11385 "MachineIndependent/glslang_tab.cpp" + break; + + case 598: /* $@11: %empty */ +#line 3928 "MachineIndependent/glslang.y" + { + ++parseContext.loopNestingLevel; + ++parseContext.statementNestingLevel; + ++parseContext.controlFlowNestingLevel; + } +#line 11395 "MachineIndependent/glslang_tab.cpp" + break; + + case 599: /* iteration_statement_nonattributed: DO $@11 statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON */ +#line 3933 "MachineIndependent/glslang.y" + { + if (! parseContext.limits.whileLoops) + parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); + + parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode)); + + (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc); + --parseContext.loopNestingLevel; + --parseContext.statementNestingLevel; + --parseContext.controlFlowNestingLevel; + } +#line 11411 "MachineIndependent/glslang_tab.cpp" + break; + + case 600: /* $@12: %empty */ +#line 3944 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.push(); + ++parseContext.loopNestingLevel; + ++parseContext.statementNestingLevel; + ++parseContext.controlFlowNestingLevel; + } +#line 11422 "MachineIndependent/glslang_tab.cpp" + break; + + case 601: /* iteration_statement_nonattributed: FOR LEFT_PAREN $@12 for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope */ +#line 3950 "MachineIndependent/glslang.y" + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); + TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast((yyvsp[-2].interm.nodePair).node1), reinterpret_cast((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc); + if (! parseContext.limits.nonInductiveForLoops) + parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop); + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc); + (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); + --parseContext.loopNestingLevel; + --parseContext.statementNestingLevel; + --parseContext.controlFlowNestingLevel; + } +#line 11439 "MachineIndependent/glslang_tab.cpp" + break; + + case 602: /* for_init_statement: expression_statement */ +#line 3965 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11447 "MachineIndependent/glslang_tab.cpp" + break; + + case 603: /* for_init_statement: declaration_statement */ +#line 3968 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11455 "MachineIndependent/glslang_tab.cpp" + break; + + case 604: /* conditionopt: condition */ +#line 3974 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); + } +#line 11463 "MachineIndependent/glslang_tab.cpp" + break; + + case 605: /* conditionopt: %empty */ +#line 3977 "MachineIndependent/glslang.y" + { + (yyval.interm.intermTypedNode) = 0; + } +#line 11471 "MachineIndependent/glslang_tab.cpp" + break; + + case 606: /* for_rest_statement: conditionopt SEMICOLON */ +#line 3983 "MachineIndependent/glslang.y" + { + (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); + (yyval.interm.nodePair).node2 = 0; + } +#line 11480 "MachineIndependent/glslang_tab.cpp" + break; + + case 607: /* for_rest_statement: conditionopt SEMICOLON expression */ +#line 3987 "MachineIndependent/glslang.y" + { + (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); + (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); + } +#line 11489 "MachineIndependent/glslang_tab.cpp" + break; + + case 608: /* jump_statement: CONTINUE SEMICOLON */ +#line 3994 "MachineIndependent/glslang.y" + { + if (parseContext.loopNestingLevel <= 0) + parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); + } +#line 11499 "MachineIndependent/glslang_tab.cpp" + break; + + case 609: /* jump_statement: BREAK SEMICOLON */ +#line 3999 "MachineIndependent/glslang.y" + { + if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) + parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); + } +#line 11509 "MachineIndependent/glslang_tab.cpp" + break; + + case 610: /* jump_statement: RETURN SEMICOLON */ +#line 4004 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); + if (parseContext.currentFunctionType->getBasicType() != EbtVoid) + parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", ""); + if (parseContext.inMain) + parseContext.postEntryPointReturn = true; + } +#line 11521 "MachineIndependent/glslang_tab.cpp" + break; + + case 611: /* jump_statement: RETURN expression SEMICOLON */ +#line 4011 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); + } +#line 11529 "MachineIndependent/glslang_tab.cpp" + break; + + case 612: /* jump_statement: DISCARD SEMICOLON */ +#line 4014 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); + } +#line 11538 "MachineIndependent/glslang_tab.cpp" + break; + + case 613: /* jump_statement: TERMINATE_INVOCATION SEMICOLON */ +#line 4018 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "terminateInvocation"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateInvocation, (yyvsp[-1].lex).loc); + } +#line 11547 "MachineIndependent/glslang_tab.cpp" + break; + + case 614: /* jump_statement: TERMINATE_RAY SEMICOLON */ +#line 4023 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "terminateRayEXT"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateRayKHR, (yyvsp[-1].lex).loc); + } +#line 11556 "MachineIndependent/glslang_tab.cpp" + break; + + case 615: /* jump_statement: IGNORE_INTERSECTION SEMICOLON */ +#line 4027 "MachineIndependent/glslang.y" + { + parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "ignoreIntersectionEXT"); + (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, (yyvsp[-1].lex).loc); + } +#line 11565 "MachineIndependent/glslang_tab.cpp" + break; + + case 616: /* translation_unit: external_declaration */ +#line 4037 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); + } +#line 11574 "MachineIndependent/glslang_tab.cpp" + break; + + case 617: /* translation_unit: translation_unit external_declaration */ +#line 4041 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermNode) != nullptr) { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); + parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); + } + } +#line 11585 "MachineIndependent/glslang_tab.cpp" + break; + + case 618: /* external_declaration: function_definition */ +#line 4050 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11593 "MachineIndependent/glslang_tab.cpp" + break; + + case 619: /* external_declaration: declaration */ +#line 4053 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + } +#line 11601 "MachineIndependent/glslang_tab.cpp" + break; + + case 620: /* external_declaration: SEMICOLON */ +#line 4057 "MachineIndependent/glslang.y" + { + parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); + parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); + (yyval.interm.intermNode) = nullptr; + } +#line 11611 "MachineIndependent/glslang_tab.cpp" + break; + + case 621: /* $@13: %empty */ +#line 4066 "MachineIndependent/glslang.y" + { + (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); + (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.push(); + ++parseContext.statementNestingLevel; + } + } +#line 11628 "MachineIndependent/glslang_tab.cpp" + break; + + case 622: /* function_definition: function_prototype $@13 compound_statement_no_new_scope */ +#line 4078 "MachineIndependent/glslang.y" + { + // May be best done as post process phase on intermediate code + if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) + parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str()); + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode)); + parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc); + (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); + (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug); + (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); + + // Set currentFunctionType to empty pointer when goes outside of the function + parseContext.currentFunctionType = nullptr; + + // For ES 100 only, according to ES shading language 100 spec: A function + // body has a scope nested inside the function's definition. + if (parseContext.profile == EEsProfile && parseContext.version == 100) + { + parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); + --parseContext.statementNestingLevel; + } + } +#line 11659 "MachineIndependent/glslang_tab.cpp" + break; + + case 623: /* attribute: LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET */ +#line 4108 "MachineIndependent/glslang.y" + { + (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); + } +#line 11667 "MachineIndependent/glslang_tab.cpp" + break; + + case 624: /* attribute_list: single_attribute */ +#line 4113 "MachineIndependent/glslang.y" + { + (yyval.interm.attributes) = (yyvsp[0].interm.attributes); + } +#line 11675 "MachineIndependent/glslang_tab.cpp" + break; + + case 625: /* attribute_list: attribute_list COMMA single_attribute */ +#line 4116 "MachineIndependent/glslang.y" + { + (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); + } +#line 11683 "MachineIndependent/glslang_tab.cpp" + break; + + case 626: /* single_attribute: IDENTIFIER */ +#line 4121 "MachineIndependent/glslang.y" + { + (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); + } +#line 11691 "MachineIndependent/glslang_tab.cpp" + break; + + case 627: /* single_attribute: IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN */ +#line 4124 "MachineIndependent/glslang.y" + { + (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); + } +#line 11699 "MachineIndependent/glslang_tab.cpp" + break; + + case 628: /* spirv_requirements_list: spirv_requirements_parameter */ +#line 4131 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvReq) = (yyvsp[0].interm.spirvReq); + } +#line 11707 "MachineIndependent/glslang_tab.cpp" + break; + + case 629: /* spirv_requirements_list: spirv_requirements_list COMMA spirv_requirements_parameter */ +#line 4134 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvReq) = parseContext.mergeSpirvRequirements((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvReq), (yyvsp[0].interm.spirvReq)); + } +#line 11715 "MachineIndependent/glslang_tab.cpp" + break; + + case 630: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET */ +#line 4139 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, (yyvsp[-1].interm.intermNode)->getAsAggregate(), nullptr); + } +#line 11723 "MachineIndependent/glslang_tab.cpp" + break; + + case 631: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET */ +#line 4142 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, nullptr, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11731 "MachineIndependent/glslang_tab.cpp" + break; + + case 632: /* spirv_extension_list: STRING_LITERAL */ +#line 4147 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); + } +#line 11739 "MachineIndependent/glslang_tab.cpp" + break; + + case 633: /* spirv_extension_list: spirv_extension_list COMMA STRING_LITERAL */ +#line 4150 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); + } +#line 11747 "MachineIndependent/glslang_tab.cpp" + break; + + case 634: /* spirv_capability_list: INTCONSTANT */ +#line 4155 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); + } +#line 11755 "MachineIndependent/glslang_tab.cpp" + break; + + case 635: /* spirv_capability_list: spirv_capability_list COMMA INTCONSTANT */ +#line 4158 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); + } +#line 11763 "MachineIndependent/glslang_tab.cpp" + break; + + case 636: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ +#line 4163 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); + (yyval.interm.intermNode) = 0; + } +#line 11772 "MachineIndependent/glslang_tab.cpp" + break; + + case 637: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ +#line 4167 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); + parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); + (yyval.interm.intermNode) = 0; + } +#line 11782 "MachineIndependent/glslang_tab.cpp" + break; + + case 638: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ +#line 4172 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + (yyval.interm.intermNode) = 0; + } +#line 11791 "MachineIndependent/glslang_tab.cpp" + break; + + case 639: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ +#line 4176 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + (yyval.interm.intermNode) = 0; + } +#line 11801 "MachineIndependent/glslang_tab.cpp" + break; + + case 640: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ +#line 4181 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + (yyval.interm.intermNode) = 0; + } +#line 11810 "MachineIndependent/glslang_tab.cpp" + break; + + case 641: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ +#line 4185 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + (yyval.interm.intermNode) = 0; + } +#line 11820 "MachineIndependent/glslang_tab.cpp" + break; + + case 642: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter */ +#line 4192 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); + } +#line 11828 "MachineIndependent/glslang_tab.cpp" + break; + + case 643: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter */ +#line 4195 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); + } +#line 11836 "MachineIndependent/glslang_tab.cpp" + break; + + case 644: /* spirv_execution_mode_parameter: FLOATCONSTANT */ +#line 4200 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); + } +#line 11844 "MachineIndependent/glslang_tab.cpp" + break; + + case 645: /* spirv_execution_mode_parameter: INTCONSTANT */ +#line 4203 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); + } +#line 11852 "MachineIndependent/glslang_tab.cpp" + break; + + case 646: /* spirv_execution_mode_parameter: UINTCONSTANT */ +#line 4206 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); + } +#line 11860 "MachineIndependent/glslang_tab.cpp" + break; + + case 647: /* spirv_execution_mode_parameter: BOOLCONSTANT */ +#line 4209 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); + } +#line 11868 "MachineIndependent/glslang_tab.cpp" + break; + + case 648: /* spirv_execution_mode_parameter: STRING_LITERAL */ +#line 4212 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); + } +#line 11876 "MachineIndependent/glslang_tab.cpp" + break; + + case 649: /* spirv_execution_mode_id_parameter_list: constant_expression */ +#line 4217 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtString) + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermTypedNode)); + } +#line 11890 "MachineIndependent/glslang_tab.cpp" + break; + + case 650: /* spirv_execution_mode_id_parameter_list: spirv_execution_mode_id_parameter_list COMMA constant_expression */ +#line 4226 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtString) + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermTypedNode)); + } +#line 11904 "MachineIndependent/glslang_tab.cpp" + break; + + case 651: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN */ +#line 4237 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-3].lex).loc); + (yyval.interm.type).qualifier.storage = EvqSpirvStorageClass; + (yyval.interm.type).qualifier.spirvStorageClass = (yyvsp[-1].lex).i; + } +#line 11914 "MachineIndependent/glslang_tab.cpp" + break; + + case 652: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ +#line 4242 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); + (yyval.interm.type).qualifier.storage = EvqSpirvStorageClass; + (yyval.interm.type).qualifier.spirvStorageClass = (yyvsp[-1].lex).i; + } +#line 11925 "MachineIndependent/glslang_tab.cpp" + break; + + case 653: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ +#line 4250 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-3].lex).loc); + (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-1].lex).i); + } +#line 11934 "MachineIndependent/glslang_tab.cpp" + break; + + case 654: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ +#line 4254 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); + (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-1].lex).i); + } +#line 11944 "MachineIndependent/glslang_tab.cpp" + break; + + case 655: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ +#line 4259 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc); + (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11953 "MachineIndependent/glslang_tab.cpp" + break; + + case 656: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ +#line 4263 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-7].lex).loc); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11963 "MachineIndependent/glslang_tab.cpp" + break; + + case 657: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ +#line 4268 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc); + (yyval.interm.type).qualifier.setSpirvDecorateId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11972 "MachineIndependent/glslang_tab.cpp" + break; + + case 658: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ +#line 4272 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-7].lex).loc); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + (yyval.interm.type).qualifier.setSpirvDecorateId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11982 "MachineIndependent/glslang_tab.cpp" + break; + + case 659: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ +#line 4277 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc); + (yyval.interm.type).qualifier.setSpirvDecorateString((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 11991 "MachineIndependent/glslang_tab.cpp" + break; + + case 660: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ +#line 4281 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-7].lex).loc); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + (yyval.interm.type).qualifier.setSpirvDecorateString((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); + } +#line 12001 "MachineIndependent/glslang_tab.cpp" + break; + + case 661: /* spirv_decorate_parameter_list: spirv_decorate_parameter */ +#line 4288 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); + } +#line 12009 "MachineIndependent/glslang_tab.cpp" + break; + + case 662: /* spirv_decorate_parameter_list: spirv_decorate_parameter_list COMMA spirv_decorate_parameter */ +#line 4291 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); + } +#line 12017 "MachineIndependent/glslang_tab.cpp" + break; + + case 663: /* spirv_decorate_parameter: FLOATCONSTANT */ +#line 4296 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); + } +#line 12025 "MachineIndependent/glslang_tab.cpp" + break; + + case 664: /* spirv_decorate_parameter: INTCONSTANT */ +#line 4299 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); + } +#line 12033 "MachineIndependent/glslang_tab.cpp" + break; + + case 665: /* spirv_decorate_parameter: UINTCONSTANT */ +#line 4302 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); + } +#line 12041 "MachineIndependent/glslang_tab.cpp" + break; + + case 666: /* spirv_decorate_parameter: BOOLCONSTANT */ +#line 4305 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); + } +#line 12049 "MachineIndependent/glslang_tab.cpp" + break; + + case 667: /* spirv_decorate_id_parameter_list: constant_expression */ +#line 4310 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool) + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermTypedNode)); + } +#line 12062 "MachineIndependent/glslang_tab.cpp" + break; + + case 668: /* spirv_decorate_id_parameter_list: spirv_decorate_id_parameter_list COMMA constant_expression */ +#line 4318 "MachineIndependent/glslang.y" + { + if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && + (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool) + parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermTypedNode)); + } +#line 12075 "MachineIndependent/glslang_tab.cpp" + break; + + case 669: /* spirv_decorate_string_parameter_list: STRING_LITERAL */ +#line 4328 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate( + parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); + } +#line 12084 "MachineIndependent/glslang_tab.cpp" + break; + + case 670: /* spirv_decorate_string_parameter_list: spirv_decorate_string_parameter_list COMMA STRING_LITERAL */ +#line 4332 "MachineIndependent/glslang.y" + { + (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); + } +#line 12092 "MachineIndependent/glslang_tab.cpp" + break; + + case 671: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ +#line 4337 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).setSpirvType(*(yyvsp[-3].interm.spirvInst), (yyvsp[-1].interm.spirvTypeParams)); + } +#line 12101 "MachineIndependent/glslang_tab.cpp" + break; + + case 672: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ +#line 4341 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-7].lex).loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); + (yyval.interm.type).setSpirvType(*(yyvsp[-3].interm.spirvInst), (yyvsp[-1].interm.spirvTypeParams)); + } +#line 12111 "MachineIndependent/glslang_tab.cpp" + break; + + case 673: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ +#line 4346 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-3].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).setSpirvType(*(yyvsp[-1].interm.spirvInst)); + } +#line 12120 "MachineIndependent/glslang_tab.cpp" + break; + + case 674: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ +#line 4350 "MachineIndependent/glslang.y" + { + (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); + parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); + (yyval.interm.type).setSpirvType(*(yyvsp[-1].interm.spirvInst)); + } +#line 12130 "MachineIndependent/glslang_tab.cpp" + break; + + case 675: /* spirv_type_parameter_list: spirv_type_parameter */ +#line 4357 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvTypeParams) = (yyvsp[0].interm.spirvTypeParams); + } +#line 12138 "MachineIndependent/glslang_tab.cpp" + break; + + case 676: /* spirv_type_parameter_list: spirv_type_parameter_list COMMA spirv_type_parameter */ +#line 4360 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvTypeParams) = parseContext.mergeSpirvTypeParameters((yyvsp[-2].interm.spirvTypeParams), (yyvsp[0].interm.spirvTypeParams)); + } +#line 12146 "MachineIndependent/glslang_tab.cpp" + break; + + case 677: /* spirv_type_parameter: constant_expression */ +#line 4365 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)->getAsConstantUnion()); + } +#line 12154 "MachineIndependent/glslang_tab.cpp" + break; + + case 678: /* spirv_type_parameter: type_specifier */ +#line 4368 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.type)); + } +#line 12162 "MachineIndependent/glslang_tab.cpp" + break; + + case 679: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ +#line 4373 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); + } +#line 12170 "MachineIndependent/glslang_tab.cpp" + break; + + case 680: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ +#line 4376 "MachineIndependent/glslang.y" + { + parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); + (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); + } +#line 12179 "MachineIndependent/glslang_tab.cpp" + break; + + case 681: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_id */ +#line 4382 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvInst) = (yyvsp[0].interm.spirvInst); + } +#line 12187 "MachineIndependent/glslang_tab.cpp" + break; + + case 682: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id */ +#line 4385 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvInst) = parseContext.mergeSpirvInstruction((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvInst), (yyvsp[0].interm.spirvInst)); + } +#line 12195 "MachineIndependent/glslang_tab.cpp" + break; + + case 683: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL STRING_LITERAL */ +#line 4390 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, *(yyvsp[0].lex).string); + } +#line 12203 "MachineIndependent/glslang_tab.cpp" + break; + + case 684: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ +#line 4393 "MachineIndependent/glslang.y" + { + (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[0].lex).i); + } +#line 12211 "MachineIndependent/glslang_tab.cpp" + break; + + +#line 12215 "MachineIndependent/glslang_tab.cpp" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + { + yypcontext_t yyctx + = {yyssp, yytoken}; + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == -1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = YY_CAST (char *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); + if (yymsg) + { + yysyntax_error_status + = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); + yymsgp = yymsg; + } + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = YYENOMEM; + } + } + yyerror (pParseContext, yymsgp); + if (yysyntax_error_status == YYENOMEM) + goto yyexhaustedlab; + } + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, pParseContext); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp, pParseContext); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + + +#if 1 +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (pParseContext, YY_("memory exhausted")); + yyresult = 2; + goto yyreturn; +#endif + + +/*-------------------------------------------------------. +| yyreturn -- parsing is finished, clean up and return. | +`-------------------------------------------------------*/ +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, pParseContext); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, pParseContext); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + return yyresult; +} + +#line 4398 "MachineIndependent/glslang.y" + diff --git a/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 000000000..596a10e6d --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,568 @@ +/* A Bison parser, made by GNU Bison 3.7.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Inc. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + CONST = 258, /* CONST */ + BOOL = 259, /* BOOL */ + INT = 260, /* INT */ + UINT = 261, /* UINT */ + FLOAT = 262, /* FLOAT */ + BVEC2 = 263, /* BVEC2 */ + BVEC3 = 264, /* BVEC3 */ + BVEC4 = 265, /* BVEC4 */ + IVEC2 = 266, /* IVEC2 */ + IVEC3 = 267, /* IVEC3 */ + IVEC4 = 268, /* IVEC4 */ + UVEC2 = 269, /* UVEC2 */ + UVEC3 = 270, /* UVEC3 */ + UVEC4 = 271, /* UVEC4 */ + VEC2 = 272, /* VEC2 */ + VEC3 = 273, /* VEC3 */ + VEC4 = 274, /* VEC4 */ + MAT2 = 275, /* MAT2 */ + MAT3 = 276, /* MAT3 */ + MAT4 = 277, /* MAT4 */ + MAT2X2 = 278, /* MAT2X2 */ + MAT2X3 = 279, /* MAT2X3 */ + MAT2X4 = 280, /* MAT2X4 */ + MAT3X2 = 281, /* MAT3X2 */ + MAT3X3 = 282, /* MAT3X3 */ + MAT3X4 = 283, /* MAT3X4 */ + MAT4X2 = 284, /* MAT4X2 */ + MAT4X3 = 285, /* MAT4X3 */ + MAT4X4 = 286, /* MAT4X4 */ + SAMPLER2D = 287, /* SAMPLER2D */ + SAMPLER3D = 288, /* SAMPLER3D */ + SAMPLERCUBE = 289, /* SAMPLERCUBE */ + SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */ + SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */ + SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */ + SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */ + ISAMPLER2D = 294, /* ISAMPLER2D */ + ISAMPLER3D = 295, /* ISAMPLER3D */ + ISAMPLERCUBE = 296, /* ISAMPLERCUBE */ + ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */ + USAMPLER2D = 298, /* USAMPLER2D */ + USAMPLER3D = 299, /* USAMPLER3D */ + USAMPLERCUBE = 300, /* USAMPLERCUBE */ + USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */ + SAMPLER = 302, /* SAMPLER */ + SAMPLERSHADOW = 303, /* SAMPLERSHADOW */ + TEXTURE2D = 304, /* TEXTURE2D */ + TEXTURE3D = 305, /* TEXTURE3D */ + TEXTURECUBE = 306, /* TEXTURECUBE */ + TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */ + ITEXTURE2D = 308, /* ITEXTURE2D */ + ITEXTURE3D = 309, /* ITEXTURE3D */ + ITEXTURECUBE = 310, /* ITEXTURECUBE */ + ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */ + UTEXTURE2D = 312, /* UTEXTURE2D */ + UTEXTURE3D = 313, /* UTEXTURE3D */ + UTEXTURECUBE = 314, /* UTEXTURECUBE */ + UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */ + ATTRIBUTE = 316, /* ATTRIBUTE */ + VARYING = 317, /* VARYING */ + FLOAT16_T = 318, /* FLOAT16_T */ + FLOAT32_T = 319, /* FLOAT32_T */ + DOUBLE = 320, /* DOUBLE */ + FLOAT64_T = 321, /* FLOAT64_T */ + INT64_T = 322, /* INT64_T */ + UINT64_T = 323, /* UINT64_T */ + INT32_T = 324, /* INT32_T */ + UINT32_T = 325, /* UINT32_T */ + INT16_T = 326, /* INT16_T */ + UINT16_T = 327, /* UINT16_T */ + INT8_T = 328, /* INT8_T */ + UINT8_T = 329, /* UINT8_T */ + I64VEC2 = 330, /* I64VEC2 */ + I64VEC3 = 331, /* I64VEC3 */ + I64VEC4 = 332, /* I64VEC4 */ + U64VEC2 = 333, /* U64VEC2 */ + U64VEC3 = 334, /* U64VEC3 */ + U64VEC4 = 335, /* U64VEC4 */ + I32VEC2 = 336, /* I32VEC2 */ + I32VEC3 = 337, /* I32VEC3 */ + I32VEC4 = 338, /* I32VEC4 */ + U32VEC2 = 339, /* U32VEC2 */ + U32VEC3 = 340, /* U32VEC3 */ + U32VEC4 = 341, /* U32VEC4 */ + I16VEC2 = 342, /* I16VEC2 */ + I16VEC3 = 343, /* I16VEC3 */ + I16VEC4 = 344, /* I16VEC4 */ + U16VEC2 = 345, /* U16VEC2 */ + U16VEC3 = 346, /* U16VEC3 */ + U16VEC4 = 347, /* U16VEC4 */ + I8VEC2 = 348, /* I8VEC2 */ + I8VEC3 = 349, /* I8VEC3 */ + I8VEC4 = 350, /* I8VEC4 */ + U8VEC2 = 351, /* U8VEC2 */ + U8VEC3 = 352, /* U8VEC3 */ + U8VEC4 = 353, /* U8VEC4 */ + DVEC2 = 354, /* DVEC2 */ + DVEC3 = 355, /* DVEC3 */ + DVEC4 = 356, /* DVEC4 */ + DMAT2 = 357, /* DMAT2 */ + DMAT3 = 358, /* DMAT3 */ + DMAT4 = 359, /* DMAT4 */ + F16VEC2 = 360, /* F16VEC2 */ + F16VEC3 = 361, /* F16VEC3 */ + F16VEC4 = 362, /* F16VEC4 */ + F16MAT2 = 363, /* F16MAT2 */ + F16MAT3 = 364, /* F16MAT3 */ + F16MAT4 = 365, /* F16MAT4 */ + F32VEC2 = 366, /* F32VEC2 */ + F32VEC3 = 367, /* F32VEC3 */ + F32VEC4 = 368, /* F32VEC4 */ + F32MAT2 = 369, /* F32MAT2 */ + F32MAT3 = 370, /* F32MAT3 */ + F32MAT4 = 371, /* F32MAT4 */ + F64VEC2 = 372, /* F64VEC2 */ + F64VEC3 = 373, /* F64VEC3 */ + F64VEC4 = 374, /* F64VEC4 */ + F64MAT2 = 375, /* F64MAT2 */ + F64MAT3 = 376, /* F64MAT3 */ + F64MAT4 = 377, /* F64MAT4 */ + DMAT2X2 = 378, /* DMAT2X2 */ + DMAT2X3 = 379, /* DMAT2X3 */ + DMAT2X4 = 380, /* DMAT2X4 */ + DMAT3X2 = 381, /* DMAT3X2 */ + DMAT3X3 = 382, /* DMAT3X3 */ + DMAT3X4 = 383, /* DMAT3X4 */ + DMAT4X2 = 384, /* DMAT4X2 */ + DMAT4X3 = 385, /* DMAT4X3 */ + DMAT4X4 = 386, /* DMAT4X4 */ + F16MAT2X2 = 387, /* F16MAT2X2 */ + F16MAT2X3 = 388, /* F16MAT2X3 */ + F16MAT2X4 = 389, /* F16MAT2X4 */ + F16MAT3X2 = 390, /* F16MAT3X2 */ + F16MAT3X3 = 391, /* F16MAT3X3 */ + F16MAT3X4 = 392, /* F16MAT3X4 */ + F16MAT4X2 = 393, /* F16MAT4X2 */ + F16MAT4X3 = 394, /* F16MAT4X3 */ + F16MAT4X4 = 395, /* F16MAT4X4 */ + F32MAT2X2 = 396, /* F32MAT2X2 */ + F32MAT2X3 = 397, /* F32MAT2X3 */ + F32MAT2X4 = 398, /* F32MAT2X4 */ + F32MAT3X2 = 399, /* F32MAT3X2 */ + F32MAT3X3 = 400, /* F32MAT3X3 */ + F32MAT3X4 = 401, /* F32MAT3X4 */ + F32MAT4X2 = 402, /* F32MAT4X2 */ + F32MAT4X3 = 403, /* F32MAT4X3 */ + F32MAT4X4 = 404, /* F32MAT4X4 */ + F64MAT2X2 = 405, /* F64MAT2X2 */ + F64MAT2X3 = 406, /* F64MAT2X3 */ + F64MAT2X4 = 407, /* F64MAT2X4 */ + F64MAT3X2 = 408, /* F64MAT3X2 */ + F64MAT3X3 = 409, /* F64MAT3X3 */ + F64MAT3X4 = 410, /* F64MAT3X4 */ + F64MAT4X2 = 411, /* F64MAT4X2 */ + F64MAT4X3 = 412, /* F64MAT4X3 */ + F64MAT4X4 = 413, /* F64MAT4X4 */ + ATOMIC_UINT = 414, /* ATOMIC_UINT */ + ACCSTRUCTNV = 415, /* ACCSTRUCTNV */ + ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */ + RAYQUERYEXT = 417, /* RAYQUERYEXT */ + FCOOPMATNV = 418, /* FCOOPMATNV */ + ICOOPMATNV = 419, /* ICOOPMATNV */ + UCOOPMATNV = 420, /* UCOOPMATNV */ + SAMPLERCUBEARRAY = 421, /* SAMPLERCUBEARRAY */ + SAMPLERCUBEARRAYSHADOW = 422, /* SAMPLERCUBEARRAYSHADOW */ + ISAMPLERCUBEARRAY = 423, /* ISAMPLERCUBEARRAY */ + USAMPLERCUBEARRAY = 424, /* USAMPLERCUBEARRAY */ + SAMPLER1D = 425, /* SAMPLER1D */ + SAMPLER1DARRAY = 426, /* SAMPLER1DARRAY */ + SAMPLER1DARRAYSHADOW = 427, /* SAMPLER1DARRAYSHADOW */ + ISAMPLER1D = 428, /* ISAMPLER1D */ + SAMPLER1DSHADOW = 429, /* SAMPLER1DSHADOW */ + SAMPLER2DRECT = 430, /* SAMPLER2DRECT */ + SAMPLER2DRECTSHADOW = 431, /* SAMPLER2DRECTSHADOW */ + ISAMPLER2DRECT = 432, /* ISAMPLER2DRECT */ + USAMPLER2DRECT = 433, /* USAMPLER2DRECT */ + SAMPLERBUFFER = 434, /* SAMPLERBUFFER */ + ISAMPLERBUFFER = 435, /* ISAMPLERBUFFER */ + USAMPLERBUFFER = 436, /* USAMPLERBUFFER */ + SAMPLER2DMS = 437, /* SAMPLER2DMS */ + ISAMPLER2DMS = 438, /* ISAMPLER2DMS */ + USAMPLER2DMS = 439, /* USAMPLER2DMS */ + SAMPLER2DMSARRAY = 440, /* SAMPLER2DMSARRAY */ + ISAMPLER2DMSARRAY = 441, /* ISAMPLER2DMSARRAY */ + USAMPLER2DMSARRAY = 442, /* USAMPLER2DMSARRAY */ + SAMPLEREXTERNALOES = 443, /* SAMPLEREXTERNALOES */ + SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT */ + ISAMPLER1DARRAY = 445, /* ISAMPLER1DARRAY */ + USAMPLER1D = 446, /* USAMPLER1D */ + USAMPLER1DARRAY = 447, /* USAMPLER1DARRAY */ + F16SAMPLER1D = 448, /* F16SAMPLER1D */ + F16SAMPLER2D = 449, /* F16SAMPLER2D */ + F16SAMPLER3D = 450, /* F16SAMPLER3D */ + F16SAMPLER2DRECT = 451, /* F16SAMPLER2DRECT */ + F16SAMPLERCUBE = 452, /* F16SAMPLERCUBE */ + F16SAMPLER1DARRAY = 453, /* F16SAMPLER1DARRAY */ + F16SAMPLER2DARRAY = 454, /* F16SAMPLER2DARRAY */ + F16SAMPLERCUBEARRAY = 455, /* F16SAMPLERCUBEARRAY */ + F16SAMPLERBUFFER = 456, /* F16SAMPLERBUFFER */ + F16SAMPLER2DMS = 457, /* F16SAMPLER2DMS */ + F16SAMPLER2DMSARRAY = 458, /* F16SAMPLER2DMSARRAY */ + F16SAMPLER1DSHADOW = 459, /* F16SAMPLER1DSHADOW */ + F16SAMPLER2DSHADOW = 460, /* F16SAMPLER2DSHADOW */ + F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW */ + F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW */ + F16SAMPLER2DRECTSHADOW = 463, /* F16SAMPLER2DRECTSHADOW */ + F16SAMPLERCUBESHADOW = 464, /* F16SAMPLERCUBESHADOW */ + F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW */ + IMAGE1D = 466, /* IMAGE1D */ + IIMAGE1D = 467, /* IIMAGE1D */ + UIMAGE1D = 468, /* UIMAGE1D */ + IMAGE2D = 469, /* IMAGE2D */ + IIMAGE2D = 470, /* IIMAGE2D */ + UIMAGE2D = 471, /* UIMAGE2D */ + IMAGE3D = 472, /* IMAGE3D */ + IIMAGE3D = 473, /* IIMAGE3D */ + UIMAGE3D = 474, /* UIMAGE3D */ + IMAGE2DRECT = 475, /* IMAGE2DRECT */ + IIMAGE2DRECT = 476, /* IIMAGE2DRECT */ + UIMAGE2DRECT = 477, /* UIMAGE2DRECT */ + IMAGECUBE = 478, /* IMAGECUBE */ + IIMAGECUBE = 479, /* IIMAGECUBE */ + UIMAGECUBE = 480, /* UIMAGECUBE */ + IMAGEBUFFER = 481, /* IMAGEBUFFER */ + IIMAGEBUFFER = 482, /* IIMAGEBUFFER */ + UIMAGEBUFFER = 483, /* UIMAGEBUFFER */ + IMAGE1DARRAY = 484, /* IMAGE1DARRAY */ + IIMAGE1DARRAY = 485, /* IIMAGE1DARRAY */ + UIMAGE1DARRAY = 486, /* UIMAGE1DARRAY */ + IMAGE2DARRAY = 487, /* IMAGE2DARRAY */ + IIMAGE2DARRAY = 488, /* IIMAGE2DARRAY */ + UIMAGE2DARRAY = 489, /* UIMAGE2DARRAY */ + IMAGECUBEARRAY = 490, /* IMAGECUBEARRAY */ + IIMAGECUBEARRAY = 491, /* IIMAGECUBEARRAY */ + UIMAGECUBEARRAY = 492, /* UIMAGECUBEARRAY */ + IMAGE2DMS = 493, /* IMAGE2DMS */ + IIMAGE2DMS = 494, /* IIMAGE2DMS */ + UIMAGE2DMS = 495, /* UIMAGE2DMS */ + IMAGE2DMSARRAY = 496, /* IMAGE2DMSARRAY */ + IIMAGE2DMSARRAY = 497, /* IIMAGE2DMSARRAY */ + UIMAGE2DMSARRAY = 498, /* UIMAGE2DMSARRAY */ + F16IMAGE1D = 499, /* F16IMAGE1D */ + F16IMAGE2D = 500, /* F16IMAGE2D */ + F16IMAGE3D = 501, /* F16IMAGE3D */ + F16IMAGE2DRECT = 502, /* F16IMAGE2DRECT */ + F16IMAGECUBE = 503, /* F16IMAGECUBE */ + F16IMAGE1DARRAY = 504, /* F16IMAGE1DARRAY */ + F16IMAGE2DARRAY = 505, /* F16IMAGE2DARRAY */ + F16IMAGECUBEARRAY = 506, /* F16IMAGECUBEARRAY */ + F16IMAGEBUFFER = 507, /* F16IMAGEBUFFER */ + F16IMAGE2DMS = 508, /* F16IMAGE2DMS */ + F16IMAGE2DMSARRAY = 509, /* F16IMAGE2DMSARRAY */ + I64IMAGE1D = 510, /* I64IMAGE1D */ + U64IMAGE1D = 511, /* U64IMAGE1D */ + I64IMAGE2D = 512, /* I64IMAGE2D */ + U64IMAGE2D = 513, /* U64IMAGE2D */ + I64IMAGE3D = 514, /* I64IMAGE3D */ + U64IMAGE3D = 515, /* U64IMAGE3D */ + I64IMAGE2DRECT = 516, /* I64IMAGE2DRECT */ + U64IMAGE2DRECT = 517, /* U64IMAGE2DRECT */ + I64IMAGECUBE = 518, /* I64IMAGECUBE */ + U64IMAGECUBE = 519, /* U64IMAGECUBE */ + I64IMAGEBUFFER = 520, /* I64IMAGEBUFFER */ + U64IMAGEBUFFER = 521, /* U64IMAGEBUFFER */ + I64IMAGE1DARRAY = 522, /* I64IMAGE1DARRAY */ + U64IMAGE1DARRAY = 523, /* U64IMAGE1DARRAY */ + I64IMAGE2DARRAY = 524, /* I64IMAGE2DARRAY */ + U64IMAGE2DARRAY = 525, /* U64IMAGE2DARRAY */ + I64IMAGECUBEARRAY = 526, /* I64IMAGECUBEARRAY */ + U64IMAGECUBEARRAY = 527, /* U64IMAGECUBEARRAY */ + I64IMAGE2DMS = 528, /* I64IMAGE2DMS */ + U64IMAGE2DMS = 529, /* U64IMAGE2DMS */ + I64IMAGE2DMSARRAY = 530, /* I64IMAGE2DMSARRAY */ + U64IMAGE2DMSARRAY = 531, /* U64IMAGE2DMSARRAY */ + TEXTURECUBEARRAY = 532, /* TEXTURECUBEARRAY */ + ITEXTURECUBEARRAY = 533, /* ITEXTURECUBEARRAY */ + UTEXTURECUBEARRAY = 534, /* UTEXTURECUBEARRAY */ + TEXTURE1D = 535, /* TEXTURE1D */ + ITEXTURE1D = 536, /* ITEXTURE1D */ + UTEXTURE1D = 537, /* UTEXTURE1D */ + TEXTURE1DARRAY = 538, /* TEXTURE1DARRAY */ + ITEXTURE1DARRAY = 539, /* ITEXTURE1DARRAY */ + UTEXTURE1DARRAY = 540, /* UTEXTURE1DARRAY */ + TEXTURE2DRECT = 541, /* TEXTURE2DRECT */ + ITEXTURE2DRECT = 542, /* ITEXTURE2DRECT */ + UTEXTURE2DRECT = 543, /* UTEXTURE2DRECT */ + TEXTUREBUFFER = 544, /* TEXTUREBUFFER */ + ITEXTUREBUFFER = 545, /* ITEXTUREBUFFER */ + UTEXTUREBUFFER = 546, /* UTEXTUREBUFFER */ + TEXTURE2DMS = 547, /* TEXTURE2DMS */ + ITEXTURE2DMS = 548, /* ITEXTURE2DMS */ + UTEXTURE2DMS = 549, /* UTEXTURE2DMS */ + TEXTURE2DMSARRAY = 550, /* TEXTURE2DMSARRAY */ + ITEXTURE2DMSARRAY = 551, /* ITEXTURE2DMSARRAY */ + UTEXTURE2DMSARRAY = 552, /* UTEXTURE2DMSARRAY */ + F16TEXTURE1D = 553, /* F16TEXTURE1D */ + F16TEXTURE2D = 554, /* F16TEXTURE2D */ + F16TEXTURE3D = 555, /* F16TEXTURE3D */ + F16TEXTURE2DRECT = 556, /* F16TEXTURE2DRECT */ + F16TEXTURECUBE = 557, /* F16TEXTURECUBE */ + F16TEXTURE1DARRAY = 558, /* F16TEXTURE1DARRAY */ + F16TEXTURE2DARRAY = 559, /* F16TEXTURE2DARRAY */ + F16TEXTURECUBEARRAY = 560, /* F16TEXTURECUBEARRAY */ + F16TEXTUREBUFFER = 561, /* F16TEXTUREBUFFER */ + F16TEXTURE2DMS = 562, /* F16TEXTURE2DMS */ + F16TEXTURE2DMSARRAY = 563, /* F16TEXTURE2DMSARRAY */ + SUBPASSINPUT = 564, /* SUBPASSINPUT */ + SUBPASSINPUTMS = 565, /* SUBPASSINPUTMS */ + ISUBPASSINPUT = 566, /* ISUBPASSINPUT */ + ISUBPASSINPUTMS = 567, /* ISUBPASSINPUTMS */ + USUBPASSINPUT = 568, /* USUBPASSINPUT */ + USUBPASSINPUTMS = 569, /* USUBPASSINPUTMS */ + F16SUBPASSINPUT = 570, /* F16SUBPASSINPUT */ + F16SUBPASSINPUTMS = 571, /* F16SUBPASSINPUTMS */ + SPIRV_INSTRUCTION = 572, /* SPIRV_INSTRUCTION */ + SPIRV_EXECUTION_MODE = 573, /* SPIRV_EXECUTION_MODE */ + SPIRV_EXECUTION_MODE_ID = 574, /* SPIRV_EXECUTION_MODE_ID */ + SPIRV_DECORATE = 575, /* SPIRV_DECORATE */ + SPIRV_DECORATE_ID = 576, /* SPIRV_DECORATE_ID */ + SPIRV_DECORATE_STRING = 577, /* SPIRV_DECORATE_STRING */ + SPIRV_TYPE = 578, /* SPIRV_TYPE */ + SPIRV_STORAGE_CLASS = 579, /* SPIRV_STORAGE_CLASS */ + SPIRV_BY_REFERENCE = 580, /* SPIRV_BY_REFERENCE */ + SPIRV_LITERAL = 581, /* SPIRV_LITERAL */ + LEFT_OP = 582, /* LEFT_OP */ + RIGHT_OP = 583, /* RIGHT_OP */ + INC_OP = 584, /* INC_OP */ + DEC_OP = 585, /* DEC_OP */ + LE_OP = 586, /* LE_OP */ + GE_OP = 587, /* GE_OP */ + EQ_OP = 588, /* EQ_OP */ + NE_OP = 589, /* NE_OP */ + AND_OP = 590, /* AND_OP */ + OR_OP = 591, /* OR_OP */ + XOR_OP = 592, /* XOR_OP */ + MUL_ASSIGN = 593, /* MUL_ASSIGN */ + DIV_ASSIGN = 594, /* DIV_ASSIGN */ + ADD_ASSIGN = 595, /* ADD_ASSIGN */ + MOD_ASSIGN = 596, /* MOD_ASSIGN */ + LEFT_ASSIGN = 597, /* LEFT_ASSIGN */ + RIGHT_ASSIGN = 598, /* RIGHT_ASSIGN */ + AND_ASSIGN = 599, /* AND_ASSIGN */ + XOR_ASSIGN = 600, /* XOR_ASSIGN */ + OR_ASSIGN = 601, /* OR_ASSIGN */ + SUB_ASSIGN = 602, /* SUB_ASSIGN */ + STRING_LITERAL = 603, /* STRING_LITERAL */ + LEFT_PAREN = 604, /* LEFT_PAREN */ + RIGHT_PAREN = 605, /* RIGHT_PAREN */ + LEFT_BRACKET = 606, /* LEFT_BRACKET */ + RIGHT_BRACKET = 607, /* RIGHT_BRACKET */ + LEFT_BRACE = 608, /* LEFT_BRACE */ + RIGHT_BRACE = 609, /* RIGHT_BRACE */ + DOT = 610, /* DOT */ + COMMA = 611, /* COMMA */ + COLON = 612, /* COLON */ + EQUAL = 613, /* EQUAL */ + SEMICOLON = 614, /* SEMICOLON */ + BANG = 615, /* BANG */ + DASH = 616, /* DASH */ + TILDE = 617, /* TILDE */ + PLUS = 618, /* PLUS */ + STAR = 619, /* STAR */ + SLASH = 620, /* SLASH */ + PERCENT = 621, /* PERCENT */ + LEFT_ANGLE = 622, /* LEFT_ANGLE */ + RIGHT_ANGLE = 623, /* RIGHT_ANGLE */ + VERTICAL_BAR = 624, /* VERTICAL_BAR */ + CARET = 625, /* CARET */ + AMPERSAND = 626, /* AMPERSAND */ + QUESTION = 627, /* QUESTION */ + INVARIANT = 628, /* INVARIANT */ + HIGH_PRECISION = 629, /* HIGH_PRECISION */ + MEDIUM_PRECISION = 630, /* MEDIUM_PRECISION */ + LOW_PRECISION = 631, /* LOW_PRECISION */ + PRECISION = 632, /* PRECISION */ + PACKED = 633, /* PACKED */ + RESOURCE = 634, /* RESOURCE */ + SUPERP = 635, /* SUPERP */ + FLOATCONSTANT = 636, /* FLOATCONSTANT */ + INTCONSTANT = 637, /* INTCONSTANT */ + UINTCONSTANT = 638, /* UINTCONSTANT */ + BOOLCONSTANT = 639, /* BOOLCONSTANT */ + IDENTIFIER = 640, /* IDENTIFIER */ + TYPE_NAME = 641, /* TYPE_NAME */ + CENTROID = 642, /* CENTROID */ + IN = 643, /* IN */ + OUT = 644, /* OUT */ + INOUT = 645, /* INOUT */ + STRUCT = 646, /* STRUCT */ + VOID = 647, /* VOID */ + WHILE = 648, /* WHILE */ + BREAK = 649, /* BREAK */ + CONTINUE = 650, /* CONTINUE */ + DO = 651, /* DO */ + ELSE = 652, /* ELSE */ + FOR = 653, /* FOR */ + IF = 654, /* IF */ + DISCARD = 655, /* DISCARD */ + RETURN = 656, /* RETURN */ + SWITCH = 657, /* SWITCH */ + CASE = 658, /* CASE */ + DEFAULT = 659, /* DEFAULT */ + TERMINATE_INVOCATION = 660, /* TERMINATE_INVOCATION */ + TERMINATE_RAY = 661, /* TERMINATE_RAY */ + IGNORE_INTERSECTION = 662, /* IGNORE_INTERSECTION */ + UNIFORM = 663, /* UNIFORM */ + SHARED = 664, /* SHARED */ + BUFFER = 665, /* BUFFER */ + FLAT = 666, /* FLAT */ + SMOOTH = 667, /* SMOOTH */ + LAYOUT = 668, /* LAYOUT */ + DOUBLECONSTANT = 669, /* DOUBLECONSTANT */ + INT16CONSTANT = 670, /* INT16CONSTANT */ + UINT16CONSTANT = 671, /* UINT16CONSTANT */ + FLOAT16CONSTANT = 672, /* FLOAT16CONSTANT */ + INT32CONSTANT = 673, /* INT32CONSTANT */ + UINT32CONSTANT = 674, /* UINT32CONSTANT */ + INT64CONSTANT = 675, /* INT64CONSTANT */ + UINT64CONSTANT = 676, /* UINT64CONSTANT */ + SUBROUTINE = 677, /* SUBROUTINE */ + DEMOTE = 678, /* DEMOTE */ + PAYLOADNV = 679, /* PAYLOADNV */ + PAYLOADINNV = 680, /* PAYLOADINNV */ + HITATTRNV = 681, /* HITATTRNV */ + CALLDATANV = 682, /* CALLDATANV */ + CALLDATAINNV = 683, /* CALLDATAINNV */ + PAYLOADEXT = 684, /* PAYLOADEXT */ + PAYLOADINEXT = 685, /* PAYLOADINEXT */ + HITATTREXT = 686, /* HITATTREXT */ + CALLDATAEXT = 687, /* CALLDATAEXT */ + CALLDATAINEXT = 688, /* CALLDATAINEXT */ + PATCH = 689, /* PATCH */ + SAMPLE = 690, /* SAMPLE */ + NONUNIFORM = 691, /* NONUNIFORM */ + COHERENT = 692, /* COHERENT */ + VOLATILE = 693, /* VOLATILE */ + RESTRICT = 694, /* RESTRICT */ + READONLY = 695, /* READONLY */ + WRITEONLY = 696, /* WRITEONLY */ + DEVICECOHERENT = 697, /* DEVICECOHERENT */ + QUEUEFAMILYCOHERENT = 698, /* QUEUEFAMILYCOHERENT */ + WORKGROUPCOHERENT = 699, /* WORKGROUPCOHERENT */ + SUBGROUPCOHERENT = 700, /* SUBGROUPCOHERENT */ + NONPRIVATE = 701, /* NONPRIVATE */ + SHADERCALLCOHERENT = 702, /* SHADERCALLCOHERENT */ + NOPERSPECTIVE = 703, /* NOPERSPECTIVE */ + EXPLICITINTERPAMD = 704, /* EXPLICITINTERPAMD */ + PERVERTEXNV = 705, /* PERVERTEXNV */ + PERPRIMITIVENV = 706, /* PERPRIMITIVENV */ + PERVIEWNV = 707, /* PERVIEWNV */ + PERTASKNV = 708, /* PERTASKNV */ + PRECISE = 709 /* PRECISE */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ +#line 97 "MachineIndependent/glslang.y" + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + glslang::TSpirvRequirement* spirvReq; + glslang::TSpirvInstruction* spirvInst; + glslang::TSpirvTypeParameters* spirvTypeParams; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 557 "MachineIndependent/glslang_tab.cpp.h" + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/libraries/glslang/glslang/MachineIndependent/intermOut.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/intermOut.cpp similarity index 93% rename from libraries/glslang/glslang/MachineIndependent/intermOut.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/intermOut.cpp index 3a93aedaf..a0fade16c 100644 --- a/libraries/glslang/glslang/MachineIndependent/intermOut.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/intermOut.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -35,7 +36,7 @@ // POSSIBILITY OF SUCH DAMAGE. // -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #include "localintermediate.h" #include "../Include/InfoSink.h" @@ -437,6 +438,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break; case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break; + case EOpConvUint64ToAccStruct: out.debug << "Convert uint64_t to acceleration structure"; break; + case EOpConvUvec2ToAccStruct: out.debug << "Convert uvec2 to acceleration strucuture "; break; + case EOpRadians: out.debug << "radians"; break; case EOpDegrees: out.debug << "degrees"; break; case EOpSin: out.debug << "sine"; break; @@ -692,6 +696,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) case EOpConstructReference: out.debug << "Construct reference type"; break; +#ifndef GLSLANG_WEB + case EOpSpirvInst: out.debug << "spirv_instruction"; break; +#endif + default: out.debug.message(EPrefixError, "Bad unary op"); } @@ -828,6 +836,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break; case EOpConstructReference: out.debug << "Construct reference"; break; case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break; + case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break; case EOpLessThan: out.debug << "Compare Less Than"; break; case EOpGreaterThan: out.debug << "Compare Greater Than"; break; @@ -881,6 +890,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpTime: out.debug << "time"; break; case EOpAtomicAdd: out.debug << "AtomicAdd"; break; + case EOpAtomicSubtract: out.debug << "AtomicSubtract"; break; case EOpAtomicMin: out.debug << "AtomicMin"; break; case EOpAtomicMax: out.debug << "AtomicMax"; break; case EOpAtomicAnd: out.debug << "AtomicAnd"; break; @@ -1079,17 +1089,51 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; case EOpTraceNV: out.debug << "traceNV"; break; - case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break; + case EOpTraceRayMotionNV: out.debug << "traceRayMotionNV"; break; + case EOpTraceKHR: out.debug << "traceRayKHR"; break; + case EOpReportIntersection: out.debug << "reportIntersectionNV"; break; case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break; + case EOpIgnoreIntersectionKHR: out.debug << "ignoreIntersectionKHR"; break; case EOpTerminateRayNV: out.debug << "terminateRayNV"; break; + case EOpTerminateRayKHR: out.debug << "terminateRayKHR"; break; case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break; + case EOpExecuteCallableKHR: out.debug << "executeCallableKHR"; break; case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break; + case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break; + case EOpRayQueryTerminate: out.debug << "rayQueryTerminateEXT"; break; + case EOpRayQueryGenerateIntersection: out.debug << "rayQueryGenerateIntersectionEXT"; break; + case EOpRayQueryConfirmIntersection: out.debug << "rayQueryConfirmIntersectionEXT"; break; + case EOpRayQueryProceed: out.debug << "rayQueryProceedEXT"; break; + case EOpRayQueryGetIntersectionType: out.debug << "rayQueryGetIntersectionTypeEXT"; break; + case EOpRayQueryGetRayTMin: out.debug << "rayQueryGetRayTMinEXT"; break; + case EOpRayQueryGetRayFlags: out.debug << "rayQueryGetRayFlagsEXT"; break; + case EOpRayQueryGetIntersectionT: out.debug << "rayQueryGetIntersectionTEXT"; break; + case EOpRayQueryGetIntersectionInstanceCustomIndex: out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break; + case EOpRayQueryGetIntersectionInstanceId: out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break; + case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break; + case EOpRayQueryGetIntersectionGeometryIndex: out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break; + case EOpRayQueryGetIntersectionPrimitiveIndex: out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break; + case EOpRayQueryGetIntersectionBarycentrics: out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break; + case EOpRayQueryGetIntersectionFrontFace: out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break; + case EOpRayQueryGetIntersectionCandidateAABBOpaque: out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break; + case EOpRayQueryGetIntersectionObjectRayDirection: out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break; + case EOpRayQueryGetIntersectionObjectRayOrigin: out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break; + case EOpRayQueryGetWorldRayDirection: out.debug << "rayQueryGetWorldRayDirectionEXT"; break; + case EOpRayQueryGetWorldRayOrigin: out.debug << "rayQueryGetWorldRayOriginEXT"; break; + case EOpRayQueryGetIntersectionObjectToWorld: out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break; + case EOpRayQueryGetIntersectionWorldToObject: out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break; + case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break; case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break; case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break; case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break; + case EOpDebugPrintf: out.debug << "Debug printf"; break; + +#ifndef GLSLANG_WEB + case EOpSpirvInst: out.debug << "spirv_instruction"; break; +#endif default: out.debug.message(EPrefixError, "Bad aggregation op"); } @@ -1295,6 +1339,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const out.debug << buf << "\n"; } break; + case EbtString: + out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n"; + break; default: out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc()); break; @@ -1380,14 +1427,17 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node) OutputTreeText(out, node, depth); switch (node->getFlowOp()) { - case EOpKill: out.debug << "Branch: Kill"; break; - case EOpBreak: out.debug << "Branch: Break"; break; - case EOpContinue: out.debug << "Branch: Continue"; break; - case EOpReturn: out.debug << "Branch: Return"; break; - case EOpCase: out.debug << "case: "; break; - case EOpDemote: out.debug << "Demote"; break; - case EOpDefault: out.debug << "default: "; break; - default: out.debug << "Branch: Unknown Branch"; break; + case EOpKill: out.debug << "Branch: Kill"; break; + case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break; + case EOpIgnoreIntersectionKHR: out.debug << "Branch: IgnoreIntersectionKHR"; break; + case EOpTerminateRayKHR: out.debug << "Branch: TerminateRayKHR"; break; + case EOpBreak: out.debug << "Branch: Break"; break; + case EOpContinue: out.debug << "Branch: Continue"; break; + case EOpReturn: out.debug << "Branch: Return"; break; + case EOpCase: out.debug << "case: "; break; + case EOpDemote: out.debug << "Demote"; break; + case EOpDefault: out.debug << "default: "; break; + default: out.debug << "Branch: Unknown Branch"; break; } if (node->getExpression()) { @@ -1446,6 +1496,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree) if (xfbMode) infoSink.debug << "in xfb mode\n"; + if (getSubgroupUniformControlFlow()) + infoSink.debug << "subgroup_uniform_control_flow\n"; + switch (language) { case EShLangVertex: break; @@ -1536,4 +1589,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree) } // end namespace glslang -#endif // not GLSLANG_WEB \ No newline at end of file +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE diff --git a/libraries/glslang/glslang/MachineIndependent/iomapper.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.cpp similarity index 60% rename from libraries/glslang/glslang/MachineIndependent/iomapper.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.cpp index 3262c0a20..7e12864f3 100644 --- a/libraries/glslang/glslang/MachineIndependent/iomapper.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.cpp @@ -33,13 +33,15 @@ // POSSIBILITY OF SUCH DAMAGE. // -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #include "../Include/Common.h" #include "../Include/InfoSink.h" +#include "../Include/Types.h" #include "gl_types.h" #include "iomapper.h" +#include "SymbolTable.h" // // Map IO bindings. @@ -79,15 +81,20 @@ public: target = &outputList; else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) target = &uniformList; + // If a global is being visited, then we should also traverse it incase it's evaluation + // ends up visiting inputs we want to tag as live + else if (base->getQualifier().storage == EvqGlobal) + addGlobalReference(base->getAccessName()); + if (target) { TVarEntryInfo ent = {base->getId(), base, ! traverseAll}; ent.stage = intermediate.getStage(); TVarLiveMap::iterator at = target->find( - ent.symbol->getName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById()); + ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById()); if (at != target->end() && at->second.id == ent.id) at->second.live = at->second.live || ! traverseAll; // update live state else - (*target)[ent.symbol->getName()] = ent; + (*target)[ent.symbol->getAccessName()] = ent; } } @@ -120,7 +127,8 @@ public: return; TVarEntryInfo ent = { base->getId() }; - TVarLiveMap::const_iterator at = source->find(base->getName()); + // Fix a defect, when block has no instance name, we need to find its block name + TVarLiveMap::const_iterator at = source->find(base->getAccessName()); if (at == source->end()) return; @@ -161,7 +169,7 @@ struct TNotifyUniformAdaptor } private: - TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&); + TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete; }; struct TNotifyInOutAdaptor @@ -176,20 +184,21 @@ struct TNotifyInOutAdaptor inline void operator()(std::pair& entKey) { - resolver.notifyInOut(stage, entKey.second); + resolver.notifyInOut(entKey.second.stage, entKey.second); } private: - TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&); + TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete; }; struct TResolverUniformAdaptor { - TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e) + TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e) : stage(s) , resolver(r) , infoSink(i) , error(e) { + memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*))); } inline void operator()(std::pair& entKey) { @@ -201,9 +210,9 @@ struct TResolverUniformAdaptor { ent.newIndex = -1; const bool isValid = resolver.validateBinding(stage, ent); if (isValid) { - resolver.resolveBinding(stage, ent); - resolver.resolveSet(stage, ent); - resolver.resolveUniformLocation(stage, ent); + resolver.resolveSet(ent.stage, ent); + resolver.resolveBinding(ent.stage, ent); + resolver.resolveUniformLocation(ent.stage, ent); if (ent.newBinding != -1) { if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) { @@ -212,6 +221,17 @@ struct TResolverUniformAdaptor { infoSink.info.message(EPrefixInternalError, err.c_str()); error = true; } + + if (ent.symbol->getQualifier().hasBinding()) { + for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) { + if (idx == ent.stage || uniformVarMap[idx] == nullptr) + continue; + auto entKey2 = uniformVarMap[idx]->find(entKey.first); + if (entKey2 != uniformVarMap[idx]->end()) { + entKey2->second.newBinding = ent.newBinding; + } + } + } } if (ent.newSet != -1) { if (ent.newSet >= int(TQualifier::layoutSetEnd)) { @@ -220,6 +240,16 @@ struct TResolverUniformAdaptor { infoSink.info.message(EPrefixInternalError, err.c_str()); error = true; } + if (ent.symbol->getQualifier().hasSet()) { + for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) { + if ((idx == stage) || (uniformVarMap[idx] == nullptr)) + continue; + auto entKey2 = uniformVarMap[idx]->find(entKey.first); + if (entKey2 != uniformVarMap[idx]->end()) { + entKey2->second.newSet = ent.newSet; + } + } + } } } else { TString errorMsg = "Invalid binding: " + entKey.first; @@ -234,9 +264,9 @@ struct TResolverUniformAdaptor { TIoMapResolver& resolver; TInfoSink& infoSink; bool& error; - + TVarLiveMap* uniformVarMap[EShLangCount]; private: - TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&); + TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete; }; struct TResolverInOutAdaptor { @@ -256,7 +286,7 @@ struct TResolverInOutAdaptor { ent.newBinding = -1; ent.newSet = -1; ent.newIndex = -1; - const bool isValid = resolver.validateInOut(stage, ent); + const bool isValid = resolver.validateInOut(ent.stage, ent); if (isValid) { resolver.resolveInOutLocation(stage, ent); resolver.resolveInOutComponent(stage, ent); @@ -283,25 +313,122 @@ struct TResolverInOutAdaptor { bool& error; private: - TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&); + TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete; }; // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings +// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform" struct TSymbolValidater { TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount], - TVarLiveMap* uniform[EShLangCount], bool& hadError) - : preStage(EShLangCount) - , currentStage(EShLangCount) - , nextStage(EShLangCount) - , resolver(r) + TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version) + : resolver(r) , infoSink(i) , hadError(hadError) + , profile(profile) + , version(version) { memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*))); memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*))); memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*))); + + std::map anonymousMemberMap; + std::vector usedUniformLocation; + std::vector usedUniformName; + usedUniformLocation.clear(); + usedUniformName.clear(); + for (int i = 0; i < EShLangCount; i++) { + if (uniformVarMap[i]) { + for (auto uniformVar : *uniformVarMap[i]) + { + TIntermSymbol* pSymbol = uniformVar.second.symbol; + TQualifier qualifier = uniformVar.second.symbol->getQualifier(); + TString symbolName = pSymbol->getAccessName(); + + // All the uniform needs multi-stage location check (block/default) + int uniformLocation = qualifier.layoutLocation; + + if (uniformLocation != TQualifier::layoutLocationEnd) { + // Total size of current uniform, could be block, struct or other types. + int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType()); + + TRange locationRange(uniformLocation, uniformLocation + size - 1); + + // Combine location and component ranges + int overlapLocation = -1; + bool diffLocation = false; + + // Check for collisions, except for vertex inputs on desktop targeting OpenGL + overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation); + + // Overlap locations of uniforms, regardless of components (multi stages) + if (overlapLocation == -1) { + usedUniformLocation.push_back(locationRange); + usedUniformName.push_back(symbolName); + } + else if (overlapLocation >= 0) { + if (diffLocation == true) { + TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str(); + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + break; + } + else { + TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str(); + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + break; + } + } + } + + if ((uniformVar.second.symbol->getBasicType() == EbtBlock) && + IsAnonymous(uniformVar.second.symbol->getName())) + { + auto blockType = uniformVar.second.symbol->getType().getStruct(); + for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) { + auto memberName = (*blockType)[memberIdx].type->getFieldName(); + if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end()) + { + if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName()) + { + TString err = "Invalid block member name: " + memberName; + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + break; + } + } + else + { + anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName(); + } + } + } + if (hadError) + break; + } + } + } + } + + // In case we need to new an intermediate, which costs too much + int checkLocationOverlap(const TRange& locationRange, std::vector& usedUniformLocation, const TString symbolName, std::vector& usedUniformName, bool& diffLocation) + { + for (size_t r = 0; r < usedUniformLocation.size(); ++r) { + if (usedUniformName[r] == symbolName) { + diffLocation = true; + return (usedUniformLocation[r].start == locationRange.start && + usedUniformLocation[r].last == locationRange.last) + ? -2 : std::max(locationRange.start, usedUniformLocation[r].start); + } + if (locationRange.overlap(usedUniformLocation[r])) { + // there is a collision; pick one + return std::max(locationRange.start, usedUniformLocation[r].start); + } + } + + return -1; // no collision } inline void operator()(std::pair& entKey) { @@ -310,43 +437,114 @@ struct TSymbolValidater const TType& type = ent1.symbol->getType(); const TString& name = entKey.first; TString mangleName1, mangleName2; - type.appendMangledName(mangleName1); EShLanguage stage = ent1.stage; - if (currentStage != stage) { - preStage = currentStage; - currentStage = stage; - nextStage = EShLangCount; - for (int i = currentStage + 1; i < EShLangCount; i++) { - if (inVarMaps[i] != nullptr) - nextStage = static_cast(i); + EShLanguage preStage, currentStage, nextStage; + + preStage = EShLangCount; + for (int i = stage - 1; i >= 0; i--) { + if (inVarMaps[i] != nullptr) { + preStage = static_cast(i); + break; } } + currentStage = stage; + nextStage = EShLangCount; + for (int i = stage + 1; i < EShLangCount; i++) { + if (inVarMaps[i] != nullptr) { + nextStage = static_cast(i); + break; + } + } + + if (type.getQualifier().isArrayedIo(stage)) { + TType subType(type, 0); + subType.appendMangledName(mangleName1); + } else { + type.appendMangledName(mangleName1); + } + + + // basic checking that symbols match + // more extensive checking in the link stage if (base->getQualifier().storage == EvqVaryingIn) { // validate stage in; if (preStage == EShLangCount) return; + if (TSymbolTable::isBuiltInSymbol(base->getId())) + return; if (outVarMaps[preStage] != nullptr) { auto ent2 = outVarMaps[preStage]->find(name); + uint32_t location = base->getType().getQualifier().layoutLocation; + if (ent2 == outVarMaps[preStage]->end() && + location != glslang::TQualifier::layoutLocationEnd) { + for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) { + if (var->second.symbol->getType().getQualifier().layoutLocation == location) { + ent2 = var; + break; + } + } + } if (ent2 != outVarMaps[preStage]->end()) { - ent2->second.symbol->getType().appendMangledName(mangleName2); - if (mangleName1 == mangleName2) + auto& type1 = base->getType(); + auto& type2 = ent2->second.symbol->getType(); + hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false); + if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) { + TType subType(ent2->second.symbol->getType(), 0); + subType.appendMangledName(mangleName2); + } else { + ent2->second.symbol->getType().appendMangledName(mangleName2); + } + + if (mangleName1 == mangleName2) { + // For ES 3.0 only, other versions have no such restrictions + // According to ES 3.0 spec: The type and presence of the interpolation qualifiers and + // storage qualifiers of variables with the same name declared in all linked shaders must + // match, otherwise the link command will fail. + if (profile == EEsProfile && version == 300) { + // Don't need to check smooth qualifier, as it uses the default interpolation mode + if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) { + if (type1.getQualifier().flat != type2.getQualifier().flat || + type1.getQualifier().nopersp != type2.getQualifier().nopersp) { + TString err = "Interpolation qualifier mismatch : " + entKey.first; + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + } + } + } return; + } else { TString err = "Invalid In/Out variable type : " + entKey.first; infoSink.info.message(EPrefixInternalError, err.c_str()); hadError = true; } } + else if (!base->getType().isBuiltIn()) { + // According to spec: A link error is generated if any statically referenced input variable + // or block does not have a matching output + if (profile == EEsProfile && ent1.live) { + hadError = true; + TString errorStr = name + ": not been declare as a output variable in pre shader stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + } return; } } else if (base->getQualifier().storage == EvqVaryingOut) { // validate stage out; if (nextStage == EShLangCount) return; - if (outVarMaps[nextStage] != nullptr) { + if (TSymbolTable::isBuiltInSymbol(base->getId())) + return; + if (inVarMaps[nextStage] != nullptr) { auto ent2 = inVarMaps[nextStage]->find(name); if (ent2 != inVarMaps[nextStage]->end()) { - ent2->second.symbol->getType().appendMangledName(mangleName2); + if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) { + TType subType(ent2->second.symbol->getType(), 0); + subType.appendMangledName(mangleName2); + } else { + ent2->second.symbol->getType().appendMangledName(mangleName2); + } if (mangleName1 == mangleName2) return; else { @@ -357,7 +555,7 @@ struct TSymbolValidater } return; } - } else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) { + } else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) { // validate uniform type; for (int i = 0; i < EShLangCount; i++) { if (i != currentStage && outVarMaps[i] != nullptr) { @@ -365,26 +563,174 @@ struct TSymbolValidater if (ent2 != uniformVarMap[i]->end()) { ent2->second.symbol->getType().appendMangledName(mangleName2); if (mangleName1 != mangleName2) { + ent2->second.symbol->getType().sameElementType(type); TString err = "Invalid Uniform variable type : " + entKey.first; infoSink.info.message(EPrefixInternalError, err.c_str()); hadError = true; } mangleName2.clear(); + + // validate instance name of blocks + if (hadError == false && + base->getType().getBasicType() == EbtBlock && + IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) { + TString err = "Matched uniform block names must also either all be lacking " + "an instance name or all having an instance name: " + entKey.first; + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + } + + // validate uniform block member qualifier and member names + auto& type1 = base->getType(); + auto& type2 = ent2->second.symbol->getType(); + if (hadError == false && base->getType().getBasicType() == EbtBlock) { + hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true); + } + else { + hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false); + } + } + else if (base->getBasicType() == EbtBlock) + { + if (IsAnonymous(base->getName())) + { + // The name of anonymous block member can't same with default uniform variable. + auto blockType1 = base->getType().getStruct(); + for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) { + auto memberName = (*blockType1)[memberIdx].type->getFieldName(); + if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end()) + { + TString err = "Invalid Uniform variable name : " + memberName; + infoSink.info.message(EPrefixInternalError, err.c_str()); + hadError = true; + break; + } + } + } } } } } } + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount]; - // Use for mark pre stage, to get more interface symbol information. - EShLanguage preStage, currentStage, nextStage; + // Use for mark current shader stage for resolver TIoMapResolver& resolver; TInfoSink& infoSink; bool& hadError; + EProfile profile; + int version; private: - TSymbolValidater& operator=(TSymbolValidater&); + TSymbolValidater& operator=(TSymbolValidater&) = delete; + + bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock) + { + bool hasError = false; + const TQualifier& qualifier1 = type1->getQualifier(); + const TQualifier& qualifier2 = type2->getQualifier(); + + if (((isBlock == false) && + (type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) || + (type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) { + if (qualifier1.precision != qualifier2.precision) { + hasError = true; + std::string errorStr = name + ": have precision conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + if (qualifier1.hasFormat() && qualifier2.hasFormat()) { + if (qualifier1.layoutFormat != qualifier2.layoutFormat) { + hasError = true; + std::string errorStr = name + ": have layout format conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + + } + } + + if (isBlock == true) { + if (qualifier1.layoutPacking != qualifier2.layoutPacking) { + hasError = true; + std::string errorStr = name + ": have layoutPacking conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) { + hasError = true; + std::string errorStr = name + ": have layoutMatrix conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + if (qualifier1.layoutOffset != qualifier2.layoutOffset) { + hasError = true; + std::string errorStr = name + ": have layoutOffset conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + if (qualifier1.layoutAlign != qualifier2.layoutAlign) { + hasError = true; + std::string errorStr = name + ": have layoutAlign conflict cross stage."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + } + } + + return hasError; + } + + bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock) + { + bool hasError = false; + if (!(type1->isStruct() && type2->isStruct())) { + hasError = hasError || qualifierCheck(type1, type2, name, isBlock); + } + else { + if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock) + isBlock = true; + const TTypeList* typeList1 = type1->getStruct(); + const TTypeList* typeList2 = type2->getStruct(); + + std::string newName = name; + size_t memberCount = typeList1->size(); + size_t index2 = 0; + for (size_t index = 0; index < memberCount; index++, index2++) { + // Skip inactive member + if (typeList1->at(index).type->getBasicType() == EbtVoid) + continue; + while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) { + ++index2; + } + + // TypeList1 has more members in list + if (index2 == typeList2->size()) { + std::string errorStr = name + ": struct mismatch."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + hasError = true; + break; + } + + if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) { + std::string errorStr = name + ": member name mismatch."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + hasError = true; + } + else { + newName = typeList1->at(index).type->getFieldName().c_str(); + } + hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock); + } + + while (index2 < typeList2->size()) + { + // TypeList2 has more members + if (typeList2->at(index2).type->getBasicType() != EbtVoid) { + std::string errorStr = name + ": struct mismatch."; + infoSink.info.message(EPrefixError, errorStr.c_str()); + hasError = true; + break; + } + ++index2; + } + } + return hasError; + } }; struct TSlotCollector { @@ -398,7 +744,7 @@ struct TSlotCollector { TInfoSink& infoSink; private: - TSlotCollector& operator=(TSlotCollector&); + TSlotCollector& operator=(TSlotCollector&) = delete; }; TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate) @@ -408,14 +754,18 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate , nextOutputLocation(0) { memset(stageMask, false, sizeof(bool) * (EShLangCount + 1)); + memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount)); + stageIntermediates[intermediate.getStage()] = &intermediate; } -int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const { - return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set)); +int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const { + return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set)) + : selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set)); } -const std::vector& TDefaultIoResolverBase::getResourceSetBinding() const { - return intermediate.getResourceSetBinding(); +const std::vector& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const { + return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding() + : intermediate.getResourceSetBinding(); } bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); } @@ -456,21 +806,21 @@ int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) { return reserveSlot(set, base, size); } -int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) { +int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); if (type.getQualifier().hasSet()) { return ent.newSet = type.getQualifier().layoutSet; } // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN) - if (getResourceSetBinding().size() == 1) { - return ent.newSet = atoi(getResourceSetBinding()[0].c_str()); + if (getResourceSetBinding(stage).size() == 1) { + return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str()); } return ent.newSet = 0; } int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const char* name = ent.symbol->getName().c_str(); + const char* name = ent.symbol->getAccessName().c_str(); // kick out of not doing this if (! doAutoLocationMapping()) { return ent.newLocation = -1; @@ -579,12 +929,12 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = ent.symbol->getAccessName(); if (currentStage != stage) { preStage = currentStage; currentStage = stage; } - // kick out of not doing this + // kick out if not doing this if (! doAutoLocationMapping()) { return ent.newLocation = -1; } @@ -627,7 +977,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name); if (iter != storageSlotMap[resourceKey].end()) { // If interface resource be found, set it has location and this symbol's new location - // equal the symbol's explicit location declarated in pre or next stage. + // equal the symbol's explicit location declaration in pre or next stage. // // vs: out vec4 a; // fs: layout(..., location = 3,...) in vec4 a; @@ -663,7 +1013,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = ent.symbol->getAccessName(); // kick out of not doing this if (! doAutoLocationMapping()) { return ent.newLocation = -1; @@ -706,7 +1056,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn TVarSlotMap::iterator iter = slotMap.find(name); if (iter != slotMap.end()) { // If uniform resource be found, set it has location and this symbol's new location - // equal the uniform's explicit location declarated in other stage. + // equal the uniform's explicit location declaration in other stage. // // vs: uniform vec4 a; // fs: layout(..., location = 3,...) uniform vec4 a; @@ -714,7 +1064,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn location = iter->second; } if (! hasLocation) { - // No explicit location declaraten in other stage. + // No explicit location declaration in other stage. // So we should find a new slot for this uniform. // // vs: uniform vec4 a; @@ -723,7 +1073,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn storageSlotMap[resourceKey][name] = location; } } else { - // the first uniform declarated in a program. + // the first uniform declaration in a program. TVarSlotMap varSlotMap; location = getFreeSlot(resourceKey, 0, size); varSlotMap[name] = location; @@ -732,10 +1082,10 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn return ent.newLocation = location; } -int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) { +int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); - // On OpenGL arrays of opaque types take a seperate binding for each element + const TString& name = ent.symbol->getAccessName(); + // On OpenGL arrays of opaque types take a separate binding for each element int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; TResourceType resource = getResourceType(type); // don't need to handle uniform symbol, it will be handled in resolveUniformLocation @@ -745,30 +1095,32 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& // There is no 'set' qualifier in OpenGL shading language, each resource has its own // binding name space, so remap the 'set' to resource type which make each resource // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS - int set = resource; + int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet; + int resourceKey = set; if (resource < EResCount) { if (type.getQualifier().hasBinding()) { - ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings); - return ent.newBinding; - } else if (ent.live && doAutoBindingMapping()) { + int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); + return ent.newBinding = newBinding; + + } else { // The resource in current stage is not declared with binding, but it is possible declared // with explicit binding in other stages, find the resourceSlotMap firstly to check whether // the resource has binding, don't need to allocate if it already has a binding bool hasBinding = false; - if (! resourceSlotMap[resource].empty()) { - TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name); - if (iter != resourceSlotMap[resource].end()) { + ent.newBinding = -1; // leave as -1 if it isn't set below + + if (! resourceSlotMap[resourceKey].empty()) { + TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name); + if (iter != resourceSlotMap[resourceKey].end()) { hasBinding = true; ent.newBinding = iter->second; } } - if (! hasBinding) { - TVarSlotMap varSlotMap; + if (!hasBinding && (ent.live && doAutoBindingMapping())) { // find free slot, the caller did make sure it passes all vars with binding // first and now all are passed that do not have a binding and needs one - int binding = getFreeSlot(resource, getBaseBinding(resource, set), numBindings); - varSlotMap[name] = binding; - resourceSlotMap[resource] = varSlotMap; + int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings); + resourceSlotMap[resourceKey][name] = binding; ent.newBinding = binding; } return ent.newBinding; @@ -809,7 +1161,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) { void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = ent.symbol->getAccessName(); TStorageQualifier storage = type.getQualifier().storage; EShLanguage stage(EShLangCount); switch (storage) { @@ -831,6 +1183,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& if (iter->second != location) { TString errorMsg = "Invalid location: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } @@ -856,6 +1209,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& if (iter->second != location) { TString errorMsg = "Invalid location: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } @@ -867,23 +1221,28 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); - int resource = getResourceType(type); + const TString& name = ent.symbol->getAccessName(); + TResourceType resource = getResourceType(type); + int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent); + int resourceKey = set; + if (type.getQualifier().hasBinding()) { - TVarSlotMap& varSlotMap = resourceSlotMap[resource]; + TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey]; TVarSlotMap::iterator iter = varSlotMap.find(name); - int binding = type.getQualifier().layoutBinding; + int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set); + if (iter == varSlotMap.end()) { // Reserve the slots for the ubo, ssbo and opaques who has explicit binding - int numBindings = type.isSizedArray() ? type.getCumulativeArraySize() : 1; + int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; varSlotMap[name] = binding; - reserveSlot(resource, binding, numBindings); + reserveSlot(resourceKey, binding, numBindings); } else { // Allocate binding by name for OpenGL driver, so the resource in different // stages should be declared with the same binding if (iter->second != binding) { TString errorMsg = "Invalid binding: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } @@ -925,7 +1284,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase { return EResCount; } - int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override { + int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override { const TType& type = ent.symbol->getType(); const int set = getLayoutSet(type); // On OpenGL arrays of opaque types take a seperate binding for each element @@ -934,11 +1293,11 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase { if (resource < EResCount) { if (type.getQualifier().hasBinding()) { return ent.newBinding = reserveSlot( - set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings); + set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); } else if (ent.live && doAutoBindingMapping()) { // find free slot, the caller did make sure it passes all vars with binding // first and now all are passed that do not have a binding and needs one - return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set), numBindings); + return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings); } } return ent.newBinding = -1; @@ -1010,17 +1369,17 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase { return EResCount; } - int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override { + int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override { const TType& type = ent.symbol->getType(); const int set = getLayoutSet(type); TResourceType resource = getResourceType(type); if (resource < EResCount) { if (type.getQualifier().hasBinding()) { - return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding); + return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding); } else if (ent.live && doAutoBindingMapping()) { // find free slot, the caller did make sure it passes all vars with binding // first and now all are passed that do not have a binding and needs one - return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set)); + return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set)); } } return ent.newBinding = -1; @@ -1059,10 +1418,10 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi else resolver = &defaultResolver; } - resolver->addStage(stage); #else resolver = &defaultResolver; #endif + resolver->addStage(stage, intermediate); TVarLiveMap inVarMap, outVarMap, uniformVarMap; TVarLiveVector inVector, outVector, uniformVector; @@ -1070,31 +1429,30 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap); root->traverse(&iter_binding_all); iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.functions.empty()) { - TIntermNode* function = iter_binding_live.functions.back(); - iter_binding_live.functions.pop_back(); - function->traverse(&iter_binding_live); + while (! iter_binding_live.destinations.empty()) { + TIntermNode* destination = iter_binding_live.destinations.back(); + iter_binding_live.destinations.pop_back(); + destination->traverse(&iter_binding_live); } + // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. - std::for_each(inVarMap.begin(), inVarMap.end(), - [&inVector](TVarLivePair p) { inVector.push_back(p); }); + for (auto& var : inVarMap) { inVector.push_back(var); } std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); }); - std::for_each(outVarMap.begin(), outVarMap.end(), - [&outVector](TVarLivePair p) { outVector.push_back(p); }); + for (auto& var : outVarMap) { outVector.push_back(var); } std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); }); - std::for_each(uniformVarMap.begin(), uniformVarMap.end(), - [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); }); + for (auto& var : uniformVarMap) { uniformVector.push_back(var); } std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); }); bool hadError = false; + TVarLiveMap* dummyUniformVarMap[EShLangCount] = {}; TNotifyInOutAdaptor inOutNotify(stage, *resolver); TNotifyUniformAdaptor uniformNotify(stage, *resolver); - TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError); + TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError); TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError); resolver->beginNotifications(stage); std::for_each(inVector.begin(), inVector.end(), inOutNotify); @@ -1102,22 +1460,22 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify); resolver->endNotifications(stage); resolver->beginResolve(stage); - std::for_each(inVector.begin(), inVector.end(), inOutResolve); + for (auto& var : inVector) { inOutResolve(var); } std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) { - auto at = inVarMap.find(p.second.symbol->getName()); - if (at != inVarMap.end()) + auto at = inVarMap.find(p.second.symbol->getAccessName()); + if (at != inVarMap.end() && p.second.id == at->second.id) at->second = p.second; }); - std::for_each(outVector.begin(), outVector.end(), inOutResolve); + for (auto& var : outVector) { inOutResolve(var); } std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) { - auto at = outVarMap.find(p.second.symbol->getName()); - if (at != outVarMap.end()) + auto at = outVarMap.find(p.second.symbol->getAccessName()); + if (at != outVarMap.end() && p.second.id == at->second.id) at->second = p.second; }); std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve); std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) { - auto at = uniformVarMap.find(p.second.symbol->getName()); - if (at != uniformVarMap.end()) + auto at = uniformVarMap.find(p.second.symbol->getAccessName()); + if (at != uniformVarMap.end() && p.second.id == at->second.id) at->second = p.second; }); resolver->endResolve(stage); @@ -1133,9 +1491,14 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi // // Returns false if the input is too malformed to do this. bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) { + bool somethingToDo = !intermediate.getResourceSetBinding().empty() || + intermediate.getAutoMapBindings() || + intermediate.getAutoMapLocations(); + + // Profile and version are use for symbol validate. + profile = intermediate.getProfile(); + version = intermediate.getVersion(); - bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() || - intermediate.getAutoMapLocations(); // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true. for (int res = 0; (res < EResCount && !somethingToDo); ++res) { @@ -1154,22 +1517,34 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn } // if no resolver is provided, use the default resolver with the given shifts and auto map settings TDefaultGlslIoResolver defaultResolver(intermediate); +#ifdef ENABLE_HLSL + TDefaultHlslIoResolver defaultHlslResolver(intermediate); + if (resolver == nullptr) { + // TODO: use a passed in IO mapper for this + if (intermediate.usingHlslIoMapping()) + resolver = &defaultHlslResolver; + else + resolver = &defaultResolver; + } +#else if (resolver == nullptr) { resolver = &defaultResolver; } - resolver->addStage(stage); - inVarMaps[stage] = new TVarLiveMap, outVarMaps[stage] = new TVarLiveMap(), uniformVarMap[stage] = new TVarLiveMap(); +#endif + resolver->addStage(stage, intermediate); + inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap(); TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage], *uniformVarMap[stage]); TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage], *uniformVarMap[stage]); root->traverse(&iter_binding_all); iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.functions.empty()) { - TIntermNode* function = iter_binding_live.functions.back(); - iter_binding_live.functions.pop_back(); - function->traverse(&iter_binding_live); + while (! iter_binding_live.destinations.empty()) { + TIntermNode* destination = iter_binding_live.destinations.back(); + iter_binding_live.destinations.pop_back(); + destination->traverse(&iter_binding_live); } + TNotifyInOutAdaptor inOutNotify(stage, *resolver); TNotifyUniformAdaptor uniformNotify(stage, *resolver); // Resolve current stage input symbol location with previous stage output here, @@ -1194,31 +1569,66 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) { resolver->endResolve(EShLangCount); if (!hadError) { //Resolve uniform location, ubo/ssbo/opaque bindings across stages - TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, infoSink, hadError); + TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError); TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError); - TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, outVarMaps, uniformVarMap, hadError); + TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, + outVarMaps, uniformVarMap, hadError, profile, version); + + TVarLiveVector inVectors[EShLangCount]; + TVarLiveVector outVectors[EShLangCount]; TVarLiveVector uniformVector; + resolver->beginResolve(EShLangCount); for (int stage = EShLangVertex; stage < EShLangCount; stage++) { if (inVarMaps[stage] != nullptr) { inOutResolve.setStage(EShLanguage(stage)); - std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), symbolValidater); - std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutResolve); - std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), symbolValidater); - std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutResolve); + + // copy vars into a sorted list + std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), + [&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); }); + std::sort(inVectors[stage].begin(), inVectors[stage].end(), + [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { + return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); + }); + + std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), + [&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); }); + std::sort(outVectors[stage].begin(), outVectors[stage].end(), + [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { + return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); + }); + + for (auto& var : inVectors[stage]) { symbolValidater(var); } + for (auto& var : inVectors[stage]) { inOutResolve(var); } + for (auto& var : outVectors[stage]) { symbolValidater(var); } + for (auto& var : outVectors[stage]) { inOutResolve(var); } + + // copy results back into maps + std::for_each(inVectors[stage].begin(), inVectors[stage].end(), + [this, stage](TVarLivePair p) { + auto at = inVarMaps[stage]->find(p.first); + if (at != inVarMaps[stage]->end()) + at->second = p.second; + }); + + std::for_each(outVectors[stage].begin(), outVectors[stage].end(), + [this, stage](TVarLivePair p) { + auto at = outVarMaps[stage]->find(p.first); + if (at != outVarMaps[stage]->end()) + at->second = p.second; + }); + } if (uniformVarMap[stage] != nullptr) { uniformResolve.setStage(EShLanguage(stage)); - // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. - std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), - [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); }); + for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); } } } std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); + return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second); }); - std::for_each(uniformVector.begin(), uniformVector.end(), symbolValidater); - std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve); + for (auto& var : uniformVector) { symbolValidater(var); } + for (auto& var : uniformVector) { uniformResolve(var); } std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); }); @@ -1227,14 +1637,18 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) { if (intermediates[stage] != nullptr) { // traverse each stage, set new location to each input/output and unifom symbol, set new binding to // ubo, ssbo and opaque symbols - TVarLiveMap** pUniformVarMap = uniformVarMap; + TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap; std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) { - auto at = pUniformVarMap[stage]->find(p.second.symbol->getName()); - if (at != pUniformVarMap[stage]->end()) + auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName()); + if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){ + int resolvedBinding = at->second.newBinding; at->second = p.second; + if (resolvedBinding > 0) + at->second.newBinding = resolvedBinding; + } }); TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage], - *uniformVarMap[stage]); + *uniformResolve.uniformVarMap[stage]); intermediates[stage]->getTreeRoot()->traverse(&iter_iomap); } } @@ -1246,4 +1660,4 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) { } // end namespace glslang -#endif // GLSLANG_WEB +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE diff --git a/libraries/glslang/glslang/MachineIndependent/iomapper.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.h similarity index 86% rename from libraries/glslang/glslang/MachineIndependent/iomapper.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.h index 684e88d57..07357c2ef 100644 --- a/libraries/glslang/glslang/MachineIndependent/iomapper.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/iomapper.h @@ -33,7 +33,7 @@ // POSSIBILITY OF SUCH DAMAGE. // -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #ifndef _IOMAPPER_INCLUDED #define _IOMAPPER_INCLUDED @@ -52,7 +52,7 @@ namespace glslang { class TIntermediate; struct TVarEntryInfo { - int id; + long long id; TIntermSymbol* symbol; bool live; int newBinding; @@ -87,6 +87,35 @@ struct TVarEntryInfo { return lPoints > rPoints; } }; + + struct TOrderByPriorityAndLive { + // ordering: + // 1) do live variables first + // 2) has both binding and set + // 3) has binding but no set + // 4) has no binding but set + // 5) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (l.live != r.live) + return l.live > r.live; + + if (lPoints != rPoints) + return lPoints > rPoints; + + return l.id < r.id; + } + }; }; // Base class for shared TIoMapResolver services, used by several derivations. @@ -107,8 +136,8 @@ public: void endCollect(EShLanguage) override {} void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} - int getBaseBinding(TResourceType res, unsigned int set) const; - const std::vector& getResourceSetBinding() const; + int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding(EShLanguage stage) const; virtual TResourceType getResourceType(const glslang::TType& type) = 0; bool doAutoBindingMapping() const; bool doAutoLocationMapping() const; @@ -122,13 +151,16 @@ public: int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - void addStage(EShLanguage stage) override { - if (stage < EShLangCount) + void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override { + if (stage < EShLangCount) { stageMask[stage] = true; + stageIntermediates[stage] = &stageIntermediate; + } } uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); TSlotSetMap slots; + bool hasError = false; protected: TDefaultIoResolverBase(TDefaultIoResolverBase&); @@ -138,6 +170,8 @@ protected: int nextInputLocation; int nextOutputLocation; bool stageMask[EShLangCount + 1]; + const TIntermediate* stageIntermediates[EShLangCount]; + // Return descriptor set specific base if there is one, and the generic base otherwise. int selectBaseBinding(int base, int descriptorSetBase) const { return descriptorSetBase != -1 ? descriptorSetBase : base; @@ -185,7 +219,7 @@ protected: } }; -// Defaulf I/O resolver for OpenGL +// Default I/O resolver for OpenGL struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { public: typedef std::map TVarSlotMap; // @@ -237,12 +271,13 @@ typedef std::map TVarLiveMap; // In the future, if the vc++ compiler can handle such a situation, // this part of the code will be removed. struct TVarLivePair : std::pair { - TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair(const std::pair& _Right) : pair(_Right.first, _Right.second) {} TVarLivePair& operator=(const TVarLivePair& _Right) { const_cast(first) = _Right.first; second = _Right.second; return (*this); } + TVarLivePair(const TVarLivePair& src) : pair(src) { } }; typedef std::vector TVarLiveVector; @@ -264,6 +299,8 @@ public: memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1)); + profile = ENoProfile; + version = 0; } virtual ~TGlslIoMapper() { for (size_t stage = 0; stage < EShLangCount; stage++) { @@ -290,10 +327,12 @@ public: *uniformVarMap[EShLangCount]; TIntermediate* intermediates[EShLangCount]; bool hadError = false; + EProfile profile; + int version; }; } // end namespace glslang #endif // _IOMAPPER_INCLUDED -#endif // GLSLANG_WEB +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE diff --git a/libraries/glslang/glslang/MachineIndependent/limits.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/limits.cpp similarity index 96% rename from libraries/glslang/glslang/MachineIndependent/limits.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/limits.cpp index 51d930034..391570579 100644 --- a/libraries/glslang/glslang/MachineIndependent/limits.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/limits.cpp @@ -63,14 +63,14 @@ namespace glslang { class TInductiveTraverser : public TIntermTraverser { public: - TInductiveTraverser(int id, TSymbolTable& st) + TInductiveTraverser(long long id, TSymbolTable& st) : loopId(id), symbolTable(st), bad(false) { } virtual bool visitBinary(TVisit, TIntermBinary* node); virtual bool visitUnary(TVisit, TIntermUnary* node); virtual bool visitAggregate(TVisit, TIntermAggregate* node); - int loopId; // unique ID of the symbol that's the loop inductive variable + long long loopId; // unique ID of the symbol that's the loop inductive variable TSymbolTable& symbolTable; bool bad; TSourceLoc badLoc; @@ -129,7 +129,7 @@ bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* n // // External function to call for loop check. // -void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable) +void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, long long loopId, TSymbolTable& symbolTable) { TInductiveTraverser it(loopId, symbolTable); diff --git a/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/linkValidate.cpp similarity index 72% rename from libraries/glslang/glslang/MachineIndependent/linkValidate.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/linkValidate.cpp index fe51ec93f..9656e2e7e 100644 --- a/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/linkValidate.cpp @@ -48,6 +48,7 @@ #include "localintermediate.h" #include "../Include/InfoSink.h" +#include "SymbolTable.h" namespace glslang { @@ -82,13 +83,63 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message) // void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) { -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) mergeCallGraphs(infoSink, unit); mergeModes(infoSink, unit); mergeTrees(infoSink, unit); #endif } +// +// check that link objects between stages +// +void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit) { + if (unit.treeRoot == nullptr || treeRoot == nullptr) + return; + + // Get the linker-object lists + TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); + TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence(); + + // filter unitLinkerObjects to only contain uniforms + auto end = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(), + [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqUniform && + node->getAsSymbolNode()->getQualifier().storage != EvqBuffer; }); + unitLinkerObjects.resize(end - unitLinkerObjects.begin()); + + // merge uniforms and do error checking + bool mergeExistingOnly = false; + mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly); + mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); +} + +// +// do error checking on the shader boundary in / out vars +// +void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) { + if (unit.treeRoot == nullptr || treeRoot == nullptr) + return; + + // Get copies of the linker-object lists + TIntermSequence linkerObjects = findLinkerObjects()->getSequence(); + TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence(); + + // filter linkerObjects to only contain out variables + auto end = std::remove_if(linkerObjects.begin(), linkerObjects.end(), + [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingOut; }); + linkerObjects.resize(end - linkerObjects.begin()); + + // filter unitLinkerObjects to only contain in variables + auto unitEnd = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(), + [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingIn; }); + unitLinkerObjects.resize(unitEnd - unitLinkerObjects.begin()); + + // do matching and error checking + mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); + + // TODO: final check; make sure that any statically used `in` have matching `out` written to +} + void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit) { if (unit.getNumEntryPoints() > 0) { @@ -104,7 +155,7 @@ void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit) callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #define MERGE_MAX(member) member = std::max(member, unit.member) #define MERGE_TRUE(member) if (unit.member) member = unit.member; @@ -136,9 +187,14 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_MAX(spvVersion.vulkanGlsl); MERGE_MAX(spvVersion.vulkan); MERGE_MAX(spvVersion.openGl); + MERGE_TRUE(spvVersion.vulkanRelaxed); numErrors += unit.getNumErrors(); - numPushConstants += unit.numPushConstants; + // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant + // is the same for all units. + if (numPushConstants > 1 || unit.numPushConstants > 1) + error(infoSink, "Only one push_constant block is allowed per stage"); + numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1); if (unit.invocations != TQualifier::layoutNotSet) { if (invocations == TQualifier::layoutNotSet) @@ -149,7 +205,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) if (vertices == TQualifier::layoutNotSet) vertices = unit.vertices; - else if (vertices != unit.vertices) { + else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) { if (language == EShLangGeometry || language == EShLangMeshNV) error(infoSink, "Contradictory layout max_vertices values"); else if (language == EShLangTessControl) @@ -168,12 +224,12 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) if (inputPrimitive == ElgNone) inputPrimitive = unit.inputPrimitive; - else if (inputPrimitive != unit.inputPrimitive) + else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive) error(infoSink, "Contradictory input layout primitives"); if (outputPrimitive == ElgNone) outputPrimitive = unit.outputPrimitive; - else if (outputPrimitive != unit.outputPrimitive) + else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive) error(infoSink, "Contradictory output layout primitives"); if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) @@ -192,12 +248,14 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_TRUE(pointMode); for (int i = 0; i < 3; ++i) { - if (!localSizeNotDefault[i] && unit.localSizeNotDefault[i]) { - localSize[i] = unit.localSize[i]; - localSizeNotDefault[i] = true; + if (unit.localSizeNotDefault[i]) { + if (!localSizeNotDefault[i]) { + localSize[i] = unit.localSize[i]; + localSizeNotDefault[i] = true; + } + else if (localSize[i] != unit.localSize[i]) + error(infoSink, "Contradictory local size"); } - else if (localSize[i] != unit.localSize[i]) - error(infoSink, "Contradictory local size"); if (localSizeSpecId[i] == TQualifier::layoutNotSet) localSizeSpecId[i] = unit.localSizeSpecId[i]; @@ -258,6 +316,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_TRUE(useUnknownFormat); MERGE_TRUE(hlslOffsets); MERGE_TRUE(useStorageBuffer); + MERGE_TRUE(invariantAll); MERGE_TRUE(hlslIoMapping); // TODO: sourceFile @@ -286,7 +345,7 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) } // Getting this far means we have two existing trees to merge... - numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks; + numShaderRecordBlocks += unit.numShaderRecordBlocks; numTaskNVBlocks += unit.numTaskNVBlocks; // Get the top-level globals of each unit @@ -299,40 +358,57 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) // Map by global name to unique ID to rationalize the same object having // differing IDs in different trees. - TMap idMap; - int maxId; - seedIdMap(idMap, maxId); - remapIds(idMap, maxId + 1, unit); + TIdMaps idMaps; + long long idShift; + seedIdMap(idMaps, idShift); + remapIds(idMaps, idShift + 1, unit); mergeBodies(infoSink, globals, unitGlobals); - mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); + bool mergeExistingOnly = false; + mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly); + mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); } #endif +static const TString& getNameForIdMap(TIntermSymbol* symbol) +{ + TShaderInterface si = symbol->getType().getShaderInterface(); + if (si == EsiNone) + return symbol->getName(); + else + return symbol->getType().getTypeName(); +} + + + // Traverser that seeds an ID map with all built-ins, and tracks the -// maximum ID used. +// maximum ID used, currently using (maximum ID + 1) as new symbol id shift seed. +// Level id will keep same after shifting. // (It would be nice to put this in a function, but that causes warnings // on having no bodies for the copy-constructor/operator=.) class TBuiltInIdTraverser : public TIntermTraverser { public: - TBuiltInIdTraverser(TMap& idMap) : idMap(idMap), maxId(0) { } + TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), idShift(0) { } // If it's a built in, add it to the map. - // Track the max ID. virtual void visitSymbol(TIntermSymbol* symbol) { const TQualifier& qualifier = symbol->getType().getQualifier(); - if (qualifier.builtIn != EbvNone) - idMap[symbol->getName()] = symbol->getId(); - maxId = std::max(maxId, symbol->getId()); + if (qualifier.builtIn != EbvNone) { + TShaderInterface si = symbol->getType().getShaderInterface(); + idMaps[si][getNameForIdMap(symbol)] = symbol->getId(); + } + idShift = (symbol->getId() & ~TSymbolTable::uniqueIdMask) | + std::max(idShift & TSymbolTable::uniqueIdMask, + symbol->getId() & TSymbolTable::uniqueIdMask); } - int getMaxId() const { return maxId; } + long long getIdShift() const { return idShift; } protected: TBuiltInIdTraverser(TBuiltInIdTraverser&); TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&); - TMap& idMap; - int maxId; + TIdMaps& idMaps; + long long idShift; }; // Traverser that seeds an ID map with non-builtins. @@ -340,31 +416,33 @@ protected: // on having no bodies for the copy-constructor/operator=.) class TUserIdTraverser : public TIntermTraverser { public: - TUserIdTraverser(TMap& idMap) : idMap(idMap) { } + TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { } // If its a non-built-in global, add it to the map. virtual void visitSymbol(TIntermSymbol* symbol) { const TQualifier& qualifier = symbol->getType().getQualifier(); - if (qualifier.builtIn == EbvNone) - idMap[symbol->getName()] = symbol->getId(); + if (qualifier.builtIn == EbvNone) { + TShaderInterface si = symbol->getType().getShaderInterface(); + idMaps[si][getNameForIdMap(symbol)] = symbol->getId(); + } } protected: TUserIdTraverser(TUserIdTraverser&); TUserIdTraverser& operator=(TUserIdTraverser&); - TMap& idMap; // over biggest id + TIdMaps& idMaps; // over biggest id }; // Initialize the the ID map with what we know of 'this' AST. -void TIntermediate::seedIdMap(TMap& idMap, int& maxId) +void TIntermediate::seedIdMap(TIdMaps& idMaps, long long& idShift) { // all built-ins everywhere need to align on IDs and contribute to the max ID - TBuiltInIdTraverser builtInIdTraverser(idMap); + TBuiltInIdTraverser builtInIdTraverser(idMaps); treeRoot->traverse(&builtInIdTraverser); - maxId = builtInIdTraverser.getMaxId(); + idShift = builtInIdTraverser.getIdShift() & TSymbolTable::uniqueIdMask; // user variables in the linker object list need to align on ids - TUserIdTraverser userIdTraverser(idMap); + TUserIdTraverser userIdTraverser(idMaps); findLinkerObjects()->traverse(&userIdTraverser); } @@ -373,7 +451,7 @@ void TIntermediate::seedIdMap(TMap& idMap, int& maxId) // on having no bodies for the copy-constructor/operator=.) class TRemapIdTraverser : public TIntermTraverser { public: - TRemapIdTraverser(const TMap& idMap, int idShift) : idMap(idMap), idShift(idShift) { } + TRemapIdTraverser(const TIdMaps& idMaps, long long idShift) : idMaps(idMaps), idShift(idShift) { } // Do the mapping: // - if the same symbol, adopt the 'this' ID // - otherwise, ensure a unique ID by shifting to a new space @@ -382,9 +460,12 @@ public: const TQualifier& qualifier = symbol->getType().getQualifier(); bool remapped = false; if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) { - auto it = idMap.find(symbol->getName()); - if (it != idMap.end()) { - symbol->changeId(it->second); + TShaderInterface si = symbol->getType().getShaderInterface(); + auto it = idMaps[si].find(getNameForIdMap(symbol)); + if (it != idMaps[si].end()) { + uint64_t id = (symbol->getId() & ~TSymbolTable::uniqueIdMask) | + (it->second & TSymbolTable::uniqueIdMask); + symbol->changeId(id); remapped = true; } } @@ -394,14 +475,14 @@ public: protected: TRemapIdTraverser(TRemapIdTraverser&); TRemapIdTraverser& operator=(TRemapIdTraverser&); - const TMap& idMap; - int idShift; + const TIdMaps& idMaps; + long long idShift; }; -void TIntermediate::remapIds(const TMap& idMap, int idShift, TIntermediate& unit) +void TIntermediate::remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate& unit) { // Remap all IDs to either share or be unique, as dictated by the idMap and idShift. - TRemapIdTraverser idTraverser(idMap, idShift); + TRemapIdTraverser idTraverser(idMaps, idShift); unit.getTreeRoot()->traverse(&idTraverser); } @@ -429,11 +510,193 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1); } +static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) { + return // 1) same stage and same shader interface + (stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) || + // 2) accross stages and both are uniform or buffer + (symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) || + (symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) || + // 3) in/out matched across stage boundary + (stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) || + (unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut); +} + +// +// Global Unfiform block stores any default uniforms (i.e. uniforms without a block) +// If two linked stages declare the same member, they are meant to be the same uniform +// and need to be in the same block +// merge the members of different stages to allow them to be linked properly +// as a single block +// +void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly) +{ + TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); + TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence(); + + // build lists of default blocks from the intermediates + TIntermSequence defaultBlocks; + TIntermSequence unitDefaultBlocks; + + auto filter = [](TIntermSequence& list, TIntermNode* node) { + if (node->getAsSymbolNode()->getQualifier().defaultBlock) { + list.push_back(node); + } + }; + + std::for_each(linkerObjects.begin(), linkerObjects.end(), + [&defaultBlocks, &filter](TIntermNode* node) { + filter(defaultBlocks, node); + }); + std::for_each(unitLinkerObjects.begin(), unitLinkerObjects.end(), + [&unitDefaultBlocks, &filter](TIntermNode* node) { + filter(unitDefaultBlocks, node); + }); + + auto itUnitBlock = unitDefaultBlocks.begin(); + for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) { + + bool add = !mergeExistingOnly; + auto itBlock = defaultBlocks.begin(); + + for (; itBlock != defaultBlocks.end(); itBlock++) { + TIntermSymbol* block = (*itBlock)->getAsSymbolNode(); + TIntermSymbol* unitBlock = (*itUnitBlock)->getAsSymbolNode(); + + assert(block && unitBlock); + + // if the two default blocks match, then merge their definitions + if (block->getType().getTypeName() == unitBlock->getType().getTypeName() && + block->getQualifier().storage == unitBlock->getQualifier().storage) { + add = false; + mergeBlockDefinitions(infoSink, block, unitBlock, &unit); + } + } + if (add) { + // push back on original list; won't change the size of the list we're iterating over + linkerObjects.push_back(*itUnitBlock); + } + } +} + +void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) { + if (block->getType() == unitBlock->getType()) { + return; + } + + if (block->getType().getTypeName() != unitBlock->getType().getTypeName() || + block->getType().getBasicType() != unitBlock->getType().getBasicType() || + block->getQualifier().storage != unitBlock->getQualifier().storage || + block->getQualifier().layoutSet != unitBlock->getQualifier().layoutSet) { + // different block names likely means different blocks + return; + } + + // merge the struct + // order of declarations doesn't matter and they matched based on member name + TTypeList* memberList = block->getType().getWritableStruct(); + TTypeList* unitMemberList = unitBlock->getType().getWritableStruct(); + + // keep track of which members have changed position + // so we don't have to search the array again + std::map memberIndexUpdates; + + size_t memberListStartSize = memberList->size(); + for (unsigned int i = 0; i < unitMemberList->size(); ++i) { + bool merge = true; + for (unsigned int j = 0; j < memberListStartSize; ++j) { + if ((*memberList)[j].type->getFieldName() == (*unitMemberList)[i].type->getFieldName()) { + merge = false; + const TType* memberType = (*memberList)[j].type; + const TType* unitMemberType = (*unitMemberList)[i].type; + + // compare types + // don't need as many checks as when merging symbols, since + // initializers and most qualifiers are stripped when the member is moved into the block + if ((*memberType) != (*unitMemberType)) { + error(infoSink, "Types must match:"); + infoSink.info << " " << memberType->getFieldName() << ": "; + infoSink.info << "\"" << memberType->getCompleteString() << "\" versus "; + infoSink.info << "\"" << unitMemberType->getCompleteString() << "\"\n"; + } + + memberIndexUpdates[i] = j; + } + } + if (merge) { + memberList->push_back((*unitMemberList)[i]); + memberIndexUpdates[i] = (unsigned int)memberList->size() - 1; + } + } + + TType unitType; + unitType.shallowCopy(unitBlock->getType()); + + // update symbol node in unit tree, + // and other nodes that may reference it + class TMergeBlockTraverser : public TIntermTraverser { + public: + TMergeBlockTraverser(const glslang::TType &type, const glslang::TType& unitType, + glslang::TIntermediate& unit, + const std::map& memberIdxUpdates) : + newType(type), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates) + { } + virtual ~TMergeBlockTraverser() { } + + const glslang::TType& newType; // type with modifications + const glslang::TType& unitType; // copy of original type + glslang::TIntermediate& unit; // intermediate that is being updated + const std::map& memberIndexUpdates; + + virtual void visitSymbol(TIntermSymbol* symbol) + { + glslang::TType& symType = symbol->getWritableType(); + + if (symType == unitType) { + // each symbol node has a local copy of the unitType + // if merging involves changing properties that aren't shared objects + // they should be updated in all instances + + // e.g. the struct list is a ptr to an object, so it can be updated + // once, outside the traverser + //*symType.getWritableStruct() = *newType.getStruct(); + } + + } + + virtual bool visitBinary(TVisit, glslang::TIntermBinary* node) + { + if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == unitType) { + // this is a dereference to a member of the block since the + // member list changed, need to update this to point to the + // right index + assert(node->getRight()->getAsConstantUnion()); + + glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion(); + unsigned int memberIdx = constNode->getConstArray()[0].getUConst(); + unsigned int newIdx = memberIndexUpdates.at(memberIdx); + TIntermTyped* newConstNode = unit.addConstantUnion(newIdx, node->getRight()->getLoc()); + + node->setRight(newConstNode); + delete constNode; + + return true; + } + return true; + } + } finalLinkTraverser(block->getType(), unitType, *unit, memberIndexUpdates); + + // update the tree to use the new type + unit->getTreeRoot()->traverse(&finalLinkTraverser); + + // update the member list + (*unitMemberList) = (*memberList); +} + // // Merge the linker objects from unitLinkerObjects into linkerObjects. // Duplication is expected and filtered out, but contradictions are an error. // -void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects) +void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage unitStage) { // Error check and merge the linker objects (duplicates should not be created) std::size_t initialNumLinkerObjects = linkerObjects.size(); @@ -443,7 +706,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); assert(symbol && unitSymbol); - if (symbol->getName() == unitSymbol->getName()) { + + bool isSameSymbol = false; + // If they are both blocks in the same shader interface, + // match by the block-name, not the identifier name. + if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) { + if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) { + isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName(); + } + } + else if (symbol->getName() == unitSymbol->getName()) + isSameSymbol = true; + + if (isSameSymbol) { // filter out copy merge = false; @@ -456,15 +731,54 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding()) symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding; + // Similarly for location + if (!symbol->getQualifier().hasLocation() && unitSymbol->getQualifier().hasLocation()) { + symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation; + } + // Update implicit array sizes mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType()); // Check for consistent types/qualification/initializers etc. - mergeErrorCheck(infoSink, *symbol, *unitSymbol, false); + mergeErrorCheck(infoSink, *symbol, *unitSymbol, unitStage); + } + // If different symbols, verify they arn't push_constant since there can only be one per stage + else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage) + error(infoSink, "Only one push_constant block is allowed per stage"); + } + if (merge) { + linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); + + // for anonymous blocks, check that their members don't conflict with other names + if (unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getBasicType() == EbtBlock && + IsAnonymous(unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getName())) { + for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { + TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); + TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); + assert(symbol && unitSymbol); + + auto checkName = [this, unitSymbol, &infoSink](const TString& name) { + for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) { + if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) { + error(infoSink, "Anonymous member name used for global variable or other anonymous member: "); + infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n"; + } + } + }; + + if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) { + checkName(symbol->getName()); + + // check members of other anonymous blocks + if (symbol->getBasicType() == EbtBlock && IsAnonymous(symbol->getName())) { + for (unsigned int i = 0; i < symbol->getType().getStruct()->size(); ++i) { + checkName((*symbol->getType().getStruct())[i].type->getFieldName()); + } + } + } + } } } - if (merge) - linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); } } @@ -496,32 +810,97 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType) // // This function only does one of intra- or cross-stage matching per call. // -void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage) +void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, EShLanguage unitStage) { -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) + bool crossStage = getStage() != unitStage; bool writeTypeComparison = false; // Types have to match - if (symbol.getType() != unitSymbol.getType()) { + { // but, we make an exception if one is an implicit array and the other is sized - if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() && - symbol.getType().sameElementType(unitSymbol.getType()) && - (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) { - error(infoSink, "Types must match:"); + // or if the array sizes differ because of the extra array dimension on some in/out boundaries + bool arraysMatch = false; + if (isIoResizeArray(symbol.getType(), getStage()) || isIoResizeArray(unitSymbol.getType(), unitStage)) { + // if the arrays have an extra dimension because of the stage. + // compare dimensions while ignoring the outer dimension + unsigned int firstDim = isIoResizeArray(symbol.getType(), getStage()) ? 1 : 0; + unsigned int numDim = symbol.getArraySizes() + ? symbol.getArraySizes()->getNumDims() : 0; + unsigned int unitFirstDim = isIoResizeArray(unitSymbol.getType(), unitStage) ? 1 : 0; + unsigned int unitNumDim = unitSymbol.getArraySizes() + ? unitSymbol.getArraySizes()->getNumDims() : 0; + arraysMatch = (numDim - firstDim) == (unitNumDim - unitFirstDim); + // check that array sizes match as well + for (unsigned int i = 0; i < (numDim - firstDim) && arraysMatch; i++) { + if (symbol.getArraySizes()->getDimSize(firstDim + i) != + unitSymbol.getArraySizes()->getDimSize(unitFirstDim + i)) { + arraysMatch = false; + break; + } + } + } + else { + arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) || + (symbol.getType().isArray() && unitSymbol.getType().isArray() && + (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray())); + } + + if (!symbol.getType().sameElementType(unitSymbol.getType()) || + !symbol.getType().sameTypeParameters(unitSymbol.getType()) || + !arraysMatch ) { writeTypeComparison = true; + error(infoSink, "Types must match:"); } } - // Qualifiers have to (almost) match + // Interface block member-wise layout qualifiers have to match + if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock && + symbol.getType().getStruct() && unitSymbol.getType().getStruct() && + symbol.getType().sameStructType(unitSymbol.getType())) { + for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) { + const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier(); + const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier(); + if (qualifier.layoutMatrix != unitQualifier.layoutMatrix || + qualifier.layoutOffset != unitQualifier.layoutOffset || + qualifier.layoutAlign != unitQualifier.layoutAlign || + qualifier.layoutLocation != unitQualifier.layoutLocation || + qualifier.layoutComponent != unitQualifier.layoutComponent) { + error(infoSink, "Interface block member layout qualifiers must match:"); + writeTypeComparison = true; + } + } + } + bool isInOut = crossStage && + ((symbol.getQualifier().storage == EvqVaryingIn && unitSymbol.getQualifier().storage == EvqVaryingOut) || + (symbol.getQualifier().storage == EvqVaryingOut && unitSymbol.getQualifier().storage == EvqVaryingIn)); + + // Qualifiers have to (almost) match // Storage... - if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { + if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { error(infoSink, "Storage qualifiers must match:"); writeTypeComparison = true; } + // Uniform and buffer blocks must either both have an instance name, or + // must both be anonymous. The names don't need to match though. + if (symbol.getQualifier().isUniformOrBuffer() && + (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) { + error(infoSink, "Matched Uniform or Storage blocks must all be anonymous," + " or all be named:"); + writeTypeComparison = true; + } + + if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage && + (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) || + (!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) { + warn(infoSink, "Matched shader interfaces are using different instance names."); + writeTypeComparison = true; + } + // Precision... - if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { + if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { error(infoSink, "Precision qualifiers must match:"); writeTypeComparison = true; } @@ -539,12 +918,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy } // Auxiliary and interpolation... - if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || + // "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ. + // These mismatches are allowed between any pair of stages ... + // those provided in the fragment shader supersede those provided in previous stages." + if (!crossStage && + (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth || symbol.getQualifier().flat != unitSymbol.getQualifier().flat || symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() || symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() || - symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective()) { + symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) { error(infoSink, "Interpolation and auxiliary storage qualifiers must match:"); writeTypeComparison = true; } @@ -555,6 +938,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent || symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent || symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent || + symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent || symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate || symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || @@ -589,12 +973,35 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy } } - if (writeTypeComparison) - infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" << - unitSymbol.getType().getCompleteString() << "\"\n"; + if (writeTypeComparison) { + infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus "; + if (symbol.getName() != unitSymbol.getName()) + infoSink.info << unitSymbol.getName() << ": "; + + infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n"; + } #endif } +void TIntermediate::sharedBlockCheck(TInfoSink& infoSink) +{ + bool has_shared_block = false; + bool has_shared_non_block = false; + TIntermSequence& linkObjects = findLinkerObjects()->getSequence(); + for (size_t i = 0; i < linkObjects.size(); ++i) { + const TType& type = linkObjects[i]->getAsTyped()->getType(); + const TQualifier& qualifier = type.getQualifier(); + if (qualifier.storage == glslang::EvqShared) { + if (type.getBasicType() == glslang::EbtBlock) + has_shared_block = true; + else + has_shared_non_block = true; + } + } + if (has_shared_block && has_shared_non_block) + error(infoSink, "cannot mix use of shared variables inside and outside blocks"); +} + // // Do final link-time error checking of a complete (merged) intermediate representation. // (Much error checking was done during merging). @@ -680,10 +1087,10 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) { + if (xfbBuffers[b].stride > (unsigned int)(4 * resources->maxTransformFeedbackInterleavedComponents)) { error(infoSink, "xfb_stride is too large:"); infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n"; + infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources->maxTransformFeedbackInterleavedComponents << "\n"; } } @@ -720,14 +1127,15 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) error(infoSink, "post_depth_coverage requires early_fragment_tests"); break; case EShLangCompute: + sharedBlockCheck(infoSink); break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: - if (numShaderRecordNVBlocks > 1) + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: + if (numShaderRecordBlocks > 1) error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage"); break; case EShLangMeshNV: @@ -752,6 +1160,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) case EShLangTaskNV: if (numTaskNVBlocks > 1) error(infoSink, "Only one taskNV interface block is allowed per shader"); + sharedBlockCheck(infoSink); break; default: error(infoSink, "Unknown Stage."); @@ -999,8 +1408,8 @@ bool TIntermediate::userOutputUsed() const return found; } -// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions -// as the accumulation is done. +// Accumulate locations used for inputs, outputs, and uniforms, payload and callable data +// and check for collisions as the accumulation is done. // // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. // @@ -1012,6 +1421,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ typeCollision = false; int set; + int setRT; if (qualifier.isPipeInput()) set = 0; else if (qualifier.isPipeOutput()) @@ -1020,11 +1430,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ set = 2; else if (qualifier.storage == EvqBuffer) set = 3; + else if (qualifier.isAnyPayload()) + setRT = 0; + else if (qualifier.isAnyCallable()) + setRT = 1; else return -1; int size; - if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) { + if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) { + size = 1; + } else if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) { if (type.isSizedArray()) size = type.getCumulativeArraySize(); else @@ -1052,10 +1468,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ // (A vertex shader input will show using only one location, even for a dvec3/4.) // // So, for the case of dvec3, we need two independent ioRanges. - + // + // For raytracing IO (payloads and callabledata) each declaration occupies a single + // slot irrespective of type. int collision = -1; // no collision #ifndef GLSLANG_WEB - if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 && + if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) { + TRange range(qualifier.layoutLocation, qualifier.layoutLocation); + collision = checkLocationRT(setRT, qualifier.layoutLocation); + if (collision < 0) + usedIoRT[setRT].push_back(range); + } else if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 && (qualifier.isPipeInput() || qualifier.isPipeOutput())) { // Dealing with dvec3 in/out split across two locations. // Need two io-ranges. @@ -1131,6 +1554,16 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp return -1; // no collision } +int TIntermediate::checkLocationRT(int set, int location) { + TRange range(location, location); + for (size_t r = 0; r < usedIoRT[set].size(); ++r) { + if (range.overlap(usedIoRT[set][r])) { + return range.start; + } + } + return -1; // no collision +} + // Accumulate bindings and offsets, and check for collisions // as the accumulation is done. // @@ -1306,9 +1739,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains // that component's size. Aggregate types are flattened down to the component // level to get this sequence of components." - if (type.isArray()) { + if (type.isSizedArray()) { // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - assert(type.isSizedArray()); + // Unsized array use to xfb should be a compile error. TType elementType(type, 0); return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType); } @@ -1494,7 +1927,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T RoundToPow2(size, alignment); stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected) // uses the assumption for rule 10 in the comment above - size = stride * type.getOuterArraySize(); + // use one element to represent the last member of SSBO which is unsized array + int arraySize = (type.isUnsizedArray() && (type.getOuterArraySize() == 0)) ? 1 : type.getOuterArraySize(); + size = stride * arraySize; return alignment; } @@ -1720,4 +2155,17 @@ int TIntermediate::computeBufferReferenceTypeSize(const TType& type) return size; } +#ifndef GLSLANG_WEB +bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) { + return type.isArray() && + ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || + (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && + ! type.getQualifier().patch) || + (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && + type.getQualifier().pervertexNV) || + (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut && + !type.getQualifier().perTaskNV)); +} +#endif // not GLSLANG_WEB + } // end namespace glslang diff --git a/libraries/glslang/glslang/MachineIndependent/localintermediate.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/localintermediate.h similarity index 77% rename from libraries/glslang/glslang/MachineIndependent/localintermediate.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/localintermediate.h index cb172e5e9..6aa9399dc 100644 --- a/libraries/glslang/glslang/MachineIndependent/localintermediate.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/localintermediate.h @@ -162,7 +162,10 @@ struct TXfbBuffer { #endif // Track a set of strings describing how the module was processed. -// Using the form: +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: // process arg0 arg1 arg2 ... // process arg0 arg1 arg2 ... // where everything is textual, and there can be zero or more arguments @@ -222,6 +225,57 @@ enum ComputeDerivativeMode { LayoutDerivativeGroupLinear, // derivative_group_linearNV }; +class TIdMaps { +public: + TMap& operator[](long long i) { return maps[i]; } + const TMap& operator[](long long i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + +class TNumericFeatures { +public: + TNumericFeatures() : features(0) { } + TNumericFeatures(const TNumericFeatures&) = delete; + TNumericFeatures& operator=(const TNumericFeatures&) = delete; + typedef enum : unsigned int { + shader_explicit_arithmetic_types = 1 << 0, + shader_explicit_arithmetic_types_int8 = 1 << 1, + shader_explicit_arithmetic_types_int16 = 1 << 2, + shader_explicit_arithmetic_types_int32 = 1 << 3, + shader_explicit_arithmetic_types_int64 = 1 << 4, + shader_explicit_arithmetic_types_float16 = 1 << 5, + shader_explicit_arithmetic_types_float32 = 1 << 6, + shader_explicit_arithmetic_types_float64 = 1 << 7, + shader_implicit_conversions = 1 << 8, + gpu_shader_fp64 = 1 << 9, + gpu_shader_int16 = 1 << 10, + gpu_shader_half_float = 1 << 11, + } feature; + void insert(feature f) { features |= f; } + void erase(feature f) { features &= ~f; } + bool contains(feature f) const { return (features & f) != 0; } +private: + unsigned int features; +}; + +// MustBeAssigned wraps a T, asserting that it has been assigned with +// operator =() before attempting to read with operator T() or operator ->(). +// Used to catch cases where fields are read before they have been assigned. +template +class MustBeAssigned +{ +public: + MustBeAssigned() = default; + MustBeAssigned(const T& v) : value(v) {} + operator const T&() const { assert(isSet); return value; } + const T* operator ->() const { assert(isSet); return &value; } + MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } +private: + T value; + bool isSet = false; +}; + // // Set of helper functions to help parse and build the tree. // @@ -229,12 +283,23 @@ class TIntermediate { public: explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), - profile(p), version(v), treeRoot(0), +#ifndef GLSLANG_ANGLE + profile(p), version(v), +#endif + treeRoot(0), + resources(TBuiltInResource{}), numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), invertY(false), useStorageBuffer(false), + invariantAll(false), nanMinMaxClamp(false), - depthReplacing(false) + depthReplacing(false), + uniqueId(0), + globalUniformBlockName(""), + atomicCounterBlockName(""), + globalUniformBlockSet(TQualifier::layoutSetEnd), + globalUniformBlockBinding(TQualifier::layoutBindingEnd), + atomicCounterBlockSet(TQualifier::layoutSetEnd) #ifndef GLSLANG_WEB , implicitThisName("@this"), implicitCounterName("@count"), @@ -244,15 +309,16 @@ public: inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false), vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), - postDepthCoverage(false), depthLayout(EldNone), + postDepthCoverage(false), depthLayout(EldNone), hlslFunctionality1(false), blendEquations(0), xfbMode(false), multiStream(false), layoutOverrideCoverage(false), geoPassthroughEXT(false), - numShaderRecordNVBlocks(0), + numShaderRecordBlocks(0), computeDerivativeMode(LayoutDerivativeNone), primitives(TQualifier::layoutNotSet), numTaskNVBlocks(0), + layoutPrimitiveCulling(false), autoMapBindings(false), autoMapLocations(false), flattenUniformArrays(false), @@ -263,7 +329,10 @@ public: textureSamplerTransformMode(EShTexSampTransKeep), needToLegalize(false), binaryDoubleOutput(false), + subgroupUniformControlFlow(false), usePhysicalStorageBuffer(false), + spirvRequirement(nullptr), + spirvExecutionMode(nullptr), uniformLocationBase(0) #endif { @@ -282,9 +351,20 @@ public: #endif } - void setVersion(int v) { version = v; } + void setVersion(int v) + { +#ifndef GLSLANG_ANGLE + version = v; +#endif + } + void setProfile(EProfile p) + { +#ifndef GLSLANG_ANGLE + profile = p; +#endif + } + int getVersion() const { return version; } - void setProfile(EProfile p) { profile = p; } EProfile getProfile() const { return profile; } void setSpv(const SpvVersion& s) { @@ -332,6 +412,9 @@ public: case EShTargetVulkan_1_1: processes.addProcess("target-env vulkan1.1"); break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; default: processes.addProcess("target-env vulkanUnknown"); break; @@ -343,6 +426,9 @@ public: EShLanguage getStage() const { return language; } void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } const std::set& getRequestedExtensions() const { return requestedExtensions; } + bool isRayTracingStage() const { + return language >= EShLangRayGen && language <= EShLangCallableNV; + } void setTreeRoot(TIntermNode* r) { treeRoot = r; } TIntermNode* getTreeRoot() const { return treeRoot; } @@ -351,6 +437,7 @@ public: int getNumErrors() const { return numErrors; } void addPushConstantCount() { ++numPushConstants; } void setLimits(const TBuiltInResource& r) { resources = r; } + const TBuiltInResource& getLimits() const { return resources; } bool postProcess(TIntermNode*, EShLanguage); void removeTree(); @@ -377,7 +464,7 @@ public: void setSource(EShSource s) { source = s; } EShSource getSource() const { return source; } #else - void setSource(EShSource s) { assert(s == EShSourceGlsl); } + void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; } EShSource getSource() const { return EShSourceGlsl; } #endif @@ -388,15 +475,15 @@ public: TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); TIntermSymbol* addSymbol(const TIntermSymbol&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + std::tuple addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); - TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&); TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; bool isIntegralPromotion(TBasicType from, TBasicType to) const; @@ -410,7 +497,7 @@ public: TIntermAggregate* makeAggregate(TIntermNode* node); TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); TIntermAggregate* makeAggregate(const TSourceLoc&); - TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&); bool areAllChildConst(TIntermAggregate* aggrNode); TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); @@ -439,10 +526,11 @@ public: // Low level functions to add nodes (no conversions or other higher level transformations) // If a type is provided, the node's type will be set to it. - TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; - TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; - TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; - TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, + const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const; // Constant folding (in Constant.cpp) TIntermTyped* fold(TIntermAggregate* aggrNode); @@ -451,18 +539,30 @@ public: TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); // Tree ops - static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false); // Linkage related void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + TIntermAggregate* findLinkerObjects() const; - void setUseStorageBuffer() - { - useStorageBuffer = true; - processes.addProcess("use-storage-buffer"); - } + void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); } + const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); } + void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; } + unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; } + void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; } + unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; } + + void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); } + const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); } + void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; } + unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; } + + + void setUseStorageBuffer() { useStorageBuffer = true; } bool usingStorageBuffer() const { return useStorageBuffer; } + void setInvariantAll() { invariantAll = true; } + bool isInvariantAll() const { return invariantAll; } void setDepthReplacing() { depthReplacing = true; } bool isDepthReplacing() const { return depthReplacing; } bool setLocalSize(int dim, int size) @@ -474,6 +574,11 @@ public: return true; } unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool isLocalSizeSet() const + { + // Return true if any component has been set (i.e. any component is not default). + return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2]; + } bool setLocalSizeSpecId(int dim, int id) { if (localSizeSpecId[dim] != TQualifier::layoutNotSet) @@ -482,6 +587,13 @@ public: return true; } int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } + bool isLocalSizeSpecialized() const + { + // Return true if any component has been specialized. + return localSizeSpecId[0] != TQualifier::layoutNotSet || + localSizeSpecId[1] != TQualifier::layoutNotSet || + localSizeSpecId[2] != TQualifier::layoutNotSet; + } #ifdef GLSLANG_WEB void output(TInfoSink&, bool tree) { } @@ -500,7 +612,7 @@ public: bool getAutoMapBindings() const { return false; } bool getAutoMapLocations() const { return false; } int getNumPushConstants() const { return 0; } - void addShaderRecordNVCount() { } + void addShaderRecordCount() { } void addTaskNVCount() { } void setUseVulkanMemoryModel() { } bool usingVulkanMemoryModel() const { return false; } @@ -580,7 +692,7 @@ public: processes.addProcess("flatten-uniform-arrays"); } bool getFlattenUniformArrays() const { return flattenUniformArrays; } -#endif +#endif void setNoStorageFormat(bool b) { useUnknownFormat = b; @@ -617,7 +729,7 @@ public: void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } int getNumPushConstants() const { return numPushConstants; } - void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } void addTaskNVCount() { ++numTaskNVBlocks; } bool setInvocations(int i) @@ -720,6 +832,8 @@ public: void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; } + bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; } bool setPrimitives(int m) { if (primitives != TQualifier::layoutNotSet) @@ -756,8 +870,34 @@ public: void setBinaryDoubleOutput() { binaryDoubleOutput = true; } bool getBinaryDoubleOutput() { return binaryDoubleOutput; } + + void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; } + bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; } + + // GL_EXT_spirv_intrinsics + void insertSpirvRequirement(const TSpirvRequirement* spirvReq); + bool hasSpirvRequirement() const { return spirvRequirement != nullptr; } + const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; } + void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr); + void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args); + bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; } + const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; } #endif // GLSLANG_WEB + void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) + { + std::string name(nameStr); + blockBackingOverrides[name] = backing; + } + TBlockStorageClass getBlockStorageOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = blockBackingOverrides.find(name); + if (pos == blockBackingOverrides.end()) + return EbsNone; + else + return pos->second; + } #ifdef ENABLE_HLSL void setHlslFunctionality1() { hlslFunctionality1 = true; } bool getHlslFunctionality1() const { return hlslFunctionality1; } @@ -781,10 +921,27 @@ public: bool usingHlslIoMapping() { return false; } #endif + bool usingScalarBlockLayout() const { + for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) { + if (*extIt == E_GL_EXT_scalar_block_layout) + return true; + } + return false; + } + + bool IsRequestedExtension(const char* extension) const + { + return (requestedExtensions.find(extension) != requestedExtensions.end()); + } + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); void merge(TInfoSink&, TIntermediate&); void finalCheck(TInfoSink&, bool keepUncalled); + void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly); + void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit); + void checkStageIO(TInfoSink&, TIntermediate&); + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; @@ -793,6 +950,7 @@ public: int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int checkLocationRT(int set, int location); int addUsedOffsets(int binding, int offset, int numOffsets); bool addUsedConstantId(int id); static int computeTypeLocationSize(const TType&, EShLanguage); @@ -807,6 +965,8 @@ public: static int getOffset(const TType& type, int index); static int getBlockSize(const TType& blockType); static int computeBufferReferenceTypeSize(const TType&); + static bool isIoResizeArray(const TType& type, EShLanguage language); + bool promote(TIntermOperator*); void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } bool getNanMinMaxClamp() const { return nanMinMaxClamp; } @@ -825,47 +985,53 @@ public: void addProcess(const std::string& process) { processes.addProcess(process); } void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } const std::vector& getProcesses() const { return processes.getProcesses(); } + unsigned long long getUniqueId() const { return uniqueId; } + void setUniqueId(unsigned long long id) { uniqueId = id; } // Certain explicit conversions are allowed conditionally #ifdef GLSLANG_WEB bool getArithemeticInt8Enabled() const { return false; } bool getArithemeticInt16Enabled() const { return false; } bool getArithemeticFloat16Enabled() const { return false; } + void updateNumericFeature(TNumericFeatures::feature f, bool on) { } #else bool getArithemeticInt8Enabled() const { - return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); } bool getArithemeticInt16Enabled() const { - return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_AMD_gpu_shader_int16) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::gpu_shader_int16) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); } bool getArithemeticFloat16Enabled() const { - return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionRequested(E_GL_AMD_gpu_shader_half_float) || - extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || + numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || + numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); } + void updateNumericFeature(TNumericFeatures::feature f, bool on) + { on ? numericFeatures.insert(f) : numericFeatures.erase(f); } #endif protected: - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); void error(TInfoSink& infoSink, const char*); void warn(TInfoSink& infoSink, const char*); void mergeCallGraphs(TInfoSink&, TIntermediate&); void mergeModes(TInfoSink&, TIntermediate&); void mergeTrees(TInfoSink&, TIntermediate&); - void seedIdMap(TMap& idMap, int& maxId); - void remapIds(const TMap& idMap, int idShift, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, long long& IdShift); + void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); - void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage); + void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot); void mergeImplicitArraySizes(TType&, const TType&); - void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage); void checkCallGraphCycles(TInfoSink&); void checkCallGraphBodies(TInfoSink&, bool keepUncalled); void inOutLocationCheck(TInfoSink&); - TIntermAggregate* findLinkerObjects() const; + void sharedBlockCheck(TInfoSink&); bool userOutputUsed() const; bool isSpecializationOperation(const TIntermOperator&) const; bool isNonuniformPropagating(TOperator) const; @@ -878,17 +1044,7 @@ protected: bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); bool isConversionAllowed(TOperator op, TIntermTyped* node) const; - std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; - - // JohnK: I think this function should go away. - // This data structure is just a log to pass on to back ends. - // Versioning and extensions are handled in Version.cpp, with a rich - // set of functions for querying stages, versions, extension enable/disabled, etc. -#ifdef GLSLANG_WEB - bool extensionRequested(const char *extension) const { return false; } -#else - bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} -#endif + std::tuple getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const; static const char* getResourceName(TResourceType); @@ -898,23 +1054,37 @@ protected: typedef std::list TGraph; TGraph callGraph; +#ifdef GLSLANG_ANGLE + const EProfile profile = ECoreProfile; + const int version = 450; +#else EProfile profile; // source profile int version; // source version +#endif SpvVersion spvVersion; TIntermNode* treeRoot; std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them - TBuiltInResource resources; + MustBeAssigned resources; int numEntryPoints; int numErrors; int numPushConstants; bool recursive; bool invertY; bool useStorageBuffer; + bool invariantAll; bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN bool depthReplacing; int localSize[3]; bool localSizeNotDefault[3]; int localSizeSpecId[3]; + unsigned long long uniqueId; + + std::string globalUniformBlockName; + std::string atomicCounterBlockName; + unsigned int globalUniformBlockSet; + unsigned int globalUniformBlockBinding; + unsigned int atomicCounterBlockSet; + #ifndef GLSLANG_WEB public: const char* const implicitThisName; @@ -942,10 +1112,11 @@ protected: bool multiStream; bool layoutOverrideCoverage; bool geoPassthroughEXT; - int numShaderRecordNVBlocks; + int numShaderRecordBlocks; ComputeDerivativeMode computeDerivativeMode; int primitives; int numTaskNVBlocks; + bool layoutPrimitiveCulling; // Base shift values std::array shiftBinding; @@ -968,15 +1139,23 @@ protected: bool needToLegalize; bool binaryDoubleOutput; + bool subgroupUniformControlFlow; bool usePhysicalStorageBuffer; + TSpirvRequirement* spirvRequirement; + TSpirvExecutionMode* spirvExecutionMode; + std::unordered_map uniformLocationOverrides; int uniformLocationBase; + TNumericFeatures numericFeatures; #endif + std::unordered_map blockBackingOverrides; std::unordered_set usedConstantId; // specialization constant ids used std::vector usedAtomics; // sets of bindings used by atomic counters std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + std::vector usedIoRT[2]; // sets of used location, one for rayPayload/rayPayloadIN and other + // for callableData/callableDataIn // set of names of statically read/written I/O that might need extra checking std::set ioAccessed; // source code of shader, useful as part of debug information diff --git a/libraries/glslang/glslang/MachineIndependent/parseConst.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseConst.cpp similarity index 87% rename from libraries/glslang/glslang/MachineIndependent/parseConst.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseConst.cpp index 1a8e6d998..6c182991f 100644 --- a/libraries/glslang/glslang/MachineIndependent/parseConst.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseConst.cpp @@ -165,22 +165,31 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) } } } else { - // matrix from vector - int count = 0; - const int startIndex = index; + // matrix from vector or scalar int nodeComps = node->getType().computeNumComponents(); - for (int i = startIndex; i < endIndex; i++) { - if (i >= instanceSize) - return; - if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 ) + if (nodeComps == 1) { + for (int c = 0; c < matrixCols; ++c) { + for (int r = 0; r < matrixRows; ++r) { + if (r == c) + leftUnionArray[index] = rightUnionArray[0]; + else + leftUnionArray[index].setDConst(0.0); + index++; + } + } + } else { + int count = 0; + for (int i = index; i < endIndex; i++) { + if (i >= instanceSize) + return; + + // construct the matrix in column-major order, from + // the components provided, in order leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setDConst(0.0); - index++; - - if (nodeComps > 1) + index++; count++; + } } } } diff --git a/libraries/glslang/glslang/MachineIndependent/parseVersions.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseVersions.h similarity index 95% rename from libraries/glslang/glslang/MachineIndependent/parseVersions.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseVersions.h index aa1964fc2..7248354e4 100644 --- a/libraries/glslang/glslang/MachineIndependent/parseVersions.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/parseVersions.h @@ -58,7 +58,7 @@ public: const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) : -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) forwardCompatible(forwardCompatible), profile(profile), #endif @@ -101,6 +101,7 @@ public: void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior) { } void fullIntegerCheck(const TSourceLoc&, const char* op) { } void doubleCheck(const TSourceLoc&, const char* op) { } bool float16Arithmetic() { return false; } @@ -115,9 +116,14 @@ public: bool relaxedErrors() const { return false; } bool suppressWarnings() const { return true; } bool isForwardCompatible() const { return false; } +#else +#ifdef GLSLANG_ANGLE + const bool forwardCompatible = true; + const EProfile profile = ECoreProfile; #else bool forwardCompatible; // true if errors are to be given for use of deprecated features EProfile profile; // the declared profile in the shader (core by default) +#endif bool isEsProfile() const { return profile == EEsProfile; } void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, @@ -139,6 +145,7 @@ public: virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc); virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior); virtual void fullIntegerCheck(const TSourceLoc&, const char* op); virtual void unimplemented(const TSourceLoc&, const char* featureDesc); @@ -170,6 +177,7 @@ public: virtual void vulkanRemoved(const TSourceLoc&, const char* op); virtual void requireVulkan(const TSourceLoc&, const char* op); virtual void requireSpv(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version); #if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) @@ -221,7 +229,8 @@ public: TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree protected: - TMap extensionBehavior; // for each extension string, what its current behavior is set to + TMap extensionBehavior; // for each extension string, what its current behavior is + TMap extensionMinSpv; // for each extension string, store minimum spirv required EShMessages messages; // errors/warnings/rule-sets int numErrors; // number of compile-time errors encountered TInputScanner* currentScanner; diff --git a/libraries/glslang/glslang/MachineIndependent/pch.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/pch.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/pch.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/pch.h diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp similarity index 97% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp index d7ff485c0..aa1e0d745 100644 --- a/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -422,10 +422,10 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo if (! parseContext.isReadingHLSL() && isMacroInput()) { if (parseContext.relaxedErrors()) parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression", - "defined", ""); + "defined", ""); else parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros", - "defined", ""); + "defined", ""); } bool needclose = 0; token = scanToken(ppToken); @@ -455,6 +455,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo token = scanToken(ppToken); } } else { + token = tokenPaste(token, *ppToken); token = evalToToken(token, shortCircuit, res, err, ppToken); return eval(token, precedence, shortCircuit, res, err, ppToken); } @@ -621,14 +622,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken) { const TSourceLoc directiveLoc = ppToken->loc; bool startWithLocalSearch = true; // to additionally include the extra "" paths - int token = scanToken(ppToken); + int token; - // handle -style #include - if (token == '<') { + // Find the first non-whitespace char after #include + int ch = getChar(); + while (ch == ' ' || ch == '\t') { + ch = getChar(); + } + if (ch == '<') { + // style startWithLocalSearch = false; token = scanHeaderName(ppToken, '>'); + } else if (ch == '"') { + // "header-name" style + token = scanHeaderName(ppToken, '"'); + } else { + // unexpected, get the full token to generate the error + ungetChar(); + token = scanToken(ppToken); } - // otherwise ppToken already has the header name and it was "header-name" style if (token != PpAtomConstString) { parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", ""); @@ -711,7 +723,9 @@ int TPpContext::CPPline(TPpToken* ppToken) const char* sourceName = nullptr; // Optional source file name. bool lineErr = false; bool fileErr = false; + disableEscapeSequences = true; token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); + disableEscapeSequences = false; if (! lineErr) { lineToken = lineRes; if (token == '\n') @@ -754,7 +768,9 @@ int TPpContext::CPPline(TPpToken* ppToken) // Handle #error int TPpContext::CPPerror(TPpToken* ppToken) { + disableEscapeSequences = true; int token = scanToken(ppToken); + disableEscapeSequences = false; std::string message; TSourceLoc loc = ppToken->loc; @@ -1169,7 +1185,9 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b int macroAtom = atomStrings.getAtom(ppToken->name); switch (macroAtom) { case PpAtomLineMacro: - ppToken->ival = parseContext.getCurrentLoc().line; + // Arguments which are macro have been replaced in the first stage. + if (ppToken->ival == 0) + ppToken->ival = parseContext.getCurrentLoc().line; snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return MacroExpandStarted; @@ -1270,6 +1288,11 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b nestStack.push_back('}'); else if (nestStack.size() > 0 && token == nestStack.back()) nestStack.pop_back(); + + //Macro replacement list is expanded in the last stage. + if (atomStrings.getAtom(ppToken->name) == PpAtomLineMacro) + ppToken->ival = parseContext.getCurrentLoc().line; + in->args[arg]->putToken(token, ppToken); tokenRecorded = true; } diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp similarity index 98% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp index cc003a8d1..1363ce2be 100644 --- a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -87,7 +87,8 @@ namespace glslang { TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false), rootFileName(rootFileName), - currentSourceFile(rootFileName) + currentSourceFile(rootFileName), + disableEscapeSequences(false) { ifdepth = 0; for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.h similarity index 99% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.h index 8470e172a..714b5eadb 100644 --- a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpContext.h @@ -105,13 +105,13 @@ public: } // Used for comparing macro definitions, so checks what is relevant for that. - bool operator==(const TPpToken& right) + bool operator==(const TPpToken& right) const { return space == right.space && ival == right.ival && dval == right.dval && i64val == right.i64val && strncmp(name, right.name, MaxTokenLength) == 0; } - bool operator!=(const TPpToken& right) { return ! operator==(right); } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } TSourceLoc loc; // True if a space (for white space or a removed comment) should also be @@ -695,6 +695,7 @@ protected: std::string currentSourceFile; std::istringstream strtodStream; + bool disableEscapeSequences; }; } // end namespace glslang diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp similarity index 92% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp index c293af3c1..ad1179200 100644 --- a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken) case '\'': return pp->characterLiteral(ppToken); case '"': - // TODO: If this gets enhanced to handle escape sequences, or - // anything that is different than what #include needs, then - // #include needs to use scanHeaderName() for this. + // #include uses scanHeaderName() to ignore these escape sequences. ch = getch(); while (ch != '"' && ch != '\n' && ch != EndOfInput) { if (len < MaxTokenLength) { + if (ch == '\\' && !pp->disableEscapeSequences) { + int nextCh = getch(); + switch (nextCh) { + case '\'': ch = 0x27; break; + case '"': ch = 0x22; break; + case '?': ch = 0x3f; break; + case '\\': ch = 0x5c; break; + case 'a': ch = 0x07; break; + case 'b': ch = 0x08; break; + case 'f': ch = 0x0c; break; + case 'n': ch = 0x0a; break; + case 'r': ch = 0x0d; break; + case 't': ch = 0x09; break; + case 'v': ch = 0x0b; break; + case 'x': + // Hex value, arbitrary number of characters. Terminated by the first + // non-hex digit + { + int numDigits = 0; + ch = 0; + while (true) { + nextCh = getch(); + if (nextCh >= '0' && nextCh <= '9') + nextCh -= '0'; + else if (nextCh >= 'A' && nextCh <= 'F') + nextCh -= 'A' - 10; + else if (nextCh >= 'a' && nextCh <= 'f') + nextCh -= 'a' - 10; + else { + ungetch(); + break; + } + numDigits++; + ch = ch * 0x10 + nextCh; + } + if (numDigits == 0) { + pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", ""); + } + break; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + // Octal value, up to three octal digits + { + int numDigits = 1; + ch = nextCh - '0'; + while (numDigits < 3) { + nextCh = getch(); + if (nextCh >= '0' && nextCh <= '7') + nextCh -= '0'; + else { + ungetch(); + break; + } + numDigits++; + ch = ch * 8 + nextCh; + } + break; + } + default: + pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", ""); + break; + } + } ppToken->name[len] = (char)ch; len++; ch = getch(); @@ -1120,10 +1188,14 @@ int TPpContext::tokenize(TPpToken& ppToken) continue; break; case PpAtomConstString: + // HLSL allows string literals. + // GLSL allows string literals with GL_EXT_debug_printf. if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) { - // HLSL allows string literals. - parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", ""); - continue; + const char* const string_literal_EXTs[] = { E_GL_EXT_debug_printf, E_GL_EXT_spirv_intrinsics }; + parseContext.requireExtensions(ppToken.loc, 2, string_literal_EXTs, "string literal"); + if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf) && + !parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) + continue; } break; case '\'': diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp diff --git a/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h diff --git a/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/propagateNoContraction.cpp similarity index 99% rename from libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/propagateNoContraction.cpp index 83a3230f5..9def592ba 100644 --- a/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/propagateNoContraction.cpp @@ -867,4 +867,4 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate) } }; -#endif // GLSLANG_WEB \ No newline at end of file +#endif // GLSLANG_WEB diff --git a/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/propagateNoContraction.h similarity index 100% rename from libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/propagateNoContraction.h diff --git a/libraries/glslang/glslang/MachineIndependent/reflection.cpp b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.cpp similarity index 83% rename from libraries/glslang/glslang/MachineIndependent/reflection.cpp rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.cpp index b09367113..9ea48c452 100644 --- a/libraries/glslang/glslang/MachineIndependent/reflection.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.cpp @@ -33,7 +33,7 @@ // POSSIBILITY OF SUCH DAMAGE. // -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #include "../Include/Common.h" #include "reflection.h" @@ -77,10 +77,10 @@ namespace glslang { // This is in the glslang namespace directly so it can be a friend of TReflection. // -class TReflectionTraverser : public TLiveTraverser { +class TReflectionTraverser : public TIntermTraverser { public: TReflectionTraverser(const TIntermediate& i, TReflection& r) : - TLiveTraverser(i), reflection(r) { } + TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { } virtual bool visitBinary(TVisit, TIntermBinary* node); virtual void visitSymbol(TIntermSymbol* base); @@ -92,11 +92,28 @@ public: if (processedDerefs.find(&base) == processedDerefs.end()) { processedDerefs.insert(&base); + int blockIndex = -1; + int offset = -1; + TList derefs; + TString baseName = base.getName(); + + if (base.getType().getBasicType() == EbtBlock) { + offset = 0; + bool anonymous = IsAnonymous(baseName); + const TString& blockName = base.getType().getTypeName(); + + if (!anonymous) + baseName = blockName; + else + baseName = ""; + + blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType())); + } + // Use a degenerate (empty) set of dereferences to immediately put as at the end of // the dereference change expected by blowUpActiveAggregate. - TList derefs; - blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0, - base.getQualifier().storage, true); + blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0, + base.getQualifier().storage, updateStageMasks); } } @@ -155,9 +172,9 @@ public: void getOffsets(const TType& type, TVector& offsets) { const TTypeList& memberList = *type.getStruct(); - int memberSize = 0; int offset = 0; + for (size_t m = 0; m < offsets.size(); ++m) { // if the user supplied an offset, snap to it now if (memberList[m].type->getQualifier().hasOffset()) @@ -233,7 +250,7 @@ public: // A value of 0 for arraySize will mean to use the full array's size. void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList& derefs, TList::const_iterator deref, int offset, int blockIndex, int arraySize, - int topLevelArrayStride, TStorageQualifier baseStorage, bool active) + int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active) { // when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query. // Broadly: @@ -262,14 +279,15 @@ public: // Visit all the indices of this array, and for each one add on the remaining dereferencing for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) { TString newBaseName = name; - if (strictArraySuffix && blockParent) + if (terminalType->getBasicType() == EbtBlock) {} + else if (strictArraySuffix && blockParent) newBaseName.append(TString("[0]")); else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) newBaseName.append(TString("[") + String(i) + "]"); TList::const_iterator nextDeref = deref; ++nextDeref; blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize, - topLevelArrayStride, baseStorage, active); + topLevelArraySize, topLevelArrayStride, baseStorage, active); if (offset >= 0) offset += stride; @@ -282,9 +300,10 @@ public: int stride = getArrayStride(baseType, visitNode->getLeft()->getType()); index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (strictArraySuffix && blockParent) { + if (terminalType->getBasicType() == EbtBlock) {} + else if (strictArraySuffix && blockParent) name.append(TString("[0]")); - } else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) { + else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) { name.append(TString("[") + String(index) + "]"); if (offset >= 0) @@ -294,7 +313,10 @@ public: if (topLevelArrayStride == 0) topLevelArrayStride = stride; - blockParent = false; + // expand top-level arrays in blocks with [0] suffix + if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) { + blockParent = false; + } break; } case EOpIndexDirectStruct: @@ -304,6 +326,12 @@ public: if (name.size() > 0) name.append("."); name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName()); + + // expand non top-level arrays with [x] suffix + if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray()) + { + blockParent = false; + } break; default: break; @@ -323,24 +351,27 @@ public: if (offset >= 0) stride = getArrayStride(baseType, *terminalType); - if (topLevelArrayStride == 0) - topLevelArrayStride = stride; - int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1); // for top-level arrays in blocks, only expand [0] to avoid explosion of items - if (strictArraySuffix && blockParent) + if ((strictArraySuffix && blockParent) || + ((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) { arrayIterateSize = 1; + } + + if (topLevelArrayStride == 0) + topLevelArrayStride = stride; for (int i = 0; i < arrayIterateSize; ++i) { TString newBaseName = name; - newBaseName.append(TString("[") + String(i) + "]"); + if (terminalType->getBasicType() != EbtBlock) + newBaseName.append(TString("[") + String(i) + "]"); TType derefType(*terminalType, 0); if (offset >= 0) offset = baseOffset + stride * i; blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0, - topLevelArrayStride, baseStorage, active); + topLevelArraySize, topLevelArrayStride, baseStorage, active); } } else { // Visit all members of this aggregate, and for each one, @@ -369,8 +400,31 @@ public: arrayStride = getArrayStride(baseType, derefType); } - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0, - arrayStride, baseStorage, active); + if (topLevelArraySize == -1 && arrayStride == 0 && blockParent) + topLevelArraySize = 1; + + if (strictArraySuffix && blockParent) { + // if this member is an array, store the top-level array stride but start the explosion from + // the inner struct type. + if (derefType.isArray() && derefType.isStruct()) { + newBaseName.append("[0]"); + auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0); + blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i], + blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false); + } + else if (derefType.isArray()) { + auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0); + blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex, + 0, dimSize, 0, terminalType->getQualifier().storage, false); + } + else { + blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex, + 0, 1, 0, terminalType->getQualifier().storage, false); + } + } else { + blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0, + topLevelArraySize, arrayStride, baseStorage, active); + } } } @@ -406,6 +460,7 @@ public: if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic()) reflection.atomicCounterUniformIndices.push_back(uniformIndex); + variables.back().topLevelArraySize = topLevelArraySize; variables.back().topLevelArrayStride = topLevelArrayStride; if ((reflection.options & EShReflectionAllBlockVariables) && active) { @@ -537,65 +592,17 @@ public: if (! anonymous) baseName = blockName; - if (base->getType().isArray()) { - TType derefType(base->getType(), 0); - - assert(! anonymous); - for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e) - blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType, - intermediate.getBlockSize(base->getType())); - baseName.append(TString("[0]")); - } else - blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType())); + blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType())); if (reflection.options & EShReflectionAllBlockVariables) { // Use a degenerate (empty) set of dereferences to immediately put as at the end of // the dereference change expected by blowUpActiveAggregate. TList derefs; - // because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each - // member in the struct definition. This will lose any information about whether the parent was a buffer - // block. So if we're using strict array rules which don't expand the first child of a buffer block we - // instead iterate over the children here. - const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix); - bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer); - - if (strictArraySuffix && blockParent) { - TType structDerefType(base->getType(), 0); - - const TType &structType = base->getType().isArray() ? structDerefType : base->getType(); - const TTypeList& typeList = *structType.getStruct(); - - TVector memberOffsets; - - memberOffsets.resize(typeList.size()); - getOffsets(structType, memberOffsets); - - for (int i = 0; i < (int)typeList.size(); ++i) { - TType derefType(structType, i); - TString name = baseName; - if (name.size() > 0) - name.append("."); - name.append(typeList[i].type->getFieldName()); - - // if this member is an array, store the top-level array stride but start the explosion from - // the inner struct type. - if (derefType.isArray() && derefType.isStruct()) { - name.append("[0]"); - blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i], - blockIndex, 0, getArrayStride(structType, derefType), - base->getQualifier().storage, false); - } else { - blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex, - 0, 0, base->getQualifier().storage, false); - } - } - } else { - // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are - // expanding root arrays anyway, just start the iteration from the base block type. - blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0, + // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are + // expanding root arrays anyway, just start the iteration from the base block type. + blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0, base->getQualifier().storage, false); - } } } @@ -626,30 +633,43 @@ public: else baseName = base->getName(); } - blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0, + blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0, base->getQualifier().storage, true); } int addBlockName(const TString& name, const TType& type, int size) { - TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage); - - int blockIndex; - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str()); - if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) { - blockIndex = (int)blocks.size(); - reflection.nameToIndex[name.c_str()] = blockIndex; - blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1)); - - blocks.back().numMembers = countAggregateMembers(type); - - EShLanguageMask& stages = blocks.back().stages; - stages = static_cast(stages | 1 << intermediate.getStage()); + int blockIndex = 0; + if (type.isArray()) { + TType derefType(type, 0); + for (int e = 0; e < type.getOuterArraySize(); ++e) { + int memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size); + if (e == 0) + blockIndex = memberBlockIndex; + } } else { - blockIndex = it->second; + TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage); - EShLanguageMask& stages = blocks[blockIndex].stages; - stages = static_cast(stages | 1 << intermediate.getStage()); + TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str()); + if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) { + blockIndex = (int)blocks.size(); + reflection.nameToIndex[name.c_str()] = blockIndex; + blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex)); + + blocks.back().numMembers = countAggregateMembers(type); + + if (updateStageMasks) { + EShLanguageMask& stages = blocks.back().stages; + stages = static_cast(stages | 1 << intermediate.getStage()); + } + } + else { + blockIndex = it->second; + if (updateStageMasks) { + EShLanguageMask& stages = blocks[blockIndex].stages; + stages = static_cast(stages | 1 << intermediate.getStage()); + } + } } return blockIndex; @@ -887,8 +907,8 @@ public: case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset; case EbtInt: return GL_INT_VEC2 + offset; case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset; - case EbtInt64: return GL_INT64_ARB + offset; - case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset; + case EbtInt64: return GL_INT64_VEC2_ARB + offset; + case EbtUint64: return GL_UNSIGNED_INT64_VEC2_ARB + offset; case EbtBool: return GL_BOOL_VEC2 + offset; case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset; default: return 0; @@ -995,8 +1015,10 @@ public: return type.isArray() ? type.getOuterArraySize() : 1; } + const TIntermediate& intermediate; TReflection& reflection; std::set processedDerefs; + bool updateStageMasks; protected: TReflectionTraverser(TReflectionTraverser&); @@ -1029,7 +1051,21 @@ bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) // To reflect non-dereferenced objects. void TReflectionTraverser::visitSymbol(TIntermSymbol* base) { - if (base->getQualifier().storage == EvqUniform) + if (base->getQualifier().storage == EvqUniform) { + if (base->getBasicType() == EbtBlock) { + if (reflection.options & EShReflectionSharedStd140UBO) { + addUniform(*base); + } + } else { + addUniform(*base); + } + } + + // #TODO add std140/layout active rules for ssbo, same with ubo. + // Storage buffer blocks will be collected and expanding in this part. + if((reflection.options & EShReflectionSharedStd140SSBO) && + (base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock && + (base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared))) addUniform(*base); if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) || @@ -1102,6 +1138,8 @@ void TReflection::buildCounterIndices(const TIntermediate& intermediate) if (index >= 0) indexToUniformBlock[i].counterIndex = index; } +#else + (void)intermediate; #endif } @@ -1135,15 +1173,47 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate) TReflectionTraverser it(intermediate, *this); - // put the entry point on the list of functions to process - it.pushFunction(intermediate.getEntryPointMangledName().c_str()); - - // process all the functions - while (! it.functions.empty()) { - TIntermNode* function = it.functions.back(); - it.functions.pop_back(); - function->traverse(&it); + for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) { + if (sequnence->getAsAggregate() != nullptr) { + if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) { + it.updateStageMasks = false; + TIntermAggregate* linkerObjects = sequnence->getAsAggregate(); + for (auto& sequnence : linkerObjects->getSequence()) { + auto pNode = sequnence->getAsSymbolNode(); + if (pNode != nullptr) { + if ((pNode->getQualifier().storage == EvqUniform && + (options & EShReflectionSharedStd140UBO)) || + (pNode->getQualifier().storage == EvqBuffer && + (options & EShReflectionSharedStd140SSBO))) { + // collect std140 and shared uniform block form AST + if ((pNode->getBasicType() == EbtBlock) && + ((pNode->getQualifier().layoutPacking == ElpStd140) || + (pNode->getQualifier().layoutPacking == ElpShared))) { + pNode->traverse(&it); + } + } + else if ((options & EShReflectionAllIOVariables) && + (pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput())) + { + pNode->traverse(&it); + } + } + } + } else { + // This traverser will travers all function in AST. + // If we want reflect uncalled function, we need set linke message EShMsgKeepUncalled. + // When EShMsgKeepUncalled been set to true, all function will be keep in AST, even it is a uncalled function. + // This will keep some uniform variables in reflection, if those uniform variables is used in these uncalled function. + // + // If we just want reflect only live node, we can use a default link message or set EShMsgKeepUncalled false. + // When linke message not been set EShMsgKeepUncalled, linker won't keep uncalled function in AST. + // So, travers all function node can equivalent to travers live function. + it.updateStageMasks = true; + sequnence->getAsAggregate()->traverse(&it); + } + } } + it.updateStageMasks = true; buildCounterIndices(intermediate); buildUniformStageMask(intermediate); @@ -1188,7 +1258,7 @@ void TReflection::dump() for (int dim=0; dim<3; ++dim) if (getLocalSize(dim) > 1) - printf("Local size %s: %d\n", axis[dim], getLocalSize(dim)); + printf("Local size %s: %u\n", axis[dim], getLocalSize(dim)); printf("\n"); } @@ -1201,4 +1271,4 @@ void TReflection::dump() } // end namespace glslang -#endif // GLSLANG_WEB +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE diff --git a/libraries/glslang/glslang/MachineIndependent/reflection.h b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.h similarity index 98% rename from libraries/glslang/glslang/MachineIndependent/reflection.h rename to libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.h index efdc8934f..5af4467c1 100644 --- a/libraries/glslang/glslang/MachineIndependent/reflection.h +++ b/libraries/ZVulkan/src/glslang/glslang/MachineIndependent/reflection.h @@ -33,7 +33,7 @@ // POSSIBILITY OF SUCH DAMAGE. // -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #ifndef _REFLECTION_INCLUDED #define _REFLECTION_INCLUDED @@ -220,4 +220,4 @@ protected: #endif // _REFLECTION_INCLUDED -#endif // GLSLANG_WEB \ No newline at end of file +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE diff --git a/libraries/ZVulkan/src/glslang/glslang/OSDependent/Unix/CMakeLists.txt b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Unix/CMakeLists.txt new file mode 100644 index 000000000..354a3e977 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Unix/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2020 The Khronos Group 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 The Khronos Group Inc. 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 HOLDERS 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. + +add_library(OSDependent STATIC ossource.cpp ../osinclude.h) +set_property(TARGET OSDependent PROPERTY FOLDER glslang) +set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) + +# Link pthread +set(CMAKE_THREAD_PREFER_PTHREAD ON) +if(${CMAKE_VERSION} VERSION_LESS "3.1.0" OR CMAKE_CROSSCOMPILING) + # Needed as long as we support CMake 2.8 for Ubuntu 14.04, + # which does not support the recommended Threads::Threads target. + # https://cmake.org/cmake/help/v2.8.12/cmake.html#module:FindThreads + # Also needed when cross-compiling to work around + # https://gitlab.kitware.com/cmake/cmake/issues/16920 + find_package(Threads) + target_link_libraries(OSDependent ${CMAKE_THREAD_LIBS_INIT}) +else() + # This is the recommended way, so we use it for 3.1+. + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads) + target_link_libraries(OSDependent Threads::Threads) +endif() + +if(ENABLE_GLSLANG_INSTALL) + install(TARGETS OSDependent EXPORT OSDependentTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) +endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/glslang/glslang/OSDependent/Unix/ossource.cpp b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Unix/ossource.cpp similarity index 100% rename from libraries/glslang/glslang/OSDependent/Unix/ossource.cpp rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/Unix/ossource.cpp diff --git a/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/CMakeLists.txt b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/CMakeLists.txt new file mode 100644 index 000000000..0f60dbcc1 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/CMakeLists.txt @@ -0,0 +1,71 @@ +# Copyright (C) 2020 The Khronos Group 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 The Khronos Group Inc. 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 HOLDERS 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. + +if(ENABLE_GLSLANG_JS) + add_executable(glslang.js "glslang.js.cpp") + glslang_set_link_args(glslang.js) + target_link_libraries(glslang.js glslang SPIRV) + + # Link library names that start with "-" are treated as link flags. + # "-Os" should be OK in MSVC; don't use /Os because CMake won't + # treat it as a link flag. + target_link_libraries(glslang.js "-Os") + + if(EMSCRIPTEN) + set_target_properties(glslang.js PROPERTIES + OUTPUT_NAME "glslang" + SUFFIX ".js") + em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js") + + target_link_libraries(glslang.js "--llvm-lto 1") + target_link_libraries(glslang.js "--closure 1") + target_link_libraries(glslang.js "-s MODULARIZE=1") + target_link_libraries(glslang.js "-s ALLOW_MEMORY_GROWTH=1") + target_link_libraries(glslang.js "-s FILESYSTEM=0") + + if(ENABLE_EMSCRIPTEN_SINGLE_FILE) + target_link_libraries(glslang.js "-s SINGLE_FILE=1") + endif(ENABLE_EMSCRIPTEN_SINGLE_FILE) + + if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) + target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") + else() + target_link_libraries(glslang.js "-s ENVIRONMENT=web,worker") + endif() + + if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) + add_custom_command(TARGET glslang.js POST_BUILD + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) + endif() + endif(EMSCRIPTEN) +endif(ENABLE_GLSLANG_JS) diff --git a/libraries/glslang/glslang/OSDependent/Web/glslang.after.js b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.after.js similarity index 100% rename from libraries/glslang/glslang/OSDependent/Web/glslang.after.js rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.after.js diff --git a/libraries/glslang/glslang/OSDependent/Web/glslang.js.cpp b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.js.cpp similarity index 91% rename from libraries/glslang/glslang/OSDependent/Web/glslang.js.cpp rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.js.cpp index 6cb93fe27..f2306a609 100644 --- a/libraries/glslang/glslang/OSDependent/Web/glslang.js.cpp +++ b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.js.cpp @@ -141,6 +141,7 @@ const TBuiltInResource DefaultTBuiltInResource = { /* .maxTaskWorkGroupSizeY_NV = */ 1, /* .maxTaskWorkGroupSizeZ_NV = */ 1, /* .maxMeshViewCountNV = */ 4, + /* .maxDualSourceDrawBuffersEXT = */ 1, /* .limits = */ { /* .nonInductiveForLoops = */ 1, @@ -176,7 +177,12 @@ extern "C" { * If null, the compilation failed. */ EMSCRIPTEN_KEEPALIVE -void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len) +void* convert_glsl_to_spirv(const char* glsl, + int stage_int, + bool gen_debug, + glslang::EShTargetLanguageVersion spirv_version, + uint32_t** spirv, + size_t* spirv_len) { if (glsl == nullptr) { fprintf(stderr, "Input pointer null\n"); @@ -194,6 +200,18 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin return nullptr; } EShLanguage stage = static_cast(stage_int); + switch (spirv_version) { + case glslang::EShTargetSpv_1_0: + case glslang::EShTargetSpv_1_1: + case glslang::EShTargetSpv_1_2: + case glslang::EShTargetSpv_1_3: + case glslang::EShTargetSpv_1_4: + case glslang::EShTargetSpv_1_5: + break; + default: + fprintf(stderr, "Invalid SPIR-V version number\n"); + return nullptr; + } if (!initialized) { glslang::InitializeProcess(); @@ -203,8 +221,8 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin glslang::TShader shader(stage); shader.setStrings(&glsl, 1); shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3); + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, spirv_version); if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) { fprintf(stderr, "Parse failed\n"); fprintf(stderr, "%s\n", shader.getInfoLog()); @@ -260,7 +278,7 @@ void main() { })"; uint32_t* output; size_t output_len; - void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len); + void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len); assert(output != nullptr); assert(output_len != 0); destroy_output_buffer(id); diff --git a/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.pre.js b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.pre.js new file mode 100644 index 000000000..46a569506 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Web/glslang.pre.js @@ -0,0 +1,56 @@ +Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) { + gen_debug = !!gen_debug; + + var shader_stage_int; // EShLanguage + switch (shader_stage) { + case 'vertex': shader_stage_int = 0; break; + case 'fragment': shader_stage_int = 4; break; + case 'compute': shader_stage_int = 5; break; + default: + throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'."); + } + + spirv_version = spirv_version || '1.0'; + var spirv_version_int; // EShTargetLanguageVersion + switch (spirv_version) { + case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break; + case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break; + case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break; + case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break; + case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break; + case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break; + default: + throw new Error("spirv_version must be '1.0' ~ '1.5'."); + } + + var p_output = Module['_malloc'](4); + var p_output_len = Module['_malloc'](4); + var id = ccall('convert_glsl_to_spirv', + 'number', + ['string', 'number', 'boolean', 'number', 'number', 'number'], + [glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]); + var output = getValue(p_output, 'i32'); + var output_len = getValue(p_output_len, 'i32'); + Module['_free'](p_output); + Module['_free'](p_output_len); + + if (id === 0) { + throw new Error('GLSL compilation failed'); + } + + var ret = {}; + var outputIndexU32 = output / 4; + ret['data'] = Module['HEAPU32'].subarray(outputIndexU32, outputIndexU32 + output_len); + ret['free'] = function() { + Module['_destroy_output_buffer'](id); + }; + + return ret; +}; + +Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) { + var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version); + var ret = compiled['data'].slice() + compiled['free'](); + return ret; +}; diff --git a/libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/CMakeLists.txt b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/CMakeLists.txt new file mode 100644 index 000000000..9cf1b7fba --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright (C) 2020 The Khronos Group 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 The Khronos Group Inc. 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 HOLDERS 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. + +set(SOURCES ossource.cpp ../osinclude.h) + +add_library(OSDependent STATIC ${SOURCES}) +set_property(TARGET OSDependent PROPERTY FOLDER glslang) +set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) + +# MinGW GCC complains about function pointer casts to void*. +# Turn that off with -fpermissive. +if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") + target_compile_options(OSDependent PRIVATE -fpermissive) +endif() + +if(WIN32) + source_group("Source" FILES ${SOURCES}) +endif(WIN32) + +if(ENABLE_GLSLANG_INSTALL) + install(TARGETS OSDependent EXPORT OSDependentTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) +endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/glslang/glslang/OSDependent/Windows/main.cpp b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/main.cpp similarity index 100% rename from libraries/glslang/glslang/OSDependent/Windows/main.cpp rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/main.cpp diff --git a/libraries/glslang/glslang/OSDependent/Windows/ossource.cpp b/libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/ossource.cpp similarity index 100% rename from libraries/glslang/glslang/OSDependent/Windows/ossource.cpp rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/Windows/ossource.cpp diff --git a/libraries/glslang/glslang/OSDependent/osinclude.h b/libraries/ZVulkan/src/glslang/glslang/OSDependent/osinclude.h similarity index 100% rename from libraries/glslang/glslang/OSDependent/osinclude.h rename to libraries/ZVulkan/src/glslang/glslang/OSDependent/osinclude.h diff --git a/libraries/glslang/glslang/Public/ShaderLang.h b/libraries/ZVulkan/src/glslang/glslang/Public/ShaderLang.h similarity index 73% rename from libraries/glslang/glslang/Public/ShaderLang.h rename to libraries/ZVulkan/src/glslang/glslang/Public/ShaderLang.h index 4cc6c2f48..d2a4bf40a 100644 --- a/libraries/glslang/glslang/Public/ShaderLang.h +++ b/libraries/ZVulkan/src/glslang/glslang/Public/ShaderLang.h @@ -44,16 +44,25 @@ #include #ifdef _WIN32 -#define C_DECL __cdecl -//#ifdef SH_EXPORTING -// #define SH_IMPORT_EXPORT __declspec(dllexport) -//#else -// #define SH_IMPORT_EXPORT __declspec(dllimport) -//#endif -#define SH_IMPORT_EXPORT + #define C_DECL __cdecl #else -#define SH_IMPORT_EXPORT -#define C_DECL + #define C_DECL +#endif + +#ifdef GLSLANG_IS_SHARED_LIBRARY + #ifdef _WIN32 + #ifdef GLSLANG_EXPORTING + #define GLSLANG_EXPORT __declspec(dllexport) + #else + #define GLSLANG_EXPORT __declspec(dllimport) + #endif + #elif __GNUC__ >= 4 + #define GLSLANG_EXPORT __attribute__((visibility("default"))) + #endif +#endif // GLSLANG_IS_SHARED_LIBRARY + +#ifndef GLSLANG_EXPORT +#define GLSLANG_EXPORT #endif // @@ -65,22 +74,17 @@ extern "C" { #endif -// This should always increase, as some paths to do not consume -// a more major number. -// It should increment by one when new functionality is added. -#define GLSLANG_MINOR_VERSION 13 - // // Call before doing any other compiler/linker operations. // // (Call once per process, not once per thread.) // -SH_IMPORT_EXPORT int ShInitialize(); +GLSLANG_EXPORT int ShInitialize(); // // Call this at process shutdown to clean up memory. // -SH_IMPORT_EXPORT int ShFinalize(); +GLSLANG_EXPORT int ShFinalize(); // // Types of languages the compiler can consume. @@ -92,32 +96,45 @@ typedef enum { EShLangGeometry, EShLangFragment, EShLangCompute, - EShLangRayGenNV, - EShLangIntersectNV, - EShLangAnyHitNV, - EShLangClosestHitNV, - EShLangMissNV, - EShLangCallableNV, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, EShLangTaskNV, EShLangMeshNV, - EShLangCount, + LAST_ELEMENT_MARKER(EShLangCount), } EShLanguage; // would be better as stage, but this is ancient now -typedef enum { +typedef enum : unsigned { EShLangVertexMask = (1 << EShLangVertex), EShLangTessControlMask = (1 << EShLangTessControl), EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), EShLangGeometryMask = (1 << EShLangGeometry), EShLangFragmentMask = (1 << EShLangFragment), EShLangComputeMask = (1 << EShLangCompute), - EShLangRayGenNVMask = (1 << EShLangRayGenNV), - EShLangIntersectNVMask = (1 << EShLangIntersectNV), - EShLangAnyHitNVMask = (1 << EShLangAnyHitNV), - EShLangClosestHitNVMask = (1 << EShLangClosestHitNV), - EShLangMissNVMask = (1 << EShLangMissNV), - EShLangCallableNVMask = (1 << EShLangCallableNV), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, EShLangTaskNVMask = (1 << EShLangTaskNV), EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), } EShLanguageMask; namespace glslang { @@ -128,24 +145,29 @@ typedef enum { EShSourceNone, EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), } EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead typedef enum { EShClientNone, // use when there is no client, e.g. for validation EShClientVulkan, EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), } EShClient; typedef enum { EShTargetNone, EShTargetSpv, // SPIR-V (preferred spelling) EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), } EShTargetLanguage; typedef enum { EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 4), } EShTargetClientVersion; typedef EShTargetClientVersion EshTargetClientVersion; @@ -157,6 +179,7 @@ typedef enum { EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 6), } EShTargetLanguageVersion; struct TInputLanguage { @@ -164,6 +187,7 @@ struct TInputLanguage { EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone EShClient dialect; int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) + bool vulkanRulesRelaxed; }; struct TClient { @@ -186,7 +210,7 @@ struct TEnvironment { TTarget target; // what to generate }; -const char* StageName(EShLanguage); +GLSLANG_EXPORT const char* StageName(EShLanguage); } // end namespace glslang @@ -206,6 +230,7 @@ typedef enum { EShOptNone, EShOptSimple, // Optimizations that can be done quickly EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), } EShOptimizationLevel; // @@ -214,12 +239,13 @@ typedef enum { typedef enum { EShTexSampTransKeep, // keep textures and samplers as is (default) EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), } EShTextureSamplerTransformMode; // // Message choices for what errors and warnings are given. // -enum EShMessages { +enum EShMessages : unsigned { EShMsgDefault = 0, // default is to give all required errors and extra warnings EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification @@ -234,21 +260,26 @@ enum EShMessages { EShMsgDebugInfo = (1 << 10), // save debug information EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages - EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics) EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), }; // // Options for building reflection // typedef enum { - EShReflectionDefault = 0, // default is original behaviour before options were added - EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes - EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection - EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader - EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately - EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive - EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + EShReflectionAllIOVariables = (1 << 6), // reflect all input/output variables, even if they are inactive + EShReflectionSharedStd140SSBO = (1 << 7), // Apply std140/shared rules for ubo to ssbo + EShReflectionSharedStd140UBO = (1 << 8), // Apply std140/shared rules for ubo to ssbo + LAST_ELEMENT_MARKER(EShReflectionCount), } EShReflectionOptions; // @@ -280,10 +311,10 @@ typedef void* ShHandle; // Driver calls these to create and destroy compiler/linker // objects. // -SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader -SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair -SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) -SH_IMPORT_EXPORT void ShDestruct(ShHandle); +GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +GLSLANG_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +GLSLANG_EXPORT void ShDestruct(ShHandle); // // The return value of ShCompile is boolean, non-zero indicating @@ -292,7 +323,7 @@ SH_IMPORT_EXPORT void ShDestruct(ShHandle); // The info-log should be written by ShCompile into // ShHandle, so it can answer future queries. // -SH_IMPORT_EXPORT int ShCompile( +GLSLANG_EXPORT int ShCompile( const ShHandle, const char* const shaderStrings[], const int numStrings, @@ -305,7 +336,7 @@ SH_IMPORT_EXPORT int ShCompile( EShMessages messages = EShMsgDefault // warnings and errors ); -SH_IMPORT_EXPORT int ShLinkExt( +GLSLANG_EXPORT int ShLinkExt( const ShHandle, // linker object const ShHandle h[], // compiler objects to link together const int numHandles); @@ -314,26 +345,26 @@ SH_IMPORT_EXPORT int ShLinkExt( // ShSetEncrpytionMethod is a place-holder for specifying // how source code is encrypted. // -SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); +GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle); // // All the following return 0 if the information is not // available in the object passed down, or the object is bad. // -SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); -SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); -SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing -SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle); +GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle); +GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings // // Tell the linker to never assign a vertex attribute to this list of physical attributes // -SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); +GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); // // Returns the location ID of the named uniform. // Returns -1 if error. // -SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); +GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); #ifdef __cplusplus } // end extern "C" @@ -364,19 +395,27 @@ class TInfoSink; namespace glslang { -const char* GetEsslVersionString(); -const char* GetGlslVersionString(); -int GetKhronosToolId(); +struct Version { + int major; + int minor; + int patch; + const char* flavor; +}; + +GLSLANG_EXPORT Version GetVersion(); +GLSLANG_EXPORT const char* GetEsslVersionString(); +GLSLANG_EXPORT const char* GetGlslVersionString(); +GLSLANG_EXPORT int GetKhronosToolId(); class TIntermediate; class TProgram; class TPoolAllocator; // Call this exactly once per process before using anything else -bool InitializeProcess(); +GLSLANG_EXPORT bool InitializeProcess(); // Call once per process to tear down everything -void FinalizeProcess(); +GLSLANG_EXPORT void FinalizeProcess(); // Resource type for IO resolver enum TResourceType { @@ -389,11 +428,22 @@ enum TResourceType { EResCount }; +enum TBlockStorageClass +{ + EbsUniform = 0, + EbsStorageBuffer, + EbsPushConstant, + EbsNone, // not a uniform or buffer variable + EbsCount, +}; + // Make one TShader per shader that you will link into a program. Then // - provide the shader through setStrings() or setStringsWithLengths() // - optionally call setEnv*(), see below for more detail // - optionally use setPreamble() to set a special shader string that will be // processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses // - call parse(): source language and target environment must be selected // either by correct setting of EShMessages sent to parse(), or by // explicitly calling setEnv*() @@ -406,40 +456,50 @@ enum TResourceType { // class TShader { public: - explicit TShader(EShLanguage); - virtual ~TShader(); - void setStrings(const char* const* s, int n); - void setStringsWithLengths(const char* const* s, const int* l, int n); - void setStringsWithLengthsAndNames( + GLSLANG_EXPORT explicit TShader(EShLanguage); + GLSLANG_EXPORT virtual ~TShader(); + GLSLANG_EXPORT void setStrings(const char* const* s, int n); + GLSLANG_EXPORT void setStringsWithLengths( + const char* const* s, const int* l, int n); + GLSLANG_EXPORT void setStringsWithLengthsAndNames( const char* const* s, const int* l, const char* const* names, int n); void setPreamble(const char* s) { preamble = s; } - void setEntryPoint(const char* entryPoint); - void setSourceEntryPoint(const char* sourceEntryPointName); - void addProcesses(const std::vector&); + GLSLANG_EXPORT void setEntryPoint(const char* entryPoint); + GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName); + GLSLANG_EXPORT void addProcesses(const std::vector&); + GLSLANG_EXPORT void setUniqueId(unsigned long long id); // IO resolver binding data: see comments in ShaderLang.cpp - void setShiftBinding(TResourceType res, unsigned int base); - void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding - void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding - void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); - void setResourceSetBinding(const std::vector& base); - void setAutoMapBindings(bool map); - void setAutoMapLocations(bool map); - void addUniformLocationOverride(const char* name, int loc); - void setUniformLocationBase(int base); - void setInvertY(bool invert); + GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base); + GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + GLSLANG_EXPORT void setResourceSetBinding(const std::vector& base); + GLSLANG_EXPORT void setAutoMapBindings(bool map); + GLSLANG_EXPORT void setAutoMapLocations(bool map); + GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc); + GLSLANG_EXPORT void setUniformLocationBase(int base); + GLSLANG_EXPORT void setInvertY(bool invert); #ifdef ENABLE_HLSL - void setHlslIoMapping(bool hlslIoMap); - void setFlattenUniformArrays(bool flatten); + GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap); + GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten); #endif - void setNoStorageFormat(bool useUnknownFormat); - void setNanMinMaxClamp(bool nanMinMaxClamp); - void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat); + GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp); + GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing); + + GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name); + GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name); + GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set); + GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding); + GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set); + GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding); // For setting up the environment (cleared to nothingness in the constructor). // These must be called so that parsing is done for the right source language and @@ -448,7 +508,7 @@ public: // // setEnvInput: The input source language and stage. If generating code for a // specific client, the input client semantics to use and the - // version of the that client's input semantics to use, otherwise + // version of that client's input semantics to use, otherwise // use EShClientNone and version of 0, e.g. for validation mode. // Note 'version' does not describe the target environment, // just the version of the source dialect to compile under. @@ -496,6 +556,9 @@ public: bool getEnvTargetHlslFunctionality1() const { return false; } #endif + void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; } + bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; } + // Interface to #include handlers. // // To support #include, a client of Glslang does the following: @@ -579,8 +642,10 @@ public: virtual void releaseInclude(IncludeResult*) override { } }; - bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages, Includer&); + GLSLANG_EXPORT bool parse( + const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, + bool forceDefaultVersionAndProfile, bool forwardCompatible, + EShMessages, Includer&); bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages) @@ -603,13 +668,14 @@ public: // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string // is not an officially supported or fully working path. - bool preprocess(const TBuiltInResource* builtInResources, - int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages message, std::string* outputString, - Includer& includer); + GLSLANG_EXPORT bool preprocess( + const TBuiltInResource* builtInResources, int defaultVersion, + EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); - const char* getInfoLog(); - const char* getInfoDebugLog(); + GLSLANG_EXPORT const char* getInfoLog(); + GLSLANG_EXPORT const char* getInfoDebugLog(); EShLanguage getStage() const { return stage; } TIntermediate* getIntermediate() const { return intermediate; } @@ -628,11 +694,11 @@ protected: // stringNames is the optional names for all the strings. If stringNames // is null, then none of the strings has name. If a certain element in // stringNames is null, then the corresponding string does not have name. - const char* const* strings; + const char* const* strings; // explicit code to compile, see previous comment const int* lengths; const char* const* stringNames; - const char* preamble; - int numStrings; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. std::string sourceEntryPointName; @@ -645,7 +711,7 @@ private: TShader& operator=(TShader&); }; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // // A reflection database and its interface, consistent with the OpenGL API reflection queries. @@ -654,11 +720,11 @@ private: // Data needed for just a single object at the granularity exchanged by the reflection API class TObjectReflection { public: - TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); const TType* getType() const { return type; } - int getBinding() const; - void dump() const; + GLSLANG_EXPORT int getBinding() const; + GLSLANG_EXPORT void dump() const; static TObjectReflection badReflection() { return TObjectReflection(); } std::string name; @@ -669,6 +735,7 @@ public: int counterIndex; int numMembers; int arrayStride; // stride of an array variable + int topLevelArraySize; // size of the top-level variable in a storage buffer member int topLevelArrayStride; // stride of the top-level variable in a storage buffer member EShLanguageMask stages; @@ -759,10 +826,10 @@ public: // Called by TSlotCollector to resolve resource locations or bindings virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline - virtual void addStage(EShLanguage stage) = 0; + virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0; }; -#endif // GLSLANG_WEB +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE // Make one TProgram per set of shaders that will get linked together. Add all // the shaders that are to be linked together. After calling shader.parse() @@ -772,40 +839,40 @@ public: // class TProgram { public: - TProgram(); - virtual ~TProgram(); + GLSLANG_EXPORT TProgram(); + GLSLANG_EXPORT virtual ~TProgram(); void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } std::list& getShaders(EShLanguage stage) { return stages[stage]; } // Link Validation interface - bool link(EShMessages); - const char* getInfoLog(); - const char* getInfoDebugLog(); + GLSLANG_EXPORT bool link(EShMessages); + GLSLANG_EXPORT const char* getInfoLog(); + GLSLANG_EXPORT const char* getInfoDebugLog(); TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) // Reflection Interface // call first, to do liveness analysis, index mapping, etc.; returns false on failure - bool buildReflection(int opts = EShReflectionDefault); - unsigned getLocalSize(int dim) const; // return dim'th local size - int getReflectionIndex(const char *name) const; - int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; - int getNumUniformVariables() const; - const TObjectReflection& getUniform(int index) const; - int getNumUniformBlocks() const; - const TObjectReflection& getUniformBlock(int index) const; - int getNumPipeInputs() const; - const TObjectReflection& getPipeInput(int index) const; - int getNumPipeOutputs() const; - const TObjectReflection& getPipeOutput(int index) const; - int getNumBufferVariables() const; - const TObjectReflection& getBufferVariable(int index) const; - int getNumBufferBlocks() const; - const TObjectReflection& getBufferBlock(int index) const; - int getNumAtomicCounters() const; - const TObjectReflection& getAtomicCounter(int index) const; + GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault); + GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size + GLSLANG_EXPORT int getReflectionIndex(const char *name) const; + GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + GLSLANG_EXPORT int getNumUniformVariables() const; + GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const; + GLSLANG_EXPORT int getNumUniformBlocks() const; + GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const; + GLSLANG_EXPORT int getNumPipeInputs() const; + GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const; + GLSLANG_EXPORT int getNumPipeOutputs() const; + GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const; + GLSLANG_EXPORT int getNumBufferVariables() const; + GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const; + GLSLANG_EXPORT int getNumBufferBlocks() const; + GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const; + GLSLANG_EXPORT int getNumAtomicCounters() const; + GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const; // Legacy Reflection Interface - expressed in terms of above interface @@ -872,22 +939,23 @@ public: // returns a TType* const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } - void dumpReflection(); + GLSLANG_EXPORT void dumpReflection(); // I/O mapping: apply base offsets and map live unbound variables // If resolver is not provided it uses the previous approach // and respects auto assignment and offsets. - bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); -#endif + GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif // !GLSLANG_WEB && !GLSLANG_ANGLE protected: - bool linkStage(EShLanguage, EShMessages); + GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages); + GLSLANG_EXPORT bool crossStageCheck(EShMessages); TPoolAllocator* pool; std::list stages[EShLangCount]; TIntermediate* intermediate[EShLangCount]; bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage TInfoSink* infoSink; -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) TReflection* reflection; #endif bool linked; diff --git a/libraries/ZVulkan/src/glslang/glslang/updateGrammar b/libraries/ZVulkan/src/glslang/glslang/updateGrammar new file mode 100644 index 000000000..9209493f3 --- /dev/null +++ b/libraries/ZVulkan/src/glslang/glslang/updateGrammar @@ -0,0 +1,49 @@ +#!/bin/bash + +# Copyright (C) 2020 The Khronos Group 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 The Khronos Group Inc. 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 HOLDERS 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. + +if [ "$1" = 'web' ] +then + m4 -P -DGLSLANG_WEB MachineIndependent/glslang.m4 > MachineIndependent/glslang.y +elif [ "$#" -eq 0 ] +then + m4 -P MachineIndependent/glslang.m4 > MachineIndependent/glslang.y +else + echo usage: + echo $0 web + echo $0 + exit +fi + +bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp diff --git a/libraries/glslang/spirv/GLSL.ext.AMD.h b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.AMD.h similarity index 100% rename from libraries/glslang/spirv/GLSL.ext.AMD.h rename to libraries/ZVulkan/src/glslang/spirv/GLSL.ext.AMD.h diff --git a/libraries/glslang/spirv/GLSL.ext.EXT.h b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.EXT.h similarity index 84% rename from libraries/glslang/spirv/GLSL.ext.EXT.h rename to libraries/ZVulkan/src/glslang/spirv/GLSL.ext.EXT.h index 40164b618..f48f1304d 100644 --- a/libraries/glslang/spirv/GLSL.ext.EXT.h +++ b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.EXT.h @@ -35,5 +35,9 @@ static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shade static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; +static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add"; +static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add"; +static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max"; +static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64"; #endif // #ifndef GLSLextEXT_H diff --git a/libraries/glslang/spirv/GLSL.ext.KHR.h b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.KHR.h similarity index 77% rename from libraries/glslang/spirv/GLSL.ext.KHR.h rename to libraries/ZVulkan/src/glslang/spirv/GLSL.ext.KHR.h index e58e836a8..5eb3e9448 100644 --- a/libraries/glslang/spirv/GLSL.ext.KHR.h +++ b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.KHR.h @@ -1,5 +1,6 @@ /* -** Copyright (c) 2014-2016 The Khronos Group Inc. +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), @@ -44,5 +45,12 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate"; +static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation"; +static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; +static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow"; #endif // #ifndef GLSLextKHR_H diff --git a/libraries/glslang/spirv/GLSL.ext.NV.h b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.NV.h similarity index 96% rename from libraries/glslang/spirv/GLSL.ext.NV.h rename to libraries/ZVulkan/src/glslang/spirv/GLSL.ext.NV.h index 50146da10..93c98bf62 100644 --- a/libraries/glslang/spirv/GLSL.ext.NV.h +++ b/libraries/ZVulkan/src/glslang/spirv/GLSL.ext.NV.h @@ -69,6 +69,9 @@ const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; //SPV_NV_raytracing const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; +//SPV_NV_ray_tracing_motion_blur +const char* const E_SPV_NV_ray_tracing_motion_blur = "SPV_NV_ray_tracing_motion_blur"; + //SPV_NV_shading_rate const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; diff --git a/libraries/glslang/spirv/GLSL.std.450.h b/libraries/ZVulkan/src/glslang/spirv/GLSL.std.450.h similarity index 100% rename from libraries/glslang/spirv/GLSL.std.450.h rename to libraries/ZVulkan/src/glslang/spirv/GLSL.std.450.h diff --git a/libraries/glslang/spirv/GlslangToSpv.cpp b/libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.cpp similarity index 82% rename from libraries/glslang/spirv/GlslangToSpv.cpp rename to libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.cpp index 075563662..42b084cbe 100644 --- a/libraries/glslang/spirv/GlslangToSpv.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.cpp @@ -1,7 +1,8 @@ // // Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -48,13 +49,16 @@ namespace spv { #include "GLSL.ext.EXT.h" #include "GLSL.ext.AMD.h" #include "GLSL.ext.NV.h" + #include "NonSemanticDebugPrintf.h" } // Glslang includes #include "../glslang/MachineIndependent/localintermediate.h" #include "../glslang/MachineIndependent/SymbolTable.h" #include "../glslang/Include/Common.h" -#include "../glslang/Include/revision.h" + +// Build-time generated includes +#include "../glslang/Include/build_info.h" #include #include @@ -145,6 +149,7 @@ protected: spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier); + spv::Decoration TranslateNonUniformDecoration(const spv::Builder::AccessChain::CoherentFlags& coherentFlags); spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type); spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); @@ -155,6 +160,7 @@ protected: spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const; spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector& operands) const; spv::StorageClass TranslateStorageClass(const glslang::TType&); + void TranslateLiterals(const glslang::TVector&, std::vector&) const; void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType); spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType); spv::Id getSampledType(const glslang::TSampler&); @@ -173,6 +179,7 @@ protected: spv::Id accessChainLoad(const glslang::TType& type); void accessChainStore(const glslang::TType& type, spv::Id rvalue); void multiTypeStore(const glslang::TType&, spv::Id rValue); + spv::Id convertLoadedBoolInUniformToUint(const glslang::TType& type, spv::Id nominalTypeId, spv::Id loadedId); glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); @@ -185,9 +192,11 @@ protected: bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam); void makeFunctions(const glslang::TIntermSequence&); void makeGlobalInitializers(const glslang::TIntermSequence&); + void collectRayTracingLinkerObjects(); void visitFunctions(const glslang::TIntermSequence&); void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, + spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); @@ -196,28 +205,36 @@ protected: glslang::TBasicType typeProxy, bool reduceComparison = true); spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize); spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands); - spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); + spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, + glslang::TBasicType typeProxy); + spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, + spv::Id typeId, std::vector& operands); + spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, + glslang::TBasicType typeProxy); + spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy); spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); spv::Id getSymbolId(const glslang::TIntermSymbol* node); void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, + int& nextConst, bool specConstant); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); spv::Id getExtBuiltins(const char* name); - std::pair getForcedType(spv::BuiltIn, const glslang::TType&); + std::pair getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&); spv::Id translateForcedType(spv::Id object); spv::Id createCompositeConstruct(spv::Id typeId, std::vector constituents); @@ -233,19 +250,24 @@ protected: spv::Builder builder; bool inEntryPoint; bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used + bool linkageOnly; // true when visiting the set of objects in the AST present only for + // establishing interface, whether or not they were statically used std::set iOSet; // all input/output variables from either static use or declaration of interface const glslang::TIntermediate* glslangIntermediate; bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp spv::Id stdBuiltins; - std::unordered_map extBuiltinMap; + spv::Id nonSemanticDebugPrintf; + std::unordered_map extBuiltinMap; - std::unordered_map symbolValues; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer + std::unordered_map symbolValues; + std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, + // rather than a pointer std::unordered_map functionMap; std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map > memberRemapper; + std::unordered_map> memberRemapper; + // for mapping glslang symbol struct to symbol Id + std::unordered_map glslangTypeToIdMap; std::stack breakForLoop; // false means break for switch std::unordered_map counterOriginator; // Map pointee types for EbtReference to their forward pointers @@ -254,6 +276,9 @@ protected: // requiring local translation to and from SPIR-V type on every access. // Maps AST-required-type-id> std::unordered_map forceType; + + // Used later for generating OpTraceKHR/OpExecuteCallableKHR + std::unordered_map locationToSymbol[2]; }; // @@ -265,6 +290,8 @@ spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile { #ifdef GLSLANG_WEB return spv::SourceLanguageESSL; +#elif defined(GLSLANG_ANGLE) + return spv::SourceLanguageGLSL; #endif switch (source) { @@ -297,12 +324,12 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) case EShLangTessControl: return spv::ExecutionModelTessellationControl; case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangRayGenNV: return spv::ExecutionModelRayGenerationNV; - case EShLangIntersectNV: return spv::ExecutionModelIntersectionNV; - case EShLangAnyHitNV: return spv::ExecutionModelAnyHitNV; - case EShLangClosestHitNV: return spv::ExecutionModelClosestHitNV; - case EShLangMissNV: return spv::ExecutionModelMissNV; - case EShLangCallableNV: return spv::ExecutionModelCallableNV; + case EShLangRayGen: return spv::ExecutionModelRayGenerationKHR; + case EShLangIntersect: return spv::ExecutionModelIntersectionKHR; + case EShLangAnyHit: return spv::ExecutionModelAnyHitKHR; + case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR; + case EShLangMiss: return spv::ExecutionModelMissKHR; + case EShLangCallable: return spv::ExecutionModelCallableKHR; case EShLangTaskNV: return spv::ExecutionModelTaskNV; case EShLangMeshNV: return spv::ExecutionModelMeshNV; #endif @@ -355,12 +382,13 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; case glslang::EvqVaryingIn: return spv::DecorationBlock; case glslang::EvqVaryingOut: return spv::DecorationBlock; + case glslang::EvqShared: return spv::DecorationBlock; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: return spv::DecorationBlock; - case glslang::EvqPayloadInNV: return spv::DecorationBlock; - case glslang::EvqHitAttrNV: return spv::DecorationBlock; - case glslang::EvqCallableDataNV: return spv::DecorationBlock; - case glslang::EvqCallableDataInNV: return spv::DecorationBlock; + case glslang::EvqPayload: return spv::DecorationBlock; + case glslang::EvqPayloadIn: return spv::DecorationBlock; + case glslang::EvqHitAttr: return spv::DecorationBlock; + case glslang::EvqCallableData: return spv::DecorationBlock; + case glslang::EvqCallableDataIn: return spv::DecorationBlock; #endif default: assert(0); @@ -372,7 +400,8 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto } // Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, bool useVulkanMemoryModel) +void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, + bool useVulkanMemoryModel) { if (!useVulkanMemoryModel) { if (qualifier.isCoherent()) @@ -410,6 +439,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T break; case glslang::EbtBlock: switch (type.getQualifier().storage) { + case glslang::EvqShared: case glslang::EvqUniform: case glslang::EvqBuffer: switch (type.getQualifier().layoutPacking) { @@ -431,11 +461,11 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T } return spv::DecorationMax; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: - case glslang::EvqPayloadInNV: - case glslang::EvqHitAttrNV: - case glslang::EvqCallableDataNV: - case glslang::EvqCallableDataInNV: + case glslang::EvqPayload: + case glslang::EvqPayloadIn: + case glslang::EvqHitAttr: + case glslang::EvqCallableData: + case glslang::EvqCallableDataIn: return spv::DecorationMax; #endif default: @@ -518,6 +548,20 @@ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glsl return spv::DecorationMax; } +// If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration. +spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration( + const spv::Builder::AccessChain::CoherentFlags& coherentFlags) +{ +#ifndef GLSLANG_WEB + if (coherentFlags.isNonUniform()) { + builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); + builder.addCapability(spv::CapabilityShaderNonUniformEXT); + return spv::DecorationNonUniformEXT; + } else +#endif + return spv::DecorationMax; +} + spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( const spv::Builder::AccessChain::CoherentFlags &coherentFlags) { @@ -527,15 +571,11 @@ spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) return mask; - if (coherentFlags.volatil || - coherentFlags.coherent || - coherentFlags.devicecoherent || - coherentFlags.queuefamilycoherent || - coherentFlags.workgroupcoherent || - coherentFlags.subgroupcoherent) { + if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) { mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask; } + if (coherentFlags.nonprivate) { mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask; } @@ -560,11 +600,7 @@ spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands( return mask; if (coherentFlags.volatil || - coherentFlags.coherent || - coherentFlags.devicecoherent || - coherentFlags.queuefamilycoherent || - coherentFlags.workgroupcoherent || - coherentFlags.subgroupcoherent) { + coherentFlags.anyCoherent()) { mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask | spv::ImageOperandsMakeTexelVisibleKHRMask; } @@ -593,17 +629,15 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere flags.workgroupcoherent = type.getQualifier().workgroupcoherent || type.getQualifier().storage == glslang::EvqShared; flags.subgroupcoherent = type.getQualifier().subgroupcoherent; + flags.shadercallcoherent = type.getQualifier().shadercallcoherent; flags.volatil = type.getQualifier().volatil; // *coherent variables are implicitly nonprivate in GLSL flags.nonprivate = type.getQualifier().nonprivate || - flags.subgroupcoherent || - flags.workgroupcoherent || - flags.queuefamilycoherent || - flags.devicecoherent || - flags.coherent || + flags.anyCoherent() || flags.volatil; flags.isImage = type.getBasicType() == glslang::EbtSampler; #endif + flags.nonUniform = type.getQualifier().nonUniform; return flags; } @@ -624,6 +658,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( scope = spv::ScopeWorkgroup; } else if (coherentFlags.subgroupcoherent) { scope = spv::ScopeSubgroup; + } else if (coherentFlags.shadercallcoherent) { + scope = spv::ScopeShaderCallKHR; } if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); @@ -638,7 +674,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( // is generated only when using the variable in an executable instruction, but not when // just declaring a struct member variable with it. This is true for PointSize, // ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration) +spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, + bool memberDeclaration) { switch (builtIn) { case glslang::EbvPointSize: @@ -696,13 +733,20 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInCullDistance; case glslang::EbvViewportIndex: - builder.addCapability(spv::CapabilityMultiViewport); + if (glslangIntermediate->getStage() == EShLangGeometry || + glslangIntermediate->getStage() == EShLangFragment) { + builder.addCapability(spv::CapabilityMultiViewport); + } if (glslangIntermediate->getStage() == EShLangVertex || glslangIntermediate->getStage() == EShLangTessControl || glslangIntermediate->getStage() == EShLangTessEvaluation) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); + if (builder.getSpvVersion() < spv::Spv_1_5) { + builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); + builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); + } + else + builder.addCapability(spv::CapabilityShaderViewportIndex); } return spv::BuiltInViewportIndex; @@ -721,13 +765,19 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI if (glslangIntermediate->getStage() == EShLangMeshNV) { return spv::BuiltInLayer; } - builder.addCapability(spv::CapabilityGeometry); + if (glslangIntermediate->getStage() == EShLangGeometry || + glslangIntermediate->getStage() == EShLangFragment) { + builder.addCapability(spv::CapabilityGeometry); + } if (glslangIntermediate->getStage() == EShLangVertex || glslangIntermediate->getStage() == EShLangTessControl || glslangIntermediate->getStage() == EShLangTessEvaluation) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); + if (builder.getSpvVersion() < spv::Spv_1_5) { + builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); + builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); + } else + builder.addCapability(spv::CapabilityShaderLayer); } return spv::BuiltInLayer; @@ -756,6 +806,16 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI builder.addCapability(spv::CapabilityStencilExportEXT); return spv::BuiltInFragStencilRefEXT; + case glslang::EbvShadingRateKHR: + builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); + builder.addCapability(spv::CapabilityFragmentShadingRateKHR); + return spv::BuiltInShadingRateKHR; + + case glslang::EbvPrimitiveShadingRateKHR: + builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); + builder.addCapability(spv::CapabilityFragmentShadingRateKHR); + return spv::BuiltInPrimitiveShadingRateKHR; + case glslang::EbvInvocationId: return spv::BuiltInInvocationId; case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; @@ -931,34 +991,52 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInInvocationsPerPixelNV; // ray tracing - case glslang::EbvLaunchIdNV: - return spv::BuiltInLaunchIdNV; - case glslang::EbvLaunchSizeNV: - return spv::BuiltInLaunchSizeNV; - case glslang::EbvWorldRayOriginNV: - return spv::BuiltInWorldRayOriginNV; - case glslang::EbvWorldRayDirectionNV: - return spv::BuiltInWorldRayDirectionNV; - case glslang::EbvObjectRayOriginNV: - return spv::BuiltInObjectRayOriginNV; - case glslang::EbvObjectRayDirectionNV: - return spv::BuiltInObjectRayDirectionNV; - case glslang::EbvRayTminNV: - return spv::BuiltInRayTminNV; - case glslang::EbvRayTmaxNV: - return spv::BuiltInRayTmaxNV; - case glslang::EbvInstanceCustomIndexNV: - return spv::BuiltInInstanceCustomIndexNV; - case glslang::EbvHitTNV: - return spv::BuiltInHitTNV; - case glslang::EbvHitKindNV: - return spv::BuiltInHitKindNV; - case glslang::EbvObjectToWorldNV: - return spv::BuiltInObjectToWorldNV; - case glslang::EbvWorldToObjectNV: - return spv::BuiltInWorldToObjectNV; - case glslang::EbvIncomingRayFlagsNV: - return spv::BuiltInIncomingRayFlagsNV; + case glslang::EbvLaunchId: + return spv::BuiltInLaunchIdKHR; + case glslang::EbvLaunchSize: + return spv::BuiltInLaunchSizeKHR; + case glslang::EbvWorldRayOrigin: + return spv::BuiltInWorldRayOriginKHR; + case glslang::EbvWorldRayDirection: + return spv::BuiltInWorldRayDirectionKHR; + case glslang::EbvObjectRayOrigin: + return spv::BuiltInObjectRayOriginKHR; + case glslang::EbvObjectRayDirection: + return spv::BuiltInObjectRayDirectionKHR; + case glslang::EbvRayTmin: + return spv::BuiltInRayTminKHR; + case glslang::EbvRayTmax: + return spv::BuiltInRayTmaxKHR; + case glslang::EbvInstanceCustomIndex: + return spv::BuiltInInstanceCustomIndexKHR; + case glslang::EbvHitT: + { + // this is a GLSL alias of RayTmax + // in SPV_NV_ray_tracing it has a dedicated builtin + // but in SPV_KHR_ray_tracing it gets mapped to RayTmax + auto& extensions = glslangIntermediate->getRequestedExtensions(); + if (extensions.find("GL_NV_ray_tracing") != extensions.end()) { + return spv::BuiltInHitTNV; + } else { + return spv::BuiltInRayTmaxKHR; + } + } + case glslang::EbvHitKind: + return spv::BuiltInHitKindKHR; + case glslang::EbvObjectToWorld: + case glslang::EbvObjectToWorld3x4: + return spv::BuiltInObjectToWorldKHR; + case glslang::EbvWorldToObject: + case glslang::EbvWorldToObject3x4: + return spv::BuiltInWorldToObjectKHR; + case glslang::EbvIncomingRayFlags: + return spv::BuiltInIncomingRayFlagsKHR; + case glslang::EbvGeometryIndex: + return spv::BuiltInRayGeometryIndexKHR; + case glslang::EbvCurrentRayTimeNV: + builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); + builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); + return spv::BuiltInCurrentRayTimeNV; // barycentrics case glslang::EbvBaryCoordNV: @@ -1054,6 +1132,10 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy builder.addCapability(spv::CapabilityStorageImageExtendedFormats); break; + case glslang::ElfR64ui: + case glslang::ElfR64i: + builder.addExtension(spv::E_SPV_EXT_shader_image_int64); + builder.addCapability(spv::CapabilityInt64ImageEXT); default: break; } @@ -1100,11 +1182,14 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy case glslang::ElfRg8ui: return spv::ImageFormatRg8ui; case glslang::ElfR16ui: return spv::ImageFormatR16ui; case glslang::ElfR8ui: return spv::ImageFormatR8ui; + case glslang::ElfR64ui: return spv::ImageFormatR64ui; + case glslang::ElfR64i: return spv::ImageFormatR64i; default: return spv::ImageFormatMax; } } -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const +spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl( + const glslang::TIntermSelection& selectionNode) const { if (selectionNode.getFlatten()) return spv::SelectionControlFlattenMask; @@ -1113,7 +1198,8 @@ spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(cons return spv::SelectionControlMaskNone; } -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const +spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) + const { if (switchNode.getFlatten()) return spv::SelectionControlFlattenMask; @@ -1167,6 +1253,12 @@ spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang: // Translate glslang type to SPIR-V storage class. spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) { + if (type.getBasicType() == glslang::EbtRayQuery) + return spv::StorageClassPrivate; +#ifndef GLSLANG_WEB + if (type.getQualifier().isSpirvByReference()) + return spv::StorageClassFunction; +#endif if (type.getQualifier().isPipeInput()) return spv::StorageClassInput; if (type.getQualifier().isPipeOutput()) @@ -1181,8 +1273,8 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T } if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().isShaderRecordNV()) { - return spv::StorageClassShaderRecordBufferNV; + type.getQualifier().isShaderRecord()) { + return spv::StorageClassShaderRecordBufferKHR; } if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { @@ -1198,17 +1290,24 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T return spv::StorageClassUniformConstant; } + if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) { + builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout); + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR); + return spv::StorageClassWorkgroup; + } + switch (type.getQualifier().storage) { case glslang::EvqGlobal: return spv::StorageClassPrivate; case glslang::EvqConstReadOnly: return spv::StorageClassFunction; case glslang::EvqTemporary: return spv::StorageClassFunction; case glslang::EvqShared: return spv::StorageClassWorkgroup; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: return spv::StorageClassRayPayloadNV; - case glslang::EvqPayloadInNV: return spv::StorageClassIncomingRayPayloadNV; - case glslang::EvqHitAttrNV: return spv::StorageClassHitAttributeNV; - case glslang::EvqCallableDataNV: return spv::StorageClassCallableDataNV; - case glslang::EvqCallableDataInNV: return spv::StorageClassIncomingCallableDataNV; + case glslang::EvqPayload: return spv::StorageClassRayPayloadKHR; + case glslang::EvqPayloadIn: return spv::StorageClassIncomingRayPayloadKHR; + case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR; + case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR; + case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR; + case glslang::EvqSpirvStorageClass: return static_cast(type.getQualifier().spirvStorageClass); #endif default: assert(0); @@ -1218,6 +1317,52 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T return spv::StorageClassFunction; } +// Translate glslang constants to SPIR-V literals +void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector& constants, + std::vector& literals) const +{ + for (auto constant : constants) { + if (constant->getBasicType() == glslang::EbtFloat) { + float floatValue = static_cast(constant->getConstArray()[0].getDConst()); + unsigned literal = *reinterpret_cast(&floatValue); + literals.push_back(literal); + } else if (constant->getBasicType() == glslang::EbtInt) { + unsigned literal = constant->getConstArray()[0].getIConst(); + literals.push_back(literal); + } else if (constant->getBasicType() == glslang::EbtUint) { + unsigned literal = constant->getConstArray()[0].getUConst(); + literals.push_back(literal); + } else if (constant->getBasicType() == glslang::EbtBool) { + unsigned literal = constant->getConstArray()[0].getBConst(); + literals.push_back(literal); + } else if (constant->getBasicType() == glslang::EbtString) { + auto str = constant->getConstArray()[0].getSConst()->c_str(); + unsigned literal = 0; + char* literalPtr = reinterpret_cast(&literal); + unsigned charCount = 0; + char ch = 0; + do { + ch = *(str++); + *(literalPtr++) = ch; + ++charCount; + if (charCount == 4) { + literals.push_back(literal); + literalPtr = reinterpret_cast(&literal); + charCount = 0; + } + } while (ch != 0); + + // Partial literal is padded with 0 + if (charCount > 0) { + for (; charCount < 4; ++charCount) + *(literalPtr++) = 0; + literals.push_back(literal); + } + } else + assert(0); // Unexpected type + } +} + // Add capabilities pertaining to how an array is indexed. void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType) @@ -1268,14 +1413,15 @@ bool IsDescriptorResource(const glslang::TType& type) // uniform and buffer blocks are included, unless it is a push_constant if (type.getBasicType() == glslang::EbtBlock) return type.getQualifier().isUniformOrBuffer() && - ! type.getQualifier().isShaderRecordNV() && + ! type.getQualifier().isShaderRecord() && ! type.getQualifier().isPushConstant(); // non block... // basically samplerXXX/subpass/sampler/texture are all included // if they are the global-scope-class, not the function parameter // (or local, if they ever exist) class. - if (type.getBasicType() == glslang::EbtSampler) + if (type.getBasicType() == glslang::EbtSampler || + type.getBasicType() == glslang::EbtAccStruct) return type.getQualifier().isUniformOrBuffer(); // None of the above. @@ -1318,6 +1464,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa child.workgroupcoherent = true; if (parent.subgroupcoherent) child.subgroupcoherent = true; + if (parent.shadercallcoherent) + child.shadercallcoherent = true; if (parent.nonprivate) child.nonprivate = true; if (parent.volatil) @@ -1329,6 +1477,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa if (parent.writeonly) child.writeonly = true; #endif + if (parent.nonUniform) + child.nonUniform = true; } bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier) @@ -1348,16 +1498,18 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie // Implement the TGlslangToSpvTraverser class. // -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) - : TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate), - nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()) +TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, + const glslang::TIntermediate* glslangIntermediate, + spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) : + TIntermTraverser(true, false, true), + options(options), + shaderEntry(nullptr), currentFunction(nullptr), + sequenceDepth(0), logger(buildLogger), + builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), + inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), + glslangIntermediate(glslangIntermediate), + nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()), + nonSemanticDebugPrintf(0) { spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); @@ -1398,9 +1550,9 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl if (glslangIntermediate->usingPhysicalStorageBuffer()) { addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT; - builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5); + builder.addIncorporatedExtension(spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5); builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT); - }; + } if (glslangIntermediate->usingVulkanMemoryModel()) { memoryModel = spv::MemoryModelVulkanKHR; builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); @@ -1427,6 +1579,17 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); } + if (glslangIntermediate->getLayoutPrimitiveCulling()) { + builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR); + } + +#ifndef GLSLANG_WEB + if (glslangIntermediate->getSubgroupUniformControlFlow()) { + builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR); + } +#endif + unsigned int mode; switch (glslangIntermediate->getStage()) { case EShLangVertex: @@ -1452,14 +1615,16 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); } - if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) + if (glslangIntermediate->isDepthReplacing()) builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); #ifndef GLSLANG_WEB + switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - default: mode = spv::ExecutionModeMax; break; + case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; + case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; + case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break; + default: mode = spv::ExecutionModeMax; break; } if (mode != spv::ExecutionModeMax) builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); @@ -1493,7 +1658,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); } #endif - break; + break; case EShLangCompute: builder.addCapability(spv::CapabilityShader); @@ -1518,7 +1683,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl glslang::TLayoutGeometry primitive; if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, + glslangIntermediate->getVertices()); primitive = glslangIntermediate->getOutputPrimitive(); } else { primitive = glslangIntermediate->getInputPrimitive(); @@ -1580,15 +1746,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: - builder.addCapability(spv::CapabilityRayTracingNV); - builder.addExtension("SPV_NV_ray_tracing"); + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: + { + auto& extensions = glslangIntermediate->getRequestedExtensions(); + if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { + builder.addCapability(spv::CapabilityRayTracingKHR); + builder.addExtension("SPV_KHR_ray_tracing"); + } + else { + builder.addCapability(spv::CapabilityRayTracingNV); + builder.addExtension("SPV_NV_ray_tracing"); + } break; + } case EShLangTaskNV: case EShLangMeshNV: builder.addCapability(spv::CapabilityMeshShadingNV); @@ -1597,8 +1772,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl glslangIntermediate->getLocalSize(1), glslangIntermediate->getLocalSize(2)); if (glslangIntermediate->getStage() == EShLangMeshNV) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, + glslangIntermediate->getVertices()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, + glslangIntermediate->getPrimitives()); switch (glslangIntermediate->getOutputPrimitive()) { case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; @@ -1615,6 +1792,53 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl default: break; } + +#ifndef GLSLANG_WEB + // + // Add SPIR-V requirements (GL_EXT_spirv_intrinsics) + // + if (glslangIntermediate->hasSpirvRequirement()) { + const glslang::TSpirvRequirement& spirvRequirement = glslangIntermediate->getSpirvRequirement(); + + // Add SPIR-V extension requirement + for (auto& extension : spirvRequirement.extensions) + builder.addExtension(extension.c_str()); + + // Add SPIR-V capability requirement + for (auto capability : spirvRequirement.capabilities) + builder.addCapability(static_cast(capability)); + } + + // + // Add SPIR-V execution mode qualifiers (GL_EXT_spirv_intrinsics) + // + if (glslangIntermediate->hasSpirvExecutionMode()) { + const glslang::TSpirvExecutionMode spirvExecutionMode = glslangIntermediate->getSpirvExecutionMode(); + + // Add spirv_execution_mode + for (auto& mode : spirvExecutionMode.modes) { + if (!mode.second.empty()) { + std::vector literals; + TranslateLiterals(mode.second, literals); + builder.addExecutionMode(shaderEntry, static_cast(mode.first), literals); + } else + builder.addExecutionMode(shaderEntry, static_cast(mode.first)); + } + + // Add spirv_execution_mode_id + for (auto& modeId : spirvExecutionMode.modeIds) { + std::vector operandIds; + assert(!modeId.second.empty()); + for (auto extraOperand : modeId.second) { + int nextConst = 0; + spv::Id operandId = createSpvConstantFromConstUnionArray( + extraOperand->getType(), extraOperand->getConstArray(), nextConst, false); + operandIds.push_back(operandId); + } + builder.addExecutionModeId(shaderEntry, static_cast(modeId.first), operandIds); + } + } +#endif } // Finish creating SPV, after the traversal is complete. @@ -1661,28 +1885,41 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector& out) void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) { SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + if (symbol->getType().isStruct()) + glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId(); + if (symbol->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); +#ifdef ENABLE_HLSL + // Skip symbol handling if it is string-typed + if (symbol->getBasicType() == glslang::EbtString) + return; +#endif + // getSymbolId() will set up all the IO decorations on the first call. // Formal function parameters were mapped during makeFunctions(). spv::Id id = getSymbolId(symbol); if (builder.isPointer(id)) { - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction - // Consider adding to the OpEntryPoint interface list. - // Only looking at structures if they have at least one member. - if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) { - spv::StorageClass sc = builder.getStorageClass(id); - // Before SPIR-V 1.4, we only want to include Input and Output. - // Starting with SPIR-V 1.4, we want all globals. - if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && sc != spv::StorageClassFunction) || - (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) { - iOSet.insert(id); + if (!symbol->getType().getQualifier().isParamInput() && + !symbol->getType().getQualifier().isParamOutput()) { + // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction + // Consider adding to the OpEntryPoint interface list. + // Only looking at structures if they have at least one member. + if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) { + spv::StorageClass sc = builder.getStorageClass(id); + // Before SPIR-V 1.4, we only want to include Input and Output. + // Starting with SPIR-V 1.4, we want all globals. + if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && builder.isGlobalStorage(id)) || + (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) { + iOSet.insert(id); + } } } - // If the SPIR-V type is required to be different than the AST type, + // If the SPIR-V type is required to be different than the AST type + // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices), // translate now from the SPIR-V type to the AST type, for the consuming // operation. // Note this turns it from an l-value to an r-value. @@ -1753,6 +1990,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); + if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { + glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); + } + if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) { + glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId(); + } SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); if (node->getType().getQualifier().isSpecConstant()) @@ -1796,9 +2039,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); // do the operation + spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); + coherentFlags |= TranslateCoherent(node->getRight()->getType()); OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; + TranslateNonUniformDecoration(coherentFlags) }; rValue = createBinaryOperation(node->getOp(), decorations, convertGlslangToSpvType(node->getType()), leftRValue, rValue, node->getType().getBasicType()); @@ -1829,14 +2074,18 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector() && node->getOp() == glslang::EOpIndexDirect) { + // Swizzle is uniform so propagate uniform into access chain + spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); + coherentFlags.nonUniform = 0; // This is essentially a hard-coded vector swizzle of size 1, // so short circuit the access-chain stuff with a swizzle. std::vector swizzle; swizzle.push_back(glslangIndex); int dummySize; builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), - TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + coherentFlags, + glslangIntermediate->getBaseAlignmentScalar( + node->getLeft()->getType(), dummySize)); } else { // Load through a block reference is performed with a dot operator that @@ -1857,13 +2106,23 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T { // This may be, e.g., an anonymous block-member selection, which generally need // index remapping due to hidden members in anonymous blocks. - std::vector& remapper = memberRemapper[node->getLeft()->getType().getStruct()]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; + long long glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()]; + if (memberRemapper.find(glslangId) != memberRemapper.end()) { + std::vector& remapper = memberRemapper[glslangId]; + assert(remapper.size() > 0); + spvIndex = remapper[glslangIndex]; + } } + // Struct reference propagates uniform lvalue + spv::Builder::AccessChain::CoherentFlags coherentFlags = + TranslateCoherent(node->getLeft()->getType()); + coherentFlags.nonUniform = 0; + // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(spvIndex), + coherentFlags, + node->getLeft()->getType().getBufferReferenceAlignment()); // Add capabilities here for accessing PointSize and clip/cull distance. // We have deferred generation of associated capabilities until now. @@ -1896,13 +2155,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // restore the saved access chain builder.setAccessChain(partial); + // Only if index is nonUniform should we propagate nonUniform into access chain + spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent(node->getRight()->getType()); + spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent(node->getLeft()->getType()); + coherent_flags.nonUniform = index_flags.nonUniform; + if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) { int dummySize; - builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()), - TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + builder.accessChainPushComponent( + index, convertGlslangToSpvType(node->getLeft()->getType()), coherent_flags, + glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), + dummySize)); } else - builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(index, coherent_flags, + node->getLeft()->getType().getBufferReferenceAlignment()); } return false; case glslang::EOpVectorSwizzle: @@ -1913,7 +2179,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T int dummySize; builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), + dummySize)); } return false; case glslang::EOpMatrixSwizzle: @@ -1929,7 +2196,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T if (isTrivial(node->getRight()->getAsTyped())) break; // handle below as a normal binary operation // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped()); + spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), + *node->getRight()->getAsTyped()); builder.clearAccessChain(); builder.setAccessChainRValue(result); } @@ -1968,24 +2236,77 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T } } +spv::Id TGlslangToSpvTraverser::convertLoadedBoolInUniformToUint(const glslang::TType& type, + spv::Id nominalTypeId, + spv::Id loadedId) +{ + if (builder.isScalarType(nominalTypeId)) { + // Conversion for bool + spv::Id boolType = builder.makeBoolType(); + if (nominalTypeId != boolType) + return builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); + } else if (builder.isVectorType(nominalTypeId)) { + // Conversion for bvec + int vecSize = builder.getNumTypeComponents(nominalTypeId); + spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); + if (nominalTypeId != bvecType) + loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, + makeSmearedConstant(builder.makeUintConstant(0), vecSize)); + } else if (builder.isArrayType(nominalTypeId)) { + // Conversion for bool array + spv::Id boolArrayTypeId = convertGlslangToSpvType(type); + if (nominalTypeId != boolArrayTypeId) + { + // Use OpCopyLogical from SPIR-V 1.4 if available. + if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) + return builder.createUnaryOp(spv::OpCopyLogical, boolArrayTypeId, loadedId); + + glslang::TType glslangElementType(type, 0); + spv::Id elementNominalTypeId = builder.getContainedTypeId(nominalTypeId); + std::vector constituents; + for (int index = 0; index < type.getOuterArraySize(); ++index) { + // get the element + spv::Id elementValue = builder.createCompositeExtract(loadedId, elementNominalTypeId, index); + + // recursively convert it + spv::Id elementConvertedValue = convertLoadedBoolInUniformToUint(glslangElementType, elementNominalTypeId, elementValue); + constituents.push_back(elementConvertedValue); + } + return builder.createCompositeConstruct(boolArrayTypeId, constituents); + } + } + + return loadedId; +} + // Figure out what, if any, type changes are needed when accessing a specific built-in. // Returns . // Also see comment for 'forceType', regarding tracking SPIR-V-required types. -std::pair TGlslangToSpvTraverser::getForcedType(spv::BuiltIn builtIn, +std::pair TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn, const glslang::TType& glslangType) { - switch(builtIn) + switch(glslangBuiltIn) { - case spv::BuiltInSubgroupEqMask: - case spv::BuiltInSubgroupGeMask: - case spv::BuiltInSubgroupGtMask: - case spv::BuiltInSubgroupLeMask: - case spv::BuiltInSubgroupLtMask: { + case glslang::EbvSubGroupEqMask: + case glslang::EbvSubGroupGeMask: + case glslang::EbvSubGroupGtMask: + case glslang::EbvSubGroupLeMask: + case glslang::EbvSubGroupLtMask: { // these require changing a 64-bit scaler -> a vector of 32-bit components if (glslangType.isVector()) break; - std::pair ret(builder.makeVectorType(builder.makeUintType(32), 4), - builder.makeUintType(64)); + spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4); + spv::Id uint64_type = builder.makeUintType(64); + std::pair ret(ivec4_type, uint64_type); + return ret; + } + // There are no SPIR-V builtins defined for these and map onto original non-transposed + // builtins. During visitBinary we insert a transpose + case glslang::EbvWorldToObject3x4: + case glslang::EbvObjectToWorld3x4: { + spv::Id mat43 = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); + spv::Id mat34 = builder.makeMatrixType(builder.makeFloatType(32), 3, 4); + std::pair ret(mat43, mat34); return ret; } default: @@ -2015,7 +2336,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) // handle 32-bit v.xy* -> 64-bit builder.clearAccessChain(); builder.setAccessChainLValue(object); - object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId); + object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); std::vector components; components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0)); components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1)); @@ -2026,7 +2347,15 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) } else { logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar"); } - } else { + } else if (builder.isMatrixType(objectTypeId)) { + // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject + // and we insert a transpose after loading the original non-transposed builtins + builder.clearAccessChain(); + builder.setAccessChainLValue(object); + object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); + return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object); + + } else { logger->missingFunctionality("forcing non 32-bit vector type"); } @@ -2077,7 +2406,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI } else { glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst(); + unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion() + ->getConstArray()[0].getUConst(); length = builder.createArrayLength(builder.accessChainGetLValue(), member); } @@ -2103,7 +2433,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // Does it need a swizzle inversion? If so, evaluation is inverted; // operate first on the swizzle base, then apply the swizzle. spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; + auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? + invertedType : convertGlslangToSpvType(node->getType()); }; if (node->getOp() == glslang::EOpInterpolateAtCentroid) invertedType = getInvertedSwizzleType(*node->getOperand()); @@ -2124,10 +2455,23 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI if (node->getOp() == glslang::EOpAtomicCounterIncrement || node->getOp() == glslang::EOpAtomicCounterDecrement || node->getOp() == glslang::EOpAtomicCounter || - node->getOp() == glslang::EOpInterpolateAtCentroid) { + (node->getOp() == glslang::EOpInterpolateAtCentroid && + glslangIntermediate->getSource() != glslang::EShSourceHlsl) || + node->getOp() == glslang::EOpRayQueryProceed || + node->getOp() == glslang::EOpRayQueryGetRayTMin || + node->getOp() == glslang::EOpRayQueryGetRayFlags || + node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin || + node->getOp() == glslang::EOpRayQueryGetWorldRayDirection || + node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque || + node->getOp() == glslang::EOpRayQueryTerminate || + node->getOp() == glslang::EOpRayQueryConfirmIntersection || + (node->getOp() == glslang::EOpSpirvInst && operandNode->getAsTyped()->getQualifier().isSpirvByReference())) { operand = builder.accessChainGetLValue(); // Special case l-value operands lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType()); + } else if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { + // Will be translated to a literal value, make a placeholder here + operand = spv::NoResult; } else #endif { @@ -2140,11 +2484,45 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // it could be a conversion if (! result) - result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType()); + result = createConversion(node->getOp(), decorations, resultType(), operand, + node->getOperand()->getBasicType()); // if not, then possibly an operation if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags); + result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, + node->getOperand()->getBasicType(), lvalueCoherentFlags); + +#ifndef GLSLANG_WEB + // it could be attached to a SPIR-V intruction + if (!result) { + if (node->getOp() == glslang::EOpSpirvInst) { + const auto& spirvInst = node->getSpirvInstruction(); + if (spirvInst.set == "") { + spv::IdImmediate idImmOp = {true, operand}; + if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { + // Translate the constant to a literal value + std::vector literals; + glslang::TVector constants; + constants.push_back(operandNode->getAsConstantUnion()); + TranslateLiterals(constants, literals); + idImmOp = {false, literals[0]}; + } + + if (node->getBasicType() == glslang::EbtVoid) + builder.createNoResultOp(static_cast(spirvInst.id), {idImmOp}); + else + result = builder.createOp(static_cast(spirvInst.id), resultType(), {idImmOp}); + } else { + result = builder.createBuiltinCall( + resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), + spirvInst.id, {operand}); + } + + if (node->getBasicType() == glslang::EbtVoid) + return false; // done with this node + } + } +#endif if (result) { if (invertedType) { @@ -2197,7 +2575,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // The result of operation is always stored, but conditionally the // consumed result. The consumed result is always an r-value. - builder.accessChainStore(result); + builder.accessChainStore(result, + TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags)); builder.clearAccessChain(); if (node->getOp() == glslang::EOpPreIncrement || node->getOp() == glslang::EOpPreDecrement) @@ -2215,6 +2594,12 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI case glslang::EOpEndStreamPrimitive: builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); return false; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand); + return false; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand); + return false; #endif default: @@ -2237,7 +2622,8 @@ spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, s std::vector rTypeConstituents; int numrTypeConstituents = builder.getNumTypeConstituents(rType); for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i)); + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, + builder.getContainedTypeId(rType, i), i)); } constituents[c] = createCompositeConstruct(lType, rTypeConstituents); } else { @@ -2263,8 +2649,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; + spv::Id invertedType = spv::NoType; // to use to override the natural type of the node + std::vector complexLvalues; // for holding swizzling l-values too complex for + // SPIR-V, for an out parameter + std::vector temporaryLvalues; // temporaries to pass, as proxies for complexLValues + + auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? + invertedType : + convertGlslangToSpvType(node->getType()); }; // try texturing result = createImageTextureFunctionCall(node); @@ -2313,6 +2705,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // anything else gets there, so visit out of order, doing them all now. makeGlobalInitializers(node->getAsAggregate()->getSequence()); + //Pre process linker objects for ray tracing stages + if (glslangIntermediate->isRayTracingStage()) + collectRayTracingLinkerObjects(); + // Initializers are done, don't want to visit again, but functions and link objects need to be processed, // so do them manually. visitFunctions(node->getAsAggregate()->getSequence()); @@ -2368,7 +2764,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.setLine(node->getLoc().line, node->getLoc().getFilename()); if (node->isUserDefined()) result = handleUserFunctionCall(node); - // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done if (result) { builder.clearAccessChain(); builder.setAccessChainRValue(result); @@ -2504,6 +2899,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt else constructed = builder.createConstructor(precision, arguments, resultType()); + if (node->getType().getQualifier().isNonUniform()) { + builder.addDecoration(constructed, spv::DecorationNonUniformEXT); + } + builder.clearAccessChain(); builder.setAccessChainRValue(constructed); @@ -2576,6 +2975,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; case glslang::EOpAtomicAdd: + case glslang::EOpAtomicSubtract: case glslang::EOpAtomicMin: case glslang::EOpAtomicMax: case glslang::EOpAtomicAnd: @@ -2622,10 +3022,43 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpIgnoreIntersectionNV: case glslang::EOpTerminateRayNV: case glslang::EOpTraceNV: + case glslang::EOpTraceRayMotionNV: + case glslang::EOpTraceKHR: case glslang::EOpExecuteCallableNV: + case glslang::EOpExecuteCallableKHR: case glslang::EOpWritePackedPrimitiveIndices4x8NV: noReturnValue = true; break; + case glslang::EOpRayQueryInitialize: + case glslang::EOpRayQueryTerminate: + case glslang::EOpRayQueryGenerateIntersection: + case glslang::EOpRayQueryConfirmIntersection: + builder.addExtension("SPV_KHR_ray_query"); + builder.addCapability(spv::CapabilityRayQueryKHR); + noReturnValue = true; + break; + case glslang::EOpRayQueryProceed: + case glslang::EOpRayQueryGetIntersectionType: + case glslang::EOpRayQueryGetRayTMin: + case glslang::EOpRayQueryGetRayFlags: + case glslang::EOpRayQueryGetIntersectionT: + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + case glslang::EOpRayQueryGetIntersectionInstanceId: + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + case glslang::EOpRayQueryGetIntersectionBarycentrics: + case glslang::EOpRayQueryGetIntersectionFrontFace: + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + case glslang::EOpRayQueryGetWorldRayDirection: + case glslang::EOpRayQueryGetWorldRayOrigin: + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + case glslang::EOpRayQueryGetIntersectionWorldToObject: + builder.addExtension("SPV_KHR_ray_query"); + builder.addCapability(spv::CapabilityRayQueryKHR); + break; case glslang::EOpCooperativeMatrixLoad: case glslang::EOpCooperativeMatrixStore: noReturnValue = true; @@ -2637,6 +3070,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; #endif + case glslang::EOpDebugPrintf: + noReturnValue = true; + break; + default: break; } @@ -2688,7 +3125,30 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt lvalue = true; break; + case glslang::EOpRayQueryInitialize: + case glslang::EOpRayQueryTerminate: + case glslang::EOpRayQueryConfirmIntersection: + case glslang::EOpRayQueryProceed: + case glslang::EOpRayQueryGenerateIntersection: + case glslang::EOpRayQueryGetIntersectionType: + case glslang::EOpRayQueryGetIntersectionT: + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + case glslang::EOpRayQueryGetIntersectionInstanceId: + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + case glslang::EOpRayQueryGetIntersectionBarycentrics: + case glslang::EOpRayQueryGetIntersectionFrontFace: + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + case glslang::EOpRayQueryGetIntersectionWorldToObject: + if (arg == 0) + lvalue = true; + break; + case glslang::EOpAtomicAdd: + case glslang::EOpAtomicSubtract: case glslang::EOpAtomicMin: case glslang::EOpAtomicMax: case glslang::EOpAtomicAnd: @@ -2709,13 +3169,24 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpInterpolateAtOffset: case glslang::EOpInterpolateAtVertex: if (arg == 0) { - lvalue = true; + // If GLSL, use the address of the interpolant argument. + // If HLSL, use an internal version of OpInterolates that takes + // the rvalue of the interpolant. A fixup pass in spirv-opt + // legalization will remove the OpLoad and convert to an lvalue. + // Had to do this because legalization will only propagate a + // builtin into an rvalue. + lvalue = glslangIntermediate->getSource() != glslang::EShSourceHlsl; // Does it need a swizzle inversion? If so, evaluation is inverted; // operate first on the swizzle base, then apply the swizzle. + // That is, we transform + // + // interpolate(v.zy) -> interpolate(v).zy + // if (glslangOperands[0]->getAsOperator() && glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); + invertedType = convertGlslangToSpvType( + glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); } break; case glslang::EOpAtomicLoad: @@ -2750,6 +3221,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt if (arg == 1) lvalue = true; break; + case glslang::EOpSpirvInst: + if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvByReference()) + lvalue = true; + break; #endif default: break; @@ -2775,8 +3250,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.setAccessChain(save); // Point to the first element of the array. - builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), - glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(elementId, + TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), + glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; unsigned int alignment = builder.getAccessChain().alignment; @@ -2786,7 +3262,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask; if (node->getOp() == glslang::EOpCooperativeMatrixStore) memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask; - if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) { + if (builder.getStorageClass(builder.getAccessChain().base) == + spv::StorageClassPhysicalStorageBufferEXT) { memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); } @@ -2796,8 +3273,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt memoryAccessOperands.push_back(spv::IdImmediate(false, alignment)); } - if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { - memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); + if (memoryAccess & + (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { + memoryAccessOperands.push_back(spv::IdImmediate(true, + builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); } } else if (arg == 2) { continue; @@ -2805,13 +3284,62 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt } #endif + // for l-values, pass the address, for r-values, pass the value if (lvalue) { - operands.push_back(builder.accessChainGetLValue()); + if (invertedType == spv::NoType && !builder.isSpvLvalue()) { + // SPIR-V cannot represent an l-value containing a swizzle that doesn't + // reduce to a simple access chain. So, we need a temporary vector to + // receive the result, and must later swizzle that into the original + // l-value. + complexLvalues.push_back(builder.getAccessChain()); + temporaryLvalues.push_back(builder.createVariable( + spv::NoPrecision, spv::StorageClassFunction, + builder.accessChainGetInferredType(), "swizzleTemp")); + operands.push_back(temporaryLvalues.back()); + } else { + operands.push_back(builder.accessChainGetLValue()); + } lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); } else { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); + glslang::TOperator glslangOp = node->getOp(); + if (arg == 1 && + (glslangOp == glslang::EOpRayQueryGetIntersectionType || + glslangOp == glslang::EOpRayQueryGetIntersectionT || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset || + glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics || + glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld || + glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject + )) { + bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst(); + operands.push_back(builder.makeIntConstant(cond ? 1 : 0)); + } else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) || + (arg == 11 && glslangOp == glslang::EOpTraceRayMotionNV) || + (arg == 1 && glslangOp == glslang::EOpExecuteCallableKHR)) { + const int opdNum = glslangOp == glslang::EOpTraceKHR ? 10 : (glslangOp == glslang::EOpTraceRayMotionNV ? 11 : 1); + const int set = glslangOp == glslang::EOpExecuteCallableKHR ? 1 : 0; + + const int location = glslangOperands[opdNum]->getAsConstantUnion()->getConstArray()[0].getUConst(); + auto itNode = locationToSymbol[set].find(location); + visitSymbol(itNode->second); + spv::Id symId = getSymbolId(itNode->second); + operands.push_back(symId); +#ifndef GLSLANG_WEB + } else if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvLiteral()) { + // Will be translated to a literal value, make a placeholder here + operands.push_back(spv::NoResult); +#endif + } else { + operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); + } } } @@ -2847,7 +3375,44 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt #endif if (atomic) { // Handle all atomics - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); + glslang::TBasicType typeProxy = (node->getOp() == glslang::EOpAtomicStore) + ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType(); + result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, + lvalueCoherentFlags); +#ifndef GLSLANG_WEB + } else if (node->getOp() == glslang::EOpSpirvInst) { + const auto& spirvInst = node->getSpirvInstruction(); + if (spirvInst.set == "") { + std::vector idImmOps; + for (int i = 0; i < glslangOperands.size(); ++i) { + if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) { + // Translate the constant to a literal value + std::vector literals; + glslang::TVector constants; + constants.push_back(glslangOperands[i]->getAsConstantUnion()); + TranslateLiterals(constants, literals); + idImmOps.push_back({false, literals[0]}); + } else + idImmOps.push_back({true, operands[i]}); + } + + if (node->getBasicType() == glslang::EbtVoid) + builder.createNoResultOp(static_cast(spirvInst.id), idImmOps); + else + result = builder.createOp(static_cast(spirvInst.id), resultType(), idImmOps); + } else { + result = builder.createBuiltinCall( + resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), + spirvInst.id, operands); + } + noReturnValue = node->getBasicType() == glslang::EbtVoid; +#endif + } else if (node->getOp() == glslang::EOpDebugPrintf) { + if (!nonSemanticDebugPrintf) { + nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf"); + } + result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands); + builder.addExtension(spv::E_SPV_KHR_non_semantic_info); } else { // Pass through to generic operations. switch (glslangOperands.size()) { @@ -2869,8 +3434,15 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); break; } - if (invertedType) + + if (invertedType != spv::NoResult) result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); + + for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) { + builder.setAccessChain(complexLvalues[i]); + builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision), + TranslateNonUniformDecoration(complexLvalues[i].coherentFlags)); + } } if (noReturnValue) @@ -2986,7 +3558,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang } else { // We need control flow to select the result. // TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path. - result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); + result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), + spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); // Selection control: const spv::SelectionControlMask control = TranslateSelectionControl(*node); @@ -3011,8 +3584,10 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang // Execute the one side needed, as per the condition const auto executeOneSide = [&]() { // Always emit control flow. - if (node->getBasicType() != glslang::EbtVoid) - result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); + if (node->getBasicType() != glslang::EbtVoid) { + result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), spv::StorageClassFunction, + convertGlslangToSpvType(node->getType())); + } // Selection control: const spv::SelectionControlMask control = TranslateSelectionControl(*node); @@ -3077,7 +3652,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T defaultSegment = (int)codeSegments.size(); else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst()); + caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion() + ->getConstArray()[0].getIConst()); } else codeSegments.push_back(child); } @@ -3090,7 +3666,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T // make the switch statement std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks); + builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, + segmentBlocks); // emit all the code in the segments breakForLoop.push(false); @@ -3110,6 +3687,11 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) { +#ifndef GLSLANG_WEB + if (node->getQualifier().isSpirvLiteral()) + return; // Translated to a literal value, skip further processing +#endif + int nextConst = 0; spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); @@ -3195,7 +3777,11 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T switch (node->getFlowOp()) { case glslang::EOpKill: - builder.makeDiscard(); + builder.makeStatementTerminator(spv::OpKill, "post-discard"); + break; + case glslang::EOpTerminateInvocation: + builder.addExtension(spv::E_SPV_KHR_terminate_invocation); + builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation"); break; case glslang::EOpBreak: if (breakForLoop.top()) @@ -3207,15 +3793,17 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T builder.createLoopContinue(); break; case glslang::EOpReturn: - if (node->getExpression()) { + if (node->getExpression() != nullptr) { const glslang::TType& glslangReturnType = node->getExpression()->getType(); spv::Id returnId = accessChainLoad(glslangReturnType); - if (builder.getTypeId(returnId) != currentFunction->getReturnType()) { + if (builder.getTypeId(returnId) != currentFunction->getReturnType() || + TranslatePrecisionDecoration(glslangReturnType) != currentFunction->getReturnPrecision()) { builder.clearAccessChain(); - spv::Id copyId = builder.createVariable(spv::StorageClassFunction, currentFunction->getReturnType()); + spv::Id copyId = builder.createVariable(currentFunction->getReturnPrecision(), + spv::StorageClassFunction, currentFunction->getReturnType()); builder.setAccessChainLValue(copyId); multiTypeStore(glslangReturnType, returnId); - returnId = builder.createLoad(copyId); + returnId = builder.createLoad(copyId, currentFunction->getReturnPrecision()); } builder.makeReturn(false, returnId); } else @@ -3230,6 +3818,12 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); break; + case glslang::EOpTerminateRayKHR: + builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR"); + break; + case glslang::EOpIgnoreIntersectionKHR: + builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR"); + break; #endif default: @@ -3284,6 +3878,11 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* break; #endif default: + if (storageClass == spv::StorageClassWorkgroup && + node->getType().getBasicType() == glslang::EbtBlock) { + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR); + break; + } if (node->getType().contains16BitFloat()) builder.addCapability(spv::CapabilityFloat16); if (node->getType().contains16BitInt()) @@ -3302,6 +3901,9 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* } else if (storageClass == spv::StorageClassStorageBuffer) { builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); + } else if (storageClass == spv::StorageClassWorkgroup && + node->getType().getBasicType() == glslang::EbtBlock) { + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR); } else { builder.addCapability(spv::CapabilityInt8); } @@ -3311,7 +3913,19 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* if (glslang::IsAnonymous(name)) name = ""; - return builder.createVariable(storageClass, spvType, name); + spv::Id initializer = spv::NoResult; + + if (node->getType().getQualifier().storage == glslang::EvqUniform && !node->getConstArray().empty()) { + int nextConst = 0; + initializer = createSpvConstantFromConstUnionArray(node->getType(), + node->getConstArray(), + nextConst, + false /* specConst */); + } else if (node->getType().getQualifier().isNullInit()) { + initializer = builder.makeNullConstant(spvType); + } + + return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer); } // Return type Id of the sampled type. @@ -3326,6 +3940,12 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); builder.addCapability(spv::CapabilityFloat16ImageAMD); return builder.makeFloatType(16); + case glslang::EbtInt64: return builder.makeIntType(64); + builder.addExtension(spv::E_SPV_EXT_shader_image_int64); + builder.addCapability(spv::CapabilityFloat16ImageAMD); + case glslang::EbtUint64: return builder.makeUintType(64); + builder.addExtension(spv::E_SPV_EXT_shader_image_int64); + builder.addCapability(spv::CapabilityFloat16ImageAMD); #endif default: assert(0); @@ -3347,7 +3967,8 @@ spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyp // When inverting a swizzle with a parent op, this function // will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult) +spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, + spv::Id parentResult) { std::vector swizzle; convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); @@ -3430,8 +4051,37 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty builder.addCapability(spv::CapabilityAtomicStorage); spvType = builder.makeUintType(32); break; - case glslang::EbtAccStructNV: - spvType = builder.makeAccelerationStructureNVType(); + case glslang::EbtAccStruct: + switch (glslangIntermediate->getStage()) { + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: + // these all should have the RayTracingNV/KHR capability already + break; + default: + { + auto& extensions = glslangIntermediate->getRequestedExtensions(); + if (extensions.find("GL_EXT_ray_query") != extensions.end()) { + builder.addExtension(spv::E_SPV_KHR_ray_query); + builder.addCapability(spv::CapabilityRayQueryKHR); + } + } + break; + } + spvType = builder.makeAccelerationStructureType(); + break; + case glslang::EbtRayQuery: + { + auto& extensions = glslangIntermediate->getRequestedExtensions(); + if (extensions.find("GL_EXT_ray_query") != extensions.end()) { + builder.addExtension(spv::E_SPV_KHR_ray_query); + builder.addCapability(spv::CapabilityRayQueryKHR); + } + spvType = builder.makeRayQueryType(); + } break; case glslang::EbtReference: { @@ -3483,10 +4133,84 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // else, we haven't seen it... if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers].resize(glslangMembers->size()); + memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size()); spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); } break; + case glslang::EbtString: + // no type used for OpString + return 0; +#ifndef GLSLANG_WEB + case glslang::EbtSpirvType: { + // GL_EXT_spirv_intrinsics + const auto& spirvType = type.getSpirvType(); + const auto& spirvInst = spirvType.spirvInst; + + std::vector operands; + for (const auto& typeParam : spirvType.typeParams) { + if (typeParam.isConstant) { + // Constant expression + if (typeParam.constant->isLiteral()) { + if (typeParam.constant->getBasicType() == glslang::EbtFloat) { + float floatValue = static_cast(typeParam.constant->getConstArray()[0].getDConst()); + unsigned literal = *reinterpret_cast(&floatValue); + operands.push_back(literal); + } else if (typeParam.constant->getBasicType() == glslang::EbtInt) { + unsigned literal = typeParam.constant->getConstArray()[0].getIConst(); + operands.push_back(literal); + } else if (typeParam.constant->getBasicType() == glslang::EbtUint) { + unsigned literal = typeParam.constant->getConstArray()[0].getUConst(); + operands.push_back(literal); + } else if (typeParam.constant->getBasicType() == glslang::EbtBool) { + unsigned literal = typeParam.constant->getConstArray()[0].getBConst(); + operands.push_back(literal); + } else if (typeParam.constant->getBasicType() == glslang::EbtString) { + auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str(); + unsigned literal = 0; + char* literalPtr = reinterpret_cast(&literal); + unsigned charCount = 0; + char ch = 0; + do { + ch = *(str++); + *(literalPtr++) = ch; + ++charCount; + if (charCount == 4) { + operands.push_back(literal); + literalPtr = reinterpret_cast(&literal); + charCount = 0; + } + } while (ch != 0); + + // Partial literal is padded with 0 + if (charCount > 0) { + for (; charCount < 4; ++charCount) + *(literalPtr++) = 0; + operands.push_back(literal); + } + } else + assert(0); // Unexpected type + } else { + int nextConst = 0; + spv::Id constant = createSpvConstantFromConstUnionArray( + typeParam.constant->getType(), typeParam.constant->getConstArray(), nextConst, false); + operands.push_back(constant); + } + } else { + // Type specifier + spv::Id typeId = convertGlslangToSpvType(*typeParam.type); + operands.push_back(typeId); + } + } + + if (spirvInst.set == "") + spvType = builder.createOp(static_cast(spirvInst.id), spv::NoType, operands); + else { + spvType = builder.createBuiltinCall( + spv::NoType, getExtBuiltins(spirvInst.set.c_str()), spirvInst.id, operands); + } + break; + } +#endif default: assert(0); break; @@ -3612,22 +4336,23 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy { // Create a vector of struct types for SPIR-V to consume std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks + int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, + // except sometimes for blocks std::vector > deferredForwardPointers; for (int i = 0; i < (int)glslangMembers->size(); i++) { glslang::TType& glslangMember = *(*glslangMembers)[i].type; if (glslangMember.hiddenMember()) { ++memberDelta; if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers][i] = -1; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; } else { if (type.getBasicType() == glslang::EbtBlock) { if (filterMember(glslangMember)) { memberDelta++; - memberRemapper[glslangMembers][i] = -1; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; continue; } - memberRemapper[glslangMembers][i] = i - memberDelta; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; } // modify just this child's view of the qualifier glslang::TQualifier memberQualifier = glslangMember.getQualifier(); @@ -3648,10 +4373,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier)); } spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true)); + convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, + true)); } else { spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false)); + convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, + false)); } } } @@ -3680,12 +4407,13 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, { // Name and decorate the non-hidden members int offset = -1; - int locationOffset = 0; // for use within the members of this struct + bool memberLocationInvalid = type.isArrayOfArrays() || + (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false)); for (int i = 0; i < (int)glslangMembers->size(); i++) { glslang::TType& glslangMember = *(*glslangMembers)[i].type; int member = i; if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangMembers][i]; + member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i]; if (filterMember(glslangMember)) continue; } @@ -3733,13 +4461,9 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, // just track whether a member needs to be decorated. // Ignore member locations if the container is an array, as that's // ill-specified and decisions have been made to not allow this. - if (! type.isArray() && memberQualifier.hasLocation()) + if (!memberLocationInvalid && memberQualifier.hasLocation()) builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); - if (qualifier.hasLocation()) // track for upcoming inheritance - locationOffset += glslangIntermediate->computeTypeLocationSize( - glslangMember, glslangIntermediate->getStage()); - // component, XFB, others if (glslangMember.getQualifier().hasComponent()) builder.addMemberDecoration(spvType, member, spv::DecorationComponent, @@ -3795,6 +4519,38 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); } + + // + // Add SPIR-V decorations for members (GL_EXT_spirv_intrinsics) + // + if (glslangMember.getQualifier().hasSprivDecorate()) { + const glslang::TSpirvDecorate& spirvDecorate = glslangMember.getQualifier().getSpirvDecorate(); + + // Add spirv_decorate + for (auto& decorate : spirvDecorate.decorates) { + if (!decorate.second.empty()) { + std::vector literals; + TranslateLiterals(decorate.second, literals); + builder.addMemberDecoration(spvType, member, static_cast(decorate.first), literals); + } + else + builder.addMemberDecoration(spvType, member, static_cast(decorate.first)); + } + + // spirv_decorate_id not applied to members + assert(spirvDecorate.decorateIds.empty()); + + // Add spirv_decorate_string + for (auto& decorateString : spirvDecorate.decorateStrings) { + std::vector strings; + assert(!decorateString.second.empty()); + for (auto extraOperand : decorateString.second) { + const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); + strings.push_back(string); + } + builder.addDecoration(spvType, static_cast(decorateString.first), strings); + } + } #endif } @@ -3813,6 +4569,8 @@ spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arra glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim); if (specNode != nullptr) { builder.clearAccessChain(); + SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); specNode->traverse(this); return accessChainLoad(specNode->getAsTyped()->getType()); } @@ -3839,26 +4597,16 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) alignment |= type.getBufferReferenceAlignment(); spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), - TranslateNonUniformDecoration(type.getQualifier()), - nominalTypeId, - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask), - TranslateMemoryScope(coherentFlags), - alignment); + TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), + TranslateNonUniformDecoration(type.getQualifier()), + nominalTypeId, + spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask), + TranslateMemoryScope(coherentFlags), + alignment); // Need to convert to abstract types when necessary if (type.getBasicType() == glslang::EbtBool) { - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) - loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } + loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId); } return loadedId; @@ -3905,8 +4653,9 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I unsigned int alignment = builder.getAccessChain().alignment; alignment |= type.getBufferReferenceAlignment(); - builder.accessChainStore(rvalue, - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask), + builder.accessChainStore(rvalue, TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), + spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & + ~spv::MemoryAccessMakePointerVisibleKHRMask), TranslateMemoryScope(coherentFlags), alignment); } @@ -3967,7 +4716,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // set up the target storage builder.clearAccessChain(); builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), + type.getBufferReferenceAlignment()); // store the member multiTypeStore(glslangElementType, elementRValue); @@ -3987,7 +4737,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // set up the target storage builder.clearAccessChain(); builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), + type.getBufferReferenceAlignment()); // store the member multiTypeStore(glslangMemberType, memberRValue); @@ -4007,6 +4758,7 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: // has to be a uniform or buffer block or task in/out blocks if (type.getQualifier().storage != glslang::EvqUniform && type.getQualifier().storage != glslang::EvqBuffer && + type.getQualifier().storage != glslang::EvqShared && !type.getQualifier().isTaskMemory()) return glslang::ElpNone; @@ -4022,18 +4774,21 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: } // Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, + glslang::TLayoutMatrix matrixLayout) { int size; int stride; - glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); return stride; } // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix // when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, + glslang::TLayoutMatrix matrixLayout) { glslang::TType elementType; elementType.shallowCopy(matrixType); @@ -4041,7 +4796,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl int size; int stride; - glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); return stride; } @@ -4052,8 +4808,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting // the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. // -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, - glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, + int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { // this will get a positive value when deemed necessary nextOffset = -1; @@ -4083,7 +4839,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType int memberSize; int dummyStride; - int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); // Adjust alignment for HLSL rules // TODO: make this consistent in early phases of code: @@ -4102,7 +4859,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType glslang::RoundToPow2(currentOffset, memberAlignment); // Bump up to vec4 if there is a bad straddle - if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset)) + if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, + currentOffset)) glslang::RoundToPow2(currentOffset, 16); nextOffset = currentOffset + memberSize; @@ -4155,8 +4913,10 @@ bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) assert(qualifier == glslang::EvqIn || qualifier == glslang::EvqOut || qualifier == glslang::EvqInOut || + qualifier == glslang::EvqUniform || qualifier == glslang::EvqConstReadOnly); - return qualifier != glslang::EvqConstReadOnly; + return qualifier != glslang::EvqConstReadOnly && + qualifier != glslang::EvqUniform; } // Is parameter pass-by-original? @@ -4168,13 +4928,17 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) return paramType.getBasicType() == glslang::EbtBlock; return paramType.containsOpaque() || // sampler, etc. +#ifndef GLSLANG_WEB + paramType.getQualifier().isSpirvByReference() || // spirv_by_reference +#endif (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO } // Make all the functions, skeletally, without actually visiting their bodies. void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) { - const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, bool useVulkanMemoryModel) { + const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, + bool useVulkanMemoryModel) { spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); if (paramPrecision != spv::NoPrecision) decorations.push_back(paramPrecision); @@ -4272,7 +5036,8 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen builder.setBuildPoint(shaderEntry->getLastBlock()); for (int i = 0; i < (int)initializers.size(); ++i) { glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) { + if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != + glslang::EOpLinkerObjects) { // We're on a top-level node that's not a function. Treat as an initializer, whose // code goes into the beginning of the entry point. @@ -4280,7 +5045,39 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen } } } +// Walk over all linker objects to create a map for payload and callable data linker objects +// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR +// This is done here since it is possible that these linker objects are not be referenced in the AST +void TGlslangToSpvTraverser::collectRayTracingLinkerObjects() +{ + glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects(); + for (auto& objSeq : linkerObjects->getSequence()) { + auto objNode = objSeq->getAsSymbolNode(); + if (objNode != nullptr) { + if (objNode->getQualifier().hasLocation()) { + unsigned int location = objNode->getQualifier().layoutLocation; + auto st = objNode->getQualifier().storage; + int set; + switch (st) + { + case glslang::EvqPayload: + case glslang::EvqPayloadIn: + set = 0; + break; + case glslang::EvqCallableData: + case glslang::EvqCallableDataIn: + set = 1; + break; + default: + set = -1; + } + if (set != -1) + locationToSymbol[set].insert(std::make_pair(location, objNode)); + } + } + } +} // Process all the functions, while skipping initializers. void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions) { @@ -4300,7 +5097,8 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate builder.setBuildPoint(functionBlock); } -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) +void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, + spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { const glslang::TIntermSequence& glslangArguments = node.getSequence(); @@ -4313,7 +5111,8 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; #ifndef GLSLANG_WEB - f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; + f16ShadowCompare = sampler.shadow && + glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; #endif } @@ -4422,8 +5221,10 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& } if (lvalue) { - arguments.push_back(builder.accessChainGetLValue()); + spv::Id lvalue_id = builder.accessChainGetLValue(); + arguments.push_back(lvalue_id); lvalueCoherentFlags = builder.getAccessChain().coherentFlags; + builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags)); lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType()); } else #endif @@ -4476,7 +5277,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags); else translateArguments(*node->getAsUnaryNode(), arguments); - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); + spv::Decoration precision = TranslatePrecisionDecoration(node->getType()); spv::Builder::TextureParameters params = { }; params.sampler = arguments[0]; @@ -4486,12 +5287,15 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint; + if (builder.isSampledImage(params.sampler) && + ((cracked.query && node->getOp() != glslang::EOpTextureQueryLod) || cracked.fragMask || cracked.fetch)) { + params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); + if (imageType.getQualifier().isNonUniform()) { + builder.addDecoration(params.sampler, spv::DecorationNonUniformEXT); + } + } // Check for queries if (cracked.query) { - // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first - if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - switch (node->getOp()) { case glslang::EOpImageQuerySize: case glslang::EOpTextureQuerySize: @@ -4520,7 +5324,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO int components = node->getType().getVectorSize(); - if (node->getOp() == glslang::EOpTextureFetch) { + if (node->getOp() == glslang::EOpImageLoad || + node->getOp() == glslang::EOpImageLoadLod || + node->getOp() == glslang::EOpTextureFetch || + node->getOp() == glslang::EOpTextureFetchOffset) { // These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed. // This will only happen through the HLSL path for operator[], so we do not have to handle e.g. // the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic @@ -4689,7 +5496,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO operands.push_back(imageOperand); } if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; + spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope( + TranslateCoherent(imageType))) }; operands.push_back(imageOperand); } @@ -4717,18 +5525,22 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // imageAtomicStore has a void return type so base the pointer type on // the type of the value operand. if (node->getOp() == glslang::EOpImageAtomicStore) { - resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(operands[2].word)); + resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt)); } else { resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); } spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); + if (imageType.getQualifier().nonUniform) { + builder.addDecoration(pointer, spv::DecorationNonUniformEXT); + } std::vector operands; operands.push_back(pointer); for (; opIt != arguments.end(); ++opIt) operands.push_back(*opIt); - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); + return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), + lvalueCoherentFlags); } } @@ -4740,10 +5552,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO auto opIt = arguments.begin(); std::vector operands; - // Extract the image if necessary - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - operands.push_back(params.sampler); ++opIt; @@ -4753,7 +5561,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO std::vector comps; comps.push_back(zero); comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); + operands.push_back(builder.makeCompositeConstant( + builder.makeVectorType(builder.makeIntType(32), 2), comps)); } for (; opIt != arguments.end(); ++opIt) @@ -4803,13 +5612,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO bias = true; } - // See if the sampler param should really be just the SPV image part - if (cracked.fetch) { - // a fetch needs to have the image extracted first - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - } - #ifndef GLSLANG_WEB if (cracked.gather) { const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); @@ -4842,7 +5644,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO else dRefComp = builder.getNumComponents(params.coords) - 1; indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); + params.Dref = builder.createCompositeExtract(params.coords, + builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); } // lod @@ -4967,7 +5770,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO flags.clear(); builder.accessChainPush(builder.makeIntConstant(i), flags, 0); - builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1)); + builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), + i+1), TranslateNonUniformDecoration(imageType.getQualifier())); } return builder.createCompositeExtract(res, resultType(), 0); } @@ -4990,10 +5794,9 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // copy the projective coordinate if we have to if (projTargetComp != projSourceComp) { spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), - projSourceComp); + builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp); params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); + builder.getTypeId(params.coords), projTargetComp); } } @@ -5073,7 +5876,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg ++lValueCount; } else if (writableParam(qualifiers[a])) { // need space to hold the copy - arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param"); + arg = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, + builder.getContainedTypeId(function->getParamType(a)), "param"); if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { // need to copy the input into output space builder.setAccessChain(lValues[lValueCount]); @@ -5085,12 +5889,14 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg ++lValueCount; } else { // process r-value, which involves a copy for a type mismatch - if (function->getParamType(a) != convertGlslangToSpvType(*argTypes[a])) { - spv::Id argCopy = builder.createVariable(spv::StorageClassFunction, function->getParamType(a), "arg"); + if (function->getParamType(a) != builder.getTypeId(rValues[rValueCount]) || + TranslatePrecisionDecoration(*argTypes[a]) != function->getParamPrecision(a)) + { + spv::Id argCopy = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, function->getParamType(a), "arg"); builder.clearAccessChain(); builder.setAccessChainLValue(argCopy); multiTypeStore(*argTypes[a], rValues[rValueCount]); - arg = builder.createLoad(argCopy); + arg = builder.createLoad(argCopy, function->getParamPrecision(a)); } else arg = rValues[rValueCount]; ++rValueCount; @@ -5101,6 +5907,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg // 3. Make the call. spv::Id result = builder.createFunctionCall(function, spvArgs); builder.setPrecision(result, TranslatePrecisionDecoration(node->getType())); + builder.addDecoration(result, TranslateNonUniformDecoration(node->getType().getQualifier())); // 4. Copy back out an "out" arguments. lValueCount = 0; @@ -5109,7 +5916,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg ++lValueCount; else if (writableParam(qualifiers[a])) { if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) { - spv::Id copy = builder.createLoad(spvArgs[a]); + spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision); + builder.addDecoration(copy, TranslateNonUniformDecoration(argTypes[a]->getQualifier())); builder.setAccessChain(lValues[lValueCount]); multiTypeStore(*argTypes[a], copy); } @@ -5354,7 +6162,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD case glslang::EOpNotEqual: case glslang::EOpVectorNotEqual: if (isFloat) - binOp = spv::OpFOrdNotEqual; + binOp = spv::OpFUnordNotEqual; else if (isBool) binOp = spv::OpLogicalNotEqual; else @@ -5488,7 +6296,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora } spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) + spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op unaryOp = spv::OpNop; int extBuiltins = -1; @@ -5749,6 +6557,24 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpFwidthCoarse: unaryOp = spv::OpFwidthCoarse; break; + case glslang::EOpRayQueryProceed: + unaryOp = spv::OpRayQueryProceedKHR; + break; + case glslang::EOpRayQueryGetRayTMin: + unaryOp = spv::OpRayQueryGetRayTMinKHR; + break; + case glslang::EOpRayQueryGetRayFlags: + unaryOp = spv::OpRayQueryGetRayFlagsKHR; + break; + case glslang::EOpRayQueryGetWorldRayOrigin: + unaryOp = spv::OpRayQueryGetWorldRayOriginKHR; + break; + case glslang::EOpRayQueryGetWorldRayDirection: + unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR; + break; + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; + break; case glslang::EOpInterpolateAtCentroid: if (typeProxy == glslang::EbtFloat16) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); @@ -5879,6 +6705,11 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpConstructReference: unaryOp = spv::OpBitcast; break; + + case glslang::EOpConvUint64ToAccStruct: + case glslang::EOpConvUvec2ToAccStruct: + unaryOp = spv::OpConvertUToAccelerationStructureKHR; + break; #endif case glslang::EOpCopyObject: @@ -6034,7 +6865,7 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora case glslang::EOpConvFloatToBool: zero = builder.makeFloatConstant(0.0F); zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); + return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); case glslang::EOpConvBoolToFloat: convOp = spv::OpSelect; zero = builder.makeFloatConstant(0.0F); @@ -6183,11 +7014,11 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora case glslang::EOpConvDoubleToBool: zero = builder.makeDoubleConstant(0.0); zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); + return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); case glslang::EOpConvFloat16ToBool: zero = builder.makeFloat16Constant(0.0F); zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); + return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); case glslang::EOpConvBoolToDouble: convOp = spv::OpSelect; zero = builder.makeDoubleConstant(0.0); @@ -6341,9 +7172,6 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora break; case glslang::EOpConvPtrToUvec2: case glslang::EOpConvUvec2ToPtr: - if (builder.isVector(operand)) - builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, - spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5); convOp = spv::OpBitcast; break; #endif @@ -6381,7 +7209,9 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector } // For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) +spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, + spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op opCode = spv::OpNop; @@ -6390,19 +7220,58 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv case glslang::EOpImageAtomicAdd: case glslang::EOpAtomicCounterAdd: opCode = spv::OpAtomicIAdd; + if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { + opCode = spv::OpAtomicFAddEXT; + builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_add); + if (typeProxy == glslang::EbtFloat16) { + builder.addExtension(spv::E_SPV_EXT_shader_atomic_float16_add); + builder.addCapability(spv::CapabilityAtomicFloat16AddEXT); + } else if (typeProxy == glslang::EbtFloat) { + builder.addCapability(spv::CapabilityAtomicFloat32AddEXT); + } else { + builder.addCapability(spv::CapabilityAtomicFloat64AddEXT); + } + } break; + case glslang::EOpAtomicSubtract: case glslang::EOpAtomicCounterSubtract: opCode = spv::OpAtomicISub; break; case glslang::EOpAtomicMin: case glslang::EOpImageAtomicMin: case glslang::EOpAtomicCounterMin: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin; + if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { + opCode = spv::OpAtomicFMinEXT; + builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); + if (typeProxy == glslang::EbtFloat16) + builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); + else if (typeProxy == glslang::EbtFloat) + builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); + else + builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); + } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { + opCode = spv::OpAtomicUMin; + } else { + opCode = spv::OpAtomicSMin; + } break; case glslang::EOpAtomicMax: case glslang::EOpImageAtomicMax: case glslang::EOpAtomicCounterMax: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax; + if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { + opCode = spv::OpAtomicFMaxEXT; + builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); + if (typeProxy == glslang::EbtFloat16) + builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); + else if (typeProxy == glslang::EbtFloat) + builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); + else + builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); + } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { + opCode = spv::OpAtomicUMax; + } else { + opCode = spv::OpAtomicSMax; + } break; case glslang::EOpAtomicAnd: case glslang::EOpImageAtomicAnd: @@ -6467,7 +7336,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv scopeId = builder.makeUintConstant(spv::ScopeDevice); } // semantics default to relaxed - spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ? + spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && + glslangIntermediate->usingVulkanMemoryModel() ? spv::MemorySemanticsVolatileMask : spv::MemorySemanticsMaskNone); spv::Id semanticsId2 = semanticsId; @@ -6480,20 +7350,24 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv valueId = operands[2]; if (operands.size() > 3) { scopeId = operands[3]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); - semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); + semanticsId = builder.makeUintConstant( + builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); + semanticsId2 = builder.makeUintConstant( + builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); } } else if (opCode == spv::OpAtomicLoad) { if (operands.size() > 1) { scopeId = operands[1]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); + semanticsId = builder.makeUintConstant( + builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); } } else { // atomic store or RMW valueId = operands[1]; if (operands.size() > 2) { scopeId = operands[2]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); + semanticsId = builder.makeUintConstant + (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); } } @@ -6506,6 +7380,10 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } + if (builder.getConstantScalar(scopeId) == spv::ScopeQueueFamily) { + builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); + } + if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); } @@ -6538,7 +7416,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv } // Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy) { bool isUnsigned = isTypeUnsignedInt(typeProxy); bool isFloat = isTypeFloat(typeProxy); @@ -6752,8 +7631,10 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || op == spv::OpSubgroupReadInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD || + op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || + op == spv::OpGroupSMinNonUniformAMD || + op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || + op == spv::OpGroupSMaxNonUniformAMD || op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); // Handle group invocation operations scalar by scalar. @@ -7142,7 +8023,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s return builder.createOp(opCode, typeId, spvGroupOperands); } -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, + spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) { bool isUnsigned = isTypeUnsignedInt(typeProxy); bool isFloat = isTypeFloat(typeProxy); @@ -7244,14 +8126,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: unsigned int executionScope = builder.getConstantScalar(operands[0]); unsigned int memoryScope = builder.getConstantScalar(operands[1]); unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); - builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); + builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, + (spv::MemorySemanticsMask)semantics); if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask | spv::MemorySemanticsVolatileMask)) { builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } - if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) { + if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || + memoryScope == spv::ScopeDevice)) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); } return 0; @@ -7334,7 +8218,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: if (builder.getNumComponents(operands[0]) == 1) frexpIntType = builder.makeIntegerType(width, true); else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0])); + frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), + builder.getNumComponents(operands[0])); typeId = builder.makeStructResultType(typeId0, frexpIntType); consumedOperands = 1; } @@ -7437,24 +8322,116 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: libCall = spv::InterpolateAtVertexAMD; break; - case glslang::EOpReportIntersectionNV: - { + case glslang::EOpReportIntersection: typeId = builder.makeBoolType(); - opCode = spv::OpReportIntersectionNV; - } - break; + opCode = spv::OpReportIntersectionKHR; + break; case glslang::EOpTraceNV: - { builder.createNoResultOp(spv::OpTraceNV, operands); return 0; - } - break; + case glslang::EOpTraceRayMotionNV: + builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); + builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); + builder.createNoResultOp(spv::OpTraceRayMotionNV, operands); + return 0; + case glslang::EOpTraceKHR: + builder.createNoResultOp(spv::OpTraceRayKHR, operands); + return 0; case glslang::EOpExecuteCallableNV: - { builder.createNoResultOp(spv::OpExecuteCallableNV, operands); return 0; - } - break; + case glslang::EOpExecuteCallableKHR: + builder.createNoResultOp(spv::OpExecuteCallableKHR, operands); + return 0; + + case glslang::EOpRayQueryInitialize: + builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands); + return 0; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands); + return 0; + case glslang::EOpRayQueryGenerateIntersection: + builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands); + return 0; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands); + return 0; + case glslang::EOpRayQueryProceed: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryProceedKHR; + break; + case glslang::EOpRayQueryGetIntersectionType: + typeId = builder.makeUintType(32); + opCode = spv::OpRayQueryGetIntersectionTypeKHR; + break; + case glslang::EOpRayQueryGetRayTMin: + typeId = builder.makeFloatType(32); + opCode = spv::OpRayQueryGetRayTMinKHR; + break; + case glslang::EOpRayQueryGetRayFlags: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetRayFlagsKHR; + break; + case glslang::EOpRayQueryGetIntersectionT: + typeId = builder.makeFloatType(32); + opCode = spv::OpRayQueryGetIntersectionTKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceId: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + typeId = builder.makeUintType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR; + break; + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionBarycentrics: + typeId = builder.makeVectorType(builder.makeFloatType(32), 2); + opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR; + break; + case glslang::EOpRayQueryGetIntersectionFrontFace: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR; + break; + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR; + break; + case glslang::EOpRayQueryGetWorldRayDirection: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetWorldRayDirectionKHR; + break; + case glslang::EOpRayQueryGetWorldRayOrigin: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetWorldRayOriginKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); + opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR; + break; + case glslang::EOpRayQueryGetIntersectionWorldToObject: + typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); + opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR; + break; case glslang::EOpWritePackedPrimitiveIndices4x8NV: builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); return 0; @@ -7544,7 +8521,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) { // GLSL memory barriers use queuefamily scope in new model, device scope in old model - spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; + spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? + spv::ScopeQueueFamilyKHR : spv::ScopeDevice; switch (op) { case glslang::EOpBarrier: @@ -7656,7 +8634,18 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: case glslang::EOpTerminateRayNV: builder.createNoResultOp(spv::OpTerminateRayNV); return 0; - + case glslang::EOpRayQueryInitialize: + builder.createNoResultOp(spv::OpRayQueryInitializeKHR); + return 0; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR); + return 0; + case glslang::EOpRayQueryGenerateIntersection: + builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR); + return 0; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR); + return 0; case glslang::EOpBeginInvocationInterlock: builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT); return 0; @@ -7708,7 +8697,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol // it was not found, create it spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - auto forcedType = getForcedType(builtIn, symbol->getType()); + auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); id = createSpvVariable(symbol, forcedType.first); symbolValues[symbol->getId()] = id; if (forcedType.second != spv::NoType) @@ -7771,16 +8760,15 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol } #ifndef GLSLANG_WEB - if (symbol->getType().isImage()) { + // Subgroup builtins which have input storage class are volatile for ray tracing stages. + if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) { std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel()); + TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, + glslangIntermediate->usingVulkanMemoryModel()); for (unsigned int i = 0; i < memory.size(); ++i) builder.addDecoration(id, memory[i]); } - // nonuniform - builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier())); - if (builtIn == spv::BuiltInSampleMask) { spv::Decoration decoration; // GL_NV_sample_mask_override_coverage extension @@ -7827,7 +8815,50 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol } if (symbol->isReference()) { - builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); + builder.addDecoration(id, symbol->getType().getQualifier().restrict ? + spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); + } + + // + // Add SPIR-V decorations for structure (GL_EXT_spirv_intrinsics) + // + if (symbol->getType().getQualifier().hasSprivDecorate()) { + const glslang::TSpirvDecorate& spirvDecorate = symbol->getType().getQualifier().getSpirvDecorate(); + + // Add spirv_decorate + for (auto& decorate : spirvDecorate.decorates) { + if (!decorate.second.empty()) { + std::vector literals; + TranslateLiterals(decorate.second, literals); + builder.addDecoration(id, static_cast(decorate.first), literals); + } + else + builder.addDecoration(id, static_cast(decorate.first)); + } + + // Add spirv_decorate_id + for (auto& decorateId : spirvDecorate.decorateIds) { + std::vector operandIds; + assert(!decorateId.second.empty()); + for (auto extraOperand : decorateId.second) { + int nextConst = 0; + spv::Id operandId = createSpvConstantFromConstUnionArray( + extraOperand->getType(), extraOperand->getConstArray(), nextConst, false); + operandIds.push_back(operandId); + } + builder.addDecoration(id, static_cast(decorateId.first), operandIds); + } + + // Add spirv_decorate_string + for (auto& decorateString : spirvDecorate.decorateStrings) { + std::vector strings; + assert(!decorateString.second.empty()); + for (auto extraOperand : decorateString.second) { + const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); + strings.push_back(string); + } + builder.addDecoration(id, static_cast(decorateString.first), strings); + } } #endif @@ -7889,12 +8920,25 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // hand off to the non-spec-constant path assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? + node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + nextConst, false); } // We now know we have a specialization constant to build + // Extra capabilities may be needed. + if (node.getType().contains8BitInt()) + builder.addCapability(spv::CapabilityInt8); + if (node.getType().contains16BitFloat()) + builder.addCapability(spv::CapabilityFloat16); + if (node.getType().contains16BitInt()) + builder.addCapability(spv::CapabilityInt16); + if (node.getType().contains64BitInt()) + builder.addCapability(spv::CapabilityInt64); + if (node.getType().containsDouble()) + builder.addCapability(spv::CapabilityFloat64); + // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants, // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { @@ -7943,7 +8987,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // If there are not enough elements present in 'consts', 0 will be substituted; // an empty 'consts' can be used to create a fully zeroed SPIR-V constant. // -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, + const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) { // vector of constants for SPIR-V std::vector spvConsts; @@ -8061,6 +9106,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar); break; #endif + case glslang::EbtString: + scalar = builder.getStringId(consts[nextConst].getSConst()->c_str()); + break; default: assert(0); break; @@ -8161,7 +9209,8 @@ bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) // Emit short-circuiting code, where 'right' is never evaluated unless // the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right) +spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, + glslang::TIntermTyped& right) { spv::Id boolTypeId = builder.makeBoolType(); @@ -8245,7 +9294,9 @@ int GetSpirvGeneratorVersion() // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code, // versions 4 and 6 each generate OpArrayLength as it has long been done // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent - return 8; // switch to new dead block eliminator; use OpUnreachable + // return 8; // switch to new dead block eliminator; use OpUnreachable + // return 9; // don't include opaque function parameters in OpEntryPoint global's operand list + return 10; // Generate OpFUnordNotEqual for != comparisons } // Write SPIR-V out to a binary file @@ -8265,14 +9316,15 @@ void OutputSpvBin(const std::vector& spirv, const char* baseName) // Write SPIR-V out to a text file with 32-bit hexadecimal words void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName) { -#ifndef GLSLANG_WEB +#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) std::ofstream out; out.open(baseName, std::ios::binary | std::ios::out); if (out.fail()) printf("ERROR: Failed to open file: %s\n", baseName); - out << "\t// " << - GetSpirvGeneratorVersion() << "." << GLSLANG_MINOR_VERSION << "." << GLSLANG_PATCH_LEVEL << - std::endl; + out << "\t// " << + GetSpirvGeneratorVersion() << + GLSLANG_VERSION_MAJOR << "." << GLSLANG_VERSION_MINOR << "." << GLSLANG_VERSION_PATCH << + GLSLANG_VERSION_FLAVOR << std::endl; if (varName != nullptr) { out << "\t #pragma once" << std::endl; out << "const uint32_t " << varName << "[] = {" << std::endl; @@ -8291,6 +9343,7 @@ void OutputSpvHex(const std::vector& spirv, const char* baseName, } if (varName != nullptr) { out << "};"; + out << std::endl; } out.close(); #endif @@ -8328,10 +9381,14 @@ void GlslangToSpv(const TIntermediate& intermediate, std::vector& // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan // eg. forward and remove memory writes of opaque types. bool prelegalization = intermediate.getSource() == EShSourceHlsl; - if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) { - SpirvToolsLegalize(intermediate, spirv, logger, options); + if ((prelegalization || options->optimizeSize) && !options->disableOptimizer) { + SpirvToolsTransform(intermediate, spirv, logger, options); prelegalization = false; } + else if (options->stripDebugInfo) { + // Strip debug info even if optimization is disabled. + SpirvToolsStripDebugInfo(intermediate, spirv, logger); + } if (options->validate) SpirvToolsValidate(intermediate, spirv, logger, prelegalization); diff --git a/libraries/glslang/spirv/GlslangToSpv.h b/libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.h similarity index 98% rename from libraries/glslang/spirv/GlslangToSpv.h rename to libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.h index 3907be43b..86e1c23bf 100644 --- a/libraries/glslang/spirv/GlslangToSpv.h +++ b/libraries/ZVulkan/src/glslang/spirv/GlslangToSpv.h @@ -40,7 +40,7 @@ #endif #include "SpvTools.h" -#include "glslang/Include/intermediate.h" +#include "../glslang/Include/intermediate.h" #include #include diff --git a/libraries/glslang/spirv/InReadableOrder.cpp b/libraries/ZVulkan/src/glslang/spirv/InReadableOrder.cpp similarity index 100% rename from libraries/glslang/spirv/InReadableOrder.cpp rename to libraries/ZVulkan/src/glslang/spirv/InReadableOrder.cpp diff --git a/libraries/glslang/spirv/Logger.cpp b/libraries/ZVulkan/src/glslang/spirv/Logger.cpp similarity index 99% rename from libraries/glslang/spirv/Logger.cpp rename to libraries/ZVulkan/src/glslang/spirv/Logger.cpp index 7ea0c6342..cdc8469c4 100644 --- a/libraries/glslang/spirv/Logger.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/Logger.cpp @@ -69,4 +69,4 @@ std::string SpvBuildLogger::getAllMessages() const { } // end spv namespace -#endif \ No newline at end of file +#endif diff --git a/libraries/glslang/spirv/Logger.h b/libraries/ZVulkan/src/glslang/spirv/Logger.h similarity index 100% rename from libraries/glslang/spirv/Logger.h rename to libraries/ZVulkan/src/glslang/spirv/Logger.h diff --git a/libraries/ZVulkan/src/glslang/spirv/NonSemanticDebugPrintf.h b/libraries/ZVulkan/src/glslang/spirv/NonSemanticDebugPrintf.h new file mode 100644 index 000000000..83796d75e --- /dev/null +++ b/libraries/ZVulkan/src/glslang/spirv/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are 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 Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS 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. +// 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 +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/libraries/glslang/spirv/SPVRemapper.cpp b/libraries/ZVulkan/src/glslang/spirv/SPVRemapper.cpp similarity index 98% rename from libraries/glslang/spirv/SPVRemapper.cpp rename to libraries/ZVulkan/src/glslang/spirv/SPVRemapper.cpp index fd0bb8950..56d6d5d4a 100644 --- a/libraries/glslang/spirv/SPVRemapper.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/SPVRemapper.cpp @@ -544,6 +544,9 @@ namespace spv { // Extended instructions: currently, assume everything is an ID. // TODO: add whatever data we need for exceptions to that if (opCode == spv::OpExtInst) { + + idFn(asId(word)); // Instruction set is an ID that also needs to be mapped + word += 2; // instruction set, and instruction from set numOperands -= 2; @@ -625,6 +628,9 @@ namespace spv { break; } + case spv::OperandVariableLiteralStrings: + return nextInst; + // Execution mode might have extra literal operands. Skip them. case spv::OperandExecutionMode: return nextInst; @@ -827,7 +833,15 @@ namespace spv { [&](spv::Id& id) { if (thisOpCode != spv::OpNop) { ++idCounter; - const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117; + const std::uint32_t hashval = + // Explicitly cast operands to unsigned int to avoid integer + // promotion to signed int followed by integer overflow, + // which would result in undefined behavior. + static_cast(opCounter[thisOpCode]) + * thisOpCode + * 50047 + + idCounter + + static_cast(fnId) * 117; if (isOldIdUnmapped(id)) localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); diff --git a/libraries/glslang/spirv/SPVRemapper.h b/libraries/ZVulkan/src/glslang/spirv/SPVRemapper.h similarity index 100% rename from libraries/glslang/spirv/SPVRemapper.h rename to libraries/ZVulkan/src/glslang/spirv/SPVRemapper.h diff --git a/libraries/glslang/spirv/SpvBuilder.cpp b/libraries/ZVulkan/src/glslang/spirv/SpvBuilder.cpp similarity index 90% rename from libraries/glslang/spirv/SpvBuilder.cpp rename to libraries/ZVulkan/src/glslang/spirv/SpvBuilder.cpp index bd208952e..e83306ebc 100644 --- a/libraries/glslang/spirv/SpvBuilder.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/SpvBuilder.cpp @@ -1,6 +1,7 @@ // // Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -496,7 +497,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) return type->getResultId(); } -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format) +Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, + ImageFormat format) { assert(sampled == 1 || sampled == 2); @@ -601,16 +603,31 @@ Id Builder::makeSampledImageType(Id imageType) } #ifndef GLSLANG_WEB -Id Builder::makeAccelerationStructureNVType() +Id Builder::makeAccelerationStructureType() { Instruction *type; - if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV); - groupedTypes[OpTypeAccelerationStructureNV].push_back(type); + if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) { + type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR); + groupedTypes[OpTypeAccelerationStructureKHR].push_back(type); constantsTypesGlobals.push_back(std::unique_ptr(type)); module.mapInstruction(type); } else { - type = groupedTypes[OpTypeAccelerationStructureNV].back(); + type = groupedTypes[OpTypeAccelerationStructureKHR].back(); + } + + return type->getResultId(); +} + +Id Builder::makeRayQueryType() +{ + Instruction *type; + if (groupedTypes[OpTypeRayQueryKHR].size() == 0) { + type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR); + groupedTypes[OpTypeRayQueryKHR].push_back(type); + constantsTypesGlobals.push_back(std::unique_ptr(type)); + module.mapInstruction(type); + } else { + type = groupedTypes[OpTypeRayQueryKHR].back(); } return type->getResultId(); @@ -726,6 +743,26 @@ Id Builder::getContainedTypeId(Id typeId, int member) const } } +// Figure out the final resulting type of the access chain. +Id Builder::getResultingAccessChainType() const +{ + assert(accessChain.base != NoResult); + Id typeId = getTypeId(accessChain.base); + + assert(isPointerType(typeId)); + typeId = getContainedTypeId(typeId); + + for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { + if (isStructType(typeId)) { + assert(isConstantScalar(accessChain.indexChain[i])); + typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i])); + } else + typeId = getContainedTypeId(typeId, accessChain.indexChain[i]); + } + + return typeId; +} + // Return the immediately contained type of a given composite type. Id Builder::getContainedTypeId(Id typeId) const { @@ -852,6 +889,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const } } +Id Builder::makeNullConstant(Id typeId) +{ + Instruction* constant; + + // See if we already made it. + Id existing = NoResult; + for (int i = 0; i < (int)nullConstants.size(); ++i) { + constant = nullConstants[i]; + if (constant->getTypeId() == typeId) + existing = constant->getResultId(); + } + + if (existing != NoResult) + return existing; + + // Make it + Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull); + constantsTypesGlobals.push_back(std::unique_ptr(c)); + nullConstants.push_back(c); + module.mapInstruction(c); + + return c->getResultId(); +} + Id Builder::makeBoolConstant(bool b, bool specConstant) { Id typeId = makeBoolType(); @@ -1166,6 +1227,28 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val executionModes.push_back(std::unique_ptr(instr)); } +void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector& literals) +{ + Instruction* instr = new Instruction(OpExecutionMode); + instr->addIdOperand(entryPoint->getId()); + instr->addImmediateOperand(mode); + for (auto literal : literals) + instr->addImmediateOperand(literal); + + executionModes.push_back(std::unique_ptr(instr)); +} + +void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector& operandIds) +{ + Instruction* instr = new Instruction(OpExecutionModeId); + instr->addIdOperand(entryPoint->getId()); + instr->addImmediateOperand(mode); + for (auto operandId : operandIds) + instr->addIdOperand(operandId); + + executionModes.push_back(std::unique_ptr(instr)); +} + void Builder::addName(Id id, const char* string) { Instruction* name = new Instruction(OpName); @@ -1204,7 +1287,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s) if (decoration == spv::DecorationMax) return; - Instruction* dec = new Instruction(OpDecorateStringGOOGLE); + Instruction* dec = new Instruction(OpDecorateString); dec->addIdOperand(id); dec->addImmediateOperand(decoration); dec->addStringOperand(s); @@ -1212,6 +1295,34 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s) decorations.push_back(std::unique_ptr(dec)); } +void Builder::addDecoration(Id id, Decoration decoration, const std::vector& literals) +{ + if (decoration == spv::DecorationMax) + return; + + Instruction* dec = new Instruction(OpDecorate); + dec->addIdOperand(id); + dec->addImmediateOperand(decoration); + for (auto literal : literals) + dec->addImmediateOperand(literal); + + decorations.push_back(std::unique_ptr(dec)); +} + +void Builder::addDecoration(Id id, Decoration decoration, const std::vector& strings) +{ + if (decoration == spv::DecorationMax) + return; + + Instruction* dec = new Instruction(OpDecorateString); + dec->addIdOperand(id); + dec->addImmediateOperand(decoration); + for (auto string : strings) + dec->addStringOperand(string); + + decorations.push_back(std::unique_ptr(dec)); +} + void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) { if (decoration == spv::DecorationMax) @@ -1225,6 +1336,21 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) decorations.push_back(std::unique_ptr(dec)); } +void Builder::addDecorationId(Id id, Decoration decoration, const std::vector& operandIds) +{ + if(decoration == spv::DecorationMax) + return; + + Instruction* dec = new Instruction(OpDecorateId); + dec->addIdOperand(id); + dec->addImmediateOperand(decoration); + + for (auto operandId : operandIds) + dec->addIdOperand(operandId); + + decorations.push_back(std::unique_ptr(dec)); +} + void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) { if (decoration == spv::DecorationMax) @@ -1254,6 +1380,36 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat decorations.push_back(std::unique_ptr(dec)); } +void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& literals) +{ + if (decoration == spv::DecorationMax) + return; + + Instruction* dec = new Instruction(OpMemberDecorate); + dec->addIdOperand(id); + dec->addImmediateOperand(member); + dec->addImmediateOperand(decoration); + for (auto literal : literals) + dec->addImmediateOperand(literal); + + decorations.push_back(std::unique_ptr(dec)); +} + +void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& strings) +{ + if (decoration == spv::DecorationMax) + return; + + Instruction* dec = new Instruction(OpMemberDecorateString); + dec->addIdOperand(id); + dec->addImmediateOperand(member); + dec->addImmediateOperand(decoration); + for (auto string : strings) + dec->addStringOperand(string); + + decorations.push_back(std::unique_ptr(dec)); +} + // Comments in header Function* Builder::makeEntryPoint(const char* entryPoint) { @@ -1270,7 +1426,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint) // Comments in header Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector& paramTypes, const std::vector>& decorations, Block **entry) + const std::vector& paramTypes, + const std::vector>& decorations, Block **entry) { // Make the function and initial instructions in it Id typeId = makeFunctionType(returnType, paramTypes); @@ -1279,9 +1436,12 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const // Set up the precisions setPrecision(function->getId(), precision); + function->setReturnPrecision(precision); for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { - for (int d = 0; d < (int)decorations[p].size(); ++d) + for (int d = 0; d < (int)decorations[p].size(); ++d) { addDecoration(firstParamId + p, decorations[p][d]); + function->addParamPrecision(p, decorations[p][d]); + } } // CFG @@ -1331,14 +1491,14 @@ void Builder::leaveFunction() } // Comments in header -void Builder::makeDiscard() +void Builder::makeStatementTerminator(spv::Op opcode, const char *name) { - buildPoint->addInstruction(std::unique_ptr(new Instruction(OpKill))); - createAndSetNoPredecessorBlock("post-discard"); + buildPoint->addInstruction(std::unique_ptr(new Instruction(opcode))); + createAndSetNoPredecessorBlock(name); } // Comments in header -Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer) +Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer) { Id pointerType = makePointer(storageClass, type); Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); @@ -1360,6 +1520,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, if (name) addName(inst->getResultId(), name); + setPrecision(inst->getResultId(), precision); return inst->getResultId(); } @@ -1373,7 +1534,8 @@ Id Builder::createUndefined(Id type) } // av/vis/nonprivate are unnecessary and illegal for some storage classes. -spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const +spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const { switch (sc) { case spv::StorageClassUniform: @@ -1392,7 +1554,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc } // Comments in header -void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, + unsigned int alignment) { Instruction* store = new Instruction(OpStore); store->addIdOperand(lValue); @@ -1414,7 +1577,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce } // Comments in header -Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess, + spv::Scope scope, unsigned int alignment) { Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); load->addIdOperand(lValue); @@ -1432,6 +1596,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope } buildPoint->addInstruction(std::unique_ptr(load)); + setPrecision(load->getResultId(), precision); return load->getResultId(); } @@ -1440,16 +1605,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) { // Figure out the final resulting type. - spv::Id typeId = getTypeId(base); - assert(isPointerType(typeId) && offsets.size() > 0); - typeId = getContainedTypeId(typeId); - for (int i = 0; i < (int)offsets.size(); ++i) { - if (isStructType(typeId)) { - assert(isConstantScalar(offsets[i])); - typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i])); - } else - typeId = getContainedTypeId(typeId, offsets[i]); - } + Id typeId = getResultingAccessChainType(); typeId = makePointer(storageClass, typeId); // Make the instruction @@ -1495,7 +1651,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) // Generate code for spec constants if in spec constant operation // generation mode. if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); + return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), + std::vector(1, index)); } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); @@ -1697,7 +1854,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& opera return op->getResultId(); } -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, + const std::vector& literals) { Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); op->addImmediateOperand((unsigned) opCode); @@ -2144,7 +2302,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b Op op; switch (getMostBasicTypeClass(valueType)) { case OpTypeFloat: - op = equal ? OpFOrdEqual : OpFOrdNotEqual; + op = equal ? OpFOrdEqual : OpFUnordNotEqual; break; case OpTypeInt: default: @@ -2187,7 +2345,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b if (constituent == 0) resultId = subResultId; else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision); + resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), + precision); } return resultId; @@ -2196,7 +2355,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b // OpCompositeConstruct Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) { - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); + assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && + getNumTypeConstituents(typeId) == (int)constituents.size())); if (generatingOpCodeForSpecConst) { // Sometime, even in spec-constant-op mode, the constant composite to be @@ -2394,7 +2554,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector& int row = 0; int col = 0; - for (int arg = 0; arg < (int)sources.size(); ++arg) { + for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) { Id argComp = sources[arg]; for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { if (getNumComponents(sources[arg]) > 1) { @@ -2406,6 +2566,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector& row = 0; col++; } + if (col == numCols) { + // If more components are provided than fit the matrix, discard the rest. + break; + } } } } @@ -2609,7 +2773,8 @@ void Builder::clearAccessChain() } // Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) +void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment) { accessChain.coherentFlags |= coherentFlags; accessChain.alignment |= alignment; @@ -2635,35 +2800,70 @@ void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizz } // Comments in header -void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) { assert(accessChain.isRValue == false); transferAccessChainSwizzle(true); - Id base = collapseAccessChain(); - Id source = rvalue; - // dynamic component should be gone - assert(accessChain.component == NoResult); + // If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores. + if (accessChain.swizzle.size() > 0 && + getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() && + accessChain.component == NoResult) { + for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { + accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i])); + accessChain.instr = NoResult; - // If swizzle still exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. - if (accessChain.swizzle.size() > 0) { - Id tempBaseId = createLoad(base); - source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); + Id base = collapseAccessChain(); + addDecoration(base, nonUniform); + + accessChain.indexChain.pop_back(); + accessChain.instr = NoResult; + + // dynamic component should be gone + assert(accessChain.component == NoResult); + + Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i); + + // take LSB of alignment + alignment = alignment & ~(alignment & (alignment-1)); + if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { + memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); + } + + createStore(source, base, memoryAccess, scope, alignment); + } } + else { + Id base = collapseAccessChain(); + addDecoration(base, nonUniform); - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); + Id source = rvalue; + + // dynamic component should be gone + assert(accessChain.component == NoResult); + + // If swizzle still exists, it may be out-of-order, we must load the target vector, + // extract and insert elements to perform writeMask and/or swizzle. + if (accessChain.swizzle.size() > 0) { + Id tempBaseId = createLoad(base, spv::NoPrecision); + source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); + } + + // take LSB of alignment + alignment = alignment & ~(alignment & (alignment-1)); + if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { + memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); + } + + createStore(source, base, memoryAccess, scope, alignment); } - - createStore(source, base, memoryAccess, scope, alignment); } // Comments in header -Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform, + Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, + spv::Scope scope, unsigned int alignment) { Id id; @@ -2687,17 +2887,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu if (constant) { id = createCompositeExtract(accessChain.base, swizzleBase, indexes); + setPrecision(id, precision); } else { Id lValue = NoResult; - if (spvVersion >= Spv_1_4) { + if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) { // make a new function variable for this r-value, using an initializer, // and mark it as NonWritable so that downstream it can be detected as a lookup // table - lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable", - accessChain.base); + lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), + "indexable", accessChain.base); addDecoration(lValue, DecorationNonWritable); } else { - lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable"); + lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), + "indexable"); // store into it createStore(accessChain.base, lValue); } @@ -2706,9 +2908,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu accessChain.isRValue = false; // load through the access chain - id = createLoad(collapseAccessChain()); + id = createLoad(collapseAccessChain(), precision); } - setPrecision(id, precision); } else id = accessChain.base; // no precision, it was set when this was defined } else { @@ -2721,9 +2922,14 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu } // load through the access chain - id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment); - setPrecision(id, precision); - addDecoration(id, nonUniform); + id = collapseAccessChain(); + // Apply nonuniform both to the access chain and the loaded value. + // Buffer accesses need the access chain decorated, and this is where + // loaded image types get decorated. TODO: This should maybe move to + // createImageTextureFunctionCall. + addDecoration(id, l_nonUniform); + id = createLoad(id, precision, memoryAccess, scope, alignment); + addDecoration(id, r_nonUniform); } // Done, unless there are swizzles to do @@ -2744,7 +2950,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu if (accessChain.component != NoResult) id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); - addDecoration(id, nonUniform); + addDecoration(id, r_nonUniform); return id; } @@ -3075,7 +3281,8 @@ void Builder::dumpSourceInstructions(std::vector& out) const dumpSourceInstructions(iItr->first, *iItr->second, out); } -void Builder::dumpInstructions(std::vector& out, const std::vector >& instructions) const +void Builder::dumpInstructions(std::vector& out, + const std::vector >& instructions) const { for (int i = 0; i < (int)instructions.size(); ++i) { instructions[i]->dump(out); diff --git a/libraries/glslang/spirv/SpvBuilder.h b/libraries/ZVulkan/src/glslang/spirv/SpvBuilder.h similarity index 82% rename from libraries/glslang/spirv/SpvBuilder.h rename to libraries/ZVulkan/src/glslang/spirv/SpvBuilder.h index 31fee975f..251b9ee82 100644 --- a/libraries/glslang/spirv/SpvBuilder.h +++ b/libraries/ZVulkan/src/glslang/spirv/SpvBuilder.h @@ -1,7 +1,8 @@ // // Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -94,6 +95,7 @@ public: const char* file_c_str = str.c_str(); fileString->addStringOperand(file_c_str); strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); stringIds[file_c_str] = strId; return strId; } @@ -181,7 +183,9 @@ public: Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); // accelerationStructureNV type - Id makeAccelerationStructureNVType(); + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); // For querying about types. Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } @@ -196,7 +200,9 @@ public: Id getContainedTypeId(Id typeId) const; Id getContainedTypeId(Id typeId, int) const; StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } - ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + Id getResultingAccessChainType() const; bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } @@ -206,12 +212,17 @@ public: bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } @@ -221,7 +232,8 @@ public: #else bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } #endif - bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } @@ -233,9 +245,17 @@ public: bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } - unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; } + bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); } + bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; } + bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); } + // See if a resultId is valid for use as an initializer. + bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); } + int getScalarTypeWidth(Id typeId) const { Id scalarTypeId = getScalarTypeId(typeId); @@ -274,15 +294,24 @@ public: } // For making new constants (will return old constant if the requested one was already made). + Id makeNullConstant(Id typeId); Id makeBoolConstant(bool b, bool specConstant = false); - Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } - Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); } - Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } - Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); } - Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } - Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); } - Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } - Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } Id makeFloatConstant(float f, bool specConstant = false); Id makeDoubleConstant(double d, bool specConstant = false); Id makeFloat16Constant(float f16, bool specConstant = false); @@ -294,13 +323,20 @@ public: // Methods for adding information outside the CFG. Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addExecutionMode(Function*, ExecutionMode mode, const std::vector& literals); + void addExecutionModeId(Function*, ExecutionMode mode, const std::vector& operandIds); void addName(Id, const char* name); void addMemberName(Id, int member, const char* name); void addDecoration(Id, Decoration, int num = -1); void addDecoration(Id, Decoration, const char*); + void addDecoration(Id, Decoration, const std::vector& literals); + void addDecoration(Id, Decoration, const std::vector& strings); void addDecorationId(Id id, Decoration, Id idDecoration); + void addDecorationId(Id id, Decoration, const std::vector& operandIds); void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& literals); + void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& strings); // At the end of what block do the next create*() instructions go? void setBuildPoint(Block* bp) { buildPoint = bp; } @@ -313,8 +349,8 @@ public: // Make a shader-style function, and create its entry block if entry is non-zero. // Return the function, pass back the entry. // The returned pointer is only valid for the lifetime of this builder. - Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector& paramTypes, - const std::vector>& precisions, Block **entry = 0); + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); // Create a return. An 'implicit' return is one not appearing in the source // code. In the case of an implicit return, no post-return block is inserted. @@ -323,20 +359,25 @@ public: // Generate all the code needed to finish up a function. void leaveFunction(); - // Create a discard. - void makeDiscard(); + // Create block terminator instruction for certain statements like + // discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT + void makeStatementTerminator(spv::Op opcode, const char *name); // Create a global or function local or IO variable. - Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr, + Id initializer = NoResult); // Create an intermediate with an undefined value. Id createUndefined(Id type); // Store into an Id and return the l-value - void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // Load from an Id and return it - Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + Id createLoad(Id lValue, spv::Decoration precision, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // Create an OpAccessChain instruction Id createAccessChain(StorageClass, Id base, const std::vector& offsets); @@ -495,7 +536,7 @@ public: // recursion stack can hold the memory for it. // void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // return argument + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // Add a branch to the innermost switch's merge block. void addSwitchBreak(); @@ -512,7 +553,7 @@ public: Block &head, &body, &merge, &continue_target; private: LoopBlocks(); - LoopBlocks& operator=(const LoopBlocks&); + LoopBlocks& operator=(const LoopBlocks&) = delete; }; // Start a new loop and prepare the builder to generate code for it. Until @@ -569,10 +610,13 @@ public: std::vector indexChain; Id instr; // cache the instruction that generates this access chain std::vector swizzle; // each std::vector element selects the next GLSL component number - Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present - Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value - unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment. + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. // Accumulate whether anything in the chain of structures has coherent decorations. struct CoherentFlags { @@ -583,15 +627,22 @@ public: CoherentFlags operator |=(const CoherentFlags &other) { return *this; } #else bool isVolatile() const { return volatil; } + bool isNonUniform() const { return nonUniform; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } unsigned coherent : 1; unsigned devicecoherent : 1; unsigned queuefamilycoherent : 1; unsigned workgroupcoherent : 1; unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; unsigned nonprivate : 1; unsigned volatil : 1; unsigned isImage : 1; + unsigned nonUniform : 1; void clear() { coherent = 0; @@ -599,9 +650,11 @@ public: queuefamilycoherent = 0; workgroupcoherent = 0; subgroupcoherent = 0; + shadercallcoherent = 0; nonprivate = 0; volatil = 0; isImage = 0; + nonUniform = 0; } CoherentFlags operator |=(const CoherentFlags &other) { @@ -610,9 +663,11 @@ public: queuefamilycoherent |= other.queuefamilycoherent; workgroupcoherent |= other.workgroupcoherent; subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; nonprivate |= other.nonprivate; volatil |= other.volatil; isImage |= other.isImage; + nonUniform |= other.nonUniform; return *this; } #endif @@ -655,11 +710,13 @@ public: } // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); // push a dynamic component selection onto the access chain, only applicable with a // non-trivial swizzle or no swizzle - void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) { if (accessChain.swizzle.size() != 1) { accessChain.component = component; @@ -671,10 +728,19 @@ public: } // use accessChain and swizzle to store value - void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + void accessChainStore(Id rvalue, Decoration nonUniform, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } // get the direct pointer for an l-value Id accessChainGetLValue(); @@ -703,7 +769,8 @@ public: void createBranch(Block* block); void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); - void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector& operands); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); // Sets to generate opcode for specialization constants. void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } @@ -729,7 +796,8 @@ public: void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; void dumpInstructions(std::vector&, const std::vector >&) const; void dumpModuleProcesses(std::vector&) const; - spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; unsigned int spvVersion; // the version of SPIR-V to emit in the header SourceLanguage source; @@ -764,10 +832,16 @@ public: std::vector > externals; std::vector > functions; - // not output, internally used for quick & dirty canonical (unique) creation - std::unordered_map> groupedConstants; // map type opcodes to constant inst. - std::unordered_map> groupedStructConstants; // map struct-id to constant instructions - std::unordered_map> groupedTypes; // map type opcodes to type instructions + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + // list of OpConstantNull instructions + std::vector nullConstants; // stack of switches std::stack switchMerges; diff --git a/libraries/glslang/spirv/SpvPostProcess.cpp b/libraries/ZVulkan/src/glslang/spirv/SpvPostProcess.cpp similarity index 93% rename from libraries/glslang/spirv/SpvPostProcess.cpp rename to libraries/ZVulkan/src/glslang/spirv/SpvPostProcess.cpp index d40174d17..23d7b5a46 100644 --- a/libraries/glslang/spirv/SpvPostProcess.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/SpvPostProcess.cpp @@ -436,6 +436,38 @@ void Builder::postProcessFeatures() { } } } + + // If any Vulkan memory model-specific functionality is used, update the + // OpMemoryModel to match. + if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) { + memoryModel = spv::MemoryModelVulkanKHR; + addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); + } + + // Add Aliased decoration if there's more than one Workgroup Block variable. + if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) { + assert(entryPoints.size() == 1); + auto &ep = entryPoints[0]; + + std::vector workgroup_variables; + for (int i = 0; i < (int)ep->getNumOperands(); i++) { + if (!ep->isIdOperand(i)) + continue; + + const Id id = ep->getIdOperand(i); + const Instruction *instr = module.getInstruction(id); + if (instr->getOpCode() != spv::OpVariable) + continue; + + if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup) + workgroup_variables.push_back(id); + } + + if (workgroup_variables.size() > 1) { + for (size_t i = 0; i < workgroup_variables.size(); i++) + addDecoration(workgroup_variables[i], spv::DecorationAliased); + } + } } #endif diff --git a/libraries/glslang/spirv/SpvTools.cpp b/libraries/ZVulkan/src/glslang/spirv/SpvTools.cpp similarity index 67% rename from libraries/glslang/spirv/SpvTools.cpp rename to libraries/ZVulkan/src/glslang/spirv/SpvTools.cpp index 7c3b03919..8acf9b139 100644 --- a/libraries/glslang/spirv/SpvTools.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/SpvTools.cpp @@ -1,6 +1,6 @@ // // Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. +// Copyright (C) 2018-2020 Google, Inc. // // All rights reserved. // @@ -44,7 +44,6 @@ #include "SpvTools.h" #include "spirv-tools/optimizer.hpp" -#include "spirv-tools/libspirv.h" namespace glslang { @@ -67,6 +66,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog logger->missingFunctionality("Target version for SPIRV-Tools validator"); return spv_target_env::SPV_ENV_VULKAN_1_1; } + case glslang::EShTargetVulkan_1_2: + return spv_target_env::SPV_ENV_VULKAN_1_2; default: break; } @@ -78,12 +79,52 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog return spv_target_env::SPV_ENV_UNIVERSAL_1_0; } +// Callback passed to spvtools::Optimizer::SetMessageConsumer +void OptimizerMesssageConsumer(spv_message_level_t level, const char *source, + const spv_position_t &position, const char *message) +{ + auto &out = std::cerr; + switch (level) + { + case SPV_MSG_FATAL: + case SPV_MSG_INTERNAL_ERROR: + case SPV_MSG_ERROR: + out << "error: "; + break; + case SPV_MSG_WARNING: + out << "warning: "; + break; + case SPV_MSG_INFO: + case SPV_MSG_DEBUG: + out << "info: "; + break; + default: + break; + } + if (source) + { + out << source << ":"; + } + out << position.line << ":" << position.column << ":" << position.index << ":"; + if (message) + { + out << " " << message; + } + out << std::endl; +} -// Use the SPIRV-Tools disassembler to print SPIR-V. +// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv) +{ + SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3); +} + +// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, + spv_target_env requested_context) { // disassemble - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3); + spv_context context = spvContextCreate(requested_context); spv_text text; spv_diagnostic diagnostic = nullptr; spvBinaryToText(context, spirv.data(), spirv.size(), @@ -112,6 +153,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector< spv_validator_options options = spvValidatorOptionsCreate(); spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); + spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); + spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); spvValidateWithOptions(context, options, &binary, &diagnostic); // report @@ -126,52 +169,21 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector< spvContextDestroy(context); } -// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of -// legalizing HLSL SPIR-V. -void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector& spirv, - spv::SpvBuildLogger*, const SpvOptions* options) +// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. +void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, const SpvOptions* options) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; + spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer( - [](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) { - auto &out = std::cerr; - switch (level) - { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - out << "error: "; - break; - case SPV_MSG_WARNING: - out << "warning: "; - break; - case SPV_MSG_INFO: - case SPV_MSG_DEBUG: - out << "info: "; - break; - default: - break; - } - if (source) - { - out << source << ":"; - } - out << position.line << ":" << position.column << ":" << position.index << ":"; - if (message) - { - out << " " << message; - } - out << std::endl; - }); + optimizer.SetMessageConsumer(OptimizerMesssageConsumer); // If debug (specifically source line info) is being generated, propagate // line information into all SPIR-V instructions. This avoids loss of // information when instructions are deleted or moved. Later, remove // redundant information to minimize final SPRIR-V size. - if (options->generateDebugInfo) { - optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass()); + if (options->stripDebugInfo) { + optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); } optimizer.RegisterPass(spvtools::CreateWrapOpKillPass()); optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); @@ -195,17 +207,35 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass()); if (options->optimizeSize) { optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); } optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); - if (options->generateDebugInfo) { - optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass()); - } spvtools::OptimizerOptions spvOptOptions; - spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on + optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); + spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on + optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); +} + +// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by +// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if +// optimization is disabled. +void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, + std::vector& spirv, spv::SpvBuildLogger* logger) +{ + spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); + + spvtools::Optimizer optimizer(target_env); + optimizer.SetMessageConsumer(OptimizerMesssageConsumer); + + optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); + + spvtools::OptimizerOptions spvOptOptions; + optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); + spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); } diff --git a/libraries/glslang/spirv/SpvTools.h b/libraries/ZVulkan/src/glslang/spirv/SpvTools.h similarity index 67% rename from libraries/glslang/spirv/SpvTools.h rename to libraries/ZVulkan/src/glslang/spirv/SpvTools.h index 59c914da0..d856c5236 100644 --- a/libraries/glslang/spirv/SpvTools.h +++ b/libraries/ZVulkan/src/glslang/spirv/SpvTools.h @@ -41,39 +41,50 @@ #ifndef GLSLANG_SPV_TOOLS_H #define GLSLANG_SPV_TOOLS_H -#ifdef ENABLE_OPT +#if ENABLE_OPT #include #include +#include "spirv-tools/libspirv.h" #endif -#include "glslang/MachineIndependent/localintermediate.h" +#include "../glslang/MachineIndependent/localintermediate.h" #include "Logger.h" namespace glslang { struct SpvOptions { - SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true), optimizeSize(false), disassemble(false), validate(false) { } bool generateDebugInfo; + bool stripDebugInfo; bool disableOptimizer; bool optimizeSize; bool disassemble; bool validate; }; -#ifdef ENABLE_OPT +#if ENABLE_OPT -// Use the SPIRV-Tools disassembler to print SPIR-V. +// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); +// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, + spv_target_env requested_context); + // Apply the SPIRV-Tools validator to generated SPIR-V. void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, spv::SpvBuildLogger*, bool prelegalization); -// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of -// legalizing HLSL SPIR-V. -void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger*, const SpvOptions*); +// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. +void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by +// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if +// optimization is disabled. +void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, + std::vector& spirv, spv::SpvBuildLogger*); #endif diff --git a/libraries/glslang/spirv/bitutils.h b/libraries/ZVulkan/src/glslang/spirv/bitutils.h similarity index 100% rename from libraries/glslang/spirv/bitutils.h rename to libraries/ZVulkan/src/glslang/spirv/bitutils.h diff --git a/libraries/glslang/spirv/disassemble.cpp b/libraries/ZVulkan/src/glslang/spirv/disassemble.cpp similarity index 97% rename from libraries/glslang/spirv/disassemble.cpp rename to libraries/ZVulkan/src/glslang/spirv/disassemble.cpp index 930e79949..73c988c5b 100644 --- a/libraries/glslang/spirv/disassemble.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/disassemble.cpp @@ -46,7 +46,6 @@ #include "disassemble.h" #include "doc.h" -#include "SpvTools.h" namespace spv { extern "C" { @@ -75,6 +74,7 @@ enum ExtInstSet { GLSLextAMDInst, GLSLextNVInst, OpenCLExtInst, + NonSemanticDebugPrintfExtInst, }; // Container class for a single instance of a SPIR-V stream, with methods for disassembly. @@ -480,8 +480,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, if (opCode == OpExtInst) { ExtInstSet extInstSet = GLSL450Inst; const char* name = idDescriptor[stream[word - 2]].c_str(); - if (0 == memcmp("OpenCL", name, 6)) { + if (strcmp("OpenCL.std", name) == 0) { extInstSet = OpenCLExtInst; + } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) { + extInstSet = OpenCLExtInst; + } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) { + extInstSet = NonSemanticDebugPrintfExtInst; } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || @@ -505,6 +509,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, } else if (extInstSet == GLSLextNVInst) { out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; + } else if (extInstSet == NonSemanticDebugPrintfExtInst) { + out << "(DebugPrintf)"; } } break; @@ -512,6 +518,10 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, case OperandLiteralString: numOperands -= disassembleString(); break; + case OperandVariableLiteralStrings: + while (numOperands > 0) + numOperands -= disassembleString(); + return; case OperandMemoryAccess: outputMask(OperandMemoryAccess, stream[word++]); --numOperands; diff --git a/libraries/glslang/spirv/disassemble.h b/libraries/ZVulkan/src/glslang/spirv/disassemble.h similarity index 100% rename from libraries/glslang/spirv/disassemble.h rename to libraries/ZVulkan/src/glslang/spirv/disassemble.h diff --git a/libraries/glslang/spirv/doc.cpp b/libraries/ZVulkan/src/glslang/spirv/doc.cpp similarity index 86% rename from libraries/glslang/spirv/doc.cpp rename to libraries/ZVulkan/src/glslang/spirv/doc.cpp index bee5c7972..dbdf7077a 100644 --- a/libraries/glslang/spirv/doc.cpp +++ b/libraries/ZVulkan/src/glslang/spirv/doc.cpp @@ -1,5 +1,6 @@ // // Copyright (C) 2014-2015 LunarG, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -99,12 +100,12 @@ const char* ExecutionModelString(int model) default: return "Bad"; - case ExecutionModelRayGenerationNV: return "RayGenerationNV"; - case ExecutionModelIntersectionNV: return "IntersectionNV"; - case ExecutionModelAnyHitNV: return "AnyHitNV"; - case ExecutionModelClosestHitNV: return "ClosestHitNV"; - case ExecutionModelMissNV: return "MissNV"; - case ExecutionModelCallableNV: return "CallableNV"; + case ExecutionModelRayGenerationKHR: return "RayGenerationKHR"; + case ExecutionModelIntersectionKHR: return "IntersectionKHR"; + case ExecutionModelAnyHitKHR: return "AnyHitKHR"; + case ExecutionModelClosestHitKHR: return "ClosestHitKHR"; + case ExecutionModelMissKHR: return "MissKHR"; + case ExecutionModelCallableKHR: return "CallableKHR"; } } @@ -133,7 +134,7 @@ const char* MemoryString(int mem) } } -const int ExecutionModeCeiling = 33; +const int ExecutionModeCeiling = 40; const char* ExecutionModeString(int mode) { @@ -172,7 +173,22 @@ const char* ExecutionModeString(int mode) case 31: return "ContractionOff"; case 32: return "Bad"; - case 4446: return "PostDepthCoverage"; + case ExecutionModeInitializer: return "Initializer"; + case ExecutionModeFinalizer: return "Finalizer"; + case ExecutionModeSubgroupSize: return "SubgroupSize"; + case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; + case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; + case ExecutionModeLocalSizeId: return "LocalSizeId"; + case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; + + case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; + case ExecutionModeDenormPreserve: return "DenormPreserve"; + case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; + case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; + case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; + case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; + case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; + case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow"; case ExecutionModeOutputLinesNV: return "OutputLinesNV"; case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; @@ -187,6 +203,11 @@ const char* ExecutionModeString(int mode) case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; + case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL"; + case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL"; + case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; + case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; + case ExecutionModeCeiling: default: return "Bad"; } @@ -209,12 +230,12 @@ const char* StorageClassString(int StorageClass) case 11: return "Image"; case 12: return "StorageBuffer"; - case StorageClassRayPayloadNV: return "RayPayloadNV"; - case StorageClassHitAttributeNV: return "HitAttributeNV"; - case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV"; - case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV"; - case StorageClassCallableDataNV: return "CallableDataNV"; - case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV"; + case StorageClassRayPayloadKHR: return "RayPayloadKHR"; + case StorageClassHitAttributeKHR: return "HitAttributeKHR"; + case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR"; + case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR"; + case StorageClassCallableDataKHR: return "CallableDataKHR"; + case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR"; case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; @@ -352,6 +373,8 @@ const char* BuiltInString(int builtIn) case 4424: return "BaseVertex"; case 4425: return "BaseInstance"; case 4426: return "DrawIndex"; + case 4432: return "PrimitiveShadingRateKHR"; + case 4444: return "ShadingRateKHR"; case 5014: return "FragStencilRefEXT"; case 4992: return "BaryCoordNoPerspAMD"; @@ -361,32 +384,33 @@ const char* BuiltInString(int builtIn) case 4996: return "BaryCoordSmoothCentroidAMD"; case 4997: return "BaryCoordSmoothSampleAMD"; case 4998: return "BaryCoordPullModelAMD"; - case BuiltInLaunchIdNV: return "LaunchIdNV"; - case BuiltInLaunchSizeNV: return "LaunchSizeNV"; - case BuiltInWorldRayOriginNV: return "WorldRayOriginNV"; - case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV"; - case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV"; - case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV"; - case BuiltInRayTminNV: return "RayTminNV"; - case BuiltInRayTmaxNV: return "RayTmaxNV"; - case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV"; - case BuiltInObjectToWorldNV: return "ObjectToWorldNV"; - case BuiltInWorldToObjectNV: return "WorldToObjectNV"; - case BuiltInHitTNV: return "HitTNV"; - case BuiltInHitKindNV: return "HitKindNV"; - case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case BuiltInLaunchIdKHR: return "LaunchIdKHR"; + case BuiltInLaunchSizeKHR: return "LaunchSizeKHR"; + case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR"; + case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR"; + case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR"; + case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; + case BuiltInRayTminKHR: return "RayTminKHR"; + case BuiltInRayTmaxKHR: return "RayTmaxKHR"; + case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; + case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; + case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; + case BuiltInWorldToObjectKHR: return "WorldToObjectKHR"; + case BuiltInHitTNV: return "HitTNV"; + case BuiltInHitKindKHR: return "HitKindKHR"; + case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR"; + case BuiltInViewportMaskNV: return "ViewportMaskNV"; + case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; + case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case BuiltInPositionPerViewNV: return "PositionPerViewNV"; + case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; // case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT // case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT - case BuiltInBaryCoordNV: return "BaryCoordNV"; - case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + case BuiltInBaryCoordNV: return "BaryCoordNV"; + case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; - case BuiltInFragSizeEXT: return "FragSizeEXT"; - case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; + case BuiltInFragSizeEXT: return "FragSizeEXT"; + case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; case 5264: return "FullyCoveredEXT"; @@ -402,6 +426,7 @@ const char* BuiltInString(int builtIn) case BuiltInSMCountNV: return "SMCountNV"; case BuiltInWarpIDNV: return "WarpIDNV"; case BuiltInSMIDNV: return "SMIDNV"; + case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV"; default: return "Bad"; } @@ -500,6 +525,8 @@ const char* ImageFormatString(int format) case 37: return "Rg8ui"; case 38: return "R16ui"; case 39: return "R8ui"; + case 40: return "R64ui"; + case 41: return "R64i"; default: return "Bad"; @@ -890,6 +917,11 @@ const char* CapabilityString(int info) case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; case CapabilityRayTracingNV: return "RayTracingNV"; + case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV"; + case CapabilityRayTracingKHR: return "RayTracingKHR"; + case CapabilityRayQueryKHR: return "RayQueryKHR"; + case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; + case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; @@ -928,11 +960,25 @@ const char* CapabilityString(int info) case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT"; case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT"; + case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR"; + case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; case CapabilityShaderClockKHR: return "ShaderClockKHR"; + case CapabilityInt64ImageEXT: return "Int64ImageEXT"; case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; + case CapabilityAtomicFloat16AddEXT: return "AtomicFloat16AddEXT"; + case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; + case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; + case CapabilityAtomicFloat16MinMaxEXT: return "AtomicFloat16MinMaxEXT"; + case CapabilityAtomicFloat32MinMaxEXT: return "AtomicFloat32MinMaxEXT"; + case CapabilityAtomicFloat64MinMaxEXT: return "AtomicFloat64MinMaxEXT"; + + case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR"; + case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR"; + case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR"; + default: return "Bad"; } } @@ -1264,6 +1310,7 @@ const char* OpcodeString(int op) case 320: return "OpImageSparseRead"; case OpModuleProcessed: return "OpModuleProcessed"; + case OpExecutionModeId: return "OpExecutionModeId"; case OpDecorateId: return "OpDecorateId"; case 333: return "OpGroupNonUniformElect"; @@ -1301,6 +1348,8 @@ const char* OpcodeString(int op) case 365: return "OpGroupNonUniformQuadBroadcast"; case 366: return "OpGroupNonUniformQuadSwap"; + case OpTerminateInvocation: return "OpTerminateInvocation"; + case 4421: return "OpSubgroupBallotKHR"; case 4422: return "OpSubgroupFirstInvocationKHR"; case 4428: return "OpSubgroupAllKHR"; @@ -1308,6 +1357,10 @@ const char* OpcodeString(int op) case 4430: return "OpSubgroupAllEqualKHR"; case 4432: return "OpSubgroupReadInvocationKHR"; + case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; + case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; + case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; + case 5000: return "OpGroupIAddNonUniformAMD"; case 5001: return "OpGroupFAddNonUniformAMD"; case 5002: return "OpGroupFMinNonUniformAMD"; @@ -1325,16 +1378,48 @@ const char* OpcodeString(int op) case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE"; case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; + case OpReportIntersectionKHR: return "OpReportIntersectionKHR"; + case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; + case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR"; + case OpTerminateRayNV: return "OpTerminateRayNV"; + case OpTerminateRayKHR: return "OpTerminateRayKHR"; + case OpTraceNV: return "OpTraceNV"; + case OpTraceRayMotionNV: return "OpTraceRayMotionNV"; + case OpTraceRayKHR: return "OpTraceRayKHR"; + case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR"; + case OpExecuteCallableNV: return "OpExecuteCallableNV"; + case OpExecuteCallableKHR: return "OpExecuteCallableKHR"; + case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR"; + case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; - case OpReportIntersectionNV: return "OpReportIntersectionNV"; - case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; - case OpTerminateRayNV: return "OpTerminateRayNV"; - case OpTraceNV: return "OpTraceNV"; - case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV"; - case OpExecuteCallableNV: return "OpExecuteCallableNV"; case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; + case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR"; + case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; + case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; + case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR"; + case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR"; + case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR"; + case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR"; + case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR"; + case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR"; + case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR"; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; + case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR"; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; + case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR"; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; + case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR"; + case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR"; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; + case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR"; + case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR"; + case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR"; + case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR"; + case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR"; + case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; @@ -1388,6 +1473,7 @@ void Parameterize() InstructionDesc[OpMemoryModel].setResultAndType(false, false); InstructionDesc[OpEntryPoint].setResultAndType(false, false); InstructionDesc[OpExecutionMode].setResultAndType(false, false); + InstructionDesc[OpExecutionModeId].setResultAndType(false, false); InstructionDesc[OpTypeVoid].setResultAndType(true, false); InstructionDesc[OpTypeBool].setResultAndType(true, false); InstructionDesc[OpTypeInt].setResultAndType(true, false); @@ -1441,6 +1527,7 @@ void Parameterize() InstructionDesc[OpBranchConditional].setResultAndType(false, false); InstructionDesc[OpSwitch].setResultAndType(false, false); InstructionDesc[OpKill].setResultAndType(false, false); + InstructionDesc[OpTerminateInvocation].setResultAndType(false, false); InstructionDesc[OpReturn].setResultAndType(false, false); InstructionDesc[OpReturnValue].setResultAndType(false, false); InstructionDesc[OpUnreachable].setResultAndType(false, false); @@ -1574,6 +1661,10 @@ void Parameterize() InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <>"); + InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'"); + InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'"); + InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <>"); + InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); @@ -1667,7 +1758,7 @@ void Parameterize() InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'"); InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); + InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); @@ -1677,7 +1768,7 @@ void Parameterize() InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'"); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'"); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); + InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); @@ -2230,6 +2321,11 @@ void Parameterize() InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); + InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'"); + InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'"); + InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'"); + InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'"); + InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); @@ -2255,6 +2351,16 @@ void Parameterize() InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); + InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Pointer'"); + InstructionDesc[OpAtomicFMinEXT].operands.push(OperandScope, "'Scope'"); + InstructionDesc[OpAtomicFMinEXT].operands.push(OperandMemorySemantics, "'Semantics'"); + InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Value'"); + + InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Pointer'"); + InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandScope, "'Scope'"); + InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandMemorySemantics, "'Semantics'"); + InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Value'"); + InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'"); InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); @@ -2633,7 +2739,7 @@ void Parameterize() InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'"); InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'"); + InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'"); InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); @@ -2694,9 +2800,9 @@ void Parameterize() InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); - InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false); + InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'"); + InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'"); @@ -2709,17 +2815,149 @@ void Parameterize() InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'"); InstructionDesc[OpTraceNV].setResultAndType(false, false); - InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'"); - InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Flags'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Cull Mask'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Miss Index'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Origin'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMin'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Direction'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMax'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Time'"); + InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Payload'"); + InstructionDesc[OpTraceRayMotionNV].setResultAndType(false, false); + + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'"); + InstructionDesc[OpTraceRayKHR].setResultAndType(false, false); + + InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'"); + InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'"); InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false); + InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false); + InstructionDesc[OpTerminateRayNV].setResultAndType(false, false); + + InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false); InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index"); InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID"); InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false); + InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index"); + InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData"); + InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false); + + InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value"); + InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true); + + // Ray Query + InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); + InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false); + + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'"); + InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'"); + InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true); + InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'"); diff --git a/libraries/glslang/spirv/doc.h b/libraries/ZVulkan/src/glslang/spirv/doc.h similarity index 99% rename from libraries/glslang/spirv/doc.h rename to libraries/ZVulkan/src/glslang/spirv/doc.h index 293256a2c..2a0b28c6b 100644 --- a/libraries/glslang/spirv/doc.h +++ b/libraries/ZVulkan/src/glslang/spirv/doc.h @@ -125,6 +125,7 @@ enum OperandClass { OperandVariableLiteralId, OperandLiteralNumber, OperandLiteralString, + OperandVariableLiteralStrings, OperandSource, OperandExecutionModel, OperandAddressing, diff --git a/libraries/glslang/spirv/hex_float.h b/libraries/ZVulkan/src/glslang/spirv/hex_float.h similarity index 99% rename from libraries/glslang/spirv/hex_float.h rename to libraries/ZVulkan/src/glslang/spirv/hex_float.h index 905b21a45..8be8e9f7e 100644 --- a/libraries/glslang/spirv/hex_float.h +++ b/libraries/ZVulkan/src/glslang/spirv/hex_float.h @@ -784,8 +784,8 @@ inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, if (val.isInfinity()) { // Fail the parse. Emulate standard behaviour by setting the value to // the closest normal value, and set the fail bit on the stream. - value.set_value((value.isNegative() | negate_value) ? T::lowest() - : T::max()); + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); is.setstate(std::ios_base::failbit); } return is; diff --git a/libraries/glslang/spirv/spirv.hpp b/libraries/ZVulkan/src/glslang/spirv/spirv.hpp similarity index 85% rename from libraries/glslang/spirv/spirv.hpp rename to libraries/ZVulkan/src/glslang/spirv/spirv.hpp index 1e96f7b4a..e0fe24980 100644 --- a/libraries/glslang/spirv/spirv.hpp +++ b/libraries/ZVulkan/src/glslang/spirv/spirv.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. +// Copyright (c) 2014-2020 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -49,12 +49,12 @@ namespace spv { typedef unsigned int Id; -#define SPV_VERSION 0x10400 -#define SPV_REVISION 1 +#define SPV_VERSION 0x10500 +#define SPV_REVISION 4 static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010400; -static const unsigned int Revision = 1; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 4; static const unsigned int OpCodeMask = 0xffff; static const unsigned int WordCountShift = 16; @@ -78,11 +78,17 @@ enum ExecutionModel { ExecutionModelKernel = 6, ExecutionModelTaskNV = 5267, ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, ExecutionModelCallableNV = 5318, ExecutionModelMax = 0x7fffffff, }; @@ -144,6 +150,7 @@ enum ExecutionMode { ExecutionModeSubgroupsPerWorkgroupId = 37, ExecutionModeLocalSizeId = 38, ExecutionModeLocalSizeHintId = 39, + ExecutionModeSubgroupUniformControlFlowKHR = 4421, ExecutionModePostDepthCoverage = 4446, ExecutionModeDenormPreserve = 4459, ExecutionModeDenormFlushToZero = 4460, @@ -162,6 +169,16 @@ enum ExecutionMode { ExecutionModeSampleInterlockUnorderedEXT = 5369, ExecutionModeShadingRateInterlockOrderedEXT = 5370, ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeSharedLocalMemorySizeINTEL = 5618, + ExecutionModeRoundingModeRTPINTEL = 5620, + ExecutionModeRoundingModeRTNINTEL = 5621, + ExecutionModeFloatingPointModeALTINTEL = 5622, + ExecutionModeFloatingPointModeIEEEINTEL = 5623, + ExecutionModeMaxWorkgroupSizeINTEL = 5893, + ExecutionModeMaxWorkDimINTEL = 5894, + ExecutionModeNoGlobalOffsetINTEL = 5895, + ExecutionModeNumSIMDWorkitemsINTEL = 5896, + ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, ExecutionModeMax = 0x7fffffff, }; @@ -179,14 +196,23 @@ enum StorageClass { StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, StorageClassShaderRecordBufferNV = 5343, StorageClassPhysicalStorageBuffer = 5349, StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassCodeSectionINTEL = 5605, + StorageClassDeviceOnlyINTEL = 5936, + StorageClassHostOnlyINTEL = 5937, StorageClassMax = 0x7fffffff, }; @@ -257,6 +283,8 @@ enum ImageFormat { ImageFormatRg8ui = 37, ImageFormatR16ui = 38, ImageFormatR8ui = 39, + ImageFormatR64ui = 40, + ImageFormatR64i = 41, ImageFormatMax = 0x7fffffff, }; @@ -355,6 +383,8 @@ enum FPFastMathModeShift { FPFastMathModeNSZShift = 2, FPFastMathModeAllowRecipShift = 3, FPFastMathModeFastShift = 4, + FPFastMathModeAllowContractFastINTELShift = 16, + FPFastMathModeAllowReassocINTELShift = 17, FPFastMathModeMax = 0x7fffffff, }; @@ -365,6 +395,8 @@ enum FPFastMathModeMask { FPFastMathModeNSZMask = 0x00000004, FPFastMathModeAllowRecipMask = 0x00000008, FPFastMathModeFastMask = 0x00000010, + FPFastMathModeAllowContractFastINTELMask = 0x00010000, + FPFastMathModeAllowReassocINTELMask = 0x00020000, }; enum FPRoundingMode { @@ -378,6 +410,7 @@ enum FPRoundingMode { enum LinkageType { LinkageTypeExport = 0, LinkageTypeImport = 1, + LinkageTypeLinkOnceODR = 2, LinkageTypeMax = 0x7fffffff, }; @@ -465,11 +498,45 @@ enum Decoration { DecorationRestrictPointerEXT = 5355, DecorationAliasedPointer = 5356, DecorationAliasedPointerEXT = 5356, + DecorationSIMTCallINTEL = 5599, + DecorationReferencedIndirectlyINTEL = 5602, + DecorationClobberINTEL = 5607, + DecorationSideEffectsINTEL = 5608, + DecorationVectorComputeVariableINTEL = 5624, + DecorationFuncParamIOKindINTEL = 5625, + DecorationVectorComputeFunctionINTEL = 5626, + DecorationStackCallINTEL = 5627, + DecorationGlobalVariableOffsetINTEL = 5628, DecorationCounterBuffer = 5634, DecorationHlslCounterBufferGOOGLE = 5634, DecorationHlslSemanticGOOGLE = 5635, DecorationUserSemantic = 5635, DecorationUserTypeGOOGLE = 5636, + DecorationFunctionRoundingModeINTEL = 5822, + DecorationFunctionDenormModeINTEL = 5823, + DecorationRegisterINTEL = 5825, + DecorationMemoryINTEL = 5826, + DecorationNumbanksINTEL = 5827, + DecorationBankwidthINTEL = 5828, + DecorationMaxPrivateCopiesINTEL = 5829, + DecorationSinglepumpINTEL = 5830, + DecorationDoublepumpINTEL = 5831, + DecorationMaxReplicatesINTEL = 5832, + DecorationSimpleDualPortINTEL = 5833, + DecorationMergeINTEL = 5834, + DecorationBankBitsINTEL = 5835, + DecorationForcePow2DepthINTEL = 5836, + DecorationBurstCoalesceINTEL = 5899, + DecorationCacheSizeINTEL = 5900, + DecorationDontStaticallyCoalesceINTEL = 5901, + DecorationPrefetchINTEL = 5902, + DecorationStallEnableINTEL = 5905, + DecorationFuseLoopsInFunctionINTEL = 5907, + DecorationBufferLocationINTEL = 5921, + DecorationIOPipeStorageINTEL = 5944, + DecorationFunctionFloatingPointModeINTEL = 6080, + DecorationSingleElementVectorINTEL = 6085, + DecorationVectorComputeCallableFunctionINTEL = 6087, DecorationMax = 0x7fffffff, }; @@ -528,8 +595,10 @@ enum BuiltIn { BuiltInBaseVertex = 4424, BuiltInBaseInstance = 4425, BuiltInDrawIndex = 4426, + BuiltInPrimitiveShadingRateKHR = 4432, BuiltInDeviceIndex = 4438, BuiltInViewIndex = 4440, + BuiltInShadingRateKHR = 4444, BuiltInBaryCoordNoPerspAMD = 4992, BuiltInBaryCoordNoPerspCentroidAMD = 4993, BuiltInBaryCoordNoPerspSampleAMD = 4994, @@ -558,20 +627,35 @@ enum BuiltIn { BuiltInFragmentSizeNV = 5292, BuiltInFragInvocationCountEXT = 5293, BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, BuiltInWorldToObjectNV = 5331, BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, BuiltInHitKindNV = 5333, + BuiltInCurrentRayTimeNV = 5334, + BuiltInIncomingRayFlagsKHR = 5351, BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, BuiltInWarpsPerSMNV = 5374, BuiltInSMCountNV = 5375, BuiltInWarpIDNV = 5376, @@ -601,6 +685,14 @@ enum LoopControlShift { LoopControlIterationMultipleShift = 6, LoopControlPeelCountShift = 7, LoopControlPartialCountShift = 8, + LoopControlInitiationIntervalINTELShift = 16, + LoopControlMaxConcurrencyINTELShift = 17, + LoopControlDependencyArrayINTELShift = 18, + LoopControlPipelineEnableINTELShift = 19, + LoopControlLoopCoalesceINTELShift = 20, + LoopControlMaxInterleavingINTELShift = 21, + LoopControlSpeculatedIterationsINTELShift = 22, + LoopControlNoFusionINTELShift = 23, LoopControlMax = 0x7fffffff, }; @@ -615,6 +707,14 @@ enum LoopControlMask { LoopControlIterationMultipleMask = 0x00000040, LoopControlPeelCountMask = 0x00000080, LoopControlPartialCountMask = 0x00000100, + LoopControlInitiationIntervalINTELMask = 0x00010000, + LoopControlMaxConcurrencyINTELMask = 0x00020000, + LoopControlDependencyArrayINTELMask = 0x00040000, + LoopControlPipelineEnableINTELMask = 0x00080000, + LoopControlLoopCoalesceINTELMask = 0x00100000, + LoopControlMaxInterleavingINTELMask = 0x00200000, + LoopControlSpeculatedIterationsINTELMask = 0x00400000, + LoopControlNoFusionINTELMask = 0x00800000, }; enum FunctionControlShift { @@ -709,6 +809,7 @@ enum Scope { ScopeInvocation = 4, ScopeQueueFamily = 5, ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, ScopeMax = 0x7fffffff, }; @@ -810,8 +911,12 @@ enum Capability { CapabilityGroupNonUniformQuad = 68, CapabilityShaderLayer = 69, CapabilityShaderViewportIndex = 70, + CapabilityFragmentShadingRateKHR = 4422, CapabilitySubgroupBallotKHR = 4423, CapabilityDrawParameters = 4427, + CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428, + CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, + CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, CapabilitySubgroupVoteKHR = 4431, CapabilityStorageBuffer16BitAccess = 4433, CapabilityStorageUniformBufferBlock16 = 4433, @@ -833,11 +938,16 @@ enum Capability { CapabilitySignedZeroInfNanPreserve = 4466, CapabilityRoundingModeRTE = 4467, CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayQueryKHR = 4472, + CapabilityRayTraversalPrimitiveCullingKHR = 4478, + CapabilityRayTracingKHR = 4479, CapabilityFloat16ImageAMD = 5008, CapabilityImageGatherBiasLodAMD = 5009, CapabilityFragmentMaskAMD = 5010, CapabilityStencilExportEXT = 5013, CapabilityImageReadWriteLodAMD = 5015, + CapabilityInt64ImageEXT = 5016, CapabilityShaderClockKHR = 5055, CapabilitySampleMaskOverrideCoverageNV = 5249, CapabilityGeometryShaderPassthroughNV = 5251, @@ -879,6 +989,7 @@ enum Capability { CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, CapabilityRayTracingNV = 5340, + CapabilityRayTracingMotionBlurNV = 5341, CapabilityVulkanMemoryModel = 5345, CapabilityVulkanMemoryModelKHR = 5345, CapabilityVulkanMemoryModelDeviceScope = 5346, @@ -886,6 +997,7 @@ enum Capability { CapabilityPhysicalStorageBufferAddresses = 5347, CapabilityPhysicalStorageBufferAddressesEXT = 5347, CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, CapabilityCooperativeMatrixNV = 5357, CapabilityFragmentShaderSampleInterlockEXT = 5363, CapabilityFragmentShaderShadingRateInterlockEXT = 5372, @@ -896,13 +1008,120 @@ enum Capability { CapabilitySubgroupBufferBlockIOINTEL = 5569, CapabilitySubgroupImageBlockIOINTEL = 5570, CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityRoundToInfinityINTEL = 5582, + CapabilityFloatingPointModeINTEL = 5583, CapabilityIntegerFunctions2INTEL = 5584, + CapabilityFunctionPointersINTEL = 5603, + CapabilityIndirectReferencesINTEL = 5604, + CapabilityAsmINTEL = 5606, + CapabilityAtomicFloat32MinMaxEXT = 5612, + CapabilityAtomicFloat64MinMaxEXT = 5613, + CapabilityAtomicFloat16MinMaxEXT = 5616, + CapabilityVectorComputeINTEL = 5617, + CapabilityVectorAnyINTEL = 5619, + CapabilityExpectAssumeKHR = 5629, CapabilitySubgroupAvcMotionEstimationINTEL = 5696, CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityVariableLengthArrayINTEL = 5817, + CapabilityFunctionFloatControlINTEL = 5821, + CapabilityFPGAMemoryAttributesINTEL = 5824, + CapabilityFPFastMathModeINTEL = 5837, + CapabilityArbitraryPrecisionIntegersINTEL = 5844, + CapabilityUnstructuredLoopControlsINTEL = 5886, + CapabilityFPGALoopControlsINTEL = 5888, + CapabilityKernelAttributesINTEL = 5892, + CapabilityFPGAKernelAttributesINTEL = 5897, + CapabilityFPGAMemoryAccessesINTEL = 5898, + CapabilityFPGAClusterAttributesINTEL = 5904, + CapabilityLoopFuseINTEL = 5906, + CapabilityFPGABufferLocationINTEL = 5920, + CapabilityUSMStorageClassesINTEL = 5935, + CapabilityIOPipesINTEL = 5943, + CapabilityBlockingPipesINTEL = 5945, + CapabilityFPGARegINTEL = 5948, + CapabilityAtomicFloat32AddEXT = 6033, + CapabilityAtomicFloat64AddEXT = 6034, + CapabilityLongConstantCompositeINTEL = 6089, + CapabilityAtomicFloat16AddEXT = 6095, CapabilityMax = 0x7fffffff, }; +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum FragmentShadingRateShift { + FragmentShadingRateVertical2PixelsShift = 0, + FragmentShadingRateVertical4PixelsShift = 1, + FragmentShadingRateHorizontal2PixelsShift = 2, + FragmentShadingRateHorizontal4PixelsShift = 3, + FragmentShadingRateMax = 0x7fffffff, +}; + +enum FragmentShadingRateMask { + FragmentShadingRateMaskNone = 0, + FragmentShadingRateVertical2PixelsMask = 0x00000001, + FragmentShadingRateVertical4PixelsMask = 0x00000002, + FragmentShadingRateHorizontal2PixelsMask = 0x00000004, + FragmentShadingRateHorizontal4PixelsMask = 0x00000008, +}; + +enum FPDenormMode { + FPDenormModePreserve = 0, + FPDenormModeFlushToZero = 1, + FPDenormModeMax = 0x7fffffff, +}; + +enum FPOperationMode { + FPOperationModeIEEE = 0, + FPOperationModeALT = 1, + FPOperationModeMax = 0x7fffffff, +}; + enum Op { OpNop = 0, OpUndef = 1, @@ -1248,12 +1467,25 @@ enum Op { OpPtrEqual = 401, OpPtrNotEqual = 402, OpPtrDiff = 403, + OpTerminateInvocation = 4416, OpSubgroupBallotKHR = 4421, OpSubgroupFirstInvocationKHR = 4422, OpSubgroupAllKHR = 4428, OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTraceRayKHR = 4445, + OpExecuteCallableKHR = 4446, + OpConvertUToAccelerationStructureKHR = 4447, + OpIgnoreIntersectionKHR = 4448, + OpTerminateRayKHR = 4449, + OpTypeRayQueryKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1268,10 +1500,14 @@ enum Op { OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, OpIgnoreIntersectionNV = 5335, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceMotionNV = 5338, + OpTraceRayMotionNV = 5339, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, @@ -1307,6 +1543,15 @@ enum Op { OpUSubSatINTEL = 5596, OpIMul32x16INTEL = 5597, OpUMul32x16INTEL = 5598, + OpConstFunctionPointerINTEL = 5600, + OpFunctionPointerCallINTEL = 5601, + OpAsmTargetINTEL = 5609, + OpAsmINTEL = 5610, + OpAsmCallINTEL = 5611, + OpAtomicFMinEXT = 5614, + OpAtomicFMaxEXT = 5615, + OpAssumeTrueKHR = 5630, + OpExpectKHR = 5631, OpDecorateString = 5632, OpDecorateStringGOOGLE = 5632, OpMemberDecorateString = 5633, @@ -1429,6 +1674,37 @@ enum Op { OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpVariableLengthArrayINTEL = 5818, + OpSaveMemoryINTEL = 5819, + OpRestoreMemoryINTEL = 5820, + OpLoopControlINTEL = 5887, + OpPtrCastToCrossWorkgroupINTEL = 5934, + OpCrossWorkgroupCastToPtrINTEL = 5938, + OpReadPipeBlockingINTEL = 5946, + OpWritePipeBlockingINTEL = 5947, + OpFPGARegINTEL = 5949, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpAtomicFAddEXT = 6035, + OpTypeBufferSurfaceINTEL = 6086, + OpTypeStructContinuedINTEL = 6090, + OpConstantCompositeContinuedINTEL = 6091, + OpSpecConstantCompositeContinuedINTEL = 6092, OpMax = 0x7fffffff, }; @@ -1781,12 +2057,25 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpPtrEqual: *hasResult = true; *hasResultType = true; break; case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break; case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break; + case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break; + case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break; + case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; @@ -1805,6 +2094,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTraceMotionNV: *hasResult = false; *hasResultType = false; break; + case OpTraceRayMotionNV: *hasResult = false; *hasResultType = false; break; case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; @@ -1840,6 +2131,15 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; + case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; + case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break; + case OpAsmINTEL: *hasResult = true; *hasResultType = true; break; + case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break; + case OpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break; + case OpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break; + case OpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break; + case OpExpectKHR: *hasResult = true; *hasResultType = true; break; case OpDecorateString: *hasResult = false; *hasResultType = false; break; case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; @@ -1960,6 +2260,37 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break; + case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break; + case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break; + case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; + case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break; + case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break; + case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; + case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; + case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break; + case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break; + case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; + case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; } } #endif /* SPV_ENABLE_UTILITY_CODE */ @@ -1974,6 +2305,8 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } +inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); } } // end namespace spv diff --git a/libraries/glslang/spirv/spvIR.h b/libraries/ZVulkan/src/glslang/spirv/spvIR.h similarity index 94% rename from libraries/glslang/spirv/spvIR.h rename to libraries/ZVulkan/src/glslang/spirv/spvIR.h index cf6a71159..486e80d00 100644 --- a/libraries/glslang/spirv/spvIR.h +++ b/libraries/ZVulkan/src/glslang/spirv/spvIR.h @@ -55,6 +55,7 @@ #include #include #include +#include namespace spv { @@ -235,8 +236,7 @@ public: assert(instructions.size() > 0); instructions.resize(1); successors.clear(); - Instruction* unreachable = new Instruction(OpUnreachable); - addInstruction(std::unique_ptr(unreachable)); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); } // Change this block into a canonical dead continue target branching to the // given header ID. Delete instructions as necessary. A canonical dead continue @@ -263,6 +263,7 @@ public: case OpBranchConditional: case OpSwitch: case OpKill: + case OpTerminateInvocation: case OpReturn: case OpReturnValue: case OpUnreachable: @@ -352,10 +353,28 @@ public: const std::vector& getBlocks() const { return blocks; } void addLocalVariable(std::unique_ptr inst); Id getReturnType() const { return functionInstruction.getTypeId(); } + void setReturnPrecision(Decoration precision) + { + if (precision == DecorationRelaxedPrecision) + reducedPrecisionReturn = true; + } + Decoration getReturnPrecision() const + { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; } void setImplicitThis() { implicitThis = true; } bool hasImplicitThis() const { return implicitThis; } + void addParamPrecision(unsigned param, Decoration precision) + { + if (precision == DecorationRelaxedPrecision) + reducedPrecisionParams.insert(param); + } + Decoration getParamPrecision(unsigned param) const + { + return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ? + DecorationRelaxedPrecision : NoPrecision; + } + void dump(std::vector& out) const { // OpFunction @@ -380,6 +399,8 @@ protected: std::vector parameterInstructions; std::vector blocks; bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument + bool reducedPrecisionReturn; + std::set reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg }; // @@ -440,7 +461,8 @@ protected: // - the OpFunction instruction // - all the OpFunctionParameter instructions __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) - : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false), + reducedPrecisionReturn(false) { // OpFunction functionInstruction.addImmediateOperand(FunctionControlMaskNone); diff --git a/src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp b/libraries/ZVulkan/src/vk_mem_alloc/vk_mem_alloc.cpp similarity index 77% rename from src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp rename to libraries/ZVulkan/src/vk_mem_alloc/vk_mem_alloc.cpp index ee988cfc4..fb0d23472 100644 --- a/src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp +++ b/libraries/ZVulkan/src/vk_mem_alloc/vk_mem_alloc.cpp @@ -5,4 +5,4 @@ #define VMA_NULLABLE #define VMA_NOT_NULL -#include "vk_mem_alloc.h" +#include "vk_mem_alloc/vk_mem_alloc.h" diff --git a/src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.natvis b/libraries/ZVulkan/src/vk_mem_alloc/vk_mem_alloc.natvis similarity index 100% rename from src/common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.natvis rename to libraries/ZVulkan/src/vk_mem_alloc/vk_mem_alloc.natvis diff --git a/src/common/rendering/vulkan/thirdparty/volk/volk.c b/libraries/ZVulkan/src/volk/volk.c similarity index 63% rename from src/common/rendering/vulkan/thirdparty/volk/volk.c rename to libraries/ZVulkan/src/volk/volk.c index bcaf541c3..7a6969b10 100644 --- a/src/common/rendering/vulkan/thirdparty/volk/volk.c +++ b/libraries/ZVulkan/src/volk/volk.c @@ -1,18 +1,26 @@ -#ifdef _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#endif -#ifdef __APPLE__ +#if defined(_WIN32) +#define VK_USE_PLATFORM_WIN32_KHR +#elif defined(__APPLE__) #define VK_USE_PLATFORM_MACOS_MVK #define VK_USE_PLATFORM_METAL_EXT +#else +#define VK_USE_PLATFORM_XLIB_KHR #endif - /* This file is part of volk library; see volk.h for version/license details */ -#include "volk.h" +/* clang-format off */ +#include "volk/volk.h" #ifdef _WIN32 -# include + typedef const char* LPCSTR; + typedef struct HINSTANCE__* HINSTANCE; + typedef HINSTANCE HMODULE; + #ifdef _WIN64 + typedef __int64 (__stdcall* FARPROC)(void); + #else + typedef int (__stdcall* FARPROC)(void); + #endif #else # include #endif @@ -21,6 +29,14 @@ extern "C" { #endif +#ifdef _WIN32 +__declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); +__declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); +#endif + +static VkInstance loadedInstance = VK_NULL_HANDLE; +static VkDevice loadedDevice = VK_NULL_HANDLE; + static void volkGenLoadLoader(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); @@ -43,11 +59,12 @@ VkResult volkInitialize(void) if (!module) return VK_ERROR_INITIALIZATION_FAILED; - vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(module, "vkGetInstanceProcAddr"); + // note: function pointer is cast through void function pointer to silence cast-function-type warning on gcc8 + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)(void(*)(void))GetProcAddress(module, "vkGetInstanceProcAddr"); #elif defined(__APPLE__) void* module = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) - module = dlopen("libvulkan.dylib.1", RTLD_NOW | RTLD_LOCAL); + module = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) module = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL); if (!module) @@ -55,9 +72,9 @@ VkResult volkInitialize(void) vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); #else - void* module = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); + void* module = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); if (!module) - module = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); + module = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); if (!module) return VK_ERROR_INITIALIZATION_FAILED; @@ -92,15 +109,33 @@ uint32_t volkGetInstanceVersion(void) void volkLoadInstance(VkInstance instance) { + loadedInstance = instance; volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); volkGenLoadDevice(instance, vkGetInstanceProcAddrStub); } +void volkLoadInstanceOnly(VkInstance instance) +{ + loadedInstance = instance; + volkGenLoadInstance(instance, vkGetInstanceProcAddrStub); +} + +VkInstance volkGetLoadedInstance() +{ + return loadedInstance; +} + void volkLoadDevice(VkDevice device) { + loadedDevice = device; volkGenLoadDevice(device, vkGetDeviceProcAddrStub); } +VkDevice volkGetLoadedDevice() +{ + return loadedDevice; +} + void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device) { volkGenLoadDeviceTable(table, device, vkGetDeviceProcAddrStub); @@ -151,6 +186,10 @@ 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_EXT_acquire_drm_display) + vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT"); + vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT"); +#endif /* defined(VK_EXT_acquire_drm_display) */ #if defined(VK_EXT_acquire_xlib_display) vkAcquireXlibDisplayEXT = (PFN_vkAcquireXlibDisplayEXT)load(context, "vkAcquireXlibDisplayEXT"); vkGetRandROutputDisplayEXT = (PFN_vkGetRandROutputDisplayEXT)load(context, "vkGetRandROutputDisplayEXT"); @@ -164,25 +203,49 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)load(context, "vkDestroyDebugReportCallbackEXT"); #endif /* defined(VK_EXT_debug_report) */ #if defined(VK_EXT_debug_utils) + vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)load(context, "vkCmdBeginDebugUtilsLabelEXT"); + vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)load(context, "vkCmdEndDebugUtilsLabelEXT"); + vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)load(context, "vkCmdInsertDebugUtilsLabelEXT"); vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)load(context, "vkCreateDebugUtilsMessengerEXT"); vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)load(context, "vkDestroyDebugUtilsMessengerEXT"); + vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)load(context, "vkQueueBeginDebugUtilsLabelEXT"); + vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)load(context, "vkQueueEndDebugUtilsLabelEXT"); + vkQueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)load(context, "vkQueueInsertDebugUtilsLabelEXT"); + vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)load(context, "vkSetDebugUtilsObjectNameEXT"); + vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)load(context, "vkSetDebugUtilsObjectTagEXT"); vkSubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT)load(context, "vkSubmitDebugUtilsMessageEXT"); #endif /* defined(VK_EXT_debug_utils) */ #if defined(VK_EXT_direct_mode_display) vkReleaseDisplayEXT = (PFN_vkReleaseDisplayEXT)load(context, "vkReleaseDisplayEXT"); #endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) + vkCreateDirectFBSurfaceEXT = (PFN_vkCreateDirectFBSurfaceEXT)load(context, "vkCreateDirectFBSurfaceEXT"); + vkGetPhysicalDeviceDirectFBPresentationSupportEXT = (PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)load(context, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"); +#endif /* defined(VK_EXT_directfb_surface) */ #if defined(VK_EXT_display_surface_counter) vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2EXT"); #endif /* defined(VK_EXT_display_surface_counter) */ +#if defined(VK_EXT_full_screen_exclusive) + vkGetPhysicalDeviceSurfacePresentModes2EXT = (PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)load(context, "vkGetPhysicalDeviceSurfacePresentModes2EXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ +#if defined(VK_EXT_headless_surface) + vkCreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT)load(context, "vkCreateHeadlessSurfaceEXT"); +#endif /* defined(VK_EXT_headless_surface) */ #if defined(VK_EXT_metal_surface) vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)load(context, "vkCreateMetalSurfaceEXT"); #endif /* defined(VK_EXT_metal_surface) */ #if defined(VK_EXT_sample_locations) vkGetPhysicalDeviceMultisamplePropertiesEXT = (PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)load(context, "vkGetPhysicalDeviceMultisamplePropertiesEXT"); #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) + vkGetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT)load(context, "vkGetPhysicalDeviceToolPropertiesEXT"); +#endif /* defined(VK_EXT_tooling_info) */ #if defined(VK_FUCHSIA_imagepipe_surface) vkCreateImagePipeSurfaceFUCHSIA = (PFN_vkCreateImagePipeSurfaceFUCHSIA)load(context, "vkCreateImagePipeSurfaceFUCHSIA"); #endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) + vkCreateStreamDescriptorSurfaceGGP = (PFN_vkCreateStreamDescriptorSurfaceGGP)load(context, "vkCreateStreamDescriptorSurfaceGGP"); +#endif /* defined(VK_GGP_stream_descriptor_surface) */ #if defined(VK_KHR_android_surface) vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)load(context, "vkCreateAndroidSurfaceKHR"); #endif /* defined(VK_KHR_android_surface) */ @@ -207,6 +270,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_KHR_external_semaphore_capabilities) vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)load(context, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"); #endif /* defined(VK_KHR_external_semaphore_capabilities) */ +#if defined(VK_KHR_fragment_shading_rate) + vkGetPhysicalDeviceFragmentShadingRatesKHR = (PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)load(context, "vkGetPhysicalDeviceFragmentShadingRatesKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_display_properties2) vkGetDisplayModeProperties2KHR = (PFN_vkGetDisplayModeProperties2KHR)load(context, "vkGetDisplayModeProperties2KHR"); vkGetDisplayPlaneCapabilities2KHR = (PFN_vkGetDisplayPlaneCapabilities2KHR)load(context, "vkGetDisplayPlaneCapabilities2KHR"); @@ -226,6 +292,10 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"); vkGetPhysicalDeviceSurfaceFormats2KHR = (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)load(context, "vkGetPhysicalDeviceSurfaceFormats2KHR"); #endif /* defined(VK_KHR_get_surface_capabilities2) */ +#if defined(VK_KHR_performance_query) + vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)load(context, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"); + vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = (PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)load(context, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR"); +#endif /* defined(VK_KHR_performance_query) */ #if defined(VK_KHR_surface) vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)load(context, "vkDestroySurfaceKHR"); vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)load(context, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); @@ -233,6 +303,10 @@ 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_queue) + vkGetPhysicalDeviceVideoCapabilitiesKHR = (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)load(context, "vkGetPhysicalDeviceVideoCapabilitiesKHR"); + vkGetPhysicalDeviceVideoFormatPropertiesKHR = (PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)load(context, "vkGetPhysicalDeviceVideoFormatPropertiesKHR"); +#endif /* defined(VK_KHR_video_queue) */ #if defined(VK_KHR_wayland_surface) vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)load(context, "vkCreateWaylandSurfaceKHR"); vkGetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)load(context, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"); @@ -258,15 +332,23 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*, #if defined(VK_NN_vi_surface) vkCreateViSurfaceNN = (PFN_vkCreateViSurfaceNN)load(context, "vkCreateViSurfaceNN"); #endif /* defined(VK_NN_vi_surface) */ -#if defined(VK_NVX_device_generated_commands) - vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX = (PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)load(context, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX"); -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_NV_acquire_winrt_display) + vkAcquireWinrtDisplayNV = (PFN_vkAcquireWinrtDisplayNV)load(context, "vkAcquireWinrtDisplayNV"); + vkGetWinrtDisplayNV = (PFN_vkGetWinrtDisplayNV)load(context, "vkGetWinrtDisplayNV"); +#endif /* defined(VK_NV_acquire_winrt_display) */ #if defined(VK_NV_cooperative_matrix) vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)load(context, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV"); #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_coverage_reduction_mode) + vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)load(context, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV"); +#endif /* defined(VK_NV_coverage_reduction_mode) */ #if defined(VK_NV_external_memory_capabilities) vkGetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)load(context, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV"); #endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_QNX_screen_surface) + vkCreateScreenSurfaceQNX = (PFN_vkCreateScreenSurfaceQNX)load(context, "vkCreateScreenSurfaceQNX"); + vkGetPhysicalDeviceScreenPresentationSupportQNX = (PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)load(context, "vkGetPhysicalDeviceScreenPresentationSupportQNX"); +#endif /* defined(VK_QNX_screen_surface) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR)load(context, "vkGetPhysicalDevicePresentRectanglesKHR"); #endif /* (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) */ @@ -416,9 +498,27 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkTrimCommandPool = (PFN_vkTrimCommandPool)load(context, "vkTrimCommandPool"); vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate)load(context, "vkUpdateDescriptorSetWithTemplate"); #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2)load(context, "vkCmdBeginRenderPass2"); + vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount)load(context, "vkCmdDrawIndexedIndirectCount"); + vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount)load(context, "vkCmdDrawIndirectCount"); + vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2)load(context, "vkCmdEndRenderPass2"); + vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2)load(context, "vkCmdNextSubpass2"); + vkCreateRenderPass2 = (PFN_vkCreateRenderPass2)load(context, "vkCreateRenderPass2"); + vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress)load(context, "vkGetBufferDeviceAddress"); + vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress)load(context, "vkGetBufferOpaqueCaptureAddress"); + vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress)load(context, "vkGetDeviceMemoryOpaqueCaptureAddress"); + vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue)load(context, "vkGetSemaphoreCounterValue"); + vkResetQueryPool = (PFN_vkResetQueryPool)load(context, "vkResetQueryPool"); + vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); + vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); +#endif /* defined(VK_VERSION_1_2) */ #if defined(VK_AMD_buffer_marker) vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_display_native_hdr) + vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); +#endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) vkCmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)load(context, "vkCmdDrawIndexedIndirectCountAMD"); vkCmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)load(context, "vkCmdDrawIndirectCountAMD"); @@ -436,6 +536,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c #if defined(VK_EXT_calibrated_timestamps) vkGetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)load(context, "vkGetCalibratedTimestampsEXT"); #endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + vkCmdSetColorWriteEnableEXT = (PFN_vkCmdSetColorWriteEnableEXT)load(context, "vkCmdSetColorWriteEnableEXT"); +#endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) vkCmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)load(context, "vkCmdBeginConditionalRenderingEXT"); vkCmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)load(context, "vkCmdEndConditionalRenderingEXT"); @@ -447,16 +550,6 @@ 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_debug_utils) - vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)load(context, "vkCmdBeginDebugUtilsLabelEXT"); - vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)load(context, "vkCmdEndDebugUtilsLabelEXT"); - vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)load(context, "vkCmdInsertDebugUtilsLabelEXT"); - vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)load(context, "vkQueueBeginDebugUtilsLabelEXT"); - vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)load(context, "vkQueueEndDebugUtilsLabelEXT"); - vkQueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)load(context, "vkQueueInsertDebugUtilsLabelEXT"); - vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)load(context, "vkSetDebugUtilsObjectNameEXT"); - vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)load(context, "vkSetDebugUtilsObjectTagEXT"); -#endif /* defined(VK_EXT_debug_utils) */ #if defined(VK_EXT_discard_rectangles) vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ @@ -466,15 +559,56 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c 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) */ +#if defined(VK_EXT_full_screen_exclusive) + vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); + vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ #if defined(VK_EXT_hdr_metadata) vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_query_reset) + vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); +#endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) vkGetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)load(context, "vkGetImageDrmFormatModifierPropertiesEXT"); #endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); +#endif /* defined(VK_EXT_line_rasterization) */ +#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_private_data) + vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); + vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); + vkGetPrivateDataEXT = (PFN_vkGetPrivateDataEXT)load(context, "vkGetPrivateDataEXT"); + vkSetPrivateDataEXT = (PFN_vkSetPrivateDataEXT)load(context, "vkSetPrivateDataEXT"); +#endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); #endif /* defined(VK_EXT_sample_locations) */ @@ -492,20 +626,87 @@ 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_external_memory) + vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); + vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + vkGetSemaphoreZirconHandleFUCHSIA = (PFN_vkGetSemaphoreZirconHandleFUCHSIA)load(context, "vkGetSemaphoreZirconHandleFUCHSIA"); + vkImportSemaphoreZirconHandleFUCHSIA = (PFN_vkImportSemaphoreZirconHandleFUCHSIA)load(context, "vkImportSemaphoreZirconHandleFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_GOOGLE_display_timing) vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_invocation_mask) + vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) + vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); + vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); + vkCmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)load(context, "vkCmdSetPerformanceMarkerINTEL"); + vkCmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)load(context, "vkCmdSetPerformanceOverrideINTEL"); + vkCmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)load(context, "vkCmdSetPerformanceStreamMarkerINTEL"); + vkGetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)load(context, "vkGetPerformanceParameterINTEL"); + vkInitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)load(context, "vkInitializePerformanceApiINTEL"); + vkQueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)load(context, "vkQueueSetPerformanceConfigurationINTEL"); + vkReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)load(context, "vkReleasePerformanceConfigurationINTEL"); + vkUninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)load(context, "vkUninitializePerformanceApiINTEL"); +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + vkBuildAccelerationStructuresKHR = (PFN_vkBuildAccelerationStructuresKHR)load(context, "vkBuildAccelerationStructuresKHR"); + vkCmdBuildAccelerationStructuresIndirectKHR = (PFN_vkCmdBuildAccelerationStructuresIndirectKHR)load(context, "vkCmdBuildAccelerationStructuresIndirectKHR"); + vkCmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)load(context, "vkCmdBuildAccelerationStructuresKHR"); + vkCmdCopyAccelerationStructureKHR = (PFN_vkCmdCopyAccelerationStructureKHR)load(context, "vkCmdCopyAccelerationStructureKHR"); + vkCmdCopyAccelerationStructureToMemoryKHR = (PFN_vkCmdCopyAccelerationStructureToMemoryKHR)load(context, "vkCmdCopyAccelerationStructureToMemoryKHR"); + vkCmdCopyMemoryToAccelerationStructureKHR = (PFN_vkCmdCopyMemoryToAccelerationStructureKHR)load(context, "vkCmdCopyMemoryToAccelerationStructureKHR"); + vkCmdWriteAccelerationStructuresPropertiesKHR = (PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)load(context, "vkCmdWriteAccelerationStructuresPropertiesKHR"); + vkCopyAccelerationStructureKHR = (PFN_vkCopyAccelerationStructureKHR)load(context, "vkCopyAccelerationStructureKHR"); + vkCopyAccelerationStructureToMemoryKHR = (PFN_vkCopyAccelerationStructureToMemoryKHR)load(context, "vkCopyAccelerationStructureToMemoryKHR"); + vkCopyMemoryToAccelerationStructureKHR = (PFN_vkCopyMemoryToAccelerationStructureKHR)load(context, "vkCopyMemoryToAccelerationStructureKHR"); + vkCreateAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)load(context, "vkCreateAccelerationStructureKHR"); + vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)load(context, "vkDestroyAccelerationStructureKHR"); + vkGetAccelerationStructureBuildSizesKHR = (PFN_vkGetAccelerationStructureBuildSizesKHR)load(context, "vkGetAccelerationStructureBuildSizesKHR"); + vkGetAccelerationStructureDeviceAddressKHR = (PFN_vkGetAccelerationStructureDeviceAddressKHR)load(context, "vkGetAccelerationStructureDeviceAddressKHR"); + vkGetDeviceAccelerationStructureCompatibilityKHR = (PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)load(context, "vkGetDeviceAccelerationStructureCompatibilityKHR"); + vkWriteAccelerationStructuresPropertiesKHR = (PFN_vkWriteAccelerationStructuresPropertiesKHR)load(context, "vkWriteAccelerationStructuresPropertiesKHR"); +#endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_bind_memory2) vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)load(context, "vkBindBufferMemory2KHR"); vkBindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)load(context, "vkBindImageMemory2KHR"); #endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + vkGetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)load(context, "vkGetBufferDeviceAddressKHR"); + vkGetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)load(context, "vkGetBufferOpaqueCaptureAddressKHR"); + vkGetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)load(context, "vkGetDeviceMemoryOpaqueCaptureAddressKHR"); +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_copy_commands2) + vkCmdBlitImage2KHR = (PFN_vkCmdBlitImage2KHR)load(context, "vkCmdBlitImage2KHR"); + vkCmdCopyBuffer2KHR = (PFN_vkCmdCopyBuffer2KHR)load(context, "vkCmdCopyBuffer2KHR"); + vkCmdCopyBufferToImage2KHR = (PFN_vkCmdCopyBufferToImage2KHR)load(context, "vkCmdCopyBufferToImage2KHR"); + vkCmdCopyImage2KHR = (PFN_vkCmdCopyImage2KHR)load(context, "vkCmdCopyImage2KHR"); + vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); + vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); +#endif /* defined(VK_KHR_copy_commands2) */ #if defined(VK_KHR_create_renderpass2) vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)load(context, "vkCmdNextSubpass2KHR"); vkCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)load(context, "vkCreateRenderPass2KHR"); #endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + vkCreateDeferredOperationKHR = (PFN_vkCreateDeferredOperationKHR)load(context, "vkCreateDeferredOperationKHR"); + vkDeferredOperationJoinKHR = (PFN_vkDeferredOperationJoinKHR)load(context, "vkDeferredOperationJoinKHR"); + vkDestroyDeferredOperationKHR = (PFN_vkDestroyDeferredOperationKHR)load(context, "vkDestroyDeferredOperationKHR"); + vkGetDeferredOperationMaxConcurrencyKHR = (PFN_vkGetDeferredOperationMaxConcurrencyKHR)load(context, "vkGetDeferredOperationMaxConcurrencyKHR"); + vkGetDeferredOperationResultKHR = (PFN_vkGetDeferredOperationResultKHR)load(context, "vkGetDeferredOperationResultKHR"); +#endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) vkCreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)load(context, "vkCreateDescriptorUpdateTemplateKHR"); vkDestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)load(context, "vkDestroyDescriptorUpdateTemplateKHR"); @@ -547,6 +748,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)load(context, "vkGetSemaphoreWin32HandleKHR"); vkImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)load(context, "vkImportSemaphoreWin32HandleKHR"); #endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + vkCmdSetFragmentShadingRateKHR = (PFN_vkCmdSetFragmentShadingRateKHR)load(context, "vkCmdSetFragmentShadingRateKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_memory_requirements2) vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)load(context, "vkGetBufferMemoryRequirements2KHR"); vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)load(context, "vkGetImageMemoryRequirements2KHR"); @@ -558,9 +762,30 @@ 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_performance_query) + vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); + vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_executable_properties) + vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); + vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); + vkGetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)load(context, "vkGetPipelineExecutableStatisticsKHR"); +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); +#endif /* defined(VK_KHR_present_wait) */ #if defined(VK_KHR_push_descriptor) vkCmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)load(context, "vkCmdPushDescriptorSetKHR"); #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_pipeline) + vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); + vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); + vkCmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)load(context, "vkCmdTraceRaysKHR"); + vkCreateRayTracingPipelinesKHR = (PFN_vkCreateRayTracingPipelinesKHR)load(context, "vkCreateRayTracingPipelinesKHR"); + vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)load(context, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR"); + vkGetRayTracingShaderGroupHandlesKHR = (PFN_vkGetRayTracingShaderGroupHandlesKHR)load(context, "vkGetRayTracingShaderGroupHandlesKHR"); + vkGetRayTracingShaderGroupStackSizeKHR = (PFN_vkGetRayTracingShaderGroupStackSizeKHR)load(context, "vkGetRayTracingShaderGroupStackSizeKHR"); +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) vkCreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)load(context, "vkCreateSamplerYcbcrConversionKHR"); vkDestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)load(context, "vkDestroySamplerYcbcrConversionKHR"); @@ -575,17 +800,52 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); #endif /* defined(VK_KHR_swapchain) */ -#if defined(VK_NVX_device_generated_commands) - vkCmdProcessCommandsNVX = (PFN_vkCmdProcessCommandsNVX)load(context, "vkCmdProcessCommandsNVX"); - vkCmdReserveSpaceForCommandsNVX = (PFN_vkCmdReserveSpaceForCommandsNVX)load(context, "vkCmdReserveSpaceForCommandsNVX"); - vkCreateIndirectCommandsLayoutNVX = (PFN_vkCreateIndirectCommandsLayoutNVX)load(context, "vkCreateIndirectCommandsLayoutNVX"); - vkCreateObjectTableNVX = (PFN_vkCreateObjectTableNVX)load(context, "vkCreateObjectTableNVX"); - vkDestroyIndirectCommandsLayoutNVX = (PFN_vkDestroyIndirectCommandsLayoutNVX)load(context, "vkDestroyIndirectCommandsLayoutNVX"); - vkDestroyObjectTableNVX = (PFN_vkDestroyObjectTableNVX)load(context, "vkDestroyObjectTableNVX"); - vkRegisterObjectsNVX = (PFN_vkRegisterObjectsNVX)load(context, "vkRegisterObjectsNVX"); - vkUnregisterObjectsNVX = (PFN_vkUnregisterObjectsNVX)load(context, "vkUnregisterObjectsNVX"); -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_KHR_synchronization2) + vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); + vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); + vkCmdSetEvent2KHR = (PFN_vkCmdSetEvent2KHR)load(context, "vkCmdSetEvent2KHR"); + vkCmdWaitEvents2KHR = (PFN_vkCmdWaitEvents2KHR)load(context, "vkCmdWaitEvents2KHR"); + vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); + vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) + vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) + vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_KHR_timeline_semaphore) + vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); + vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); + vkWaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)load(context, "vkWaitSemaphoresKHR"); +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + vkCmdDecodeVideoKHR = (PFN_vkCmdDecodeVideoKHR)load(context, "vkCmdDecodeVideoKHR"); +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); + vkCmdBeginVideoCodingKHR = (PFN_vkCmdBeginVideoCodingKHR)load(context, "vkCmdBeginVideoCodingKHR"); + vkCmdControlVideoCodingKHR = (PFN_vkCmdControlVideoCodingKHR)load(context, "vkCmdControlVideoCodingKHR"); + vkCmdEndVideoCodingKHR = (PFN_vkCmdEndVideoCodingKHR)load(context, "vkCmdEndVideoCodingKHR"); + vkCreateVideoSessionKHR = (PFN_vkCreateVideoSessionKHR)load(context, "vkCreateVideoSessionKHR"); + vkCreateVideoSessionParametersKHR = (PFN_vkCreateVideoSessionParametersKHR)load(context, "vkCreateVideoSessionParametersKHR"); + vkDestroyVideoSessionKHR = (PFN_vkDestroyVideoSessionKHR)load(context, "vkDestroyVideoSessionKHR"); + vkDestroyVideoSessionParametersKHR = (PFN_vkDestroyVideoSessionParametersKHR)load(context, "vkDestroyVideoSessionParametersKHR"); + vkGetVideoSessionMemoryRequirementsKHR = (PFN_vkGetVideoSessionMemoryRequirementsKHR)load(context, "vkGetVideoSessionMemoryRequirementsKHR"); + vkUpdateVideoSessionParametersKHR = (PFN_vkUpdateVideoSessionParametersKHR)load(context, "vkUpdateVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + vkCmdCuLaunchKernelNVX = (PFN_vkCmdCuLaunchKernelNVX)load(context, "vkCmdCuLaunchKernelNVX"); + vkCreateCuFunctionNVX = (PFN_vkCreateCuFunctionNVX)load(context, "vkCreateCuFunctionNVX"); + vkCreateCuModuleNVX = (PFN_vkCreateCuModuleNVX)load(context, "vkCreateCuModuleNVX"); + vkDestroyCuFunctionNVX = (PFN_vkDestroyCuFunctionNVX)load(context, "vkDestroyCuFunctionNVX"); + vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); +#endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) + vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); #endif /* defined(VK_NVX_image_view_handle) */ #if defined(VK_NV_clip_space_w_scaling) @@ -595,9 +855,23 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_generated_commands) + vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); + vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); + vkCmdPreprocessGeneratedCommandsNV = (PFN_vkCmdPreprocessGeneratedCommandsNV)load(context, "vkCmdPreprocessGeneratedCommandsNV"); + vkCreateIndirectCommandsLayoutNV = (PFN_vkCreateIndirectCommandsLayoutNV)load(context, "vkCreateIndirectCommandsLayoutNV"); + vkDestroyIndirectCommandsLayoutNV = (PFN_vkDestroyIndirectCommandsLayoutNV)load(context, "vkDestroyIndirectCommandsLayoutNV"); + vkGetGeneratedCommandsMemoryRequirementsNV = (PFN_vkGetGeneratedCommandsMemoryRequirementsNV)load(context, "vkGetGeneratedCommandsMemoryRequirementsNV"); +#endif /* defined(VK_NV_device_generated_commands) */ +#if defined(VK_NV_external_memory_rdma) + vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); +#endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) vkGetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)load(context, "vkGetMemoryWin32HandleNV"); #endif /* defined(VK_NV_external_memory_win32) */ +#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_mesh_shader) vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); @@ -625,9 +899,12 @@ 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_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) +#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_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)) */ +#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)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); @@ -781,9 +1058,27 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkTrimCommandPool = (PFN_vkTrimCommandPool)load(context, "vkTrimCommandPool"); table->vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate)load(context, "vkUpdateDescriptorSetWithTemplate"); #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) + table->vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2)load(context, "vkCmdBeginRenderPass2"); + table->vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount)load(context, "vkCmdDrawIndexedIndirectCount"); + table->vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount)load(context, "vkCmdDrawIndirectCount"); + table->vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2)load(context, "vkCmdEndRenderPass2"); + table->vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2)load(context, "vkCmdNextSubpass2"); + table->vkCreateRenderPass2 = (PFN_vkCreateRenderPass2)load(context, "vkCreateRenderPass2"); + table->vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress)load(context, "vkGetBufferDeviceAddress"); + table->vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress)load(context, "vkGetBufferOpaqueCaptureAddress"); + table->vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress)load(context, "vkGetDeviceMemoryOpaqueCaptureAddress"); + table->vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue)load(context, "vkGetSemaphoreCounterValue"); + table->vkResetQueryPool = (PFN_vkResetQueryPool)load(context, "vkResetQueryPool"); + table->vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore"); + table->vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores"); +#endif /* defined(VK_VERSION_1_2) */ #if defined(VK_AMD_buffer_marker) table->vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD"); #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_display_native_hdr) + table->vkSetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)load(context, "vkSetLocalDimmingAMD"); +#endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) table->vkCmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)load(context, "vkCmdDrawIndexedIndirectCountAMD"); table->vkCmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)load(context, "vkCmdDrawIndirectCountAMD"); @@ -801,6 +1096,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, #if defined(VK_EXT_calibrated_timestamps) table->vkGetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)load(context, "vkGetCalibratedTimestampsEXT"); #endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) + table->vkCmdSetColorWriteEnableEXT = (PFN_vkCmdSetColorWriteEnableEXT)load(context, "vkCmdSetColorWriteEnableEXT"); +#endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) table->vkCmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)load(context, "vkCmdBeginConditionalRenderingEXT"); table->vkCmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)load(context, "vkCmdEndConditionalRenderingEXT"); @@ -812,16 +1110,6 @@ 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_debug_utils) - table->vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)load(context, "vkCmdBeginDebugUtilsLabelEXT"); - table->vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)load(context, "vkCmdEndDebugUtilsLabelEXT"); - table->vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)load(context, "vkCmdInsertDebugUtilsLabelEXT"); - table->vkQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)load(context, "vkQueueBeginDebugUtilsLabelEXT"); - table->vkQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)load(context, "vkQueueEndDebugUtilsLabelEXT"); - table->vkQueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)load(context, "vkQueueInsertDebugUtilsLabelEXT"); - table->vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)load(context, "vkSetDebugUtilsObjectNameEXT"); - table->vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)load(context, "vkSetDebugUtilsObjectTagEXT"); -#endif /* defined(VK_EXT_debug_utils) */ #if defined(VK_EXT_discard_rectangles) table->vkCmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)load(context, "vkCmdSetDiscardRectangleEXT"); #endif /* defined(VK_EXT_discard_rectangles) */ @@ -831,15 +1119,56 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, 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) */ +#if defined(VK_EXT_full_screen_exclusive) + table->vkAcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)load(context, "vkAcquireFullScreenExclusiveModeEXT"); + table->vkReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)load(context, "vkReleaseFullScreenExclusiveModeEXT"); +#endif /* defined(VK_EXT_full_screen_exclusive) */ #if defined(VK_EXT_hdr_metadata) table->vkSetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)load(context, "vkSetHdrMetadataEXT"); #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_host_query_reset) + table->vkResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)load(context, "vkResetQueryPoolEXT"); +#endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) table->vkGetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)load(context, "vkGetImageDrmFormatModifierPropertiesEXT"); #endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) + table->vkCmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)load(context, "vkCmdSetLineStippleEXT"); +#endif /* defined(VK_EXT_line_rasterization) */ +#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_private_data) + table->vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT"); + table->vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT"); + table->vkGetPrivateDataEXT = (PFN_vkGetPrivateDataEXT)load(context, "vkGetPrivateDataEXT"); + table->vkSetPrivateDataEXT = (PFN_vkSetPrivateDataEXT)load(context, "vkSetPrivateDataEXT"); +#endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) table->vkCmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)load(context, "vkCmdSetSampleLocationsEXT"); #endif /* defined(VK_EXT_sample_locations) */ @@ -857,20 +1186,87 @@ 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_external_memory) + table->vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA"); + table->vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) + table->vkGetSemaphoreZirconHandleFUCHSIA = (PFN_vkGetSemaphoreZirconHandleFUCHSIA)load(context, "vkGetSemaphoreZirconHandleFUCHSIA"); + table->vkImportSemaphoreZirconHandleFUCHSIA = (PFN_vkImportSemaphoreZirconHandleFUCHSIA)load(context, "vkImportSemaphoreZirconHandleFUCHSIA"); +#endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_GOOGLE_display_timing) table->vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)load(context, "vkGetPastPresentationTimingGOOGLE"); table->vkGetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)load(context, "vkGetRefreshCycleDurationGOOGLE"); #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_invocation_mask) + table->vkCmdBindInvocationMaskHUAWEI = (PFN_vkCmdBindInvocationMaskHUAWEI)load(context, "vkCmdBindInvocationMaskHUAWEI"); +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) + table->vkCmdSubpassShadingHUAWEI = (PFN_vkCmdSubpassShadingHUAWEI)load(context, "vkCmdSubpassShadingHUAWEI"); + table->vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = (PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)load(context, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"); +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) + table->vkAcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)load(context, "vkAcquirePerformanceConfigurationINTEL"); + table->vkCmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)load(context, "vkCmdSetPerformanceMarkerINTEL"); + table->vkCmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)load(context, "vkCmdSetPerformanceOverrideINTEL"); + table->vkCmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)load(context, "vkCmdSetPerformanceStreamMarkerINTEL"); + table->vkGetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)load(context, "vkGetPerformanceParameterINTEL"); + table->vkInitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)load(context, "vkInitializePerformanceApiINTEL"); + table->vkQueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)load(context, "vkQueueSetPerformanceConfigurationINTEL"); + table->vkReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)load(context, "vkReleasePerformanceConfigurationINTEL"); + table->vkUninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)load(context, "vkUninitializePerformanceApiINTEL"); +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) + table->vkBuildAccelerationStructuresKHR = (PFN_vkBuildAccelerationStructuresKHR)load(context, "vkBuildAccelerationStructuresKHR"); + table->vkCmdBuildAccelerationStructuresIndirectKHR = (PFN_vkCmdBuildAccelerationStructuresIndirectKHR)load(context, "vkCmdBuildAccelerationStructuresIndirectKHR"); + table->vkCmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)load(context, "vkCmdBuildAccelerationStructuresKHR"); + table->vkCmdCopyAccelerationStructureKHR = (PFN_vkCmdCopyAccelerationStructureKHR)load(context, "vkCmdCopyAccelerationStructureKHR"); + table->vkCmdCopyAccelerationStructureToMemoryKHR = (PFN_vkCmdCopyAccelerationStructureToMemoryKHR)load(context, "vkCmdCopyAccelerationStructureToMemoryKHR"); + table->vkCmdCopyMemoryToAccelerationStructureKHR = (PFN_vkCmdCopyMemoryToAccelerationStructureKHR)load(context, "vkCmdCopyMemoryToAccelerationStructureKHR"); + table->vkCmdWriteAccelerationStructuresPropertiesKHR = (PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)load(context, "vkCmdWriteAccelerationStructuresPropertiesKHR"); + table->vkCopyAccelerationStructureKHR = (PFN_vkCopyAccelerationStructureKHR)load(context, "vkCopyAccelerationStructureKHR"); + table->vkCopyAccelerationStructureToMemoryKHR = (PFN_vkCopyAccelerationStructureToMemoryKHR)load(context, "vkCopyAccelerationStructureToMemoryKHR"); + table->vkCopyMemoryToAccelerationStructureKHR = (PFN_vkCopyMemoryToAccelerationStructureKHR)load(context, "vkCopyMemoryToAccelerationStructureKHR"); + table->vkCreateAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)load(context, "vkCreateAccelerationStructureKHR"); + table->vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)load(context, "vkDestroyAccelerationStructureKHR"); + table->vkGetAccelerationStructureBuildSizesKHR = (PFN_vkGetAccelerationStructureBuildSizesKHR)load(context, "vkGetAccelerationStructureBuildSizesKHR"); + table->vkGetAccelerationStructureDeviceAddressKHR = (PFN_vkGetAccelerationStructureDeviceAddressKHR)load(context, "vkGetAccelerationStructureDeviceAddressKHR"); + table->vkGetDeviceAccelerationStructureCompatibilityKHR = (PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)load(context, "vkGetDeviceAccelerationStructureCompatibilityKHR"); + table->vkWriteAccelerationStructuresPropertiesKHR = (PFN_vkWriteAccelerationStructuresPropertiesKHR)load(context, "vkWriteAccelerationStructuresPropertiesKHR"); +#endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_bind_memory2) table->vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)load(context, "vkBindBufferMemory2KHR"); table->vkBindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)load(context, "vkBindImageMemory2KHR"); #endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) + table->vkGetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)load(context, "vkGetBufferDeviceAddressKHR"); + table->vkGetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)load(context, "vkGetBufferOpaqueCaptureAddressKHR"); + table->vkGetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)load(context, "vkGetDeviceMemoryOpaqueCaptureAddressKHR"); +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_copy_commands2) + table->vkCmdBlitImage2KHR = (PFN_vkCmdBlitImage2KHR)load(context, "vkCmdBlitImage2KHR"); + table->vkCmdCopyBuffer2KHR = (PFN_vkCmdCopyBuffer2KHR)load(context, "vkCmdCopyBuffer2KHR"); + table->vkCmdCopyBufferToImage2KHR = (PFN_vkCmdCopyBufferToImage2KHR)load(context, "vkCmdCopyBufferToImage2KHR"); + table->vkCmdCopyImage2KHR = (PFN_vkCmdCopyImage2KHR)load(context, "vkCmdCopyImage2KHR"); + table->vkCmdCopyImageToBuffer2KHR = (PFN_vkCmdCopyImageToBuffer2KHR)load(context, "vkCmdCopyImageToBuffer2KHR"); + table->vkCmdResolveImage2KHR = (PFN_vkCmdResolveImage2KHR)load(context, "vkCmdResolveImage2KHR"); +#endif /* defined(VK_KHR_copy_commands2) */ #if defined(VK_KHR_create_renderpass2) table->vkCmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)load(context, "vkCmdBeginRenderPass2KHR"); table->vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)load(context, "vkCmdEndRenderPass2KHR"); table->vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)load(context, "vkCmdNextSubpass2KHR"); table->vkCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)load(context, "vkCreateRenderPass2KHR"); #endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) + table->vkCreateDeferredOperationKHR = (PFN_vkCreateDeferredOperationKHR)load(context, "vkCreateDeferredOperationKHR"); + table->vkDeferredOperationJoinKHR = (PFN_vkDeferredOperationJoinKHR)load(context, "vkDeferredOperationJoinKHR"); + table->vkDestroyDeferredOperationKHR = (PFN_vkDestroyDeferredOperationKHR)load(context, "vkDestroyDeferredOperationKHR"); + table->vkGetDeferredOperationMaxConcurrencyKHR = (PFN_vkGetDeferredOperationMaxConcurrencyKHR)load(context, "vkGetDeferredOperationMaxConcurrencyKHR"); + table->vkGetDeferredOperationResultKHR = (PFN_vkGetDeferredOperationResultKHR)load(context, "vkGetDeferredOperationResultKHR"); +#endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) table->vkCreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)load(context, "vkCreateDescriptorUpdateTemplateKHR"); table->vkDestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)load(context, "vkDestroyDescriptorUpdateTemplateKHR"); @@ -912,6 +1308,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)load(context, "vkGetSemaphoreWin32HandleKHR"); table->vkImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)load(context, "vkImportSemaphoreWin32HandleKHR"); #endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) + table->vkCmdSetFragmentShadingRateKHR = (PFN_vkCmdSetFragmentShadingRateKHR)load(context, "vkCmdSetFragmentShadingRateKHR"); +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_memory_requirements2) table->vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)load(context, "vkGetBufferMemoryRequirements2KHR"); table->vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)load(context, "vkGetImageMemoryRequirements2KHR"); @@ -923,9 +1322,30 @@ 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_performance_query) + table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR"); + table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR"); +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_executable_properties) + table->vkGetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)load(context, "vkGetPipelineExecutableInternalRepresentationsKHR"); + table->vkGetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)load(context, "vkGetPipelineExecutablePropertiesKHR"); + table->vkGetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)load(context, "vkGetPipelineExecutableStatisticsKHR"); +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) + table->vkWaitForPresentKHR = (PFN_vkWaitForPresentKHR)load(context, "vkWaitForPresentKHR"); +#endif /* defined(VK_KHR_present_wait) */ #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_pipeline) + table->vkCmdSetRayTracingPipelineStackSizeKHR = (PFN_vkCmdSetRayTracingPipelineStackSizeKHR)load(context, "vkCmdSetRayTracingPipelineStackSizeKHR"); + table->vkCmdTraceRaysIndirectKHR = (PFN_vkCmdTraceRaysIndirectKHR)load(context, "vkCmdTraceRaysIndirectKHR"); + table->vkCmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)load(context, "vkCmdTraceRaysKHR"); + table->vkCreateRayTracingPipelinesKHR = (PFN_vkCreateRayTracingPipelinesKHR)load(context, "vkCreateRayTracingPipelinesKHR"); + table->vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = (PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)load(context, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR"); + table->vkGetRayTracingShaderGroupHandlesKHR = (PFN_vkGetRayTracingShaderGroupHandlesKHR)load(context, "vkGetRayTracingShaderGroupHandlesKHR"); + table->vkGetRayTracingShaderGroupStackSizeKHR = (PFN_vkGetRayTracingShaderGroupStackSizeKHR)load(context, "vkGetRayTracingShaderGroupStackSizeKHR"); +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) table->vkCreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)load(context, "vkCreateSamplerYcbcrConversionKHR"); table->vkDestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)load(context, "vkDestroySamplerYcbcrConversionKHR"); @@ -940,17 +1360,52 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)load(context, "vkGetSwapchainImagesKHR"); table->vkQueuePresentKHR = (PFN_vkQueuePresentKHR)load(context, "vkQueuePresentKHR"); #endif /* defined(VK_KHR_swapchain) */ -#if defined(VK_NVX_device_generated_commands) - table->vkCmdProcessCommandsNVX = (PFN_vkCmdProcessCommandsNVX)load(context, "vkCmdProcessCommandsNVX"); - table->vkCmdReserveSpaceForCommandsNVX = (PFN_vkCmdReserveSpaceForCommandsNVX)load(context, "vkCmdReserveSpaceForCommandsNVX"); - table->vkCreateIndirectCommandsLayoutNVX = (PFN_vkCreateIndirectCommandsLayoutNVX)load(context, "vkCreateIndirectCommandsLayoutNVX"); - table->vkCreateObjectTableNVX = (PFN_vkCreateObjectTableNVX)load(context, "vkCreateObjectTableNVX"); - table->vkDestroyIndirectCommandsLayoutNVX = (PFN_vkDestroyIndirectCommandsLayoutNVX)load(context, "vkDestroyIndirectCommandsLayoutNVX"); - table->vkDestroyObjectTableNVX = (PFN_vkDestroyObjectTableNVX)load(context, "vkDestroyObjectTableNVX"); - table->vkRegisterObjectsNVX = (PFN_vkRegisterObjectsNVX)load(context, "vkRegisterObjectsNVX"); - table->vkUnregisterObjectsNVX = (PFN_vkUnregisterObjectsNVX)load(context, "vkUnregisterObjectsNVX"); -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_KHR_synchronization2) + table->vkCmdPipelineBarrier2KHR = (PFN_vkCmdPipelineBarrier2KHR)load(context, "vkCmdPipelineBarrier2KHR"); + table->vkCmdResetEvent2KHR = (PFN_vkCmdResetEvent2KHR)load(context, "vkCmdResetEvent2KHR"); + table->vkCmdSetEvent2KHR = (PFN_vkCmdSetEvent2KHR)load(context, "vkCmdSetEvent2KHR"); + table->vkCmdWaitEvents2KHR = (PFN_vkCmdWaitEvents2KHR)load(context, "vkCmdWaitEvents2KHR"); + table->vkCmdWriteTimestamp2KHR = (PFN_vkCmdWriteTimestamp2KHR)load(context, "vkCmdWriteTimestamp2KHR"); + table->vkQueueSubmit2KHR = (PFN_vkQueueSubmit2KHR)load(context, "vkQueueSubmit2KHR"); +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) + table->vkCmdWriteBufferMarker2AMD = (PFN_vkCmdWriteBufferMarker2AMD)load(context, "vkCmdWriteBufferMarker2AMD"); +#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) + table->vkGetQueueCheckpointData2NV = (PFN_vkGetQueueCheckpointData2NV)load(context, "vkGetQueueCheckpointData2NV"); +#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_KHR_timeline_semaphore) + table->vkGetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)load(context, "vkGetSemaphoreCounterValueKHR"); + table->vkSignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)load(context, "vkSignalSemaphoreKHR"); + table->vkWaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)load(context, "vkWaitSemaphoresKHR"); +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) + table->vkCmdDecodeVideoKHR = (PFN_vkCmdDecodeVideoKHR)load(context, "vkCmdDecodeVideoKHR"); +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) + table->vkCmdEncodeVideoKHR = (PFN_vkCmdEncodeVideoKHR)load(context, "vkCmdEncodeVideoKHR"); +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) + table->vkBindVideoSessionMemoryKHR = (PFN_vkBindVideoSessionMemoryKHR)load(context, "vkBindVideoSessionMemoryKHR"); + table->vkCmdBeginVideoCodingKHR = (PFN_vkCmdBeginVideoCodingKHR)load(context, "vkCmdBeginVideoCodingKHR"); + table->vkCmdControlVideoCodingKHR = (PFN_vkCmdControlVideoCodingKHR)load(context, "vkCmdControlVideoCodingKHR"); + table->vkCmdEndVideoCodingKHR = (PFN_vkCmdEndVideoCodingKHR)load(context, "vkCmdEndVideoCodingKHR"); + table->vkCreateVideoSessionKHR = (PFN_vkCreateVideoSessionKHR)load(context, "vkCreateVideoSessionKHR"); + table->vkCreateVideoSessionParametersKHR = (PFN_vkCreateVideoSessionParametersKHR)load(context, "vkCreateVideoSessionParametersKHR"); + table->vkDestroyVideoSessionKHR = (PFN_vkDestroyVideoSessionKHR)load(context, "vkDestroyVideoSessionKHR"); + table->vkDestroyVideoSessionParametersKHR = (PFN_vkDestroyVideoSessionParametersKHR)load(context, "vkDestroyVideoSessionParametersKHR"); + table->vkGetVideoSessionMemoryRequirementsKHR = (PFN_vkGetVideoSessionMemoryRequirementsKHR)load(context, "vkGetVideoSessionMemoryRequirementsKHR"); + table->vkUpdateVideoSessionParametersKHR = (PFN_vkUpdateVideoSessionParametersKHR)load(context, "vkUpdateVideoSessionParametersKHR"); +#endif /* defined(VK_KHR_video_queue) */ +#if defined(VK_NVX_binary_import) + table->vkCmdCuLaunchKernelNVX = (PFN_vkCmdCuLaunchKernelNVX)load(context, "vkCmdCuLaunchKernelNVX"); + table->vkCreateCuFunctionNVX = (PFN_vkCreateCuFunctionNVX)load(context, "vkCreateCuFunctionNVX"); + table->vkCreateCuModuleNVX = (PFN_vkCreateCuModuleNVX)load(context, "vkCreateCuModuleNVX"); + table->vkDestroyCuFunctionNVX = (PFN_vkDestroyCuFunctionNVX)load(context, "vkDestroyCuFunctionNVX"); + table->vkDestroyCuModuleNVX = (PFN_vkDestroyCuModuleNVX)load(context, "vkDestroyCuModuleNVX"); +#endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) + table->vkGetImageViewAddressNVX = (PFN_vkGetImageViewAddressNVX)load(context, "vkGetImageViewAddressNVX"); table->vkGetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)load(context, "vkGetImageViewHandleNVX"); #endif /* defined(VK_NVX_image_view_handle) */ #if defined(VK_NV_clip_space_w_scaling) @@ -960,9 +1415,23 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, table->vkCmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)load(context, "vkCmdSetCheckpointNV"); table->vkGetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)load(context, "vkGetQueueCheckpointDataNV"); #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_generated_commands) + table->vkCmdBindPipelineShaderGroupNV = (PFN_vkCmdBindPipelineShaderGroupNV)load(context, "vkCmdBindPipelineShaderGroupNV"); + table->vkCmdExecuteGeneratedCommandsNV = (PFN_vkCmdExecuteGeneratedCommandsNV)load(context, "vkCmdExecuteGeneratedCommandsNV"); + table->vkCmdPreprocessGeneratedCommandsNV = (PFN_vkCmdPreprocessGeneratedCommandsNV)load(context, "vkCmdPreprocessGeneratedCommandsNV"); + table->vkCreateIndirectCommandsLayoutNV = (PFN_vkCreateIndirectCommandsLayoutNV)load(context, "vkCreateIndirectCommandsLayoutNV"); + 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_external_memory_rdma) + table->vkGetMemoryRemoteAddressNV = (PFN_vkGetMemoryRemoteAddressNV)load(context, "vkGetMemoryRemoteAddressNV"); +#endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) table->vkGetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)load(context, "vkGetMemoryWin32HandleNV"); #endif /* defined(VK_NV_external_memory_win32) */ +#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_mesh_shader) table->vkCmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)load(context, "vkCmdDrawMeshTasksIndirectCountNV"); table->vkCmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)load(context, "vkCmdDrawMeshTasksIndirectNV"); @@ -990,9 +1459,12 @@ 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_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) +#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_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)) */ +#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)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) table->vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)load(context, "vkGetDeviceGroupPresentCapabilitiesKHR"); table->vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)load(context, "vkGetDeviceGroupSurfacePresentModesKHR"); @@ -1004,8 +1476,12 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context, } #ifdef __GNUC__ +#ifdef VOLK_DEFAULT_VISIBILITY +# pragma GCC visibility push(default) +#else # pragma GCC visibility push(hidden) #endif +#endif /* VOLK_GENERATE_PROTOTYPES_C */ #if defined(VK_VERSION_1_0) @@ -1177,9 +1653,27 @@ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseIma PFN_vkTrimCommandPool vkTrimCommandPool; PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate; #endif /* defined(VK_VERSION_1_1) */ +#if defined(VK_VERSION_1_2) +PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2; +PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount; +PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount; +PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2; +PFN_vkCmdNextSubpass2 vkCmdNextSubpass2; +PFN_vkCreateRenderPass2 vkCreateRenderPass2; +PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress; +PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress; +PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress; +PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue; +PFN_vkResetQueryPool vkResetQueryPool; +PFN_vkSignalSemaphore vkSignalSemaphore; +PFN_vkWaitSemaphores vkWaitSemaphores; +#endif /* defined(VK_VERSION_1_2) */ #if defined(VK_AMD_buffer_marker) PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD; #endif /* defined(VK_AMD_buffer_marker) */ +#if defined(VK_AMD_display_native_hdr) +PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD; +#endif /* defined(VK_AMD_display_native_hdr) */ #if defined(VK_AMD_draw_indirect_count) PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD; PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD; @@ -1191,6 +1685,10 @@ PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD; PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; #endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */ +#if defined(VK_EXT_acquire_drm_display) +PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT; +PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT; +#endif /* defined(VK_EXT_acquire_drm_display) */ #if defined(VK_EXT_acquire_xlib_display) PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT; PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT; @@ -1202,6 +1700,9 @@ PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT; PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT; PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT; #endif /* defined(VK_EXT_calibrated_timestamps) */ +#if defined(VK_EXT_color_write_enable) +PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT; +#endif /* defined(VK_EXT_color_write_enable) */ #if defined(VK_EXT_conditional_rendering) PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT; PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT; @@ -1234,6 +1735,10 @@ PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT; #if defined(VK_EXT_direct_mode_display) PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT; #endif /* defined(VK_EXT_direct_mode_display) */ +#if defined(VK_EXT_directfb_surface) +PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT; +PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT; +#endif /* defined(VK_EXT_directfb_surface) */ #if defined(VK_EXT_discard_rectangles) PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT; #endif /* defined(VK_EXT_discard_rectangles) */ @@ -1246,22 +1751,70 @@ 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) */ +#if defined(VK_EXT_full_screen_exclusive) +PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT; +PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT; +PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT; +#endif /* defined(VK_EXT_full_screen_exclusive) */ #if defined(VK_EXT_hdr_metadata) PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT; #endif /* defined(VK_EXT_hdr_metadata) */ +#if defined(VK_EXT_headless_surface) +PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT; +#endif /* defined(VK_EXT_headless_surface) */ +#if defined(VK_EXT_host_query_reset) +PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT; +#endif /* defined(VK_EXT_host_query_reset) */ #if defined(VK_EXT_image_drm_format_modifier) PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT; #endif /* defined(VK_EXT_image_drm_format_modifier) */ +#if defined(VK_EXT_line_rasterization) +PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT; +#endif /* defined(VK_EXT_line_rasterization) */ #if defined(VK_EXT_metal_surface) PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; #endif /* defined(VK_EXT_metal_surface) */ +#if defined(VK_EXT_multi_draw) +PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT; +PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT; +#endif /* defined(VK_EXT_multi_draw) */ +#if defined(VK_EXT_private_data) +PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT; +PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT; +PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT; +PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT; +#endif /* defined(VK_EXT_private_data) */ #if defined(VK_EXT_sample_locations) PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT; PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT; #endif /* defined(VK_EXT_sample_locations) */ +#if defined(VK_EXT_tooling_info) +PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT; +#endif /* defined(VK_EXT_tooling_info) */ #if defined(VK_EXT_transform_feedback) PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT; PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT; @@ -1276,13 +1829,63 @@ 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_external_memory) +PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA; +PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_memory) */ +#if defined(VK_FUCHSIA_external_semaphore) +PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA; +PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA; +#endif /* defined(VK_FUCHSIA_external_semaphore) */ #if defined(VK_FUCHSIA_imagepipe_surface) PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; #endif /* defined(VK_FUCHSIA_imagepipe_surface) */ +#if defined(VK_GGP_stream_descriptor_surface) +PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP; +#endif /* defined(VK_GGP_stream_descriptor_surface) */ #if defined(VK_GOOGLE_display_timing) PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; #endif /* defined(VK_GOOGLE_display_timing) */ +#if defined(VK_HUAWEI_invocation_mask) +PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI; +#endif /* defined(VK_HUAWEI_invocation_mask) */ +#if defined(VK_HUAWEI_subpass_shading) +PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI; +PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI; +#endif /* defined(VK_HUAWEI_subpass_shading) */ +#if defined(VK_INTEL_performance_query) +PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL; +PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL; +PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL; +PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL; +PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL; +PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL; +PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL; +PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL; +PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL; +#endif /* defined(VK_INTEL_performance_query) */ +#if defined(VK_KHR_acceleration_structure) +PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR; +PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR; +PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR; +PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR; +PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR; +PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR; +PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR; +PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR; +PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR; +PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR; +PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR; +PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR; +PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR; +PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR; +PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR; +PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR; +#endif /* defined(VK_KHR_acceleration_structure) */ #if defined(VK_KHR_android_surface) PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; #endif /* defined(VK_KHR_android_surface) */ @@ -1290,12 +1893,32 @@ PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; #endif /* defined(VK_KHR_bind_memory2) */ +#if defined(VK_KHR_buffer_device_address) +PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR; +PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR; +PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR; +#endif /* defined(VK_KHR_buffer_device_address) */ +#if defined(VK_KHR_copy_commands2) +PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR; +PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR; +PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR; +PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR; +PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR; +PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR; +#endif /* defined(VK_KHR_copy_commands2) */ #if defined(VK_KHR_create_renderpass2) PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR; PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR; PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR; PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR; #endif /* defined(VK_KHR_create_renderpass2) */ +#if defined(VK_KHR_deferred_host_operations) +PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR; +PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR; +PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR; +PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR; +PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR; +#endif /* defined(VK_KHR_deferred_host_operations) */ #if defined(VK_KHR_descriptor_update_template) PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; @@ -1358,6 +1981,10 @@ PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; #endif /* defined(VK_KHR_external_semaphore_win32) */ +#if defined(VK_KHR_fragment_shading_rate) +PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR; +PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR; +#endif /* defined(VK_KHR_fragment_shading_rate) */ #if defined(VK_KHR_get_display_properties2) PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR; PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR; @@ -1388,9 +2015,32 @@ PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; #if defined(VK_KHR_maintenance3) PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR; #endif /* defined(VK_KHR_maintenance3) */ +#if defined(VK_KHR_performance_query) +PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR; +PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR; +PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR; +PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR; +#endif /* defined(VK_KHR_performance_query) */ +#if defined(VK_KHR_pipeline_executable_properties) +PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR; +PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR; +PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR; +#endif /* defined(VK_KHR_pipeline_executable_properties) */ +#if defined(VK_KHR_present_wait) +PFN_vkWaitForPresentKHR vkWaitForPresentKHR; +#endif /* defined(VK_KHR_present_wait) */ #if defined(VK_KHR_push_descriptor) PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; #endif /* defined(VK_KHR_push_descriptor) */ +#if defined(VK_KHR_ray_tracing_pipeline) +PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR; +PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR; +PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR; +PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR; +PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR; +PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR; +PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR; +#endif /* defined(VK_KHR_ray_tracing_pipeline) */ #if defined(VK_KHR_sampler_ycbcr_conversion) PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; @@ -1412,6 +2062,45 @@ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; PFN_vkQueuePresentKHR vkQueuePresentKHR; #endif /* defined(VK_KHR_swapchain) */ +#if defined(VK_KHR_synchronization2) +PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR; +PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR; +PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR; +PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR; +PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR; +PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; +#endif /* defined(VK_KHR_synchronization2) */ +#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) +PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */ +#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) +PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV; +#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_KHR_timeline_semaphore) +PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR; +PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR; +PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR; +#endif /* defined(VK_KHR_timeline_semaphore) */ +#if defined(VK_KHR_video_decode_queue) +PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR; +#endif /* defined(VK_KHR_video_decode_queue) */ +#if defined(VK_KHR_video_encode_queue) +PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR; +#endif /* defined(VK_KHR_video_encode_queue) */ +#if defined(VK_KHR_video_queue) +PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR; +PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR; +PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR; +PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR; +PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR; +PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR; +PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR; +PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR; +PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR; +PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR; +PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR; +PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR; +#endif /* defined(VK_KHR_video_queue) */ #if defined(VK_KHR_wayland_surface) PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; @@ -1437,36 +2126,54 @@ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; #if defined(VK_NN_vi_surface) PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN; #endif /* defined(VK_NN_vi_surface) */ -#if defined(VK_NVX_device_generated_commands) -PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX; -PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX; -PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX; -PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX; -PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX; -PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX; -PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX; -PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX; -PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX; -#endif /* defined(VK_NVX_device_generated_commands) */ +#if defined(VK_NVX_binary_import) +PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX; +PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX; +PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX; +PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX; +PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX; +#endif /* defined(VK_NVX_binary_import) */ #if defined(VK_NVX_image_view_handle) +PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX; PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX; #endif /* defined(VK_NVX_image_view_handle) */ +#if defined(VK_NV_acquire_winrt_display) +PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV; +PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV; +#endif /* defined(VK_NV_acquire_winrt_display) */ #if defined(VK_NV_clip_space_w_scaling) PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV; #endif /* defined(VK_NV_clip_space_w_scaling) */ #if defined(VK_NV_cooperative_matrix) PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV; #endif /* defined(VK_NV_cooperative_matrix) */ +#if defined(VK_NV_coverage_reduction_mode) +PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV; +#endif /* defined(VK_NV_coverage_reduction_mode) */ #if defined(VK_NV_device_diagnostic_checkpoints) PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV; PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV; #endif /* defined(VK_NV_device_diagnostic_checkpoints) */ +#if defined(VK_NV_device_generated_commands) +PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV; +PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV; +PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV; +PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV; +PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV; +PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV; +#endif /* defined(VK_NV_device_generated_commands) */ #if defined(VK_NV_external_memory_capabilities) PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV; #endif /* defined(VK_NV_external_memory_capabilities) */ +#if defined(VK_NV_external_memory_rdma) +PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV; +#endif /* defined(VK_NV_external_memory_rdma) */ #if defined(VK_NV_external_memory_win32) PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV; #endif /* defined(VK_NV_external_memory_win32) */ +#if defined(VK_NV_fragment_shading_rate_enums) +PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV; +#endif /* defined(VK_NV_fragment_shading_rate_enums) */ #if defined(VK_NV_mesh_shader) PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV; PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV; @@ -1494,9 +2201,16 @@ PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV; PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV; PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV; #endif /* defined(VK_NV_shading_rate_image) */ -#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) +#if defined(VK_QNX_screen_surface) +PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX; +PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX; +#endif /* defined(VK_QNX_screen_surface) */ +#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_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)) */ +#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)) */ #if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1)) PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR; PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR; @@ -1514,3 +2228,4 @@ PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR; #ifdef __cplusplus } #endif +/* clang-format on */ diff --git a/libraries/ZVulkan/src/vulkanbuilders.cpp b/libraries/ZVulkan/src/vulkanbuilders.cpp new file mode 100644 index 000000000..bfa138080 --- /dev/null +++ b/libraries/ZVulkan/src/vulkanbuilders.cpp @@ -0,0 +1,1808 @@ + +#include "vulkanbuilders.h" +#include "vulkansurface.h" +#include "vulkancompatibledevice.h" +#include "vulkanswapchain.h" +#include "glslang/glslang/Public/ShaderLang.h" +#include "glslang/spirv/GlslangToSpv.h" + +static const TBuiltInResource DefaultTBuiltInResource = { + /* .MaxLights = */ 32, + /* .MaxClipPlanes = */ 6, + /* .MaxTextureUnits = */ 32, + /* .MaxTextureCoords = */ 32, + /* .MaxVertexAttribs = */ 64, + /* .MaxVertexUniformComponents = */ 4096, + /* .MaxVaryingFloats = */ 64, + /* .MaxVertexTextureImageUnits = */ 32, + /* .MaxCombinedTextureImageUnits = */ 80, + /* .MaxTextureImageUnits = */ 32, + /* .MaxFragmentUniformComponents = */ 4096, + /* .MaxDrawBuffers = */ 32, + /* .MaxVertexUniformVectors = */ 128, + /* .MaxVaryingVectors = */ 8, + /* .MaxFragmentUniformVectors = */ 16, + /* .MaxVertexOutputVectors = */ 16, + /* .MaxFragmentInputVectors = */ 15, + /* .MinProgramTexelOffset = */ -8, + /* .MaxProgramTexelOffset = */ 7, + /* .MaxClipDistances = */ 8, + /* .MaxComputeWorkGroupCountX = */ 65535, + /* .MaxComputeWorkGroupCountY = */ 65535, + /* .MaxComputeWorkGroupCountZ = */ 65535, + /* .MaxComputeWorkGroupSizeX = */ 1024, + /* .MaxComputeWorkGroupSizeY = */ 1024, + /* .MaxComputeWorkGroupSizeZ = */ 64, + /* .MaxComputeUniformComponents = */ 1024, + /* .MaxComputeTextureImageUnits = */ 16, + /* .MaxComputeImageUniforms = */ 8, + /* .MaxComputeAtomicCounters = */ 8, + /* .MaxComputeAtomicCounterBuffers = */ 1, + /* .MaxVaryingComponents = */ 60, + /* .MaxVertexOutputComponents = */ 64, + /* .MaxGeometryInputComponents = */ 64, + /* .MaxGeometryOutputComponents = */ 128, + /* .MaxFragmentInputComponents = */ 128, + /* .MaxImageUnits = */ 8, + /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, + /* .MaxCombinedShaderOutputResources = */ 8, + /* .MaxImageSamples = */ 0, + /* .MaxVertexImageUniforms = */ 0, + /* .MaxTessControlImageUniforms = */ 0, + /* .MaxTessEvaluationImageUniforms = */ 0, + /* .MaxGeometryImageUniforms = */ 0, + /* .MaxFragmentImageUniforms = */ 8, + /* .MaxCombinedImageUniforms = */ 8, + /* .MaxGeometryTextureImageUnits = */ 16, + /* .MaxGeometryOutputVertices = */ 256, + /* .MaxGeometryTotalOutputComponents = */ 1024, + /* .MaxGeometryUniformComponents = */ 1024, + /* .MaxGeometryVaryingComponents = */ 64, + /* .MaxTessControlInputComponents = */ 128, + /* .MaxTessControlOutputComponents = */ 128, + /* .MaxTessControlTextureImageUnits = */ 16, + /* .MaxTessControlUniformComponents = */ 1024, + /* .MaxTessControlTotalOutputComponents = */ 4096, + /* .MaxTessEvaluationInputComponents = */ 128, + /* .MaxTessEvaluationOutputComponents = */ 128, + /* .MaxTessEvaluationTextureImageUnits = */ 16, + /* .MaxTessEvaluationUniformComponents = */ 1024, + /* .MaxTessPatchComponents = */ 120, + /* .MaxPatchVertices = */ 32, + /* .MaxTessGenLevel = */ 64, + /* .MaxViewports = */ 16, + /* .MaxVertexAtomicCounters = */ 0, + /* .MaxTessControlAtomicCounters = */ 0, + /* .MaxTessEvaluationAtomicCounters = */ 0, + /* .MaxGeometryAtomicCounters = */ 0, + /* .MaxFragmentAtomicCounters = */ 8, + /* .MaxCombinedAtomicCounters = */ 8, + /* .MaxAtomicCounterBindings = */ 1, + /* .MaxVertexAtomicCounterBuffers = */ 0, + /* .MaxTessControlAtomicCounterBuffers = */ 0, + /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, + /* .MaxGeometryAtomicCounterBuffers = */ 0, + /* .MaxFragmentAtomicCounterBuffers = */ 1, + /* .MaxCombinedAtomicCounterBuffers = */ 1, + /* .MaxAtomicCounterBufferSize = */ 16384, + /* .MaxTransformFeedbackBuffers = */ 4, + /* .MaxTransformFeedbackInterleavedComponents = */ 64, + /* .MaxCullDistances = */ 8, + /* .MaxCombinedClipAndCullDistances = */ 8, + /* .MaxSamples = */ 4, + /* .maxMeshOutputVerticesNV = */ 256, + /* .maxMeshOutputPrimitivesNV = */ 512, + /* .maxMeshWorkGroupSizeX_NV = */ 32, + /* .maxMeshWorkGroupSizeY_NV = */ 1, + /* .maxMeshWorkGroupSizeZ_NV = */ 1, + /* .maxTaskWorkGroupSizeX_NV = */ 32, + /* .maxTaskWorkGroupSizeY_NV = */ 1, + /* .maxTaskWorkGroupSizeZ_NV = */ 1, + /* .maxMeshViewCountNV = */ 4, + /* .maxDualSourceDrawBuffersEXT = */ 1, + + /* .limits = */ { + /* .nonInductiveForLoops = */ 1, + /* .whileLoops = */ 1, + /* .doWhileLoops = */ 1, + /* .generalUniformIndexing = */ 1, + /* .generalAttributeMatrixVectorIndexing = */ 1, + /* .generalVaryingIndexing = */ 1, + /* .generalSamplerIndexing = */ 1, + /* .generalVariableIndexing = */ 1, + /* .generalConstantMatrixVectorIndexing = */ 1, + } +}; + +void ShaderBuilder::Init() +{ + ShInitialize(); +} + +void ShaderBuilder::Deinit() +{ + ShFinalize(); +} + +ShaderBuilder::ShaderBuilder() +{ +} + +ShaderBuilder& ShaderBuilder::VertexShader(const std::string& c) +{ + code = c; + stage = EShLanguage::EShLangVertex; + return *this; +} + +ShaderBuilder& ShaderBuilder::FragmentShader(const std::string& c) +{ + code = c; + stage = EShLanguage::EShLangFragment; + return *this; +} + +std::unique_ptr ShaderBuilder::Create(const char *shadername, VulkanDevice *device) +{ + EShLanguage stage = (EShLanguage)this->stage; + const char *sources[] = { code.c_str() }; + + TBuiltInResource resources = DefaultTBuiltInResource; + + glslang::TShader shader(stage); + shader.setStrings(sources, 1); + shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); + if (device->Instance->ApiVersion >= VK_API_VERSION_1_2) + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); + } + else + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); + } + bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules); + if (!compileSuccess) + { + throw std::runtime_error(std::string("Shader compile failed: ") + shader.getInfoLog()); + } + + glslang::TProgram program; + program.addShader(&shader); + bool linkSuccess = program.link(EShMsgDefault); + if (!linkSuccess) + { + throw std::runtime_error(std::string("Shader link failed: ") + program.getInfoLog()); + } + + glslang::TIntermediate *intermediate = program.getIntermediate(stage); + if (!intermediate) + { + throw std::runtime_error("Internal shader compiler error"); + } + + glslang::SpvOptions spvOptions; + spvOptions.generateDebugInfo = false; + spvOptions.disableOptimizer = false; + spvOptions.optimizeSize = true; + + std::vector spirv; + spv::SpvBuildLogger logger; + glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions); + + VkShaderModuleCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = spirv.size() * sizeof(unsigned int); + createInfo.pCode = spirv.data(); + + VkShaderModule shaderModule; + VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create vulkan shader module"); + + auto obj = std::make_unique(device, shaderModule); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +CommandPoolBuilder::CommandPoolBuilder() +{ +} + +CommandPoolBuilder& CommandPoolBuilder::QueueFamily(int index) +{ + queueFamilyIndex = index; + return *this; +} + +std::unique_ptr CommandPoolBuilder::Create(VulkanDevice* device) +{ + auto obj = std::make_unique(device, queueFamilyIndex != -1 ? queueFamilyIndex : device->GraphicsFamily); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +SemaphoreBuilder::SemaphoreBuilder() +{ +} + +std::unique_ptr SemaphoreBuilder::Create(VulkanDevice* device) +{ + auto obj = std::make_unique(device); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +FenceBuilder::FenceBuilder() +{ +} + +std::unique_ptr FenceBuilder::Create(VulkanDevice* device) +{ + auto obj = std::make_unique(device); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ImageBuilder::ImageBuilder() +{ + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent.depth = 1; + imageInfo.arrayLayers = 1; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Note: must either be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.flags = 0; +} + +ImageBuilder& ImageBuilder::Size(int width, int height, int mipLevels, int arrayLayers) +{ + imageInfo.extent.width = width; + imageInfo.extent.height = height; + imageInfo.mipLevels = mipLevels; + imageInfo.arrayLayers = arrayLayers; + return *this; +} + +ImageBuilder& ImageBuilder::Samples(VkSampleCountFlagBits samples) +{ + imageInfo.samples = samples; + return *this; +} + +ImageBuilder& ImageBuilder::Format(VkFormat format) +{ + imageInfo.format = format; + return *this; +} + +ImageBuilder& ImageBuilder::LinearTiling() +{ + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + return *this; +} + +ImageBuilder& ImageBuilder::Usage(VkImageUsageFlags usage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) +{ + imageInfo.usage = usage; + allocInfo.usage = memoryUsage; + allocInfo.flags = allocFlags; + return *this; +} + +ImageBuilder& ImageBuilder::MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) +{ + allocInfo.requiredFlags = requiredFlags; + allocInfo.preferredFlags = preferredFlags; + allocInfo.memoryTypeBits = memoryTypeBits; + return *this; +} + +bool ImageBuilder::IsFormatSupported(VulkanDevice* device, VkFormatFeatureFlags bufferFeatures) +{ + VkImageFormatProperties properties = { }; + VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); + if (result != VK_SUCCESS) return false; + if (imageInfo.extent.width > properties.maxExtent.width) return false; + if (imageInfo.extent.height > properties.maxExtent.height) return false; + if (imageInfo.extent.depth > properties.maxExtent.depth) return false; + if (imageInfo.mipLevels > properties.maxMipLevels) return false; + if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; + if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; + if (bufferFeatures != 0) + { + VkFormatProperties formatProperties = { }; + vkGetPhysicalDeviceFormatProperties(device->PhysicalDevice.Device, imageInfo.format, &formatProperties); + if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures) + return false; + } + return true; +} + +std::unique_ptr ImageBuilder::Create(VulkanDevice* device, VkDeviceSize* allocatedBytes) +{ + VkImage image; + VmaAllocation allocation; + + VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); + CheckVulkanError(result, "Could not create vulkan image"); + + if (allocatedBytes != nullptr) + { + VmaAllocationInfo allocatedInfo; + vmaGetAllocationInfo(device->allocator, allocation, &allocatedInfo); + + *allocatedBytes = allocatedInfo.size; + } + + auto obj = std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +std::unique_ptr ImageBuilder::TryCreate(VulkanDevice* device) +{ + VkImage image; + VmaAllocation allocation; + + VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); + if (result != VK_SUCCESS) + return nullptr; + + auto obj = std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ImageViewBuilder::ImageViewBuilder() +{ + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.subresourceRange.baseMipLevel = 0; + viewInfo.subresourceRange.baseArrayLayer = 0; + viewInfo.subresourceRange.layerCount = 1; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +} + +ImageViewBuilder& ImageViewBuilder::Type(VkImageViewType type) +{ + viewInfo.viewType = type; + return *this; +} + +ImageViewBuilder& ImageViewBuilder::Image(VulkanImage* image, VkFormat format, VkImageAspectFlags aspectMask) +{ + viewInfo.image = image->image; + viewInfo.format = format; + viewInfo.subresourceRange.levelCount = image->mipLevels; + viewInfo.subresourceRange.aspectMask = aspectMask; + viewInfo.subresourceRange.layerCount = image->layerCount; + return *this; +} + +std::unique_ptr ImageViewBuilder::Create(VulkanDevice* device) +{ + VkImageView view; + VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view); + CheckVulkanError(result, "Could not create texture image view"); + + auto obj = std::make_unique(device, view); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +SamplerBuilder::SamplerBuilder() +{ + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 100.0f; +} + +SamplerBuilder& SamplerBuilder::AddressMode(VkSamplerAddressMode addressMode) +{ + samplerInfo.addressModeU = addressMode; + samplerInfo.addressModeV = addressMode; + samplerInfo.addressModeW = addressMode; + return *this; +} + +SamplerBuilder& SamplerBuilder::AddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w) +{ + samplerInfo.addressModeU = u; + samplerInfo.addressModeV = v; + samplerInfo.addressModeW = w; + return *this; +} + +SamplerBuilder& SamplerBuilder::MinFilter(VkFilter minFilter) +{ + samplerInfo.minFilter = minFilter; + return *this; +} + +SamplerBuilder& SamplerBuilder::MagFilter(VkFilter magFilter) +{ + samplerInfo.magFilter = magFilter; + return *this; +} + +SamplerBuilder& SamplerBuilder::MipmapMode(VkSamplerMipmapMode mode) +{ + samplerInfo.mipmapMode = mode; + return *this; +} + +SamplerBuilder& SamplerBuilder::Anisotropy(float maxAnisotropy) +{ + samplerInfo.anisotropyEnable = VK_TRUE; + samplerInfo.maxAnisotropy = maxAnisotropy; + return *this; +} + +SamplerBuilder& SamplerBuilder::MipLodBias(float bias) +{ + samplerInfo.mipLodBias = bias; + return *this; +} + +SamplerBuilder& SamplerBuilder::MaxLod(float value) +{ + samplerInfo.maxLod = value; + return *this; +} + +std::unique_ptr SamplerBuilder::Create(VulkanDevice* device) +{ + VkSampler sampler; + VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler); + CheckVulkanError(result, "Could not create texture sampler"); + auto obj = std::make_unique(device, sampler); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +BufferBuilder::BufferBuilder() +{ + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; +} + +BufferBuilder& BufferBuilder::Size(size_t size) +{ + bufferInfo.size = std::max(size, (size_t)16); + return *this; +} + +BufferBuilder& BufferBuilder::Usage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) +{ + bufferInfo.usage = bufferUsage; + allocInfo.usage = memoryUsage; + allocInfo.flags = allocFlags; + return *this; +} + +BufferBuilder& BufferBuilder::MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) +{ + allocInfo.requiredFlags = requiredFlags; + allocInfo.preferredFlags = preferredFlags; + allocInfo.memoryTypeBits = memoryTypeBits; + return *this; +} + +std::unique_ptr BufferBuilder::Create(VulkanDevice* device) +{ + VkBuffer buffer; + VmaAllocation allocation; + + VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); + CheckVulkanError(result, "Could not allocate memory for vulkan buffer"); + + auto obj = std::make_unique(device, buffer, allocation, bufferInfo.size); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +AccelerationStructureBuilder::AccelerationStructureBuilder() +{ +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Type(VkAccelerationStructureTypeKHR type) +{ + createInfo.type = type; + return *this; +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Buffer(VulkanBuffer* buffer, VkDeviceSize size) +{ + createInfo.buffer = buffer->buffer; + createInfo.offset = 0; + createInfo.size = size; + return *this; +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Buffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size) +{ + createInfo.buffer = buffer->buffer; + createInfo.offset = offset; + createInfo.size = size; + return *this; +} + +std::unique_ptr AccelerationStructureBuilder::Create(VulkanDevice* device) +{ + VkAccelerationStructureKHR hande = {}; + VkResult result = vkCreateAccelerationStructureKHR(device->device, &createInfo, nullptr, &hande); + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); + auto obj = std::make_unique(device, hande); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ComputePipelineBuilder::ComputePipelineBuilder() +{ + pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; +} + +ComputePipelineBuilder& ComputePipelineBuilder::Cache(VulkanPipelineCache* cache) +{ + this->cache = cache; + return *this; +} + +ComputePipelineBuilder& ComputePipelineBuilder::Layout(VulkanPipelineLayout* layout) +{ + pipelineInfo.layout = layout->layout; + return *this; +} + +ComputePipelineBuilder& ComputePipelineBuilder::ComputeShader(VulkanShader* shader) +{ + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = shader->module; + stageInfo.pName = "main"; + + pipelineInfo.stage = stageInfo; + return *this; +} + +std::unique_ptr ComputePipelineBuilder::Create(VulkanDevice* device) +{ + VkPipeline pipeline; + vkCreateComputePipelines(device->device, cache ? cache->cache : VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); + auto obj = std::make_unique(device, pipeline); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder() +{ +} + +DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::Flags(VkDescriptorSetLayoutCreateFlags flags) +{ + layoutInfo.flags = flags; + return *this; +} + +DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::AddBinding(int index, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags, VkDescriptorBindingFlags flags) +{ + VkDescriptorSetLayoutBinding binding = { }; + binding.binding = index; + binding.descriptorType = type; + binding.descriptorCount = arrayCount; + binding.stageFlags = stageFlags; + binding.pImmutableSamplers = nullptr; + bindings.push_back(binding); + bindingFlags.push_back(flags); + + layoutInfo.bindingCount = (uint32_t)bindings.size(); + layoutInfo.pBindings = bindings.data(); + + bindingFlagsInfo.bindingCount = (uint32_t)bindings.size(); + bindingFlagsInfo.pBindingFlags = bindingFlags.data(); + + if (flags != 0) + layoutInfo.pNext = &bindingFlagsInfo; + + return *this; +} + +std::unique_ptr DescriptorSetLayoutBuilder::Create(VulkanDevice* device) +{ + VkDescriptorSetLayout layout; + VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout); + CheckVulkanError(result, "Could not create descriptor set layout"); + auto obj = std::make_unique(device, layout); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +DescriptorPoolBuilder::DescriptorPoolBuilder() +{ + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.maxSets = 1; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; +} + +DescriptorPoolBuilder& DescriptorPoolBuilder::Flags(VkDescriptorPoolCreateFlags flags) +{ + poolInfo.flags = flags | VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + return *this; +} + +DescriptorPoolBuilder& DescriptorPoolBuilder::MaxSets(int value) +{ + poolInfo.maxSets = value; + return *this; +} + +DescriptorPoolBuilder& DescriptorPoolBuilder::AddPoolSize(VkDescriptorType type, int count) +{ + VkDescriptorPoolSize size; + size.type = type; + size.descriptorCount = count; + poolSizes.push_back(size); + + poolInfo.poolSizeCount = (uint32_t)poolSizes.size(); + poolInfo.pPoolSizes = poolSizes.data(); + return *this; +} + +std::unique_ptr DescriptorPoolBuilder::Create(VulkanDevice* device) +{ + VkDescriptorPool descriptorPool; + VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool); + CheckVulkanError(result, "Could not create descriptor pool"); + auto obj = std::make_unique(device, descriptorPool); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +QueryPoolBuilder::QueryPoolBuilder() +{ + poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; +} + +QueryPoolBuilder& QueryPoolBuilder::QueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics) +{ + poolInfo.queryType = type; + poolInfo.queryCount = count; + poolInfo.pipelineStatistics = pipelineStatistics; + return *this; +} + +std::unique_ptr QueryPoolBuilder::Create(VulkanDevice* device) +{ + VkQueryPool queryPool; + VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool); + CheckVulkanError(result, "Could not create query pool"); + auto obj = std::make_unique(device, queryPool); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +FramebufferBuilder::FramebufferBuilder() +{ + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; +} + +FramebufferBuilder& FramebufferBuilder::RenderPass(VulkanRenderPass* renderPass) +{ + framebufferInfo.renderPass = renderPass->renderPass; + return *this; +} + +FramebufferBuilder& FramebufferBuilder::AddAttachment(VulkanImageView* view) +{ + attachments.push_back(view->view); + + framebufferInfo.attachmentCount = (uint32_t)attachments.size(); + framebufferInfo.pAttachments = attachments.data(); + return *this; +} + +FramebufferBuilder& FramebufferBuilder::AddAttachment(VkImageView view) +{ + attachments.push_back(view); + + framebufferInfo.attachmentCount = (uint32_t)attachments.size(); + framebufferInfo.pAttachments = attachments.data(); + return *this; +} + +FramebufferBuilder& FramebufferBuilder::Size(int width, int height, int layers) +{ + framebufferInfo.width = width; + framebufferInfo.height = height; + framebufferInfo.layers = 1; + return *this; +} + +std::unique_ptr FramebufferBuilder::Create(VulkanDevice* device) +{ + VkFramebuffer framebuffer = 0; + VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer); + CheckVulkanError(result, "Could not create framebuffer"); + auto obj = std::make_unique(device, framebuffer); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +GraphicsPipelineBuilder::GraphicsPipelineBuilder() +{ + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pDepthStencilState = &depthStencil; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.pDynamicState = &dynamicState; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.basePipelineIndex = -1; + + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexBindingDescriptionCount = 0; + vertexInputInfo.pVertexBindingDescriptions = nullptr; + vertexInputInfo.vertexAttributeDescriptionCount = 0; + vertexInputInfo.pVertexAttributeDescriptions = nullptr; + + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + depthStencil.depthBoundsTestEnable = VK_FALSE; + depthStencil.minDepthBounds = 0.0f; + depthStencil.maxDepthBounds = 1.0f; + depthStencil.stencilTestEnable = VK_FALSE; + depthStencil.front = {}; + depthStencil.back = {}; + + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_NONE; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.minSampleShading = 1.0f; + multisampling.pSampleMask = nullptr; + 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; + colorBlending.blendConstants[3] = 0.0f; + + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::RasterizationSamples(VkSampleCountFlagBits samples) +{ + multisampling.rasterizationSamples = samples; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Cache(VulkanPipelineCache* cache) +{ + this->cache = cache; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Subpass(int subpass) +{ + pipelineInfo.subpass = subpass; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Layout(VulkanPipelineLayout* layout) +{ + pipelineInfo.layout = layout->layout; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::RenderPass(VulkanRenderPass* renderPass) +{ + pipelineInfo.renderPass = renderPass->renderPass; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Topology(VkPrimitiveTopology topology) +{ + inputAssembly.topology = topology; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Viewport(float x, float y, float width, float height, float minDepth, float maxDepth) +{ + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = width; + viewport.height = height; + viewport.minDepth = minDepth; + viewport.maxDepth = maxDepth; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Scissor(int x, int y, int width, int height) +{ + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = width; + scissor.extent.height = height; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Cull(VkCullModeFlags cullMode, VkFrontFace frontFace) +{ + rasterizer.cullMode = cullMode; + rasterizer.frontFace = frontFace; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthStencilEnable(bool test, bool write, bool stencil) +{ + depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE; + depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE; + depthStencil.stencilTestEnable = stencil ? VK_TRUE : VK_FALSE; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Stencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference) +{ + depthStencil.front.failOp = failOp; + depthStencil.front.passOp = passOp; + depthStencil.front.depthFailOp = depthFailOp; + depthStencil.front.compareOp = compareOp; + depthStencil.front.compareMask = compareMask; + depthStencil.front.writeMask = writeMask; + depthStencil.front.reference = reference; + + depthStencil.back.failOp = failOp; + depthStencil.back.passOp = passOp; + depthStencil.back.depthFailOp = depthFailOp; + depthStencil.back.compareOp = compareOp; + depthStencil.back.compareMask = compareMask; + depthStencil.back.writeMask = writeMask; + depthStencil.back.reference = reference; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthFunc(VkCompareOp func) +{ + depthStencil.depthCompareOp = func; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthClampEnable(bool value) +{ + rasterizer.depthClampEnable = value ? VK_TRUE : VK_FALSE; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor) +{ + rasterizer.depthBiasEnable = enable ? VK_TRUE : VK_FALSE; + rasterizer.depthBiasConstantFactor = biasConstantFactor; + rasterizer.depthBiasClamp = biasClamp; + rasterizer.depthBiasSlopeFactor = biasSlopeFactor; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::ColorWriteMask(VkColorComponentFlags mask) +{ + 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(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexShader(VulkanShader* shader) +{ + VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = shader->module; + vertShaderStageInfo.pName = "main"; + shaderStages.push_back(vertShaderStageInfo); + + pipelineInfo.stageCount = (uint32_t)shaderStages.size(); + pipelineInfo.pStages = shaderStages.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddFragmentShader(VulkanShader* shader) +{ + VkPipelineShaderStageCreateInfo fragShaderStageInfo = {}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = shader->module; + fragShaderStageInfo.pName = "main"; + shaderStages.push_back(fragShaderStageInfo); + + pipelineInfo.stageCount = (uint32_t)shaderStages.size(); + pipelineInfo.pStages = shaderStages.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexBufferBinding(int index, size_t stride) +{ + VkVertexInputBindingDescription desc = {}; + desc.binding = index; + desc.stride = (uint32_t)stride; + desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + vertexInputBindings.push_back(desc); + + vertexInputInfo.vertexBindingDescriptionCount = (uint32_t)vertexInputBindings.size(); + vertexInputInfo.pVertexBindingDescriptions = vertexInputBindings.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexAttribute(int location, int binding, VkFormat format, size_t offset) +{ + VkVertexInputAttributeDescription desc = { }; + desc.location = location; + desc.binding = binding; + desc.format = format; + desc.offset = (uint32_t)offset; + vertexInputAttributes.push_back(desc); + + vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)vertexInputAttributes.size(); + vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributes.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddDynamicState(VkDynamicState state) +{ + dynamicStates.push_back(state); + dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size(); + dynamicState.pDynamicStates = dynamicStates.data(); + return *this; +} + +std::unique_ptr GraphicsPipelineBuilder::Create(VulkanDevice* device) +{ + 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"); + auto obj = std::make_unique(device, pipeline); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +PipelineLayoutBuilder::PipelineLayoutBuilder() +{ + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; +} + +PipelineLayoutBuilder& PipelineLayoutBuilder::AddSetLayout(VulkanDescriptorSetLayout* setLayout) +{ + setLayouts.push_back(setLayout->layout); + pipelineLayoutInfo.setLayoutCount = (uint32_t)setLayouts.size(); + pipelineLayoutInfo.pSetLayouts = setLayouts.data(); + return *this; +} + +PipelineLayoutBuilder& PipelineLayoutBuilder::AddPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size) +{ + VkPushConstantRange range = { }; + range.stageFlags = stageFlags; + range.offset = (uint32_t)offset; + range.size = (uint32_t)size; + pushConstantRanges.push_back(range); + pipelineLayoutInfo.pushConstantRangeCount = (uint32_t)pushConstantRanges.size(); + pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data(); + return *this; +} + +std::unique_ptr PipelineLayoutBuilder::Create(VulkanDevice* device) +{ + VkPipelineLayout pipelineLayout; + VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout); + CheckVulkanError(result, "Could not create pipeline layout"); + auto obj = std::make_unique(device, pipelineLayout); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +PipelineCacheBuilder::PipelineCacheBuilder() +{ + pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; +} + +PipelineCacheBuilder& PipelineCacheBuilder::InitialData(const void* data, size_t size) +{ + initData.resize(size); + memcpy(initData.data(), data, size); + return *this; +} + +PipelineCacheBuilder& PipelineCacheBuilder::Flags(VkPipelineCacheCreateFlags flags) +{ + pipelineCacheInfo.flags = flags; + return *this; +} + +std::unique_ptr PipelineCacheBuilder::Create(VulkanDevice* device) +{ + pipelineCacheInfo.pInitialData = nullptr; + pipelineCacheInfo.initialDataSize = 0; + + // Check if the saved cache data is compatible with our device: + if (initData.size() >= sizeof(VkPipelineCacheHeaderVersionOne)) + { + VkPipelineCacheHeaderVersionOne* header = (VkPipelineCacheHeaderVersionOne*)initData.data(); + if (header->headerVersion == VK_PIPELINE_CACHE_HEADER_VERSION_ONE && + header->vendorID == device->PhysicalDevice.Properties.vendorID && + header->deviceID == device->PhysicalDevice.Properties.deviceID && + memcmp(header->pipelineCacheUUID, device->PhysicalDevice.Properties.pipelineCacheUUID, VK_UUID_SIZE) == 0) + { + pipelineCacheInfo.pInitialData = initData.data(); + pipelineCacheInfo.initialDataSize = initData.size(); + } + } + + VkPipelineCache pipelineCache; + VkResult result = vkCreatePipelineCache(device->device, &pipelineCacheInfo, nullptr, &pipelineCache); + CheckVulkanError(result, "Could not create pipeline cache"); + auto obj = std::make_unique(device, pipelineCache); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +RenderPassBuilder::RenderPassBuilder() +{ + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; +} + +RenderPassBuilder& RenderPassBuilder::AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout) +{ + VkAttachmentDescription attachment = {}; + attachment.format = format; + attachment.samples = samples; + attachment.loadOp = load; + attachment.storeOp = store; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = initialLayout; + attachment.finalLayout = finalLayout; + attachments.push_back(attachment); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.attachmentCount = (uint32_t)attachments.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout) +{ + VkAttachmentDescription attachment = {}; + attachment.format = format; + attachment.samples = samples; + attachment.loadOp = load; + attachment.storeOp = store; + attachment.stencilLoadOp = stencilLoad; + attachment.stencilStoreOp = stencilStore; + attachment.initialLayout = initialLayout; + attachment.finalLayout = finalLayout; + attachments.push_back(attachment); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.attachmentCount = (uint32_t)attachments.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = srcStageMask; + dependency.srcAccessMask = srcAccessMask; + dependency.dstStageMask = dstStageMask; + dependency.dstAccessMask = dstAccessMask; + + dependencies.push_back(dependency); + renderPassInfo.pDependencies = dependencies.data(); + renderPassInfo.dependencyCount = (uint32_t)dependencies.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpass() +{ + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + + subpasses.push_back(subpass); + renderPassInfo.pSubpasses = subpasses.data(); + renderPassInfo.subpassCount = (uint32_t)subpasses.size(); + + subpassData.push_back(std::make_unique()); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout) +{ + VkAttachmentReference colorAttachmentRef = {}; + colorAttachmentRef.attachment = index; + colorAttachmentRef.layout = layout; + + subpassData.back()->colorRefs.push_back(colorAttachmentRef); + subpasses.back().pColorAttachments = subpassData.back()->colorRefs.data(); + subpasses.back().colorAttachmentCount = (uint32_t)subpassData.back()->colorRefs.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout) +{ + VkAttachmentReference& depthAttachmentRef = subpassData.back()->depthRef; + depthAttachmentRef.attachment = index; + depthAttachmentRef.layout = layout; + + VkSubpassDescription& subpass = subpasses.back(); + subpass.pDepthStencilAttachment = &depthAttachmentRef; + return *this; +} + +std::unique_ptr RenderPassBuilder::Create(VulkanDevice* device) +{ + VkRenderPass renderPass = 0; + VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass); + CheckVulkanError(result, "Could not create render pass"); + auto obj = std::make_unique(device, renderPass); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +PipelineBarrier& PipelineBarrier::AddMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + memoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + return AddBuffer(buffer, 0, buffer->size, srcAccessMask, dstAccessMask); +} + +PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkBufferMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = buffer->buffer; + barrier.offset = offset; + barrier.size = size; + bufferMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount); +} + +PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + VkImageMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = aspectMask; + barrier.subresourceRange.baseMipLevel = baseMipLevel; + barrier.subresourceRange.levelCount = levelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + imageMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer* buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkBufferMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.buffer = buffer->buffer; + barrier.offset = 0; + barrier.size = buffer->size; + bufferMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddQueueTransfer(int srcFamily, int dstFamily, VulkanImage* image, VkImageLayout layout, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + VkImageMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = layout; + barrier.newLayout = layout; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.image = image->image; + barrier.subresourceRange.aspectMask = aspectMask; + barrier.subresourceRange.baseMipLevel = baseMipLevel; + barrier.subresourceRange.levelCount = levelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + imageMemoryBarriers.push_back(barrier); + return *this; +} + +void PipelineBarrier::Execute(VulkanCommandBuffer* commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags) +{ + commandBuffer->pipelineBarrier( + srcStageMask, dstStageMask, dependencyFlags, + (uint32_t)memoryBarriers.size(), memoryBarriers.data(), + (uint32_t)bufferMemoryBarriers.size(), bufferMemoryBarriers.data(), + (uint32_t)imageMemoryBarriers.size(), imageMemoryBarriers.data()); +} + +///////////////////////////////////////////////////////////////////////////// + +QueueSubmit::QueueSubmit() +{ + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; +} + +QueueSubmit& QueueSubmit::AddCommandBuffer(VulkanCommandBuffer* buffer) +{ + commandBuffers.push_back(buffer->buffer); + submitInfo.pCommandBuffers = commandBuffers.data(); + submitInfo.commandBufferCount = (uint32_t)commandBuffers.size(); + return *this; +} + +QueueSubmit& QueueSubmit::AddWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore* semaphore) +{ + waitStages.push_back(waitStageMask); + waitSemaphores.push_back(semaphore->semaphore); + + submitInfo.pWaitDstStageMask = waitStages.data(); + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size(); + return *this; +} + +QueueSubmit& QueueSubmit::AddSignal(VulkanSemaphore* semaphore) +{ + signalSemaphores.push_back(semaphore->semaphore); + submitInfo.pSignalSemaphores = signalSemaphores.data(); + submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.size(); + return *this; +} + +void QueueSubmit::Execute(VulkanDevice* device, VkQueue queue, VulkanFence* fence) +{ + VkResult result = vkQueueSubmit(device->GraphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE); + CheckVulkanError(result, "Could not submit command buffer"); +} + +///////////////////////////////////////////////////////////////////////////// + +WriteDescriptors& WriteDescriptors::AddBuffer(VulkanDescriptorSet* descriptorSet, int binding, VkDescriptorType type, VulkanBuffer* buffer) +{ + return AddBuffer(descriptorSet, binding, type, buffer, 0, buffer->size); +} + +WriteDescriptors& WriteDescriptors::AddBuffer(VulkanDescriptorSet* descriptorSet, int binding, VkDescriptorType type, VulkanBuffer* buffer, size_t offset, size_t range) +{ + VkDescriptorBufferInfo bufferInfo = {}; + bufferInfo.buffer = buffer->buffer; + bufferInfo.offset = offset; + bufferInfo.range = range; + + auto extra = std::make_unique(); + extra->bufferInfo = bufferInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = type; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = &extra->bufferInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddStorageImage(VulkanDescriptorSet* descriptorSet, int binding, VulkanImageView* view, VkImageLayout imageLayout) +{ + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = view->view; + imageInfo.imageLayout = imageLayout; + + auto extra = std::make_unique(); + extra->imageInfo = imageInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pImageInfo = &extra->imageInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddCombinedImageSampler(VulkanDescriptorSet* descriptorSet, int binding, VulkanImageView* view, VulkanSampler* sampler, VkImageLayout imageLayout) +{ + return AddCombinedImageSampler(descriptorSet, binding, 0, view, sampler, imageLayout); +} + +WriteDescriptors& WriteDescriptors::AddCombinedImageSampler(VulkanDescriptorSet* descriptorSet, int binding, int arrayIndex, VulkanImageView* view, VulkanSampler* sampler, VkImageLayout imageLayout) +{ + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = view->view; + imageInfo.sampler = sampler->sampler; + imageInfo.imageLayout = imageLayout; + + auto extra = std::make_unique(); + extra->imageInfo = imageInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = arrayIndex; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pImageInfo = &extra->imageInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddAccelerationStructure(VulkanDescriptorSet* descriptorSet, int binding, VulkanAccelerationStructure* accelStruct) +{ + auto extra = std::make_unique(); + extra->accelStruct = {}; + extra->accelStruct.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + extra->accelStruct.accelerationStructureCount = 1; + extra->accelStruct.pAccelerationStructures = &accelStruct->accelstruct; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pNext = &extra->accelStruct; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +void WriteDescriptors::Execute(VulkanDevice* device) +{ + if (!writes.empty()) + vkUpdateDescriptorSets(device->device, (uint32_t)writes.size(), writes.data(), 0, nullptr); +} + +///////////////////////////////////////////////////////////////////////////// + +VulkanInstanceBuilder::VulkanInstanceBuilder() +{ + apiVersionsToTry = { VK_API_VERSION_1_2, VK_API_VERSION_1_1, VK_API_VERSION_1_0 }; + + OptionalExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME); + OptionalExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +} + +VulkanInstanceBuilder& VulkanInstanceBuilder::ApiVersionsToTry(const std::vector& versions) +{ + apiVersionsToTry = versions; + return *this; +} + +VulkanInstanceBuilder& VulkanInstanceBuilder::RequireExtension(const std::string& extensionName) +{ + requiredExtensions.insert(extensionName); + return *this; +} + +VulkanInstanceBuilder& VulkanInstanceBuilder::RequireSurfaceExtensions(bool enable) +{ + if (enable) + { + RequireExtension(VK_KHR_SURFACE_EXTENSION_NAME); + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + RequireExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_MACOS_MVK) + RequireExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + RequireExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); +#endif + + OptionalExtension(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); // For HDR support + } + return *this; +} + +VulkanInstanceBuilder& VulkanInstanceBuilder::OptionalExtension(const std::string& extensionName) +{ + optionalExtensions.insert(extensionName); + return *this; +} + +VulkanInstanceBuilder& VulkanInstanceBuilder::DebugLayer(bool enable) +{ + debugLayer = enable; + return *this; +} + +std::shared_ptr VulkanInstanceBuilder::Create() +{ + return std::make_shared(apiVersionsToTry, requiredExtensions, optionalExtensions, debugLayer); +} + +///////////////////////////////////////////////////////////////////////////// + +#ifdef VK_USE_PLATFORM_WIN32_KHR + +VulkanSurfaceBuilder::VulkanSurfaceBuilder() +{ +} + +VulkanSurfaceBuilder& VulkanSurfaceBuilder::Win32Window(HWND hwnd) +{ + this->hwnd = hwnd; + return *this; +} + +std::shared_ptr VulkanSurfaceBuilder::Create(std::shared_ptr instance) +{ + return std::make_shared(std::move(instance), hwnd); +} + +#endif + +///////////////////////////////////////////////////////////////////////////// + +VulkanDeviceBuilder::VulkanDeviceBuilder() +{ + OptionalExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME); + OptionalExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::RequireExtension(const std::string& extensionName) +{ + requiredDeviceExtensions.insert(extensionName); + return *this; +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::OptionalExtension(const std::string& extensionName) +{ + optionalDeviceExtensions.insert(extensionName); + return *this; +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::OptionalRayQuery() +{ + OptionalExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + OptionalExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); + OptionalExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); + OptionalExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME); + return *this; +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::OptionalDescriptorIndexing() +{ + OptionalExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); + return *this; +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::Surface(std::shared_ptr surface) +{ + if (surface) + { + RequireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + OptionalExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME); +#endif + } + this->surface = std::move(surface); + return *this; +} + +VulkanDeviceBuilder& VulkanDeviceBuilder::SelectDevice(int index) +{ + deviceIndex = index; + return *this; +} + +std::vector VulkanDeviceBuilder::FindDevices(const std::shared_ptr& instance) +{ + std::vector supportedDevices; + + for (size_t idx = 0; idx < instance->PhysicalDevices.size(); idx++) + { + const auto& info = instance->PhysicalDevices[idx]; + + // Check if all required extensions are there + std::set requiredExtensionSearch = requiredDeviceExtensions; + for (const auto& ext : info.Extensions) + requiredExtensionSearch.erase(ext.extensionName); + if (!requiredExtensionSearch.empty()) + continue; + + // Check if all required features are there + if (info.Features.Features.samplerAnisotropy != VK_TRUE || + info.Features.Features.fragmentStoresAndAtomics != VK_TRUE) + continue; + + VulkanCompatibleDevice dev; + dev.Device = &instance->PhysicalDevices[idx]; + dev.EnabledDeviceExtensions = requiredDeviceExtensions; + + // Enable optional extensions we are interested in, if they are available on this device + for (const auto& ext : dev.Device->Extensions) + { + if (optionalDeviceExtensions.find(ext.extensionName) != optionalDeviceExtensions.end()) + { + dev.EnabledDeviceExtensions.insert(ext.extensionName); + } + } + + // Enable optional features we are interested in, if they are available on this device + auto& enabledFeatures = dev.EnabledFeatures; + auto& deviceFeatures = dev.Device->Features; + enabledFeatures.Features.samplerAnisotropy = deviceFeatures.Features.samplerAnisotropy; + enabledFeatures.Features.fragmentStoresAndAtomics = deviceFeatures.Features.fragmentStoresAndAtomics; + enabledFeatures.Features.depthClamp = deviceFeatures.Features.depthClamp; + enabledFeatures.Features.shaderClipDistance = deviceFeatures.Features.shaderClipDistance; + enabledFeatures.BufferDeviceAddress.bufferDeviceAddress = deviceFeatures.BufferDeviceAddress.bufferDeviceAddress; + enabledFeatures.AccelerationStructure.accelerationStructure = deviceFeatures.AccelerationStructure.accelerationStructure; + enabledFeatures.RayQuery.rayQuery = deviceFeatures.RayQuery.rayQuery; + enabledFeatures.DescriptorIndexing.runtimeDescriptorArray = deviceFeatures.DescriptorIndexing.runtimeDescriptorArray; + enabledFeatures.DescriptorIndexing.descriptorBindingPartiallyBound = deviceFeatures.DescriptorIndexing.descriptorBindingPartiallyBound; + enabledFeatures.DescriptorIndexing.descriptorBindingSampledImageUpdateAfterBind = deviceFeatures.DescriptorIndexing.descriptorBindingSampledImageUpdateAfterBind; + enabledFeatures.DescriptorIndexing.descriptorBindingVariableDescriptorCount = deviceFeatures.DescriptorIndexing.descriptorBindingVariableDescriptorCount; + + // Figure out which queue can present + if (surface) + { + for (int i = 0; i < (int)info.QueueFamilies.size(); i++) + { + VkBool32 presentSupport = false; + VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(info.Device, i, surface->Surface, &presentSupport); + if (result == VK_SUCCESS && info.QueueFamilies[i].queueCount > 0 && presentSupport) + { + dev.PresentFamily = i; + break; + } + } + } + + // The vulkan spec states that graphics and compute queues can always do transfer. + // Furthermore the spec states that graphics queues always can do compute. + // Last, the spec makes it OPTIONAL whether the VK_QUEUE_TRANSFER_BIT is set for such queues, but they MUST support transfer. + // + // In short: pick the first graphics queue family for everything. + for (int i = 0; i < (int)info.QueueFamilies.size(); i++) + { + const auto& queueFamily = info.QueueFamilies[i]; + if (queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) + { + dev.GraphicsFamily = i; + dev.GraphicsTimeQueries = queueFamily.timestampValidBits != 0; + break; + } + } + + // Only use device if we found the required graphics and present queues + if (dev.GraphicsFamily != -1 && (!surface || dev.PresentFamily != -1)) + { + supportedDevices.push_back(dev); + } + } + + // The device order returned by Vulkan can be anything. Prefer discrete > integrated > virtual gpu > cpu > other + auto sortFunc = [&](const auto& a, const auto b) + { + // Sort by GPU type first. This will ensure the "best" device is most likely to map to vk_device 0 + static const int typeSort[] = { 4, 1, 0, 2, 3 }; + int sortA = a.Device->Properties.deviceType < 5 ? typeSort[a.Device->Properties.deviceType] : (int)a.Device->Properties.deviceType; + int sortB = b.Device->Properties.deviceType < 5 ? typeSort[b.Device->Properties.deviceType] : (int)b.Device->Properties.deviceType; + 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.pipelineCacheUUID, b.Device->Properties.pipelineCacheUUID, VK_UUID_SIZE); + return sortUUID < 0; + }; + std::stable_sort(supportedDevices.begin(), supportedDevices.end(), sortFunc); + + return supportedDevices; +} + +std::shared_ptr VulkanDeviceBuilder::Create(std::shared_ptr instance) +{ + if (instance->PhysicalDevices.empty()) + VulkanError("No Vulkan devices found. The graphics card may have no vulkan support or the driver may be too old."); + + std::vector supportedDevices = FindDevices(instance); + if (supportedDevices.empty()) + VulkanError("No Vulkan device found supports the minimum requirements of this application"); + + size_t selected = deviceIndex; + if (selected >= supportedDevices.size()) + selected = 0; + return std::make_shared(instance, surface, supportedDevices[selected]); +} + +///////////////////////////////////////////////////////////////////////////// + +VulkanSwapChainBuilder::VulkanSwapChainBuilder() +{ +} + +std::shared_ptr VulkanSwapChainBuilder::Create(VulkanDevice* device) +{ + return std::make_shared(device); +} diff --git a/libraries/ZVulkan/src/vulkandevice.cpp b/libraries/ZVulkan/src/vulkandevice.cpp new file mode 100644 index 000000000..2edd93d05 --- /dev/null +++ b/libraries/ZVulkan/src/vulkandevice.cpp @@ -0,0 +1,159 @@ + +#include "vulkandevice.h" +#include "vulkanobjects.h" +#include "vulkancompatibledevice.h" +#include +#include +#include + +VulkanDevice::VulkanDevice(std::shared_ptr instance, std::shared_ptr surface, const VulkanCompatibleDevice& selectedDevice) : Instance(instance), Surface(surface) +{ + PhysicalDevice = *selectedDevice.Device; + EnabledDeviceExtensions = selectedDevice.EnabledDeviceExtensions; + EnabledFeatures = selectedDevice.EnabledFeatures; + + GraphicsFamily = selectedDevice.GraphicsFamily; + PresentFamily = selectedDevice.PresentFamily; + GraphicsTimeQueries = selectedDevice.GraphicsTimeQueries; + + try + { + CreateDevice(); + CreateAllocator(); + } + catch (...) + { + ReleaseResources(); + throw; + } +} + +VulkanDevice::~VulkanDevice() +{ + ReleaseResources(); +} + +bool VulkanDevice::SupportsDeviceExtension(const char* ext) const +{ + return EnabledDeviceExtensions.find(ext) != EnabledDeviceExtensions.end(); +} + +void VulkanDevice::CreateAllocator() +{ + VmaAllocatorCreateInfo allocinfo = {}; + allocinfo.vulkanApiVersion = Instance->ApiVersion; + if (SupportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + allocinfo.physicalDevice = PhysicalDevice.Device; + allocinfo.device = device; + allocinfo.instance = Instance->Instance; + allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024; + if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS) + VulkanError("Unable to create allocator"); +} + +void VulkanDevice::CreateDevice() +{ + float queuePriority = 1.0f; + std::vector queueCreateInfos; + + std::set neededFamilies; + if (GraphicsFamily != -1) + neededFamilies.insert(GraphicsFamily); + if (PresentFamily != -1) + neededFamilies.insert(PresentFamily); + + for (int index : neededFamilies) + { + VkDeviceQueueCreateInfo queueCreateInfo = {}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = index; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } + + std::vector extensionNames; + extensionNames.reserve(EnabledDeviceExtensions.size()); + for (const auto& name : EnabledDeviceExtensions) + extensionNames.push_back(name.c_str()); + + VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size(); + deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data(); + deviceCreateInfo.enabledExtensionCount = (uint32_t)extensionNames.size(); + deviceCreateInfo.ppEnabledExtensionNames = extensionNames.data(); + deviceCreateInfo.enabledLayerCount = 0; + + VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; + deviceFeatures2.features = EnabledFeatures.Features; + + void** next = const_cast(&deviceCreateInfo.pNext); + if (SupportsDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + { + *next = &deviceFeatures2; + next = &deviceFeatures2.pNext; + } + else // vulkan 1.0 specified features in a different way + { + deviceCreateInfo.pEnabledFeatures = &deviceFeatures2.features; + } + + if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + { + *next = &EnabledFeatures.BufferDeviceAddress; + next = &EnabledFeatures.BufferDeviceAddress.pNext; + } + if (SupportsDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) + { + *next = &EnabledFeatures.AccelerationStructure; + next = &EnabledFeatures.AccelerationStructure.pNext; + } + if (SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + { + *next = &EnabledFeatures.RayQuery; + next = &EnabledFeatures.RayQuery.pNext; + } + if (SupportsDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) + { + *next = &EnabledFeatures.DescriptorIndexing; + next = &EnabledFeatures.DescriptorIndexing.pNext; + } + + VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device); + CheckVulkanError(result, "Could not create vulkan device"); + + volkLoadDevice(device); + + if (GraphicsFamily != -1) + vkGetDeviceQueue(device, GraphicsFamily, 0, &GraphicsQueue); + if (PresentFamily != -1) + vkGetDeviceQueue(device, PresentFamily, 0, &PresentQueue); +} + +void VulkanDevice::ReleaseResources() +{ + if (device) + vkDeviceWaitIdle(device); + + if (allocator) + vmaDestroyAllocator(allocator); + + if (device) + vkDestroyDevice(device, nullptr); + device = nullptr; +} + +void VulkanDevice::SetObjectName(const char* name, uint64_t handle, VkObjectType type) +{ + if (!DebugLayerActive) return; + + VkDebugUtilsObjectNameInfoEXT info = {}; + info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + info.objectHandle = handle; + info.objectType = type; + info.pObjectName = name; + vkSetDebugUtilsObjectNameEXT(device, &info); +} diff --git a/libraries/ZVulkan/src/vulkaninstance.cpp b/libraries/ZVulkan/src/vulkaninstance.cpp new file mode 100644 index 000000000..7d41a9e6a --- /dev/null +++ b/libraries/ZVulkan/src/vulkaninstance.cpp @@ -0,0 +1,387 @@ + +#include "vulkaninstance.h" +#include "vulkanbuilders.h" +#include +#include +#include +#include + +VulkanInstance::VulkanInstance(std::vector apiVersionsToTry, std::set requiredExtensions, std::set optionalExtensions, bool wantDebugLayer) + : ApiVersionsToTry(std::move(apiVersionsToTry)), RequiredExtensions(std::move(requiredExtensions)), OptionalExtensions(std::move(optionalExtensions)), WantDebugLayer(wantDebugLayer) +{ + try + { + ShaderBuilder::Init(); + InitVolk(); + CreateInstance(); + } + catch (...) + { + ReleaseResources(); + throw; + } +} + +VulkanInstance::~VulkanInstance() +{ + ReleaseResources(); +} + +void VulkanInstance::ReleaseResources() +{ + if (debugMessenger) + vkDestroyDebugUtilsMessengerEXT(Instance, debugMessenger, nullptr); + debugMessenger = VK_NULL_HANDLE; + + if (Instance) + vkDestroyInstance(Instance, nullptr); + Instance = nullptr; +} + +void VulkanInstance::InitVolk() +{ + if (volkInitialize() != VK_SUCCESS) + { + VulkanError("Unable to find Vulkan"); + } + auto iver = volkGetInstanceVersion(); + if (iver == 0) + { + VulkanError("Vulkan not supported"); + } +} + +void VulkanInstance::CreateInstance() +{ + AvailableLayers = GetAvailableLayers(); + AvailableExtensions = GetExtensions(); + EnabledExtensions = RequiredExtensions; + + std::string debugLayer = "VK_LAYER_KHRONOS_validation"; + bool debugLayerFound = false; + if (WantDebugLayer) + { + for (const VkLayerProperties& layer : AvailableLayers) + { + if (layer.layerName == debugLayer) + { + EnabledValidationLayers.insert(layer.layerName); + EnabledExtensions.insert(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + debugLayerFound = true; + break; + } + } + } + + // Enable optional instance extensions we are interested in + for (const auto& ext : AvailableExtensions) + { + if (OptionalExtensions.find(ext.extensionName) != OptionalExtensions.end()) + { + EnabledExtensions.insert(ext.extensionName); + } + } + + std::vector enabledValidationLayersCStr; + for (const std::string& layer : EnabledValidationLayers) + enabledValidationLayersCStr.push_back(layer.c_str()); + + std::vector enabledExtensionsCStr; + for (const std::string& ext : EnabledExtensions) + enabledExtensionsCStr.push_back(ext.c_str()); + + // Try get the highest vulkan version we can get + VkResult result = VK_ERROR_INITIALIZATION_FAILED; + for (uint32_t apiVersion : ApiVersionsToTry) + { + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "VulkanDrv"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "VulkanDrv"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = apiVersion; + + VkInstanceCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size(); + createInfo.enabledLayerCount = (uint32_t)enabledValidationLayersCStr.size(); + createInfo.ppEnabledLayerNames = enabledValidationLayersCStr.data(); + createInfo.ppEnabledExtensionNames = enabledExtensionsCStr.data(); + + result = vkCreateInstance(&createInfo, nullptr, &Instance); + if (result >= VK_SUCCESS) + { + ApiVersion = apiVersion; + break; + } + } + CheckVulkanError(result, "Could not create vulkan instance"); + + volkLoadInstance(Instance); + + if (debugLayerFound) + { + VkDebugUtilsMessengerCreateInfoEXT dbgCreateInfo = {}; + dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + dbgCreateInfo.messageSeverity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + dbgCreateInfo.messageType = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + dbgCreateInfo.pfnUserCallback = DebugCallback; + dbgCreateInfo.pUserData = this; + result = vkCreateDebugUtilsMessengerEXT(Instance, &dbgCreateInfo, nullptr, &debugMessenger); + CheckVulkanError(result, "vkCreateDebugUtilsMessengerEXT failed"); + + DebugLayerActive = true; + } + + PhysicalDevices = GetPhysicalDevices(Instance, ApiVersion); +} + +std::vector VulkanInstance::GetPhysicalDevices(VkInstance instance, uint32_t apiVersion) +{ + uint32_t deviceCount = 0; + VkResult result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + if (result == VK_ERROR_INITIALIZATION_FAILED) // Some drivers return this when a card does not support vulkan + return {}; + CheckVulkanError(result, "vkEnumeratePhysicalDevices failed"); + if (deviceCount == 0) + return {}; + + std::vector devices(deviceCount); + result = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + CheckVulkanError(result, "vkEnumeratePhysicalDevices failed (2)"); + + std::vector devinfo(deviceCount); + for (size_t i = 0; i < devices.size(); i++) + { + auto& dev = devinfo[i]; + dev.Device = devices[i]; + + vkGetPhysicalDeviceMemoryProperties(dev.Device, &dev.MemoryProperties); + vkGetPhysicalDeviceProperties(dev.Device, &dev.Properties); + + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, nullptr); + dev.QueueFamilies.resize(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, dev.QueueFamilies.data()); + + uint32_t deviceExtensionCount = 0; + vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, nullptr); + dev.Extensions.resize(deviceExtensionCount); + vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, dev.Extensions.data()); + + auto checkForExtension = [&](const char* name) + { + for (const auto& ext : dev.Extensions) + { + if (strcmp(ext.extensionName, name) == 0) + return true; + } + return false; + }; + + if (apiVersion != VK_API_VERSION_1_0) + { + VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; + + void** next = const_cast(&deviceFeatures2.pNext); + if (checkForExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + { + *next = &dev.Features.BufferDeviceAddress; + next = &dev.Features.BufferDeviceAddress.pNext; + } + if (checkForExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) + { + *next = &dev.Features.AccelerationStructure; + next = &dev.Features.AccelerationStructure.pNext; + } + if (checkForExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + { + *next = &dev.Features.RayQuery; + next = &dev.Features.RayQuery.pNext; + } + if (checkForExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) + { + *next = &dev.Features.DescriptorIndexing; + next = &dev.Features.DescriptorIndexing.pNext; + } + + vkGetPhysicalDeviceFeatures2(dev.Device, &deviceFeatures2); + dev.Features.Features = deviceFeatures2.features; + dev.Features.BufferDeviceAddress.pNext = nullptr; + dev.Features.AccelerationStructure.pNext = nullptr; + dev.Features.RayQuery.pNext = nullptr; + dev.Features.DescriptorIndexing.pNext = nullptr; + } + else + { + vkGetPhysicalDeviceFeatures(dev.Device, &dev.Features.Features); + } + } + return devinfo; +} + +std::vector VulkanInstance::GetAvailableLayers() +{ + uint32_t layerCount; + VkResult result = vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + result = vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + return availableLayers; +} + +std::vector VulkanInstance::GetExtensions() +{ + uint32_t extensionCount = 0; + VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); + + std::vector extensions(extensionCount); + result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + return extensions; +} + +VkBool32 VulkanInstance::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData) +{ + VulkanInstance* instance = (VulkanInstance*)userData; + + static std::mutex mtx; + static std::set seenMessages; + static int totalMessages; + + std::unique_lock lock(mtx); + + std::string msg = callbackData->pMessage; + + // Attempt to parse the string because the default formatting is totally unreadable and half of what it writes is totally useless! + auto parts = SplitString(msg, " | "); + if (parts.size() == 3) + { + msg = parts[2]; + size_t pos = msg.find(" The Vulkan spec states:"); + if (pos != std::string::npos) + msg = msg.substr(0, pos); + + if (callbackData->objectCount > 0) + { + msg += " ("; + for (uint32_t i = 0; i < callbackData->objectCount; i++) + { + if (i > 0) + msg += ", "; + if (callbackData->pObjects[i].pObjectName) + msg += callbackData->pObjects[i].pObjectName; + else + msg += ""; + } + msg += ")"; + } + } + + bool found = seenMessages.find(msg) != seenMessages.end(); + if (!found) + { + if (totalMessages < 20) + { + totalMessages++; + seenMessages.insert(msg); + + const char* typestr; + bool showcallstack = false; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + { + typestr = "vulkan error"; + showcallstack = true; + } + else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) + { + typestr = "vulkan warning"; + } + else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) + { + typestr = "vulkan info"; + } + else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) + { + typestr = "vulkan verbose"; + } + else + { + typestr = "vulkan"; + } + + VulkanPrintLog(typestr, msg); + } + } + + return VK_FALSE; +} + +std::vector VulkanInstance::SplitString(const std::string& s, const std::string& seperator) +{ + std::vector output; + std::string::size_type prev_pos = 0, pos = 0; + + while ((pos = s.find(seperator, pos)) != std::string::npos) + { + std::string substring(s.substr(prev_pos, pos - prev_pos)); + + output.push_back(substring); + + pos += seperator.length(); + prev_pos = pos; + } + + output.push_back(s.substr(prev_pos, pos - prev_pos)); // Last word + return output; +} + +std::string VkResultToString(VkResult result) +{ + switch (result) + { + case VK_SUCCESS: return "success"; + case VK_NOT_READY: return "not ready"; + case VK_TIMEOUT: return "timeout"; + case VK_EVENT_SET: return "event set"; + case VK_EVENT_RESET: return "event reset"; + case VK_INCOMPLETE: return "incomplete"; + case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory"; + case VK_ERROR_INITIALIZATION_FAILED: return "initialization failed"; + case VK_ERROR_DEVICE_LOST: return "device lost"; + case VK_ERROR_MEMORY_MAP_FAILED: return "memory map failed"; + case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present"; + case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present"; + case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present"; + case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver"; + case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects"; + case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported"; + case VK_ERROR_FRAGMENTED_POOL: return "fragmented pool"; + case VK_ERROR_OUT_OF_POOL_MEMORY: return "out of pool memory"; + case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "invalid external handle"; + case VK_ERROR_SURFACE_LOST_KHR: return "surface lost"; + case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "native window in use"; + case VK_SUBOPTIMAL_KHR: return "suboptimal"; + case VK_ERROR_OUT_OF_DATE_KHR: return "out of date"; + case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "incompatible display"; + case VK_ERROR_VALIDATION_FAILED_EXT: return "validation failed"; + case VK_ERROR_INVALID_SHADER_NV: return "invalid shader"; + case VK_ERROR_FRAGMENTATION_EXT: return "fragmentation"; + case VK_ERROR_NOT_PERMITTED_EXT: return "not permitted"; + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "full screen exclusive mode lost"; + case VK_THREAD_IDLE_KHR: return "thread idle"; + case VK_THREAD_DONE_KHR: return "thread done"; + case VK_OPERATION_DEFERRED_KHR: return "operation deferred"; + case VK_OPERATION_NOT_DEFERRED_KHR: return "operation not deferred"; + case VK_PIPELINE_COMPILE_REQUIRED_EXT: return "pipeline compile required"; + default: break; + } + return "vkResult " + std::to_string((int)result); +} diff --git a/libraries/ZVulkan/src/vulkansurface.cpp b/libraries/ZVulkan/src/vulkansurface.cpp new file mode 100644 index 000000000..ae6ede107 --- /dev/null +++ b/libraries/ZVulkan/src/vulkansurface.cpp @@ -0,0 +1,27 @@ + +#include "vulkansurface.h" +#include "vulkaninstance.h" + +VulkanSurface::VulkanSurface(std::shared_ptr instance, VkSurfaceKHR surface) : Instance(std::move(instance)), Surface(surface) +{ +} + +VulkanSurface::~VulkanSurface() +{ + vkDestroySurfaceKHR(Instance->Instance, Surface, nullptr); +} + +#ifdef VK_USE_PLATFORM_WIN32_KHR + +VulkanSurface::VulkanSurface(std::shared_ptr instance, HWND window) : Instance(std::move(instance)), Window(window) +{ + VkWin32SurfaceCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; + createInfo.hwnd = window; + createInfo.hinstance = GetModuleHandle(nullptr); + + VkResult result = vkCreateWin32SurfaceKHR(Instance->Instance, &createInfo, nullptr, &Surface); + if (result != VK_SUCCESS) + VulkanError("Could not create vulkan surface"); +} + +#endif diff --git a/libraries/ZVulkan/src/vulkanswapchain.cpp b/libraries/ZVulkan/src/vulkanswapchain.cpp new file mode 100644 index 000000000..9162109c4 --- /dev/null +++ b/libraries/ZVulkan/src/vulkanswapchain.cpp @@ -0,0 +1,371 @@ + +#include "vulkanswapchain.h" +#include "vulkanobjects.h" +#include "vulkansurface.h" +#include "vulkanbuilders.h" + +VulkanSwapChain::VulkanSwapChain(VulkanDevice* device) : device(device) +{ +} + +VulkanSwapChain::~VulkanSwapChain() +{ + views.clear(); + images.clear(); + if (swapchain) + vkDestroySwapchainKHR(device->device, swapchain, nullptr); +} + +void VulkanSwapChain::Create(int width, int height, int imageCount, bool vsync, bool hdr, bool exclusivefullscreen) +{ + views.clear(); + images.clear(); + + SelectFormat(hdr); + SelectPresentMode(vsync, exclusivefullscreen); + + VkSwapchainKHR oldSwapchain = swapchain; + CreateSwapchain(width, height, imageCount, exclusivefullscreen, oldSwapchain); + if (oldSwapchain) + vkDestroySwapchainKHR(device->device, oldSwapchain, nullptr); + + if (exclusivefullscreen && lost) + { + // We could not acquire exclusive fullscreen. Fall back to normal fullsceen instead. + exclusivefullscreen = false; + + SelectFormat(hdr); + SelectPresentMode(vsync, exclusivefullscreen); + + oldSwapchain = swapchain; + CreateSwapchain(width, height, imageCount, exclusivefullscreen, oldSwapchain); + if (oldSwapchain) + vkDestroySwapchainKHR(device->device, oldSwapchain, nullptr); + } + + if (swapchain) + { + uint32_t imageCount; + VkResult result = vkGetSwapchainImagesKHR(device->device, swapchain, &imageCount, nullptr); + if (result != VK_SUCCESS) + throw std::runtime_error("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)"); + + for (VkImage vkimage : swapchainImages) + { + auto image = std::make_unique(device, vkimage, nullptr, actualExtent.width, actualExtent.height, 1, 1); + auto view = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_2D) + .Image(image.get(), format.format) + .DebugName("SwapchainImageView") + .Create(device); + images.push_back(std::move(image)); + views.push_back(std::move(view)); + } + } +} + +void VulkanSwapChain::SelectFormat(bool hdr) +{ + std::vector surfaceFormats = GetSurfaceFormats(); + if (surfaceFormats.empty()) + throw std::runtime_error("No surface formats supported"); + + if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED) + { + format.format = VK_FORMAT_B8G8R8A8_UNORM; + format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + return; + } + + if (hdr) + { + for (const auto& f : surfaceFormats) + { + if (f.format == VK_FORMAT_R16G16B16A16_SFLOAT && f.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT) + { + format = f; + return; + } + } + } + + for (const auto& f : surfaceFormats) + { + if (f.format == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + format = f; + return; + } + } + + format = surfaceFormats.front(); +} + +void VulkanSwapChain::SelectPresentMode(bool vsync, bool exclusivefullscreen) +{ + std::vector presentModes = GetPresentModes(exclusivefullscreen); + if (presentModes.empty()) + throw std::runtime_error("No surface present modes supported"); + + presentMode = VK_PRESENT_MODE_FIFO_KHR; + if (vsync) + { + bool supportsFifoRelaxed = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != presentModes.end(); + if (supportsFifoRelaxed) + presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } + else + { + bool supportsMailbox = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != presentModes.end(); + bool supportsImmediate = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != presentModes.end(); + if (supportsMailbox) + presentMode = VK_PRESENT_MODE_MAILBOX_KHR; + else if (supportsImmediate) + presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } +} + +bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, bool exclusivefullscreen, VkSwapchainKHR oldSwapChain) +{ + lost = false; + + VkResult result; + VkSurfaceCapabilitiesKHR surfaceCapabilities; +#ifdef WIN32 + if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) + { + VkPhysicalDeviceSurfaceInfo2KHR info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR }; + VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT }; + VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT }; + info.surface = device->Surface->Surface; + info.pNext = &exclusiveInfo; + exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT; + exclusiveInfo.pNext = &exclusiveWin32Info; + exclusiveWin32Info.hmonitor = MonitorFromWindow(device->Surface->Window, MONITOR_DEFAULTTONEAREST); + + VkSurfaceCapabilities2KHR capabilites = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR }; + VkSurfaceCapabilitiesFullScreenExclusiveEXT exclusiveCapabilities = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT }; + capabilites.pNext = &exclusiveCapabilities; + + result = vkGetPhysicalDeviceSurfaceCapabilities2KHR(device->PhysicalDevice.Device, &info, &capabilites); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilities2EXT failed"); + + surfaceCapabilities = capabilites.surfaceCapabilities; + exclusivefullscreen = exclusiveCapabilities.fullScreenExclusiveSupported == VK_TRUE; + } + else + { + result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceCapabilities); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"); + exclusivefullscreen = false; + } +#else + result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceCapabilities); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"); + exclusivefullscreen = false; +#endif + + actualExtent = { static_cast(width), static_cast(height) }; + actualExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, actualExtent.width)); + actualExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, actualExtent.height)); + if (actualExtent.width == 0 || actualExtent.height == 0) + { + swapchain = VK_NULL_HANDLE; + lost = true; + return false; + } + + imageCount = std::max(surfaceCapabilities.minImageCount, std::min(surfaceCapabilities.maxImageCount, (uint32_t)imageCount)); + + VkSwapchainCreateInfoKHR swapChainCreateInfo = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; + swapChainCreateInfo.surface = device->Surface->Surface; + swapChainCreateInfo.minImageCount = imageCount; + swapChainCreateInfo.imageFormat = format.format; + swapChainCreateInfo.imageColorSpace = format.colorSpace; + swapChainCreateInfo.imageExtent = actualExtent; + swapChainCreateInfo.imageArrayLayers = 1; + swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + uint32_t queueFamilyIndices[] = { (uint32_t)device->GraphicsFamily, (uint32_t)device->PresentFamily }; + if (device->GraphicsFamily != device->PresentFamily) + { + swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapChainCreateInfo.queueFamilyIndexCount = 2; + swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; + } + else + { + swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapChainCreateInfo.queueFamilyIndexCount = 0; + swapChainCreateInfo.pQueueFamilyIndices = nullptr; + } + + swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform; + swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // If alpha channel is passed on to the DWM or not + swapChainCreateInfo.presentMode = presentMode; + swapChainCreateInfo.clipped = VK_FALSE;// VK_TRUE; + swapChainCreateInfo.oldSwapchain = oldSwapChain; + +#ifdef WIN32 + VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT }; + VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT }; + if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) + { + swapChainCreateInfo.pNext = &exclusiveInfo; + exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT; + exclusiveInfo.pNext = &exclusiveWin32Info; + exclusiveWin32Info.hmonitor = MonitorFromWindow(device->Surface->Window, MONITOR_DEFAULTTONEAREST); + } +#endif + + result = vkCreateSwapchainKHR(device->device, &swapChainCreateInfo, nullptr, &swapchain); + if (result != VK_SUCCESS) + { + swapchain = VK_NULL_HANDLE; + lost = true; + return false; + } + +#ifdef WIN32 + if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) + { + result = vkAcquireFullScreenExclusiveModeEXT(device->device, swapchain); + if (result != VK_SUCCESS) + { + lost = true; + } + } +#endif + + return true; +} + +int VulkanSwapChain::AcquireImage(VulkanSemaphore* semaphore, VulkanFence* fence) +{ + if (lost) + return -1; + + uint32_t imageIndex; + VkResult result = vkAcquireNextImageKHR(device->device, swapchain, 1'000'000'000, semaphore ? semaphore->semaphore : VK_NULL_HANDLE, fence ? fence->fence : VK_NULL_HANDLE, &imageIndex); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) + { + return imageIndex; + } + else if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { + lost = true; + return -1; + } + else if (result == VK_NOT_READY || result == VK_TIMEOUT) + { + return -1; + } + else + { + throw std::runtime_error("Failed to acquire next image!"); + } +} + +void VulkanSwapChain::QueuePresent(int imageIndex, VulkanSemaphore* semaphore) +{ + uint32_t index = imageIndex; + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = semaphore ? 1 : 0; + presentInfo.pWaitSemaphores = semaphore ? &semaphore->semaphore : VK_NULL_HANDLE; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + presentInfo.pImageIndices = &index; + presentInfo.pResults = nullptr; + VkResult result = vkQueuePresentKHR(device->PresentQueue, &presentInfo); + if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) + { + return; + } + else if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_SURFACE_LOST_KHR || result == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT) + { + lost = true; + } + else if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY) + { + // 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"); + } + else if (result == VK_ERROR_DEVICE_LOST) + { + throw std::runtime_error("vkQueuePresentKHR failed: device lost"); + } + else + { + throw std::runtime_error("vkQueuePresentKHR failed"); + } +} + +std::vector VulkanSwapChain::GetSurfaceFormats() +{ + 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"); + else if (surfaceFormatCount == 0) + return {}; + + std::vector surfaceFormats(surfaceFormatCount); + result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, surfaceFormats.data()); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed"); + return surfaceFormats; +} + +std::vector VulkanSwapChain::GetPresentModes(bool exclusivefullscreen) +{ +#ifdef WIN32 + if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) + { + VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR }; + VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT }; + surfaceInfo.surface = device->Surface->Surface; + surfaceInfo.pNext = &exclusiveInfo; + exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT; + + uint32_t presentModeCount = 0; + VkResult result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, nullptr); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); + else if (presentModeCount == 0) + return {}; + + std::vector presentModes(presentModeCount); + result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, presentModes.data()); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed"); + return presentModes; + } + else +#endif + { + 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"); + else if (presentModeCount == 0) + return {}; + + std::vector presentModes(presentModeCount); + result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, presentModes.data()); + if (result != VK_SUCCESS) + throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed"); + return presentModes; + } +} diff --git a/libraries/bzip2/CMakeLists.txt b/libraries/bzip2/CMakeLists.txt index 6ca7a4e6d..452954c8a 100644 --- a/libraries/bzip2/CMakeLists.txt +++ b/libraries/bzip2/CMakeLists.txt @@ -2,6 +2,10 @@ cmake_minimum_required( VERSION 3.1.0 ) make_release_only() +if (MSVC) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4244" ) +endif() + add_definitions( -DBZ_NO_STDIO ) add_library( bz2 STATIC blocksort.c diff --git a/libraries/discordrpc/.clang-format b/libraries/discordrpc/.clang-format new file mode 100644 index 000000000..1be83906c --- /dev/null +++ b/libraries/discordrpc/.clang-format @@ -0,0 +1,92 @@ +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Stroustrup +BreakBeforeInheritanceComma: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: true +ForEachMacros: [] +IndentCaseLabels: false +IncludeCategories: + - Regex: '^("|<)stdafx\.h(pp)?("|>)' + Priority: -1 + - Regex: '^<(W|w)indows.h>' + Priority: 1 + - Regex: '^<' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '(_test|_win|_linux|_mac|_ios|_osx|_null)?$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 0 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 9999999 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +--- +Language: Cpp +--- +Language: ObjC +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +--- +Language: Java +BasedOnStyle: Google +BreakAfterJavaFieldAnnotations: true +... diff --git a/libraries/discordrpc/.gitignore b/libraries/discordrpc/.gitignore new file mode 100644 index 000000000..223c07d70 --- /dev/null +++ b/libraries/discordrpc/.gitignore @@ -0,0 +1,5 @@ +/build*/ +/.vscode/ +/thirdparty/ +.vs/ +.DS_Store \ No newline at end of file diff --git a/libraries/discordrpc/.travis.yml b/libraries/discordrpc/.travis.yml new file mode 100644 index 000000000..42cc09d5b --- /dev/null +++ b/libraries/discordrpc/.travis.yml @@ -0,0 +1,47 @@ +language: cpp + +env: + global: + - CLANG_FORMAT_SUFFIX="-dummy" # don't use formatting on Travis, this is + # needed not to use default 3.5 version + # which is too old. + +matrix: + include: + - os: linux + env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + - os: linux + env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0" + addons: + apt: + sources: + - llvm-toolchain-trusty-4.0 + packages: + - clang-4.0 + - os: linux + env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0" + addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + packages: + - clang-5.0 + - os: osx + osx_image: xcode9 + +# prevent Travis from overwriting our CXX variables +before_install: + - eval "${MATRIX_EVAL}" + - echo $CXX + +script: + - mkdir build + - cd build + - cmake -DCLANG_FORMAT_SUFFIX=$CLANG_FORMAT_SUFFIX -DWARNINGS_AS_ERRORS=On --config Release .. + - cmake --build . -- -j2 diff --git a/libraries/discordrpc/CMakeLists.txt b/libraries/discordrpc/CMakeLists.txt new file mode 100644 index 000000000..a369a7dc1 --- /dev/null +++ b/libraries/discordrpc/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required (VERSION 3.2.0) +project (DiscordRPC) + +include(GNUInstallDirs) + +# format +file(GLOB_RECURSE ALL_SOURCE_FILES + include/*.h + src/*.cpp src/*.h src/*.c +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../src/common/thirdparty) + +# add subdirs + +add_subdirectory(src) diff --git a/libraries/discordrpc/LICENSE b/libraries/discordrpc/LICENSE new file mode 100644 index 000000000..17fca3d50 --- /dev/null +++ b/libraries/discordrpc/LICENSE @@ -0,0 +1,19 @@ +Copyright 2017 Discord, Inc. + +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. diff --git a/libraries/discordrpc/README.md b/libraries/discordrpc/README.md new file mode 100644 index 000000000..1285fb844 --- /dev/null +++ b/libraries/discordrpc/README.md @@ -0,0 +1,158 @@ +# Discord RPC + +## Deprecation Notice + +This library has been deprecated in favor of Discord's GameSDK. [Learn more here](https://discordapp.com/developers/docs/game-sdk/sdk-starter-guide) + +--- + +This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs. + +Included here are some quick demos that implement the very minimal subset to show current status, and +have callbacks for where a more complete game would do more things (joining, spectating, etc). + +## Documentation + +The most up to date documentation for Rich Presence can always be found on our [developer site](https://discordapp.com/developers/docs/rich-presence/how-to)! If you're interested in rolling your own native implementation of Rich Presence via IPC sockets instead of using our SDK—hey, you've got free time, right?—check out the ["Hard Mode" documentation](https://github.com/discordapp/discord-rpc/blob/master/documentation/hard-mode.md). + +## Basic Usage + +Zeroith, you should be set up to build things because you are a game developer, right? + +First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me) and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init function. + +### Unreal Engine 4 Setup + +To use the Rich Presense plugin with Unreal Engine Projects: + +1. Download the latest [release](https://github.com/discordapp/discord-rpc/releases) for each operating system you are targeting and the zipped source code +2. In the source code zip, copy the UE plugin—`examples/unrealstatus/Plugins/discordrpc`—to your project's plugin directory +3. At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create an `Include` folder and copy `discord_rpc.h` and `discord_register.h` to it from the zip +4. Follow the steps below for each OS +5. Build your UE4 project +6. Launch the editor, and enable the Discord plugin. + +#### Windows + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Win64` folder +- Copy `lib/discord-rpc.lib` and `bin/discord-rpc.dll` from `[RELEASE_ZIP]/win64-dynamic` to the `Win64` folder + +#### Mac + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Mac` folder +- Copy `libdiscord-rpc.dylib` from `[RELEASE_ZIP]/osx-dynamic/lib` to the `Mac` folder + +#### Linux + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Linux` folder +- Inside, create another folder `x86_64-unknown-linux-gnu` +- Copy `libdiscord-rpc.so` from `[RELEASE_ZIP]/linux-dynamic/lib` to `Linux/x86_64-unknown-linux-gnu` + +### Unity Setup + +If you're a Unity developer looking to integrate Rich Presence into your game, follow this simple guide to get started towards success: + +1. Download the DLLs for any platform that you need from [our releases](https://github.com/discordapp/discord-rpc/releases) +2. In your Unity project, create a `Plugins` folder inside your `Assets` folder if you don't already have one +3. Copy the file `DiscordRpc.cs` from [here](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordRpc.cs) into your `Assets` folder. This is basically your header file for the SDK + +We've got our `Plugins` folder ready, so let's get platform-specific! + +#### Windows + +4. Create `x86` and `x86_64` folders inside `Assets/Plugins/` +5. Copy `discord-rpc-win/win64-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86_64/` +6. Copy `discord-rpc-win/win32-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86/` +7. Click on both DLLs and make sure they are targetting the correct architectures in the Unity editor properties pane +8. Done! + +#### MacOS + +4. Copy `discord-rpc-osx/osx-dynamic/lib/libdiscord-rpc.dylib` to `Assets/Plugins/` +5. Rename `libdiscord-rpc.dylib` to `discord-rpc.bundle` +6. Done! + +#### Linux + +4. Copy `discord-rpc-linux/linux-dynamic-lib/libdiscord-rpc.so` to `Assets/Plugins/` +5. Done! + +You're ready to roll! For code examples on how to interact with the SDK using the `DiscordRpc.cs` header file, check out [our example](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordController.cs) + +### From package + +Download a release package for your platform(s) -- they have subdirs with various prebuilt options, select the one you need add `/include` to your compile includes, `/lib` to your linker paths, and link with `discord-rpc`. For the dynamically linked builds, you'll need to ship the associated file along with your game. + +### From repo + +First-eth, you'll want `CMake`. There's a few different ways to install it on your system, and you should refer to [their website](https://cmake.org/install/). Many package managers provide ways of installing CMake as well. + +To make sure it's installed correctly, type `cmake --version` into your flavor of terminal/cmd. If you get a response with a version number, you're good to go! + +There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for you; Sometimes I use it like this: + +```sh + cd + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX= + cmake --build . --config Release --target install +``` + +There is a wrapper build script `build.py` that runs `cmake` with a few different options. + +Usually, I run `build.py` to get things started, then use the generated project files as I work on things. It does depend on `click` library, so do a quick `pip install click` to make sure you have it if you want to run `build.py`. + +There are some CMake options you might care about: + +| flag | default | does | +| ---------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself. | +| `USE_STATIC_CRT` | `OFF` | (Windows) Enable to statically link the CRT, avoiding requiring users install the redistributable package. (The prebuilt binaries enable this option) | +| [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/v3.7/variable/BUILD_SHARED_LIBS.html) | `OFF` | Build library as a DLL | +| `WARNINGS_AS_ERRORS` | `OFF` | When enabled, compiles with `-Werror` (on \*nix platforms). | + +## Continuous Builds + +Why do we have three of these? Three times the fun! + +| CI | badge | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| TravisCI | [![Build status](https://travis-ci.org/discordapp/discord-rpc.svg?branch=master)](https://travis-ci.org/discordapp/discord-rpc) | +| AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/qvkoc0w1c4f4b8tj?svg=true)](https://ci.appveyor.com/project/crmarsh/discord-rpc) | +| Buildkite (internal) | [![Build status](https://badge.buildkite.com/e103d79d247f6776605a15246352a04b8fd83d69211b836111.svg)](https://buildkite.com/discord/discord-rpc) | + +## Sample: send-presence + +This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence update on each command. + +## Sample: button-clicker + +This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and sends presence updates when you click on a button. Run `python build.py unity` in the root directory to build the correct library files and place them in their respective folders. + +## Sample: unrealstatus + +This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to make a very simple UI. Run `python build.py unreal` in the root directory to build the correct library files and place them in their respective folders. + +## Wrappers and Implementations + +Below is a table of unofficial, community-developed wrappers for and implementations of Rich Presence in various languages. If you would like to have yours added, please make a pull request adding your repository to the table. The repository should include: + +- The code +- A brief ReadMe of how to use it +- A working example + +###### Rich Presence Wrappers and Implementations + +| Name | Language | +| ------------------------------------------------------------------------- | --------------------------------- | +| [Discord RPC C#](https://github.com/Lachee/discord-rpc-csharp) | C# | +| [Discord RPC D](https://github.com/voidblaster/discord-rpc-d) | [D](https://dlang.org/) | +| [discord-rpc.jar](https://github.com/Vatuu/discord-rpc 'Discord-RPC.jar') | Java | +| [java-discord-rpc](https://github.com/MinnDevelopment/java-discord-rpc) | Java | +| [Discord-IPC](https://github.com/jagrosh/DiscordIPC) | Java | +| [Discord Rich Presence](https://npmjs.org/discord-rich-presence) | JavaScript | +| [drpc4k](https://github.com/Bluexin/drpc4k) | [Kotlin](https://kotlinlang.org/) | +| [lua-discordRPC](https://github.com/pfirsich/lua-discordRPC) | LuaJIT (FFI) | +| [pypresence](https://github.com/qwertyquerty/pypresence) | [Python](https://python.org/) | +| [SwordRPC](https://github.com/Azoy/SwordRPC) | [Swift](https://swift.org) | diff --git a/libraries/discordrpc/appveyor.yml b/libraries/discordrpc/appveyor.yml new file mode 100644 index 000000000..1c328b878 --- /dev/null +++ b/libraries/discordrpc/appveyor.yml @@ -0,0 +1,17 @@ +version: '{build}' +install: + - python -m pip install click + +build_script: + - mkdir examples\unrealstatus\Plugins\discordrpc\Binaries\ThirdParty\discordrpcLibrary\Win64 + - python build.py + +artifacts: +- path: builds\install\win32-dynamic + name: win32-dynamic +- path: builds\install\win32-static + name: win32-static +- path: builds\install\win64-dynamic + name: win64-dynamic +- path: builds\install\win64-static + name: win64-static diff --git a/libraries/discordrpc/build.py b/libraries/discordrpc/build.py new file mode 100644 index 000000000..215d3586b --- /dev/null +++ b/libraries/discordrpc/build.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +import os +import subprocess +import sys +import shutil +import zipfile +from contextlib import contextmanager +import click + + +def get_platform(): + """ a name for the platform """ + if sys.platform.startswith('win'): + return 'win' + elif sys.platform == 'darwin': + return 'osx' + elif sys.platform.startswith('linux'): + return 'linux' + raise Exception('Unsupported platform ' + sys.platform) + + +SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) +# we use Buildkite which sets this env variable by default +IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true' +PLATFORM = get_platform() +INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install') + + +def get_signtool(): + """ get path to code signing tool """ + if PLATFORM == 'win': + sdk_dir = 'c:\\Program Files (x86)\\Windows Kits\\10' # os.environ['WindowsSdkDir'] + return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe') + elif PLATFORM == 'osx': + return '/usr/bin/codesign' + + +@contextmanager +def cd(new_dir): + """ Temporarily change current directory """ + if new_dir: + old_dir = os.getcwd() + os.chdir(new_dir) + yield + if new_dir: + os.chdir(old_dir) + + +def mkdir_p(path): + """ mkdir -p """ + if not os.path.isdir(path): + click.secho('Making ' + path, fg='yellow') + os.makedirs(path) + + +@click.group(invoke_without_command=True) +@click.pass_context +@click.option('--clean', is_flag=True) +def cli(ctx, clean): + """ click wrapper for command line stuff """ + if ctx.invoked_subcommand is None: + ctx.invoke(libs, clean=clean) + if IS_BUILD_MACHINE: + ctx.invoke(sign) + ctx.invoke(archive) + + +@cli.command() +@click.pass_context +def unity(ctx): + """ build just dynamic libs for use in unity project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unity example') + UNITY_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Plugins') + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.dll' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNITY_64_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86_64') + BUILDS.append({BUILD_64_BASE_PATH: UNITY_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNITY_32_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + BUILDS.append({BUILD_32_BASE_PATH: UNITY_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'discord-rpc.bundle' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNITY_DLL_PATH = UNITY_PROJECT_PATH + os.rename( + os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.dylib'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.bundle')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'discord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNITY_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + os.rename(os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.so'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.so')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +@cli.command() +@click.pass_context +def unreal(ctx): + """ build libs and copy them into the unreal project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unreal example') + UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc') + UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include') + mkdir_p(UNREAL_INCLUDE_PATH) + shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord_rpc.h'), UNREAL_INCLUDE_PATH) + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.lib' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNREAL_64_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64') + BUILDS.append({BUILD_64_BASE_PATH: UNREAL_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNREAL_32_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win32') + BUILDS.append({BUILD_32_BASE_PATH: UNREAL_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'libdiscord-rpc.dylib' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Mac') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'libdiscord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Linux') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +def build_lib(build_name, generator, options, just_release): + """ Create a dir under builds, run build and install in it """ + build_path = os.path.join(SCRIPT_PATH, 'builds', build_name) + install_path = os.path.join(INSTALL_ROOT, build_name) + mkdir_p(build_path) + mkdir_p(install_path) + with cd(build_path): + initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)] + if generator: + initial_cmake.extend(['-G', generator]) + for key in options: + val = options[key] + if type(val) is bool: + val = 'ON' if val else 'OFF' + initial_cmake.append('-D%s=%s' % (key, val)) + click.echo('--- Building ' + build_name) + subprocess.check_call(initial_cmake) + if not just_release: + subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug']) + subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install']) + + +@cli.command() +def archive(): + """ create zip of install dir """ + click.echo('--- Archiving') + archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform()) + archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED) + archive_src_base_path = INSTALL_ROOT + archive_dst_base_path = 'discord-rpc' + with cd(archive_src_base_path): + for path, _, filenames in os.walk('.'): + for fname in filenames: + fpath = os.path.join(path, fname) + dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath)) + click.echo('Adding ' + dst_path) + archive_file.write(fpath, dst_path) + + +@cli.command() +def sign(): + """ Do code signing within install directory using our cert """ + tool = get_signtool() + signable_extensions = set() + if PLATFORM == 'win': + signable_extensions.add('.dll') + sign_command_base = [ + tool, + 'sign', + '/n', + 'Discord Inc.', + '/a', + '/tr', + 'http://timestamp.digicert.com/rfc3161', + '/as', + '/td', + 'sha256', + '/fd', + 'sha256', + ] + elif PLATFORM == 'osx': + signable_extensions.add('.dylib') + sign_command_base = [ + tool, + '--keychain', + os.path.expanduser('~/Library/Keychains/login.keychain'), + '-vvvv', + '--deep', + '--force', + '--sign', + 'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)', + ] + else: + click.secho('Not signing things on this platform yet', fg='red') + return + + click.echo('--- Signing') + for path, _, filenames in os.walk(INSTALL_ROOT): + for fname in filenames: + ext = os.path.splitext(fname)[1] + if ext not in signable_extensions: + continue + fpath = os.path.join(path, fname) + click.echo('Sign ' + fpath) + sign_command = sign_command_base + [fpath] + subprocess.check_call(sign_command) + + +@cli.command() +@click.option('--clean', is_flag=True) +@click.option('--static', is_flag=True) +@click.option('--shared', is_flag=True) +@click.option('--skip_formatter', is_flag=True) +@click.option('--just_release', is_flag=True) +def libs(clean, static, shared, skip_formatter, just_release): + """ Do all the builds for this platform """ + if clean: + shutil.rmtree('builds', ignore_errors=True) + + mkdir_p('builds') + + if not (static or shared): + static = True + shared = True + + static_options = {} + dynamic_options = { + 'BUILD_SHARED_LIBS': True, + 'USE_STATIC_CRT': True, + } + + if skip_formatter or IS_BUILD_MACHINE: + static_options['CLANG_FORMAT_SUFFIX'] = 'none' + dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none' + + if IS_BUILD_MACHINE: + just_release = True + static_options['WARNINGS_AS_ERRORS'] = True + dynamic_options['WARNINGS_AS_ERRORS'] = True + + if PLATFORM == 'win': + generator32 = 'Visual Studio 14 2015' + generator64 = 'Visual Studio 14 2015 Win64' + if static: + build_lib('win32-static', generator32, static_options, just_release) + build_lib('win64-static', generator64, static_options, just_release) + if shared: + build_lib('win32-dynamic', generator32, dynamic_options, just_release) + build_lib('win64-dynamic', generator64, dynamic_options, just_release) + elif PLATFORM == 'osx': + if static: + build_lib('osx-static', None, static_options, just_release) + if shared: + build_lib('osx-dynamic', None, dynamic_options, just_release) + elif PLATFORM == 'linux': + if static: + build_lib('linux-static', None, static_options, just_release) + if shared: + build_lib('linux-dynamic', None, dynamic_options, just_release) + + +if __name__ == '__main__': + os.chdir(SCRIPT_PATH) + sys.exit(cli()) diff --git a/libraries/discordrpc/documentation/hard-mode.md b/libraries/discordrpc/documentation/hard-mode.md new file mode 100644 index 000000000..35042cbcb --- /dev/null +++ b/libraries/discordrpc/documentation/hard-mode.md @@ -0,0 +1,164 @@ +# Hard Mode: Roll Your Own Client + +Discord's Rich Presence feature is designed as an obfuscated addition to our existing [RPC infrastructure](https://discordapp.com/developers/docs/topics/rpc). The standalone library and header files make it easy for any dev to drop it into their game. + +Our library communicates with Discord over the local Discord RPC socket. We've already done the work in connecting properly, handling disconnects and reconnects, and other RPC intracacies, but those who have done this implementation for our private alpha Voice and Chat SDK can simply make use of the new RPC commands and events to implement Rich Presence. + +## Hark! A warning! + +By committing to an RPC-only integration, you decide to forego the work our library and header file have done for you in the way of error handling, state storage, disconnecting and reconnecting, and other quality of life abstractions. While simply implementing the new RPC command and events will enable Rich Presence for your game, we highly suggest that you do your best to mimic the functionality of the SDK the most that you can. It ensure not only code quality on your part, but also an excellent experience on the part of your players. + +## Application Protocol Registration + +One thing that cannot be explicitly done over RPC is registering an application protocol for your game. If you choose to do an RPC-only implementation, you will have to register your application protocol yourself in the format of `discord-[your_app_id]://`. You can use `Discord_Register()` as a good(?) example of how to properly register an application protocol for use with Discord. For OSX and Linux it is probably simpler to handle the protocol registration as part of your install/packaging. + +## New RPC Command + +The new RPC command for Rich Presence is `SET_ACTIVITY`. The fields are similar to what is outlined in the SDK; we've combined similar fields into objects for the sake of less data on the wire. + +The one major difference is the `party.size` field. It is an array with a size of two. The first element is the current party size, `partySize` from the main documentation. The second element is the maximum party size, `partyMax` from the main documentation. + +Below is a full example of a `SET_ACTIVITY` command. Field restrictions like size are the same as outlined in the main documentation. + +``` +{ + "cmd": "SET_ACTIVITY", + "args": { + "pid": 9999, // Your application's process id - required field + "activity": { + "state": "In a Group", + "details": "Competitive | In a Match", + "timestamps": { + "start": time(nullptr), + "end": time(nullptr) + ((60 * 5) + 23) + }, + "assets": { + "large_image": "numbani_map", + "large_text": "Numbani", + "small_image": "pharah_profile", + "small_text": "Pharah" + }, + "party": { + "id": GameEngine.GetPartyId(), + "size": [3, 6] + }, + "secrets": { + "join": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f", + "spectate": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0", + "match": "4b2fdce12f639de8bfa7e3591b71a0d679d7c93f" + }, + "instance": true + } + }, + "nonce": "647d814a-4cf8-4fbb-948f-898abd24f55b" +} +``` + +## New RPC Events + +The three new RPC events for Rich Presence power the ability to join and spectate your friends' games. + +First is the `ACTIVITY_JOIN` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "secret": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f" + }, + "evt": "ACTIVITY_JOIN" +} +``` + +Second is the `ACTIVITY_SPECTATE` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "secret": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0" + }, + "evt": "ACTIVITY_SPECTATE" +} +``` + +And third is the `ACTIVITY_JOIN_REQUEST` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "user": { + "id": "53908232506183680", + "username": "Mason", + "discriminator": "1337", + "avatar": "a_bab14f271d565501444b2ca3be944b25" + } + }, + "evt": "ACTIVITY_JOIN_REQUEST" +} +``` + +In order to receive these events, you need to [subscribe](https://discordapp.com/developers/docs/topics/rpc#subscribe) to them like so: + +```json +{ + "nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015", + "evt": "ACTIVITY_JOIN", + "cmd": "SUBSCRIBE" +} +``` + +```json +{ + "nonce": "ae9qdde3-31d0-8989-a8e9-dnakwy174he", + "evt": "ACTIVITY_SPECTATE", + "cmd": "SUBSCRIBE" +} +``` + +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-bbb52e9d6afa", + "evt": "ACTIVITY_JOIN_REQUEST", + "cmd": "SUBSCRIBE" +} +``` + +To unsubscribe from these events, resend with the command `UNSUBSCRIBE` + +## Responding +A discord user will request access to the game. If the ACTIVITY_JOIN_REQUEST has been subscribed too, the ACTIVITY_JOIN_REQUEST event will be sent to the host's game. Accept it with following model: +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-15aerg126", + "cmd": "SEND_ACTIVITY_JOIN_INVITE", + "args": + { + "user_id": "53908232506183680" + } +} +``` + +To reject the request, use `CLOSE_ACTIVITY_REQUEST`: +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-dasg256eafg", + "cmd": "CLOSE_ACTIVITY_REQUEST", + "args": + { + "user_id": "53908232506183680" + } +} +``` + +## Notes +Here are just some quick notes to help with some common troubleshooting problems. +* IPC will echo back every command you send as a response. Use this as a lock-step feature to avoid flooding messages. Can be used to validate messages such as the Presence or Subscribes. +* The pipe expects for frames to be written in a single byte array. You cannot do multiple `stream.Write(opcode);` `stream.Write(length);` as it will break the pipe. Instead create a buffer, write the data to the buffer, then send the entire buffer to the stream. +* Discord can be on any pipe ranging from `discord-ipc-0` to `discord-ipc-9`. It is a good idea to try and connect to each one and keeping the first one you connect too. For multiple clients (eg Discord and Canary), you might want to add a feature to manually select the pipe so you can more easily debug the application. +* All enums are `lower_snake_case`. +* The opcode and length in the header are `Little Endian Unsigned Integers (32bits)`. In some languages, you must convert them as they can be architecture specific. +* [Discord Rich Presence How-To](https://discordapp.com/developers/docs/rich-presence/how-to) contains a lot of the information this document doesn't. For example, it will tell you about the response payload. +* In the documentation, DISCORD_REPLY_IGNORE is just implemented the same as DISCORD_REPLY_NO. +* You can test the Join / Spectate feature by enabling them in your profile and whitelisting a test account. Use Canary to run 2 accounts on the same machine. diff --git a/libraries/discordrpc/documentation/images/rp-dev-dashboard.png b/libraries/discordrpc/documentation/images/rp-dev-dashboard.png new file mode 100644 index 000000000..f246cfb2d Binary files /dev/null and b/libraries/discordrpc/documentation/images/rp-dev-dashboard.png differ diff --git a/libraries/discordrpc/documentation/images/rp-profile-view.png b/libraries/discordrpc/documentation/images/rp-profile-view.png new file mode 100644 index 000000000..f9ddc3130 Binary files /dev/null and b/libraries/discordrpc/documentation/images/rp-profile-view.png differ diff --git a/libraries/discordrpc/documentation/images/rp-secret-example.png b/libraries/discordrpc/documentation/images/rp-secret-example.png new file mode 100644 index 000000000..4ff21b093 Binary files /dev/null and b/libraries/discordrpc/documentation/images/rp-secret-example.png differ diff --git a/libraries/discordrpc/include/discord_register.h b/libraries/discordrpc/include/discord_register.h new file mode 100644 index 000000000..16fb42f32 --- /dev/null +++ b/libraries/discordrpc/include/discord_register.h @@ -0,0 +1,26 @@ +#pragma once + +#if defined(DISCORD_DYNAMIC_LIB) +#if defined(_WIN32) +#if defined(DISCORD_BUILDING_SDK) +#define DISCORD_EXPORT __declspec(dllexport) +#else +#define DISCORD_EXPORT __declspec(dllimport) +#endif +#else +#define DISCORD_EXPORT __attribute__((visibility("default"))) +#endif +#else +#define DISCORD_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command); +DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId); + +#ifdef __cplusplus +} +#endif diff --git a/libraries/discordrpc/include/discord_rpc.h b/libraries/discordrpc/include/discord_rpc.h new file mode 100644 index 000000000..9470434a8 --- /dev/null +++ b/libraries/discordrpc/include/discord_rpc.h @@ -0,0 +1,90 @@ +#pragma once +#include + +// clang-format off + +#if defined(DISCORD_DYNAMIC_LIB) +# if defined(_WIN32) +# if defined(DISCORD_BUILDING_SDK) +# define DISCORD_EXPORT __declspec(dllexport) +# else +# define DISCORD_EXPORT __declspec(dllimport) +# endif +# else +# define DISCORD_EXPORT __attribute__((visibility("default"))) +# endif +#else +# define DISCORD_EXPORT +#endif + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DiscordRichPresence { + const char* state; /* max 128 bytes */ + const char* details; /* max 128 bytes */ + int64_t startTimestamp; + int64_t endTimestamp; + const char* largeImageKey; /* max 32 bytes */ + const char* largeImageText; /* max 128 bytes */ + const char* smallImageKey; /* max 32 bytes */ + const char* smallImageText; /* max 128 bytes */ + const char* partyId; /* max 128 bytes */ + int partySize; + int partyMax; + int partyPrivacy; + const char* matchSecret; /* max 128 bytes */ + const char* joinSecret; /* max 128 bytes */ + const char* spectateSecret; /* max 128 bytes */ + int8_t instance; +} DiscordRichPresence; + +typedef struct DiscordUser { + const char* userId; + const char* username; + const char* discriminator; + const char* avatar; +} DiscordUser; + +typedef struct DiscordEventHandlers { + void (*ready)(const DiscordUser* request); + void (*disconnected)(int errorCode, const char* message); + void (*errored)(int errorCode, const char* message); + void (*joinGame)(const char* joinSecret); + void (*spectateGame)(const char* spectateSecret); + void (*joinRequest)(const DiscordUser* request); +} DiscordEventHandlers; + +#define DISCORD_REPLY_NO 0 +#define DISCORD_REPLY_YES 1 +#define DISCORD_REPLY_IGNORE 2 +#define DISCORD_PARTY_PRIVATE 0 +#define DISCORD_PARTY_PUBLIC 1 + +DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId); +DISCORD_EXPORT void Discord_Shutdown(void); + +/* checks for incoming messages, dispatches callbacks */ +DISCORD_EXPORT void Discord_RunCallbacks(void); + +/* If you disable the lib starting its own io thread, you'll need to call this from your own */ +#ifdef DISCORD_DISABLE_IO_THREAD +DISCORD_EXPORT void Discord_UpdateConnection(void); +#endif + +DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence); +DISCORD_EXPORT void Discord_ClearPresence(void); + +DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply); + +DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/libraries/discordrpc/src/CMakeLists.txt b/libraries/discordrpc/src/CMakeLists.txt new file mode 100644 index 000000000..34aca1e4b --- /dev/null +++ b/libraries/discordrpc/src/CMakeLists.txt @@ -0,0 +1,141 @@ +include_directories(${PROJECT_SOURCE_DIR}/include) + +option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON) +option(USE_STATIC_CRT "Use /MT[d] for dynamic library" OFF) +option(WARNINGS_AS_ERRORS "When enabled, compiles with `-Werror` (on *nix platforms)." OFF) + +set(CMAKE_CXX_STANDARD 14) + +set(BASE_RPC_SRC + ${PROJECT_SOURCE_DIR}/include/discord_rpc.h + discord_rpc.cpp + ${PROJECT_SOURCE_DIR}/include/discord_register.h + rpc_connection.h + rpc_connection.cpp + serialization.h + serialization.cpp + connection.h + backoff.h + msg_queue.h +) + +if (${BUILD_SHARED_LIBS}) + if(WIN32) + set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp) + endif(WIN32) +endif(${BUILD_SHARED_LIBS}) + +if(WIN32) + add_definitions(-DDISCORD_WINDOWS) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp) + add_library(discord-rpc ${BASE_RPC_SRC}) + if (MSVC) + if(USE_STATIC_CRT) + foreach(CompilerFlag + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() + endif(USE_STATIC_CRT) + target_compile_options(discord-rpc PRIVATE /EHsc + /wd4100 # unreferenced formal parameter + /wd4514 # unreferenced inline + /wd4625 # copy constructor deleted + /wd5026 # move constructor deleted + /wd4626 # move assignment operator deleted + /wd4668 # not defined preprocessor macro + /wd4710 # function not inlined + /wd4711 # function was inlined + /wd4820 # structure padding + /wd4946 # reinterpret_cast used between related classes + /wd5027 # move assignment operator was implicitly defined as deleted + ) + endif(MSVC) + target_link_libraries(discord-rpc PRIVATE psapi advapi32) +endif(WIN32) + +if(UNIX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_unix.cpp) + + if (APPLE) + add_definitions(-DDISCORD_OSX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_osx.m) + else (APPLE) + add_definitions(-DDISCORD_LINUX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp) + endif(APPLE) + + add_library(discord-rpc ${BASE_RPC_SRC}) + target_link_libraries(discord-rpc PUBLIC pthread) + + target_compile_options(discord-rpc PRIVATE + -Wall + -Wextra + -Wpedantic + ) + + if (${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo) + target_compile_options(discord-rpc PRIVATE -g) + endif () + + if (${WARNINGS_AS_ERRORS}) + target_compile_options(discord-rpc PRIVATE -Werror) + endif (${WARNINGS_AS_ERRORS}) + + target_compile_options(discord-rpc PRIVATE + -Wno-unknown-pragmas # pragma push thing doesn't work on clang + -Wno-old-style-cast # it's fine + -Wno-c++98-compat # that was almost 2 decades ago + -Wno-c++98-compat-pedantic + -Wno-missing-noreturn + -Wno-padded # structure padding + -Wno-covered-switch-default + -Wno-exit-time-destructors # not sure about these + -Wno-global-constructors + ) + + if (${BUILD_SHARED_LIBS}) + target_compile_options(discord-rpc PRIVATE -fPIC) + endif (${BUILD_SHARED_LIBS}) + + if (APPLE) + target_link_libraries(discord-rpc PRIVATE "-framework AppKit") + endif (APPLE) +endif(UNIX) + +target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include) + +if (NOT ${ENABLE_IO_THREAD}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD) +endif (NOT ${ENABLE_IO_THREAD}) + +if (${BUILD_SHARED_LIBS}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB) + target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK) +endif(${BUILD_SHARED_LIBS}) + +# install + +install( + TARGETS discord-rpc + EXPORT "discord-rpc" + RUNTIME + DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + INCLUDES + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + FILES + "../include/discord_rpc.h" + "../include/discord_register.h" + DESTINATION "include" +) diff --git a/libraries/discordrpc/src/backoff.h b/libraries/discordrpc/src/backoff.h new file mode 100644 index 000000000..a3e736fb7 --- /dev/null +++ b/libraries/discordrpc/src/backoff.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include + +struct Backoff { + int64_t minAmount; + int64_t maxAmount; + int64_t current; + int fails; + std::mt19937_64 randGenerator; + std::uniform_real_distribution<> randDistribution; + + double rand01() { return randDistribution(randGenerator); } + + Backoff(int64_t min, int64_t max) + : minAmount(min) + , maxAmount(max) + , current(min) + , fails(0) + , randGenerator((uint64_t)time(0)) + { + } + + void reset() + { + fails = 0; + current = minAmount; + } + + int64_t nextDelay() + { + ++fails; + int64_t delay = (int64_t)((double)current * 2.0 * rand01()); + current = std::min(current + delay, maxAmount); + return current; + } +}; diff --git a/libraries/discordrpc/src/connection.h b/libraries/discordrpc/src/connection.h new file mode 100644 index 000000000..a8f99b9f1 --- /dev/null +++ b/libraries/discordrpc/src/connection.h @@ -0,0 +1,19 @@ +#pragma once + +// This is to wrap the platform specific kinds of connect/read/write. + +#include +#include + +// not really connectiony, but need per-platform +int GetProcessId(); + +struct BaseConnection { + static BaseConnection* Create(); + static void Destroy(BaseConnection*&); + bool isOpen{false}; + bool Open(); + bool Close(); + bool Write(const void* data, size_t length); + bool Read(void* data, size_t length); +}; diff --git a/libraries/discordrpc/src/connection_unix.cpp b/libraries/discordrpc/src/connection_unix.cpp new file mode 100644 index 000000000..85dace3cc --- /dev/null +++ b/libraries/discordrpc/src/connection_unix.cpp @@ -0,0 +1,125 @@ +#include "connection.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int GetProcessId() +{ + return ::getpid(); +} + +struct BaseConnectionUnix : public BaseConnection { + int sock{-1}; +}; + +static BaseConnectionUnix Connection; +static sockaddr_un PipeAddr{}; +#ifdef MSG_NOSIGNAL +static int MsgFlags = MSG_NOSIGNAL; +#else +static int MsgFlags = 0; +#endif + +static const char* GetTempPath() +{ + const char* temp = getenv("XDG_RUNTIME_DIR"); + temp = temp ? temp : getenv("TMPDIR"); + temp = temp ? temp : getenv("TMP"); + temp = temp ? temp : getenv("TEMP"); + temp = temp ? temp : "/tmp"; + return temp; +} + +/*static*/ BaseConnection* BaseConnection::Create() +{ + PipeAddr.sun_family = AF_UNIX; + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + const char* tempPath = GetTempPath(); + auto self = reinterpret_cast(this); + self->sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (self->sock == -1) { + return false; + } + fcntl(self->sock, F_SETFL, O_NONBLOCK); +#ifdef SO_NOSIGPIPE + int optval = 1; + setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)); +#endif + + for (int pipeNum = 0; pipeNum < 10; ++pipeNum) { + snprintf( + PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); + int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr)); + if (err == 0) { + self->isOpen = true; + return true; + } + } + self->Close(); + return false; +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + if (self->sock == -1) { + return false; + } + close(self->sock); + self->sock = -1; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + ssize_t sentBytes = send(self->sock, data, length, MsgFlags); + if (sentBytes < 0) { + Close(); + } + return sentBytes == (ssize_t)length; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + int res = (int)recv(self->sock, data, length, MsgFlags); + if (res < 0) { + if (errno == EAGAIN) { + return false; + } + Close(); + } + else if (res == 0) { + Close(); + } + return res == (int)length; +} diff --git a/libraries/discordrpc/src/connection_win.cpp b/libraries/discordrpc/src/connection_win.cpp new file mode 100644 index 000000000..2dd2750c0 --- /dev/null +++ b/libraries/discordrpc/src/connection_win.cpp @@ -0,0 +1,128 @@ +#include "connection.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include + +int GetProcessId() +{ + return (int)::GetCurrentProcessId(); +} + +struct BaseConnectionWin : public BaseConnection { + HANDLE pipe{INVALID_HANDLE_VALUE}; +}; + +static BaseConnectionWin Connection; + +/*static*/ BaseConnection* BaseConnection::Create() +{ + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"}; + const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; + pipeName[pipeDigit] = L'0'; + auto self = reinterpret_cast(this); + for (;;) { + self->pipe = ::CreateFileW( + pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); + if (self->pipe != INVALID_HANDLE_VALUE) { + self->isOpen = true; + return true; + } + + auto lastError = GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND) { + if (pipeName[pipeDigit] < L'9') { + pipeName[pipeDigit]++; + continue; + } + } + else if (lastError == ERROR_PIPE_BUSY) { + if (!WaitNamedPipeW(pipeName, 10000)) { + return false; + } + continue; + } + return false; + } +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + ::CloseHandle(self->pipe); + self->pipe = INVALID_HANDLE_VALUE; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + if (length == 0) { + return true; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + assert(data); + if (!data) { + return false; + } + const DWORD bytesLength = (DWORD)length; + DWORD bytesWritten = 0; + return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE && + bytesWritten == bytesLength; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + assert(data); + if (!data) { + return false; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + DWORD bytesAvailable = 0; + if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) { + if (bytesAvailable >= length) { + DWORD bytesToRead = (DWORD)length; + DWORD bytesRead = 0; + if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) { + assert(bytesToRead == bytesRead); + return true; + } + else { + Close(); + } + } + } + else { + Close(); + } + return false; +} diff --git a/libraries/discordrpc/src/discord_register_linux.cpp b/libraries/discordrpc/src/discord_register_linux.cpp new file mode 100644 index 000000000..dd92eea0d --- /dev/null +++ b/libraries/discordrpc/src/discord_register_linux.cpp @@ -0,0 +1,102 @@ +#include "discord_rpc.h" +#include "discord_register.h" +#include + +#include +#include +#include +#include +#include +#include + +static bool Mkdir(const char* path) +{ + int result = mkdir(path, 0755); + if (result == 0) { + return true; + } + if (errno == EEXIST) { + return true; + } + return false; +} + +// we want to register games so we can run them from Discord client as discord-:// +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + // Add a desktop file and update some mime handlers so that xdg-open does the right thing. + + const char* home = getenv("HOME"); + if (!home) { + return; + } + + char exePath[1024]; + if (!command || !command[0]) { + ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath)); + if (size <= 0 || size >= (ssize_t)sizeof(exePath)) { + return; + } + exePath[size] = '\0'; + command = exePath; + } + + const char* desktopFileFormat = "[Desktop Entry]\n" + "Name=Game %s\n" + "Exec=%s %%u\n" // note: it really wants that %u in there + "Type=Application\n" + "NoDisplay=true\n" + "Categories=Discord;Games;\n" + "MimeType=x-scheme-handler/discord-%s;\n"; + char desktopFile[2048]; + int fileLen = snprintf( + desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId); + if (fileLen <= 0) { + return; + } + + char desktopFilename[256]; + snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId); + + char desktopFilePath[1024]; + snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/share"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/applications"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, desktopFilename); + + FILE* fp = fopen(desktopFilePath, "w"); + if (fp) { + fwrite(desktopFile, 1, fileLen, fp); + fclose(fp); + } + else { + return; + } + + char xdgMimeCommand[1024]; + snprintf(xdgMimeCommand, + sizeof(xdgMimeCommand), + "xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s", + applicationId, + applicationId); + if (system(xdgMimeCommand) < 0) { + fprintf(stderr, "Failed to register mime handler\n"); + } +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + char command[256]; + sprintf(command, "xdg-open steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/libraries/discordrpc/src/discord_register_osx.m b/libraries/discordrpc/src/discord_register_osx.m new file mode 100644 index 000000000..d71010286 --- /dev/null +++ b/libraries/discordrpc/src/discord_register_osx.m @@ -0,0 +1,80 @@ +#include +#include + +#import + +#include "discord_register.h" + +static void RegisterCommand(const char* applicationId, const char* command) +{ + // There does not appear to be a way to register arbitrary commands on OSX, so instead we'll save the command + // to a file in the Discord config path, and when it is needed, Discord can try to load the file there, open + // the command therein (will pass to js's window.open, so requires a url-like thing) + + // Note: will not work for sandboxed apps + NSString *home = NSHomeDirectory(); + if (!home) { + return; + } + + NSString *path = [[[[[[home stringByAppendingPathComponent:@"Library"] + stringByAppendingPathComponent:@"Application Support"] + stringByAppendingPathComponent:@"discord"] + stringByAppendingPathComponent:@"games"] + stringByAppendingPathComponent:[NSString stringWithUTF8String:applicationId]] + stringByAppendingPathExtension:@"json"]; + [[NSFileManager defaultManager] createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + + NSString *jsonBuffer = [NSString stringWithFormat:@"{\"command\": \"%s\"}", command]; + [jsonBuffer writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + +static void RegisterURL(const char* applicationId) +{ + char url[256]; + snprintf(url, sizeof(url), "discord-%s", applicationId); + CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8); + + NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier]; + if (!myBundleId) { + fprintf(stderr, "No bundle id found\n"); + return; + } + + NSURL* myURL = [[NSBundle mainBundle] bundleURL]; + if (!myURL) { + fprintf(stderr, "No bundle url found\n"); + return; + } + + OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId); + if (status != noErr) { + fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status); + return; + } + + status = LSRegisterURL((__bridge CFURLRef)myURL, true); + if (status != noErr) { + fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status); + } +} + +void Discord_Register(const char* applicationId, const char* command) +{ + if (command) { + RegisterCommand(applicationId, command); + } + else { + // raii lite + @autoreleasepool { + RegisterURL(applicationId); + } + } +} + +void Discord_RegisterSteamGame(const char* applicationId, const char* steamId) +{ + char command[256]; + snprintf(command, 256, "steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/libraries/discordrpc/src/discord_register_win.cpp b/libraries/discordrpc/src/discord_register_win.cpp new file mode 100644 index 000000000..0b1c4a13d --- /dev/null +++ b/libraries/discordrpc/src/discord_register_win.cpp @@ -0,0 +1,186 @@ +#include "discord_rpc.h" +#include "discord_register.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include +#include + +/** + * Updated fixes for MinGW and WinXP + * This block is written the way it does not involve changing the rest of the code + * Checked to be compiling + * 1) strsafe.h belongs to Windows SDK and cannot be added to MinGW + * #include guarded, functions redirected to substitutes + * 2) RegSetKeyValueW and LSTATUS are not declared in + * The entire function is rewritten + */ +#ifdef __MINGW32__ +#include +/// strsafe.h fixes +static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) +{ + HRESULT ret; + va_list va; + va_start(va, pszFormat); + cbDest /= 2; // Size is divided by 2 to convert from bytes to wide characters - causes segfault + // othervise + ret = vsnwprintf(pszDest, cbDest, pszFormat, va); + pszDest[cbDest - 1] = 0; // Terminate the string in case a buffer overflow; -1 will be returned + va_end(va); + return ret; +} +#else +#include +#include +#endif // __MINGW32__ + +/// winreg.h fixes +#ifndef LSTATUS +#define LSTATUS LONG +#endif +#ifdef RegSetKeyValueW +#undefine RegSetKeyValueW +#endif +#define RegSetKeyValueW regset +static LSTATUS regset(HKEY hkey, + LPCWSTR subkey, + LPCWSTR name, + DWORD type, + const void* data, + DWORD len) +{ + HKEY htkey = hkey, hsubkey = nullptr; + LSTATUS ret; + if (subkey && subkey[0]) { + if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) != + ERROR_SUCCESS) + return ret; + htkey = hsubkey; + } + ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len); + if (hsubkey && hsubkey != hkey) + RegCloseKey(hsubkey); + return ret; +} + +static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) +{ + // https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx + // we want to register games so we can run them as discord-:// + // Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. + + wchar_t exeFilePath[MAX_PATH]; + DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH); + wchar_t openCommand[1024]; + + if (command && command[0]) { + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command); + } + else { + // StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath); + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", exeFilePath); + } + + wchar_t protocolName[64]; + StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId); + wchar_t protocolDescription[128]; + StringCbPrintfW( + protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId); + wchar_t urlProtocol = 0; + + wchar_t keyName[256]; + StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName); + HKEY key; + auto status = + RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error creating key\n"); + return; + } + DWORD len; + LSTATUS result; + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = + RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = RegSetKeyValueW(key, nullptr, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + result = RegSetKeyValueW( + key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing icon\n"); + } + + len = (DWORD)lstrlenW(openCommand) + 1; + result = RegSetKeyValueW( + key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing command\n"); + } + RegCloseKey(key); +} + +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t openCommand[1024]; + const wchar_t* wcommand = nullptr; + if (command && command[0]) { + const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand); + MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen); + wcommand = openCommand; + } + + Discord_RegisterW(appId, wcommand); +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t wSteamId[32]; + MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32); + + HKEY key; + auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error opening Steam key\n"); + return; + } + + wchar_t steamPath[MAX_PATH]; + DWORD pathBytes = sizeof(steamPath); + status = RegQueryValueExW(key, L"SteamExe", nullptr, nullptr, (BYTE*)steamPath, &pathBytes); + RegCloseKey(key); + if (status != ERROR_SUCCESS || pathBytes < 1) { + fprintf(stderr, "Error reading SteamExe key\n"); + return; + } + + DWORD pathChars = pathBytes / sizeof(wchar_t); + for (DWORD i = 0; i < pathChars; ++i) { + if (steamPath[i] == L'/') { + steamPath[i] = L'\\'; + } + } + + wchar_t command[1024]; + StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId); + + Discord_RegisterW(appId, command); +} diff --git a/libraries/discordrpc/src/discord_rpc.cpp b/libraries/discordrpc/src/discord_rpc.cpp new file mode 100644 index 000000000..03924538c --- /dev/null +++ b/libraries/discordrpc/src/discord_rpc.cpp @@ -0,0 +1,504 @@ +#include "discord_rpc.h" + +#include "backoff.h" +#include "discord_register.h" +#include "msg_queue.h" +#include "rpc_connection.h" +#include "serialization.h" + +#include +#include +#include + +#ifndef DISCORD_DISABLE_IO_THREAD +#include +#include +#endif + +constexpr size_t MaxMessageSize{16 * 1024}; +constexpr size_t MessageQueueSize{8}; +constexpr size_t JoinQueueSize{8}; + +struct QueuedMessage { + size_t length; + char buffer[MaxMessageSize]; + + void Copy(const QueuedMessage& other) + { + length = other.length; + if (length) { + memcpy(buffer, other.buffer, length); + } + } +}; + +struct User { + // snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null + // terminator = 21 + char userId[32]; + // 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null + // terminator = 129 + char username[344]; + // 4 decimal digits + 1 null terminator = 5 + char discriminator[8]; + // optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35 + char avatar[128]; + // Rounded way up because I'm paranoid about games breaking from future changes in these sizes +}; + +static RpcConnection* Connection{nullptr}; +static DiscordEventHandlers QueuedHandlers{}; +static DiscordEventHandlers Handlers{}; +static std::atomic_bool WasJustConnected{false}; +static std::atomic_bool WasJustDisconnected{false}; +static std::atomic_bool GotErrorMessage{false}; +static std::atomic_bool WasJoinGame{false}; +static std::atomic_bool WasSpectateGame{false}; +static std::atomic_bool UpdatePresence{false}; +static char JoinGameSecret[256]; +static char SpectateGameSecret[256]; +static int LastErrorCode{0}; +static char LastErrorMessage[256]; +static int LastDisconnectErrorCode{0}; +static char LastDisconnectErrorMessage[256]; +static std::mutex PresenceMutex; +static std::mutex HandlerMutex; +static QueuedMessage QueuedPresence{}; +static MsgQueue SendQueue; +static MsgQueue JoinAskQueue; +static User connectedUser; + +// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential +// backoff from 0.5 seconds to 1 minute +static Backoff ReconnectTimeMs(500, 60 * 1000); +static auto NextConnect = std::chrono::system_clock::now(); +static int Pid{0}; +static int Nonce{1}; + +#ifndef DISCORD_DISABLE_IO_THREAD +static void Discord_UpdateConnection(void); +class IoThreadHolder { +private: + std::atomic_bool keepRunning{true}; + std::mutex waitForIOMutex; + std::condition_variable waitForIOActivity; + std::thread ioThread; + +public: + void Start() + { + keepRunning.store(true); + ioThread = std::thread([&]() { + const std::chrono::duration maxWait{500LL}; + Discord_UpdateConnection(); + while (keepRunning.load()) { + std::unique_lock lock(waitForIOMutex); + waitForIOActivity.wait_for(lock, maxWait); + Discord_UpdateConnection(); + } + }); + } + + void Notify() { waitForIOActivity.notify_all(); } + + void Stop() + { + keepRunning.exchange(false); + Notify(); + if (ioThread.joinable()) { + ioThread.join(); + } + } + + ~IoThreadHolder() { Stop(); } +}; +#else +class IoThreadHolder { +public: + void Start() {} + void Stop() {} + void Notify() {} +}; +#endif // DISCORD_DISABLE_IO_THREAD +static IoThreadHolder* IoThread{nullptr}; + +static void UpdateReconnectTime() +{ + NextConnect = std::chrono::system_clock::now() + + std::chrono::duration{ReconnectTimeMs.nextDelay()}; +} + +#ifdef DISCORD_DISABLE_IO_THREAD +extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void) +#else +static void Discord_UpdateConnection(void) +#endif +{ + if (!Connection) { + return; + } + + if (!Connection->IsOpen()) { + if (std::chrono::system_clock::now() >= NextConnect) { + UpdateReconnectTime(); + Connection->Open(); + } + } + else { + // reads + + for (;;) { + JsonDocument message; + + if (!Connection->Read(message)) { + break; + } + + const char* evtName = GetStrMember(&message, "evt"); + const char* nonce = GetStrMember(&message, "nonce"); + + if (nonce) { + // in responses only -- should use to match up response when needed. + + if (evtName && strcmp(evtName, "ERROR") == 0) { + auto data = GetObjMember(&message, "data"); + LastErrorCode = GetIntMember(data, "code"); + StringCopy(LastErrorMessage, GetStrMember(data, "message", "")); + GotErrorMessage.store(true); + } + } + else { + // should have evt == name of event, optional data + if (evtName == nullptr) { + continue; + } + + auto data = GetObjMember(&message, "data"); + + if (strcmp(evtName, "ACTIVITY_JOIN") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(JoinGameSecret, secret); + WasJoinGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(SpectateGameSecret, secret); + WasSpectateGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) { + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + auto joinReq = JoinAskQueue.GetNextAddMessage(); + if (userId && username && joinReq) { + StringCopy(joinReq->userId, userId); + StringCopy(joinReq->username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(joinReq->discriminator, discriminator); + } + if (avatar) { + StringCopy(joinReq->avatar, avatar); + } + else { + joinReq->avatar[0] = 0; + } + JoinAskQueue.CommitAdd(); + } + } + } + } + + // writes + if (UpdatePresence.exchange(false) && QueuedPresence.length) { + QueuedMessage local; + { + std::lock_guard guard(PresenceMutex); + local.Copy(QueuedPresence); + } + if (!Connection->Write(local.buffer, local.length)) { + // if we fail to send, requeue + std::lock_guard guard(PresenceMutex); + QueuedPresence.Copy(local); + UpdatePresence.exchange(true); + } + } + + while (SendQueue.HavePendingSends()) { + auto qmessage = SendQueue.GetNextSendMessage(); + Connection->Write(qmessage->buffer, qmessage->length); + SendQueue.CommitSend(); + } + } +} + +static void SignalIOActivity() +{ + if (IoThread != nullptr) { + IoThread->Notify(); + } +} + +static bool RegisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +static bool DeregisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId) +{ + IoThread = new (std::nothrow) IoThreadHolder(); + if (IoThread == nullptr) { + return; + } + + if (autoRegister) { + if (optionalSteamId && optionalSteamId[0]) { + Discord_RegisterSteamGame(applicationId, optionalSteamId); + } + else { + Discord_Register(applicationId, nullptr); + } + } + + Pid = GetProcessId(); + + { + std::lock_guard guard(HandlerMutex); + + if (handlers) { + QueuedHandlers = *handlers; + } + else { + QueuedHandlers = {}; + } + + Handlers = {}; + } + + if (Connection) { + return; + } + + Connection = RpcConnection::Create(applicationId); + Connection->onConnect = [](JsonDocument& readyMessage) { + Discord_UpdateHandlers(&QueuedHandlers); + if (QueuedPresence.length > 0) { + UpdatePresence.exchange(true); + SignalIOActivity(); + } + auto data = GetObjMember(&readyMessage, "data"); + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + if (userId && username) { + StringCopy(connectedUser.userId, userId); + StringCopy(connectedUser.username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(connectedUser.discriminator, discriminator); + } + if (avatar) { + StringCopy(connectedUser.avatar, avatar); + } + else { + connectedUser.avatar[0] = 0; + } + } + WasJustConnected.exchange(true); + ReconnectTimeMs.reset(); + }; + Connection->onDisconnect = [](int err, const char* message) { + LastDisconnectErrorCode = err; + StringCopy(LastDisconnectErrorMessage, message); + WasJustDisconnected.exchange(true); + UpdateReconnectTime(); + }; + + IoThread->Start(); +} + +extern "C" DISCORD_EXPORT void Discord_Shutdown(void) +{ + if (!Connection) { + return; + } + Connection->onConnect = nullptr; + Connection->onDisconnect = nullptr; + Handlers = {}; + QueuedPresence.length = 0; + UpdatePresence.exchange(false); + if (IoThread != nullptr) { + IoThread->Stop(); + delete IoThread; + IoThread = nullptr; + } + + RpcConnection::Destroy(Connection); +} + +extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) +{ + { + std::lock_guard guard(PresenceMutex); + QueuedPresence.length = JsonWriteRichPresenceObj( + QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); + UpdatePresence.exchange(true); + } + SignalIOActivity(); +} + +extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) +{ + Discord_UpdatePresence(nullptr); +} + +extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) +{ + // if we are not connected, let's not batch up stale messages for later + if (!Connection || !Connection->IsOpen()) { + return; + } + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++); + SendQueue.CommitAdd(); + SignalIOActivity(); + } +} + +extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) +{ + // Note on some weirdness: internally we might connect, get other signals, disconnect any number + // of times inbetween calls here. Externally, we want the sequence to seem sane, so any other + // signals are book-ended by calls to ready and disconnect. + + if (!Connection) { + return; + } + + bool wasDisconnected = WasJustDisconnected.exchange(false); + bool isConnected = Connection->IsOpen(); + + if (isConnected) { + // if we are connected, disconnect cb first + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } + + if (WasJustConnected.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.ready) { + DiscordUser du{connectedUser.userId, + connectedUser.username, + connectedUser.discriminator, + connectedUser.avatar}; + Handlers.ready(&du); + } + } + + if (GotErrorMessage.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.errored) { + Handlers.errored(LastErrorCode, LastErrorMessage); + } + } + + if (WasJoinGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinGame) { + Handlers.joinGame(JoinGameSecret); + } + } + + if (WasSpectateGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.spectateGame) { + Handlers.spectateGame(SpectateGameSecret); + } + } + + // Right now this batches up any requests and sends them all in a burst; I could imagine a world + // where the implementer would rather sequentially accept/reject each one before the next invite + // is sent. I left it this way because I could also imagine wanting to process these all and + // maybe show them in one common dialog and/or start fetching the avatars in parallel, and if + // not it should be trivial for the implementer to make a queue themselves. + while (JoinAskQueue.HavePendingSends()) { + auto req = JoinAskQueue.GetNextSendMessage(); + { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinRequest) { + DiscordUser du{req->userId, req->username, req->discriminator, req->avatar}; + Handlers.joinRequest(&du); + } + } + JoinAskQueue.CommitSend(); + } + + if (!isConnected) { + // if we are not connected, disconnect message last + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } +} + +extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) +{ + if (newHandlers) { +#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ + if (!Handlers.handler_name && newHandlers->handler_name) { \ + RegisterForEvent(event); \ + } \ + else if (Handlers.handler_name && !newHandlers->handler_name) { \ + DeregisterForEvent(event); \ + } + + std::lock_guard guard(HandlerMutex); + HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN") + HANDLE_EVENT_REGISTRATION(spectateGame, "ACTIVITY_SPECTATE") + HANDLE_EVENT_REGISTRATION(joinRequest, "ACTIVITY_JOIN_REQUEST") + +#undef HANDLE_EVENT_REGISTRATION + + Handlers = *newHandlers; + } + else { + std::lock_guard guard(HandlerMutex); + Handlers = {}; + } + return; +} diff --git a/libraries/discordrpc/src/dllmain.cpp b/libraries/discordrpc/src/dllmain.cpp new file mode 100644 index 000000000..fbfc2950d --- /dev/null +++ b/libraries/discordrpc/src/dllmain.cpp @@ -0,0 +1,8 @@ +#include + +// outsmart GCC's missing-declarations warning +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID); +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) +{ + return TRUE; +} diff --git a/libraries/discordrpc/src/msg_queue.h b/libraries/discordrpc/src/msg_queue.h new file mode 100644 index 000000000..77f380e70 --- /dev/null +++ b/libraries/discordrpc/src/msg_queue.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +// A simple queue. No locks, but only works with a single thread as producer and a single thread as +// a consumer. Mutex up as needed. + +template +class MsgQueue { + ElementType queue_[QueueSize]; + std::atomic_uint nextAdd_{0}; + std::atomic_uint nextSend_{0}; + std::atomic_uint pendingSends_{0}; + +public: + MsgQueue() {} + + ElementType* GetNextAddMessage() + { + // if we are falling behind, bail + if (pendingSends_.load() >= QueueSize) { + return nullptr; + } + auto index = (nextAdd_++) % QueueSize; + return &queue_[index]; + } + void CommitAdd() { ++pendingSends_; } + + bool HavePendingSends() const { return pendingSends_.load() != 0; } + ElementType* GetNextSendMessage() + { + auto index = (nextSend_++) % QueueSize; + return &queue_[index]; + } + void CommitSend() { --pendingSends_; } +}; diff --git a/libraries/discordrpc/src/rpc_connection.cpp b/libraries/discordrpc/src/rpc_connection.cpp new file mode 100644 index 000000000..093316216 --- /dev/null +++ b/libraries/discordrpc/src/rpc_connection.cpp @@ -0,0 +1,137 @@ +#include "rpc_connection.h" +#include "serialization.h" + +#include + +static const int RpcVersion = 1; +static RpcConnection Instance; + +/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) +{ + Instance.connection = BaseConnection::Create(); + StringCopy(Instance.appId, applicationId); + return &Instance; +} + +/*static*/ void RpcConnection::Destroy(RpcConnection*& c) +{ + c->Close(); + BaseConnection::Destroy(c->connection); + c = nullptr; +} + +void RpcConnection::Open() +{ + if (state == State::Connected) { + return; + } + + if (state == State::Disconnected && !connection->Open()) { + return; + } + + if (state == State::SentHandshake) { + JsonDocument message; + if (Read(message)) { + auto cmd = GetStrMember(&message, "cmd"); + auto evt = GetStrMember(&message, "evt"); + if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) { + state = State::Connected; + if (onConnect) { + onConnect(message); + } + } + } + } + else { + sendFrame.opcode = Opcode::Handshake; + sendFrame.length = (uint32_t)JsonWriteHandshakeObj( + sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId); + + if (connection->Write(&sendFrame, sizeof(MessageFrameHeader) + sendFrame.length)) { + state = State::SentHandshake; + } + else { + Close(); + } + } +} + +void RpcConnection::Close() +{ + if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) { + onDisconnect(lastErrorCode, lastErrorMessage); + } + connection->Close(); + state = State::Disconnected; +} + +bool RpcConnection::Write(const void* data, size_t length) +{ + sendFrame.opcode = Opcode::Frame; + memcpy(sendFrame.message, data, length); + sendFrame.length = (uint32_t)length; + if (!connection->Write(&sendFrame, sizeof(MessageFrameHeader) + length)) { + Close(); + return false; + } + return true; +} + +bool RpcConnection::Read(JsonDocument& message) +{ + if (state != State::Connected && state != State::SentHandshake) { + return false; + } + MessageFrame readFrame; + for (;;) { + bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader)); + if (!didRead) { + if (!connection->isOpen) { + lastErrorCode = (int)ErrorCode::PipeClosed; + StringCopy(lastErrorMessage, "Pipe closed"); + Close(); + } + return false; + } + + if (readFrame.length > 0) { + didRead = connection->Read(readFrame.message, readFrame.length); + if (!didRead) { + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Partial data in frame"); + Close(); + return false; + } + readFrame.message[readFrame.length] = 0; + } + + switch (readFrame.opcode) { + case Opcode::Close: { + message.ParseInsitu(readFrame.message); + lastErrorCode = GetIntMember(&message, "code"); + StringCopy(lastErrorMessage, GetStrMember(&message, "message", "")); + Close(); + return false; + } + case Opcode::Frame: + message.ParseInsitu(readFrame.message); + return true; + case Opcode::Ping: + readFrame.opcode = Opcode::Pong; + if (!connection->Write(&readFrame, sizeof(MessageFrameHeader) + readFrame.length)) { + Close(); + } + break; + case Opcode::Pong: + break; + case Opcode::Handshake: + default: + // something bad happened + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Bad ipc frame"); + Close(); + return false; + } + } +} diff --git a/libraries/discordrpc/src/rpc_connection.h b/libraries/discordrpc/src/rpc_connection.h new file mode 100644 index 000000000..bbdd05c79 --- /dev/null +++ b/libraries/discordrpc/src/rpc_connection.h @@ -0,0 +1,59 @@ +#pragma once + +#include "connection.h" +#include "serialization.h" + +// I took this from the buffer size libuv uses for named pipes; I suspect ours would usually be much +// smaller. +constexpr size_t MaxRpcFrameSize = 64 * 1024; + +struct RpcConnection { + enum class ErrorCode : int { + Success = 0, + PipeClosed = 1, + ReadCorrupt = 2, + }; + + enum class Opcode : uint32_t { + Handshake = 0, + Frame = 1, + Close = 2, + Ping = 3, + Pong = 4, + }; + + struct MessageFrameHeader { + Opcode opcode; + uint32_t length; + }; + + struct MessageFrame : public MessageFrameHeader { + char message[MaxRpcFrameSize - sizeof(MessageFrameHeader)]; + }; + + enum class State : uint32_t { + Disconnected, + SentHandshake, + AwaitingResponse, + Connected, + }; + + BaseConnection* connection{nullptr}; + State state{State::Disconnected}; + void (*onConnect)(JsonDocument& message){nullptr}; + void (*onDisconnect)(int errorCode, const char* message){nullptr}; + char appId[64]{}; + int lastErrorCode{0}; + char lastErrorMessage[256]{}; + RpcConnection::MessageFrame sendFrame; + + static RpcConnection* Create(const char* applicationId); + static void Destroy(RpcConnection*&); + + inline bool IsOpen() const { return state == State::Connected; } + + void Open(); + void Close(); + bool Write(const void* data, size_t length); + bool Read(JsonDocument& message); +}; diff --git a/libraries/discordrpc/src/serialization.cpp b/libraries/discordrpc/src/serialization.cpp new file mode 100644 index 000000000..70efa637f --- /dev/null +++ b/libraries/discordrpc/src/serialization.cpp @@ -0,0 +1,250 @@ +#include "serialization.h" +#include "connection.h" +#include "discord_rpc.h" + +template +void NumberToString(char* dest, T number) +{ + if (!number) { + *dest++ = '0'; + *dest++ = 0; + return; + } + if (number < 0) { + *dest++ = '-'; + number = -number; + } + char temp[32]; + int place = 0; + while (number) { + auto digit = number % 10; + number = number / 10; + temp[place++] = '0' + (char)digit; + } + for (--place; place >= 0; --place) { + *dest++ = temp[place]; + } + *dest = 0; +} + +// it's ever so slightly faster to not have to strlen the key +template +void WriteKey(JsonWriter& w, T& k) +{ + w.Key(k, sizeof(T) - 1); +} + +struct WriteObject { + JsonWriter& writer; + WriteObject(JsonWriter& w) + : writer(w) + { + writer.StartObject(); + } + template + WriteObject(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartObject(); + } + ~WriteObject() { writer.EndObject(); } +}; + +struct WriteArray { + JsonWriter& writer; + template + WriteArray(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartArray(); + } + ~WriteArray() { writer.EndArray(); } +}; + +template +void WriteOptionalString(JsonWriter& w, T& k, const char* value) +{ + if (value && value[0]) { + w.Key(k, sizeof(T) - 1); + w.String(value); + } +} + +static void JsonWriteNonce(JsonWriter& writer, int nonce) +{ + WriteKey(writer, "nonce"); + char nonceBuffer[32]; + NumberToString(nonceBuffer, nonce); + writer.String(nonceBuffer); +} + +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject top(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SET_ACTIVITY"); + + { + WriteObject args(writer, "args"); + + WriteKey(writer, "pid"); + writer.Int(pid); + + if (presence != nullptr) { + WriteObject activity(writer, "activity"); + + WriteOptionalString(writer, "state", presence->state); + WriteOptionalString(writer, "details", presence->details); + + if (presence->startTimestamp || presence->endTimestamp) { + WriteObject timestamps(writer, "timestamps"); + + if (presence->startTimestamp) { + WriteKey(writer, "start"); + writer.Int64(presence->startTimestamp); + } + + if (presence->endTimestamp) { + WriteKey(writer, "end"); + writer.Int64(presence->endTimestamp); + } + } + + if ((presence->largeImageKey && presence->largeImageKey[0]) || + (presence->largeImageText && presence->largeImageText[0]) || + (presence->smallImageKey && presence->smallImageKey[0]) || + (presence->smallImageText && presence->smallImageText[0])) { + WriteObject assets(writer, "assets"); + WriteOptionalString(writer, "large_image", presence->largeImageKey); + WriteOptionalString(writer, "large_text", presence->largeImageText); + WriteOptionalString(writer, "small_image", presence->smallImageKey); + WriteOptionalString(writer, "small_text", presence->smallImageText); + } + + if ((presence->partyId && presence->partyId[0]) || presence->partySize || + presence->partyMax || presence->partyPrivacy) { + WriteObject party(writer, "party"); + WriteOptionalString(writer, "id", presence->partyId); + if (presence->partySize && presence->partyMax) { + WriteArray size(writer, "size"); + writer.Int(presence->partySize); + writer.Int(presence->partyMax); + } + + if (presence->partyPrivacy) { + WriteKey(writer, "privacy"); + writer.Int(presence->partyPrivacy); + } + } + + if ((presence->matchSecret && presence->matchSecret[0]) || + (presence->joinSecret && presence->joinSecret[0]) || + (presence->spectateSecret && presence->spectateSecret[0])) { + WriteObject secrets(writer, "secrets"); + WriteOptionalString(writer, "match", presence->matchSecret); + WriteOptionalString(writer, "join", presence->joinSecret); + WriteOptionalString(writer, "spectate", presence->spectateSecret); + } + + writer.Key("instance"); + writer.Bool(presence->instance != 0); + } + } + } + + return writer.Size(); +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + WriteKey(writer, "v"); + writer.Int(version); + WriteKey(writer, "client_id"); + writer.String(applicationId); + } + + return writer.Size(); +} + +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("UNSUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + WriteKey(writer, "cmd"); + if (reply == DISCORD_REPLY_YES) { + writer.String("SEND_ACTIVITY_JOIN_INVITE"); + } + else { + writer.String("CLOSE_ACTIVITY_JOIN_REQUEST"); + } + + WriteKey(writer, "args"); + { + WriteObject args(writer); + + WriteKey(writer, "user_id"); + writer.String(userId); + } + + JsonWriteNonce(writer, nonce); + } + + return writer.Size(); +} diff --git a/libraries/discordrpc/src/serialization.h b/libraries/discordrpc/src/serialization.h new file mode 100644 index 000000000..ddea73b25 --- /dev/null +++ b/libraries/discordrpc/src/serialization.h @@ -0,0 +1,216 @@ +#pragma once + +#include + +#ifndef __MINGW32__ +#pragma warning(push) + +#pragma warning(disable : 4061) // enum is not explicitly handled by a case label +#pragma warning(disable : 4365) // signed/unsigned mismatch +#pragma warning(disable : 4464) // relative include path contains +#pragma warning(disable : 4668) // is not defined as a preprocessor macro +#pragma warning(disable : 6313) // Incorrect operator +#pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified +#endif // __MINGW32__ + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#ifndef __MINGW32__ +#pragma warning(pop) +#endif // __MINGW32__ + +// if only there was a standard library function for this +template +inline size_t StringCopy(char (&dest)[Len], const char* src) +{ + if (!src || !Len) { + return 0; + } + size_t copied; + char* out = dest; + for (copied = 1; *src && copied < Len; ++copied) { + *out++ = *src++; + } + *out = 0; + return copied - 1; +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId); + +// Commands +struct DiscordRichPresence; +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence); +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce); + +// I want to use as few allocations as I can get away with, and to do that with RapidJson, you need +// to supply some of your own allocators for stuff rather than use the defaults + +class LinearAllocator { +public: + char* buffer_; + char* end_; + LinearAllocator() + { + assert(0); // needed for some default case in rapidjson, should not use + } + LinearAllocator(char* buffer, size_t size) + : buffer_(buffer) + , end_(buffer + size) + { + } + static const bool kNeedFree = false; + void* Malloc(size_t size) + { + char* res = buffer_; + buffer_ += size; + if (buffer_ > end_) { + buffer_ = res; + return nullptr; + } + return res; + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + if (newSize == 0) { + return nullptr; + } + // allocate how much you need in the first place + assert(!originalPtr && !originalSize); + // unused parameter warning + (void)(originalPtr); + (void)(originalSize); + return Malloc(newSize); + } + static void Free(void* ptr) + { + /* shrug */ + (void)ptr; + } +}; + +template +class FixedLinearAllocator : public LinearAllocator { +public: + char fixedBuffer_[Size]; + FixedLinearAllocator() + : LinearAllocator(fixedBuffer_, Size) + { + } + static const bool kNeedFree = false; +}; + +// wonder why this isn't a thing already, maybe I missed it +class DirectStringBuffer { +public: + using Ch = char; + char* buffer_; + char* end_; + char* current_; + + DirectStringBuffer(char* buffer, size_t maxLen) + : buffer_(buffer) + , end_(buffer + maxLen) + , current_(buffer) + { + } + + void Put(char c) + { + if (current_ < end_) { + *current_++ = c; + } + } + void Flush() {} + size_t GetSize() const { return (size_t)(current_ - buffer_); } +}; + +using MallocAllocator = rapidjson::CrtAllocator; +using PoolAllocator = rapidjson::MemoryPoolAllocator; +using UTF8 = rapidjson::UTF8; +// Writer appears to need about 16 bytes per nested object level (with 64bit size_t) +using StackAllocator = FixedLinearAllocator<2048>; +constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t)); +using JsonWriterBase = + rapidjson::Writer; +class JsonWriter : public JsonWriterBase { +public: + DirectStringBuffer stringBuffer_; + StackAllocator stackAlloc_; + + JsonWriter(char* dest, size_t maxLen) + : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels) + , stringBuffer_(dest, maxLen) + , stackAlloc_() + { + } + + size_t Size() const { return stringBuffer_.GetSize(); } +}; + +using JsonDocumentBase = rapidjson::GenericDocument; +class JsonDocument : public JsonDocumentBase { +public: + static const int kDefaultChunkCapacity = 32 * 1024; + // json parser will use this buffer first, then allocate more if needed; I seriously doubt we + // send any messages that would use all of this, though. + char parseBuffer_[32 * 1024]; + MallocAllocator mallocAllocator_; + PoolAllocator poolAllocator_; + StackAllocator stackAllocator_; + JsonDocument() + : JsonDocumentBase(rapidjson::kObjectType, + &poolAllocator_, + sizeof(stackAllocator_.fixedBuffer_), + &stackAllocator_) + , poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_) + , stackAllocator_() + { + } +}; + +using JsonValue = rapidjson::GenericValue; + +inline JsonValue* GetObjMember(JsonValue* obj, const char* name) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsObject()) { + return &member->value; + } + } + return nullptr; +} + +inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsInt()) { + return member->value.GetInt(); + } + } + return notFoundDefault; +} + +inline const char* GetStrMember(JsonValue* obj, + const char* name, + const char* notFoundDefault = nullptr) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsString()) { + return member->value.GetString(); + } + } + return notFoundDefault; +} diff --git a/libraries/glslang/OGLCompilersDLL/CMakeLists.txt b/libraries/glslang/OGLCompilersDLL/CMakeLists.txt deleted file mode 100644 index 392fa7900..000000000 --- a/libraries/glslang/OGLCompilersDLL/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) - -make_release_only() -use_fast_math() - -# Request C++11 -if(${CMAKE_VERSION} VERSION_LESS 3.1) - # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD - # remove this block once CMake >=3.1 has fixated in the ecosystem - add_compile_options(-std=c++11) -else() - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) -endif() - -set(SOURCES InitializeDll.cpp InitializeDll.h) - -add_library(OGLCompiler STATIC ${SOURCES}) -set_property(TARGET OGLCompiler PROPERTY FOLDER glslang) -set_property(TARGET OGLCompiler PROPERTY POSITION_INDEPENDENT_CODE ON) - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OGLCompiler - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(ENABLE_GLSLANG_INSTALL) - diff --git a/libraries/glslang/glslang/CMakeLists.txt b/libraries/glslang/glslang/CMakeLists.txt deleted file mode 100644 index 30b57c588..000000000 --- a/libraries/glslang/glslang/CMakeLists.txt +++ /dev/null @@ -1,161 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) - -make_release_only() -use_fast_math() - -if(WIN32) - add_subdirectory(OSDependent/Windows) -elseif(UNIX) - add_subdirectory(OSDependent/Unix) -else(WIN32) - message("unknown platform") -endif(WIN32) - -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions) - add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. -elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable) - add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. -endif() - -# Request C++11 -if(${CMAKE_VERSION} VERSION_LESS 3.1) - # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD - # remove this block once CMake >=3.1 has fixated in the ecosystem - add_compile_options(-std=c++11) -else() - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) -endif() - -set(SOURCES - MachineIndependent/glslang.y - MachineIndependent/glslang_tab.cpp - MachineIndependent/attribute.cpp - MachineIndependent/Constant.cpp - MachineIndependent/iomapper.cpp - MachineIndependent/InfoSink.cpp - MachineIndependent/Initialize.cpp - MachineIndependent/IntermTraverse.cpp - MachineIndependent/Intermediate.cpp - MachineIndependent/ParseContextBase.cpp - MachineIndependent/ParseHelper.cpp - MachineIndependent/PoolAlloc.cpp - MachineIndependent/RemoveTree.cpp - MachineIndependent/Scan.cpp - MachineIndependent/ShaderLang.cpp - MachineIndependent/SymbolTable.cpp - MachineIndependent/Versions.cpp - MachineIndependent/intermOut.cpp - MachineIndependent/limits.cpp - MachineIndependent/linkValidate.cpp - MachineIndependent/parseConst.cpp - MachineIndependent/reflection.cpp - MachineIndependent/preprocessor/Pp.cpp - MachineIndependent/preprocessor/PpAtom.cpp - MachineIndependent/preprocessor/PpContext.cpp - MachineIndependent/preprocessor/PpScanner.cpp - MachineIndependent/preprocessor/PpTokens.cpp - MachineIndependent/propagateNoContraction.cpp - GenericCodeGen/CodeGen.cpp - GenericCodeGen/Link.cpp) - -set(HEADERS - Public/ShaderLang.h - Include/arrays.h - Include/BaseTypes.h - Include/Common.h - Include/ConstantUnion.h - Include/InfoSink.h - Include/InitializeGlobals.h - Include/intermediate.h - Include/PoolAlloc.h - Include/ResourceLimits.h - Include/revision.h - Include/ShHandle.h - Include/Types.h - MachineIndependent/attribute.h - MachineIndependent/glslang_tab.cpp.h - MachineIndependent/gl_types.h - MachineIndependent/Initialize.h - MachineIndependent/iomapper.h - MachineIndependent/LiveTraverser.h - MachineIndependent/localintermediate.h - MachineIndependent/ParseHelper.h - MachineIndependent/reflection.h - MachineIndependent/RemoveTree.h - MachineIndependent/Scan.h - MachineIndependent/ScanContext.h - MachineIndependent/SymbolTable.h - MachineIndependent/Versions.h - MachineIndependent/parseVersions.h - MachineIndependent/propagateNoContraction.h - MachineIndependent/preprocessor/PpContext.h - MachineIndependent/preprocessor/PpTokens.h) - -# This might be useful for making grammar changes: -# -# find_package(BISON) -# add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp.h -# COMMAND ${BISON_EXECUTABLE} --defines=${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp.h -t ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang.y -o ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp -# MAIN_DEPENDENCY MachineIndependent/glslang.y -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -# set(BISON_GLSLParser_OUTPUT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp) - -# Precompiled header macro. Parameters are source file list and filename for pch cpp file. -macro(glslang_pch SRCS PCHCPP) - if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio") - set(PCH_NAME "$(IntDir)\\pch.pch") - # make source files use/depend on PCH_NAME - set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}") - # make PCHCPP file compile and generate PCH_NAME - set_source_files_properties(${PCHCPP} PROPERTIES COMPILE_FLAGS "/Ycpch.h /Fp${PCH_NAME} /Zm300" OBJECT_OUTPUTS "${PCH_NAME}") - list(APPEND ${SRCS} "${PCHCPP}") - endif() -endmacro(glslang_pch) - -glslang_pch(SOURCES MachineIndependent/pch.cpp) - -add_library(glslang STATIC ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS}) -set_property(TARGET glslang PROPERTY FOLDER glslang) -set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) -target_link_libraries(glslang OGLCompiler OSDependent) -target_include_directories(glslang PUBLIC ..) - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(glslang PROPERTIES PREFIX "") -endif() - -if(ENABLE_HLSL) - target_link_libraries(glslang HLSL) -endif() - -if(WIN32) - source_group("Public" REGULAR_EXPRESSION "Public/*") - source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*") - source_group("Include" REGULAR_EXPRESSION "Include/[^/]*") - source_group("GenericCodeGen" REGULAR_EXPRESSION "GenericCodeGen/*") - source_group("MachineIndependent\\Preprocessor" REGULAR_EXPRESSION "MachineIndependent/preprocessor/*") -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - if(BUILD_SHARED_LIBS) - install(TARGETS glslang - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - else() - install(TARGETS glslang - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() -endif(ENABLE_GLSLANG_INSTALL) - -if(ENABLE_GLSLANG_INSTALL) - foreach(file ${HEADERS}) - get_filename_component(dir ${file} DIRECTORY) - install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir}) - endforeach() -endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/glslang/glslang/Include/revision.h b/libraries/glslang/glslang/Include/revision.h deleted file mode 100644 index a0e4b2066..000000000 --- a/libraries/glslang/glslang/Include/revision.h +++ /dev/null @@ -1,3 +0,0 @@ -// This header is generated by the make-revision script. - -#define GLSLANG_PATCH_LEVEL 3559 diff --git a/libraries/glslang/glslang/Include/revision.template b/libraries/glslang/glslang/Include/revision.template deleted file mode 100644 index 4a16beeb0..000000000 --- a/libraries/glslang/glslang/Include/revision.template +++ /dev/null @@ -1,13 +0,0 @@ -// The file revision.h should be updated to the latest version, somehow, on -// check-in, if glslang has changed. -// -// revision.template is the source for revision.h when using SubWCRev as the -// method of updating revision.h. You don't have to do it this way, the -// requirement is only that revision.h gets updated. -// -// revision.h is under source control so that not all consumers of glslang -// source have to figure out how to create revision.h just to get a build -// going. However, if it is not updated, it can be a version behind. - -#define GLSLANG_REVISION "$WCREV$" -#define GLSLANG_DATE "$WCDATE$" diff --git a/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp b/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp deleted file mode 100644 index d2967973d..000000000 --- a/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp +++ /dev/null @@ -1,10405 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - - 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 3 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. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.0.4" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 1 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* Copy the first part of user declarations. */ -#line 68 "MachineIndependent/glslang.y" /* yacc.c:339 */ - - -/* Based on: -ANSI C Yacc grammar - -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. - -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. - -Jutta Degener, 1995 -*/ - -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "../Public/ShaderLang.h" -#include "attribute.h" - -using namespace glslang; - - -#line 92 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339 */ - -# ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 1 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "glslang_tab.cpp.h". */ -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - CONST = 258, - BOOL = 259, - INT = 260, - UINT = 261, - FLOAT = 262, - BVEC2 = 263, - BVEC3 = 264, - BVEC4 = 265, - IVEC2 = 266, - IVEC3 = 267, - IVEC4 = 268, - UVEC2 = 269, - UVEC3 = 270, - UVEC4 = 271, - VEC2 = 272, - VEC3 = 273, - VEC4 = 274, - MAT2 = 275, - MAT3 = 276, - MAT4 = 277, - MAT2X2 = 278, - MAT2X3 = 279, - MAT2X4 = 280, - MAT3X2 = 281, - MAT3X3 = 282, - MAT3X4 = 283, - MAT4X2 = 284, - MAT4X3 = 285, - MAT4X4 = 286, - SAMPLER2D = 287, - SAMPLER3D = 288, - SAMPLERCUBE = 289, - SAMPLER2DSHADOW = 290, - SAMPLERCUBESHADOW = 291, - SAMPLER2DARRAY = 292, - SAMPLER2DARRAYSHADOW = 293, - ISAMPLER2D = 294, - ISAMPLER3D = 295, - ISAMPLERCUBE = 296, - ISAMPLER2DARRAY = 297, - USAMPLER2D = 298, - USAMPLER3D = 299, - USAMPLERCUBE = 300, - USAMPLER2DARRAY = 301, - SAMPLER = 302, - SAMPLERSHADOW = 303, - TEXTURE2D = 304, - TEXTURE3D = 305, - TEXTURECUBE = 306, - TEXTURE2DARRAY = 307, - ITEXTURE2D = 308, - ITEXTURE3D = 309, - ITEXTURECUBE = 310, - ITEXTURE2DARRAY = 311, - UTEXTURE2D = 312, - UTEXTURE3D = 313, - UTEXTURECUBE = 314, - UTEXTURE2DARRAY = 315, - ATTRIBUTE = 316, - VARYING = 317, - FLOAT16_T = 318, - FLOAT32_T = 319, - DOUBLE = 320, - FLOAT64_T = 321, - INT64_T = 322, - UINT64_T = 323, - INT32_T = 324, - UINT32_T = 325, - INT16_T = 326, - UINT16_T = 327, - INT8_T = 328, - UINT8_T = 329, - I64VEC2 = 330, - I64VEC3 = 331, - I64VEC4 = 332, - U64VEC2 = 333, - U64VEC3 = 334, - U64VEC4 = 335, - I32VEC2 = 336, - I32VEC3 = 337, - I32VEC4 = 338, - U32VEC2 = 339, - U32VEC3 = 340, - U32VEC4 = 341, - I16VEC2 = 342, - I16VEC3 = 343, - I16VEC4 = 344, - U16VEC2 = 345, - U16VEC3 = 346, - U16VEC4 = 347, - I8VEC2 = 348, - I8VEC3 = 349, - I8VEC4 = 350, - U8VEC2 = 351, - U8VEC3 = 352, - U8VEC4 = 353, - DVEC2 = 354, - DVEC3 = 355, - DVEC4 = 356, - DMAT2 = 357, - DMAT3 = 358, - DMAT4 = 359, - F16VEC2 = 360, - F16VEC3 = 361, - F16VEC4 = 362, - F16MAT2 = 363, - F16MAT3 = 364, - F16MAT4 = 365, - F32VEC2 = 366, - F32VEC3 = 367, - F32VEC4 = 368, - F32MAT2 = 369, - F32MAT3 = 370, - F32MAT4 = 371, - F64VEC2 = 372, - F64VEC3 = 373, - F64VEC4 = 374, - F64MAT2 = 375, - F64MAT3 = 376, - F64MAT4 = 377, - DMAT2X2 = 378, - DMAT2X3 = 379, - DMAT2X4 = 380, - DMAT3X2 = 381, - DMAT3X3 = 382, - DMAT3X4 = 383, - DMAT4X2 = 384, - DMAT4X3 = 385, - DMAT4X4 = 386, - F16MAT2X2 = 387, - F16MAT2X3 = 388, - F16MAT2X4 = 389, - F16MAT3X2 = 390, - F16MAT3X3 = 391, - F16MAT3X4 = 392, - F16MAT4X2 = 393, - F16MAT4X3 = 394, - F16MAT4X4 = 395, - F32MAT2X2 = 396, - F32MAT2X3 = 397, - F32MAT2X4 = 398, - F32MAT3X2 = 399, - F32MAT3X3 = 400, - F32MAT3X4 = 401, - F32MAT4X2 = 402, - F32MAT4X3 = 403, - F32MAT4X4 = 404, - F64MAT2X2 = 405, - F64MAT2X3 = 406, - F64MAT2X4 = 407, - F64MAT3X2 = 408, - F64MAT3X3 = 409, - F64MAT3X4 = 410, - F64MAT4X2 = 411, - F64MAT4X3 = 412, - F64MAT4X4 = 413, - ATOMIC_UINT = 414, - ACCSTRUCTNV = 415, - FCOOPMATNV = 416, - ICOOPMATNV = 417, - UCOOPMATNV = 418, - SAMPLERCUBEARRAY = 419, - SAMPLERCUBEARRAYSHADOW = 420, - ISAMPLERCUBEARRAY = 421, - USAMPLERCUBEARRAY = 422, - SAMPLER1D = 423, - SAMPLER1DARRAY = 424, - SAMPLER1DARRAYSHADOW = 425, - ISAMPLER1D = 426, - SAMPLER1DSHADOW = 427, - SAMPLER2DRECT = 428, - SAMPLER2DRECTSHADOW = 429, - ISAMPLER2DRECT = 430, - USAMPLER2DRECT = 431, - SAMPLERBUFFER = 432, - ISAMPLERBUFFER = 433, - USAMPLERBUFFER = 434, - SAMPLER2DMS = 435, - ISAMPLER2DMS = 436, - USAMPLER2DMS = 437, - SAMPLER2DMSARRAY = 438, - ISAMPLER2DMSARRAY = 439, - USAMPLER2DMSARRAY = 440, - SAMPLEREXTERNALOES = 441, - SAMPLEREXTERNAL2DY2YEXT = 442, - ISAMPLER1DARRAY = 443, - USAMPLER1D = 444, - USAMPLER1DARRAY = 445, - F16SAMPLER1D = 446, - F16SAMPLER2D = 447, - F16SAMPLER3D = 448, - F16SAMPLER2DRECT = 449, - F16SAMPLERCUBE = 450, - F16SAMPLER1DARRAY = 451, - F16SAMPLER2DARRAY = 452, - F16SAMPLERCUBEARRAY = 453, - F16SAMPLERBUFFER = 454, - F16SAMPLER2DMS = 455, - F16SAMPLER2DMSARRAY = 456, - F16SAMPLER1DSHADOW = 457, - F16SAMPLER2DSHADOW = 458, - F16SAMPLER1DARRAYSHADOW = 459, - F16SAMPLER2DARRAYSHADOW = 460, - F16SAMPLER2DRECTSHADOW = 461, - F16SAMPLERCUBESHADOW = 462, - F16SAMPLERCUBEARRAYSHADOW = 463, - IMAGE1D = 464, - IIMAGE1D = 465, - UIMAGE1D = 466, - IMAGE2D = 467, - IIMAGE2D = 468, - UIMAGE2D = 469, - IMAGE3D = 470, - IIMAGE3D = 471, - UIMAGE3D = 472, - IMAGE2DRECT = 473, - IIMAGE2DRECT = 474, - UIMAGE2DRECT = 475, - IMAGECUBE = 476, - IIMAGECUBE = 477, - UIMAGECUBE = 478, - IMAGEBUFFER = 479, - IIMAGEBUFFER = 480, - UIMAGEBUFFER = 481, - IMAGE1DARRAY = 482, - IIMAGE1DARRAY = 483, - UIMAGE1DARRAY = 484, - IMAGE2DARRAY = 485, - IIMAGE2DARRAY = 486, - UIMAGE2DARRAY = 487, - IMAGECUBEARRAY = 488, - IIMAGECUBEARRAY = 489, - UIMAGECUBEARRAY = 490, - IMAGE2DMS = 491, - IIMAGE2DMS = 492, - UIMAGE2DMS = 493, - IMAGE2DMSARRAY = 494, - IIMAGE2DMSARRAY = 495, - UIMAGE2DMSARRAY = 496, - F16IMAGE1D = 497, - F16IMAGE2D = 498, - F16IMAGE3D = 499, - F16IMAGE2DRECT = 500, - F16IMAGECUBE = 501, - F16IMAGE1DARRAY = 502, - F16IMAGE2DARRAY = 503, - F16IMAGECUBEARRAY = 504, - F16IMAGEBUFFER = 505, - F16IMAGE2DMS = 506, - F16IMAGE2DMSARRAY = 507, - TEXTURECUBEARRAY = 508, - ITEXTURECUBEARRAY = 509, - UTEXTURECUBEARRAY = 510, - TEXTURE1D = 511, - ITEXTURE1D = 512, - UTEXTURE1D = 513, - TEXTURE1DARRAY = 514, - ITEXTURE1DARRAY = 515, - UTEXTURE1DARRAY = 516, - TEXTURE2DRECT = 517, - ITEXTURE2DRECT = 518, - UTEXTURE2DRECT = 519, - TEXTUREBUFFER = 520, - ITEXTUREBUFFER = 521, - UTEXTUREBUFFER = 522, - TEXTURE2DMS = 523, - ITEXTURE2DMS = 524, - UTEXTURE2DMS = 525, - TEXTURE2DMSARRAY = 526, - ITEXTURE2DMSARRAY = 527, - UTEXTURE2DMSARRAY = 528, - F16TEXTURE1D = 529, - F16TEXTURE2D = 530, - F16TEXTURE3D = 531, - F16TEXTURE2DRECT = 532, - F16TEXTURECUBE = 533, - F16TEXTURE1DARRAY = 534, - F16TEXTURE2DARRAY = 535, - F16TEXTURECUBEARRAY = 536, - F16TEXTUREBUFFER = 537, - F16TEXTURE2DMS = 538, - F16TEXTURE2DMSARRAY = 539, - SUBPASSINPUT = 540, - SUBPASSINPUTMS = 541, - ISUBPASSINPUT = 542, - ISUBPASSINPUTMS = 543, - USUBPASSINPUT = 544, - USUBPASSINPUTMS = 545, - F16SUBPASSINPUT = 546, - F16SUBPASSINPUTMS = 547, - LEFT_OP = 548, - RIGHT_OP = 549, - INC_OP = 550, - DEC_OP = 551, - LE_OP = 552, - GE_OP = 553, - EQ_OP = 554, - NE_OP = 555, - AND_OP = 556, - OR_OP = 557, - XOR_OP = 558, - MUL_ASSIGN = 559, - DIV_ASSIGN = 560, - ADD_ASSIGN = 561, - MOD_ASSIGN = 562, - LEFT_ASSIGN = 563, - RIGHT_ASSIGN = 564, - AND_ASSIGN = 565, - XOR_ASSIGN = 566, - OR_ASSIGN = 567, - SUB_ASSIGN = 568, - LEFT_PAREN = 569, - RIGHT_PAREN = 570, - LEFT_BRACKET = 571, - RIGHT_BRACKET = 572, - LEFT_BRACE = 573, - RIGHT_BRACE = 574, - DOT = 575, - COMMA = 576, - COLON = 577, - EQUAL = 578, - SEMICOLON = 579, - BANG = 580, - DASH = 581, - TILDE = 582, - PLUS = 583, - STAR = 584, - SLASH = 585, - PERCENT = 586, - LEFT_ANGLE = 587, - RIGHT_ANGLE = 588, - VERTICAL_BAR = 589, - CARET = 590, - AMPERSAND = 591, - QUESTION = 592, - INVARIANT = 593, - HIGH_PRECISION = 594, - MEDIUM_PRECISION = 595, - LOW_PRECISION = 596, - PRECISION = 597, - PACKED = 598, - RESOURCE = 599, - SUPERP = 600, - FLOATCONSTANT = 601, - INTCONSTANT = 602, - UINTCONSTANT = 603, - BOOLCONSTANT = 604, - IDENTIFIER = 605, - TYPE_NAME = 606, - CENTROID = 607, - IN = 608, - OUT = 609, - INOUT = 610, - STRUCT = 611, - VOID = 612, - WHILE = 613, - BREAK = 614, - CONTINUE = 615, - DO = 616, - ELSE = 617, - FOR = 618, - IF = 619, - DISCARD = 620, - RETURN = 621, - SWITCH = 622, - CASE = 623, - DEFAULT = 624, - UNIFORM = 625, - SHARED = 626, - BUFFER = 627, - FLAT = 628, - SMOOTH = 629, - LAYOUT = 630, - DOUBLECONSTANT = 631, - INT16CONSTANT = 632, - UINT16CONSTANT = 633, - FLOAT16CONSTANT = 634, - INT32CONSTANT = 635, - UINT32CONSTANT = 636, - INT64CONSTANT = 637, - UINT64CONSTANT = 638, - SUBROUTINE = 639, - DEMOTE = 640, - PAYLOADNV = 641, - PAYLOADINNV = 642, - HITATTRNV = 643, - CALLDATANV = 644, - CALLDATAINNV = 645, - PATCH = 646, - SAMPLE = 647, - NONUNIFORM = 648, - COHERENT = 649, - VOLATILE = 650, - RESTRICT = 651, - READONLY = 652, - WRITEONLY = 653, - DEVICECOHERENT = 654, - QUEUEFAMILYCOHERENT = 655, - WORKGROUPCOHERENT = 656, - SUBGROUPCOHERENT = 657, - NONPRIVATE = 658, - NOPERSPECTIVE = 659, - EXPLICITINTERPAMD = 660, - PERVERTEXNV = 661, - PERPRIMITIVENV = 662, - PERVIEWNV = 663, - PERTASKNV = 664, - PRECISE = 665 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -union YYSTYPE -{ -#line 96 "MachineIndependent/glslang.y" /* yacc.c:355 */ - - struct { - glslang::TSourceLoc loc; - union { - glslang::TString *string; - int i; - unsigned int u; - long long i64; - unsigned long long u64; - bool b; - double d; - }; - glslang::TSymbol* symbol; - } lex; - struct { - glslang::TSourceLoc loc; - glslang::TOperator op; - union { - TIntermNode* intermNode; - glslang::TIntermNodePair nodePair; - glslang::TIntermTyped* intermTypedNode; - glslang::TAttributes* attributes; - }; - union { - glslang::TPublicType type; - glslang::TFunction* function; - glslang::TParameter param; - glslang::TTypeLoc typeLine; - glslang::TTypeList* typeList; - glslang::TArraySizes* arraySizes; - glslang::TIdentifierList* identifierList; - }; - glslang::TArraySizes* typeParameters; - } interm; - -#line 579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355 */ -}; - -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - - -int yyparse (glslang::TParseContext* pParseContext); - -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ - -/* Copy the second part of user declarations. */ -#line 132 "MachineIndependent/glslang.y" /* yacc.c:358 */ - - -/* windows only pragma */ -#ifdef _MSC_VER - #pragma warning(disable : 4065) - #pragma warning(disable : 4127) - #pragma warning(disable : 4244) -#endif - -#define parseContext (*pParseContext) -#define yyerror(context, msg) context->parserError(msg) - -extern int yylex(YYSTYPE*, TParseContext&); - - -#line 610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358 */ - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) -# else -# define YY_ATTRIBUTE(Spec) /* empty */ -# endif -#endif - -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 386 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 9369 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 411 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 111 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 582 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 727 - -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 665 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ -static const yytype_uint16 yytranslate[] = -{ - 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, 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, 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, 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, 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, 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, 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, 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, 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, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 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, 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 -}; - -#if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 352, 352, 358, 361, 366, 369, 372, 376, 380, - 384, 388, 392, 396, 400, 404, 408, 416, 419, 422, - 425, 428, 433, 441, 448, 455, 461, 465, 472, 475, - 481, 488, 498, 506, 511, 539, 548, 554, 558, 562, - 582, 583, 584, 585, 591, 592, 597, 602, 611, 612, - 617, 625, 626, 632, 641, 642, 647, 652, 657, 665, - 666, 675, 687, 688, 697, 698, 707, 708, 717, 718, - 726, 727, 735, 736, 744, 745, 745, 763, 764, 780, - 784, 788, 792, 797, 801, 805, 809, 813, 817, 821, - 828, 831, 842, 849, 854, 859, 866, 870, 874, 878, - 883, 888, 897, 897, 908, 912, 919, 926, 929, 936, - 944, 964, 987, 1002, 1027, 1038, 1048, 1058, 1068, 1077, - 1080, 1084, 1088, 1093, 1101, 1108, 1113, 1118, 1123, 1132, - 1142, 1169, 1178, 1185, 1193, 1200, 1207, 1215, 1225, 1232, - 1243, 1249, 1252, 1259, 1263, 1267, 1276, 1286, 1289, 1300, - 1303, 1306, 1310, 1314, 1319, 1323, 1330, 1334, 1339, 1345, - 1351, 1358, 1363, 1371, 1377, 1389, 1403, 1409, 1414, 1422, - 1430, 1438, 1446, 1453, 1457, 1462, 1467, 1472, 1477, 1482, - 1486, 1490, 1494, 1498, 1504, 1515, 1522, 1525, 1534, 1539, - 1549, 1554, 1562, 1566, 1576, 1579, 1585, 1591, 1598, 1608, - 1612, 1616, 1620, 1625, 1629, 1634, 1639, 1644, 1649, 1654, - 1659, 1664, 1669, 1674, 1680, 1686, 1692, 1697, 1702, 1707, - 1712, 1717, 1722, 1727, 1732, 1737, 1742, 1747, 1753, 1758, - 1763, 1768, 1773, 1778, 1783, 1788, 1793, 1798, 1803, 1808, - 1813, 1819, 1825, 1831, 1837, 1843, 1849, 1855, 1861, 1867, - 1873, 1879, 1885, 1891, 1897, 1903, 1909, 1915, 1921, 1927, - 1933, 1939, 1945, 1951, 1957, 1963, 1969, 1975, 1981, 1987, - 1993, 1999, 2005, 2011, 2017, 2023, 2029, 2035, 2041, 2047, - 2053, 2059, 2065, 2071, 2077, 2083, 2089, 2095, 2101, 2107, - 2113, 2119, 2125, 2131, 2137, 2143, 2149, 2155, 2161, 2167, - 2173, 2179, 2185, 2191, 2197, 2203, 2209, 2215, 2221, 2227, - 2233, 2239, 2245, 2251, 2257, 2263, 2269, 2275, 2281, 2287, - 2293, 2299, 2305, 2311, 2317, 2321, 2326, 2332, 2337, 2342, - 2347, 2352, 2357, 2362, 2368, 2373, 2378, 2383, 2388, 2393, - 2399, 2405, 2411, 2417, 2423, 2429, 2435, 2441, 2447, 2453, - 2459, 2465, 2471, 2477, 2482, 2487, 2492, 2497, 2502, 2507, - 2513, 2518, 2523, 2528, 2533, 2538, 2543, 2548, 2554, 2559, - 2564, 2569, 2574, 2579, 2584, 2589, 2594, 2599, 2604, 2609, - 2614, 2619, 2624, 2630, 2635, 2640, 2646, 2652, 2657, 2662, - 2667, 2673, 2678, 2683, 2688, 2694, 2699, 2704, 2709, 2715, - 2720, 2725, 2730, 2736, 2742, 2748, 2754, 2759, 2765, 2771, - 2777, 2782, 2787, 2792, 2797, 2802, 2808, 2813, 2818, 2823, - 2829, 2834, 2839, 2844, 2850, 2855, 2860, 2865, 2871, 2876, - 2881, 2886, 2892, 2897, 2902, 2907, 2913, 2918, 2923, 2928, - 2934, 2939, 2944, 2949, 2955, 2960, 2965, 2970, 2976, 2981, - 2986, 2991, 2997, 3002, 3007, 3012, 3018, 3023, 3028, 3033, - 3039, 3044, 3049, 3054, 3060, 3065, 3070, 3075, 3081, 3086, - 3091, 3096, 3102, 3107, 3112, 3118, 3124, 3130, 3136, 3143, - 3150, 3156, 3162, 3168, 3174, 3180, 3186, 3193, 3198, 3214, - 3219, 3224, 3232, 3232, 3243, 3243, 3253, 3256, 3269, 3291, - 3318, 3322, 3328, 3333, 3344, 3348, 3354, 3365, 3368, 3375, - 3379, 3380, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3394, - 3400, 3409, 3410, 3414, 3410, 3426, 3427, 3431, 3431, 3438, - 3438, 3452, 3455, 3463, 3471, 3482, 3483, 3487, 3491, 3498, - 3505, 3509, 3517, 3521, 3534, 3538, 3545, 3545, 3565, 3568, - 3574, 3586, 3598, 3602, 3609, 3609, 3624, 3624, 3640, 3640, - 3661, 3664, 3670, 3673, 3679, 3683, 3690, 3695, 3700, 3707, - 3710, 3719, 3723, 3732, 3735, 3739, 3748, 3748, 3771, 3777, - 3780, 3785, 3788 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || 1 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "CONST", "BOOL", "INT", "UINT", "FLOAT", - "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", "UVEC2", "UVEC3", - "UVEC4", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4", "MAT2X2", - "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", "MAT4X3", - "MAT4X4", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE", "SAMPLER2DSHADOW", - "SAMPLERCUBESHADOW", "SAMPLER2DARRAY", "SAMPLER2DARRAYSHADOW", - "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", "ISAMPLER2DARRAY", - "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER2DARRAY", "SAMPLER", - "SAMPLERSHADOW", "TEXTURE2D", "TEXTURE3D", "TEXTURECUBE", - "TEXTURE2DARRAY", "ITEXTURE2D", "ITEXTURE3D", "ITEXTURECUBE", - "ITEXTURE2DARRAY", "UTEXTURE2D", "UTEXTURE3D", "UTEXTURECUBE", - "UTEXTURE2DARRAY", "ATTRIBUTE", "VARYING", "FLOAT16_T", "FLOAT32_T", - "DOUBLE", "FLOAT64_T", "INT64_T", "UINT64_T", "INT32_T", "UINT32_T", - "INT16_T", "UINT16_T", "INT8_T", "UINT8_T", "I64VEC2", "I64VEC3", - "I64VEC4", "U64VEC2", "U64VEC3", "U64VEC4", "I32VEC2", "I32VEC3", - "I32VEC4", "U32VEC2", "U32VEC3", "U32VEC4", "I16VEC2", "I16VEC3", - "I16VEC4", "U16VEC2", "U16VEC3", "U16VEC4", "I8VEC2", "I8VEC3", "I8VEC4", - "U8VEC2", "U8VEC3", "U8VEC4", "DVEC2", "DVEC3", "DVEC4", "DMAT2", - "DMAT3", "DMAT4", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2", "F16MAT3", - "F16MAT4", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2", "F32MAT3", - "F32MAT4", "F64VEC2", "F64VEC3", "F64VEC4", "F64MAT2", "F64MAT3", - "F64MAT4", "DMAT2X2", "DMAT2X3", "DMAT2X4", "DMAT3X2", "DMAT3X3", - "DMAT3X4", "DMAT4X2", "DMAT4X3", "DMAT4X4", "F16MAT2X2", "F16MAT2X3", - "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2", - "F16MAT4X3", "F16MAT4X4", "F32MAT2X2", "F32MAT2X3", "F32MAT2X4", - "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", "F32MAT4X3", - "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", - "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", - "ATOMIC_UINT", "ACCSTRUCTNV", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", - "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", - "USAMPLERCUBEARRAY", "SAMPLER1D", "SAMPLER1DARRAY", - "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", "SAMPLER1DSHADOW", "SAMPLER2DRECT", - "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT", - "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLER2DMS", - "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", - "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", - "ISAMPLER1DARRAY", "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", - "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", - "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY", - "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY", - "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW", - "F16SAMPLER2DARRAYSHADOW", "F16SAMPLER2DRECTSHADOW", - "F16SAMPLERCUBESHADOW", "F16SAMPLERCUBEARRAYSHADOW", "IMAGE1D", - "IIMAGE1D", "UIMAGE1D", "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", - "IIMAGE3D", "UIMAGE3D", "IMAGE2DRECT", "IIMAGE2DRECT", "UIMAGE2DRECT", - "IMAGECUBE", "IIMAGECUBE", "UIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", - "UIMAGEBUFFER", "IMAGE1DARRAY", "IIMAGE1DARRAY", "UIMAGE1DARRAY", - "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBEARRAY", - "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "IMAGE2DMS", "IIMAGE2DMS", - "UIMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY", - "F16IMAGE1D", "F16IMAGE2D", "F16IMAGE3D", "F16IMAGE2DRECT", - "F16IMAGECUBE", "F16IMAGE1DARRAY", "F16IMAGE2DARRAY", - "F16IMAGECUBEARRAY", "F16IMAGEBUFFER", "F16IMAGE2DMS", - "F16IMAGE2DMSARRAY", "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY", - "UTEXTURECUBEARRAY", "TEXTURE1D", "ITEXTURE1D", "UTEXTURE1D", - "TEXTURE1DARRAY", "ITEXTURE1DARRAY", "UTEXTURE1DARRAY", "TEXTURE2DRECT", - "ITEXTURE2DRECT", "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER", - "UTEXTUREBUFFER", "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS", - "TEXTURE2DMSARRAY", "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY", - "F16TEXTURE1D", "F16TEXTURE2D", "F16TEXTURE3D", "F16TEXTURE2DRECT", - "F16TEXTURECUBE", "F16TEXTURE1DARRAY", "F16TEXTURE2DARRAY", - "F16TEXTURECUBEARRAY", "F16TEXTUREBUFFER", "F16TEXTURE2DMS", - "F16TEXTURE2DMSARRAY", "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT", - "ISUBPASSINPUTMS", "USUBPASSINPUT", "USUBPASSINPUTMS", "F16SUBPASSINPUT", - "F16SUBPASSINPUTMS", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", - "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", - "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", - "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", - "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", - "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", - "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION", - "INVARIANT", "HIGH_PRECISION", "MEDIUM_PRECISION", "LOW_PRECISION", - "PRECISION", "PACKED", "RESOURCE", "SUPERP", "FLOATCONSTANT", - "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", "IDENTIFIER", "TYPE_NAME", - "CENTROID", "IN", "OUT", "INOUT", "STRUCT", "VOID", "WHILE", "BREAK", - "CONTINUE", "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "SWITCH", - "CASE", "DEFAULT", "UNIFORM", "SHARED", "BUFFER", "FLAT", "SMOOTH", - "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT", "UINT16CONSTANT", - "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", "INT64CONSTANT", - "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV", "PAYLOADINNV", - "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PATCH", "SAMPLE", - "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY", - "WRITEONLY", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", - "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", "NOPERSPECTIVE", - "EXPLICITINTERPAMD", "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV", - "PERTASKNV", "PRECISE", "$accept", "variable_identifier", - "primary_expression", "postfix_expression", "integer_expression", - "function_call", "function_call_or_method", "function_call_generic", - "function_call_header_no_parameters", - "function_call_header_with_parameters", "function_call_header", - "function_identifier", "unary_expression", "unary_operator", - "multiplicative_expression", "additive_expression", "shift_expression", - "relational_expression", "equality_expression", "and_expression", - "exclusive_or_expression", "inclusive_or_expression", - "logical_and_expression", "logical_xor_expression", - "logical_or_expression", "conditional_expression", "$@1", - "assignment_expression", "assignment_operator", "expression", - "constant_expression", "declaration", "block_structure", "$@2", - "identifier_list", "function_prototype", "function_declarator", - "function_header_with_parameters", "function_header", - "parameter_declarator", "parameter_declaration", - "parameter_type_specifier", "init_declarator_list", "single_declaration", - "fully_specified_type", "invariant_qualifier", "interpolation_qualifier", - "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id", - "precise_qualifier", "type_qualifier", "single_type_qualifier", - "storage_qualifier", "non_uniform_qualifier", "type_name_list", - "type_specifier", "array_specifier", "type_parameter_specifier_opt", - "type_parameter_specifier", "type_parameter_specifier_list", - "type_specifier_nonarray", "precision_qualifier", "struct_specifier", - "$@3", "$@4", "struct_declaration_list", "struct_declaration", - "struct_declarator_list", "struct_declarator", "initializer", - "initializer_list", "declaration_statement", "statement", - "simple_statement", "demote_statement", "compound_statement", "$@5", - "$@6", "statement_no_new_scope", "statement_scoped", "$@7", "$@8", - "compound_statement_no_new_scope", "statement_list", - "expression_statement", "selection_statement", - "selection_statement_nonattributed", "selection_rest_statement", - "condition", "switch_statement", "switch_statement_nonattributed", "$@9", - "switch_statement_list", "case_label", "iteration_statement", - "iteration_statement_nonattributed", "$@10", "$@11", "$@12", - "for_init_statement", "conditionopt", "for_rest_statement", - "jump_statement", "translation_unit", "external_declaration", - "function_definition", "$@13", "attribute", "attribute_list", - "single_attribute", YY_NULLPTR -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 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, 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, 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, 596, 597, 598, 599, 600, 601, 602, 603, 604, - 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, - 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, - 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, - 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, - 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665 -}; -# endif - -#define YYPACT_NINF -453 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-453))) - -#define YYTABLE_NINF -528 - -#define yytable_value_is_error(Yytable_value) \ - 0 - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 3994, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, 97, -453, -453, -453, - -453, -453, 6, -453, -453, -453, -453, -453, -453, -307, - -241, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -3, 95, 36, - 125, 6034, 82, -453, -22, -453, -453, -453, -453, 4402, - -453, -453, -453, -453, 131, -453, -453, 730, -453, -453, - 11, -453, 153, -28, 127, -453, 7, -453, 157, -453, - 6034, -453, -453, -453, 6034, 129, 134, -453, 13, -453, - 73, -453, -453, 8391, 162, -453, -453, -453, 161, 6034, - -453, 163, -453, -309, -453, -453, 27, 6831, -453, 16, - 1138, -453, -453, -453, -453, 162, 23, -453, 7221, 49, - -453, 138, -453, 87, 8391, 8391, 8391, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, 68, -453, -453, -453, - 174, 60, 8781, 176, -453, 8391, -453, -453, -320, 175, - -453, 6034, 142, 4810, -453, 6034, 8391, -453, -28, -453, - 143, -453, -453, 119, 128, 32, 21, 38, 158, 160, - 165, 195, 194, 18, 183, 7611, -453, 185, 184, -453, - -453, 188, 180, 181, -453, 196, 197, 190, 8001, 198, - 8391, 187, 193, 122, -453, -453, 91, -453, 95, 204, - 205, -453, -453, -453, -453, -453, 1546, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -353, 175, 7221, 69, - 7221, -453, -453, 7221, 6034, -453, 170, -453, -453, -453, - 78, -453, -453, 8391, 171, -453, -453, 8391, 207, -453, - -453, -453, 8391, -453, 142, 162, 93, -453, -453, -453, - 5218, -453, -453, -453, -453, 8391, 8391, 8391, 8391, 8391, - 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, - 8391, 8391, 8391, 8391, -453, -453, -453, 206, 177, -453, - 1954, -453, -453, -453, 1954, -453, 8391, -453, -453, 100, - 8391, 144, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, 8391, 8391, -453, -453, -453, - -453, -453, -453, -453, 7221, -453, 140, -453, 5626, -453, - -453, 209, 208, -453, -453, -453, 123, 175, 142, -453, - -453, -453, -453, -453, 119, 119, 128, 128, 32, 32, - 32, 32, 21, 21, 38, 158, 160, 165, 195, 194, - 8391, -453, 214, 56, -453, 1954, 3586, 172, 3178, 80, - -453, 81, -453, -453, -453, -453, -453, 6441, -453, -453, - -453, -453, 146, 8391, 215, 177, 212, 208, 186, 6034, - 219, 221, -453, -453, 3586, 220, -453, -453, -453, 8391, - 222, -453, -453, -453, 216, 2362, 8391, -453, 217, 227, - 182, 225, 2770, -453, 229, -453, -453, 7221, -453, -453, - -453, 89, 8391, 2362, 220, -453, -453, 1954, -453, 224, - 208, -453, -453, 1954, 226, -453, -453 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint16 yydefact[] = -{ - 0, 156, 203, 201, 202, 200, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 204, 205, 206, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 327, 328, 329, 330, 331, 332, 333, 353, 354, 355, - 356, 357, 358, 359, 368, 381, 382, 369, 370, 372, - 371, 373, 374, 375, 376, 377, 378, 379, 380, 164, - 165, 229, 230, 228, 231, 238, 239, 236, 237, 234, - 235, 232, 233, 261, 262, 263, 273, 274, 275, 258, - 259, 260, 270, 271, 272, 255, 256, 257, 267, 268, - 269, 252, 253, 254, 264, 265, 266, 240, 241, 242, - 276, 277, 278, 243, 244, 245, 288, 289, 290, 246, - 247, 248, 300, 301, 302, 249, 250, 251, 312, 313, - 314, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 325, 324, 484, - 485, 486, 337, 338, 361, 364, 326, 335, 336, 352, - 334, 383, 384, 387, 388, 389, 391, 392, 393, 395, - 396, 397, 399, 400, 474, 475, 360, 362, 363, 339, - 340, 341, 385, 342, 346, 347, 350, 390, 394, 398, - 343, 344, 348, 349, 386, 345, 351, 430, 432, 433, - 434, 436, 437, 438, 440, 441, 442, 444, 445, 446, - 448, 449, 450, 452, 453, 454, 456, 457, 458, 460, - 461, 462, 464, 465, 466, 468, 469, 470, 472, 473, - 431, 435, 439, 443, 447, 455, 459, 463, 451, 467, - 471, 365, 366, 367, 401, 410, 412, 406, 411, 413, - 414, 416, 417, 418, 420, 421, 422, 424, 425, 426, - 428, 429, 402, 403, 404, 415, 405, 407, 408, 409, - 419, 423, 427, 476, 477, 480, 481, 482, 483, 478, - 479, 575, 131, 489, 490, 491, 0, 488, 160, 158, - 159, 157, 0, 199, 161, 162, 163, 133, 132, 0, - 183, 169, 170, 168, 171, 172, 166, 167, 185, 173, - 179, 180, 181, 182, 174, 175, 176, 177, 178, 134, - 135, 136, 137, 138, 139, 146, 574, 0, 576, 0, - 108, 107, 0, 119, 124, 153, 152, 150, 154, 0, - 147, 149, 155, 129, 195, 151, 487, 0, 571, 573, - 0, 494, 0, 0, 0, 96, 0, 93, 0, 106, - 0, 115, 109, 117, 0, 118, 0, 94, 125, 99, - 0, 148, 130, 0, 188, 194, 1, 572, 0, 0, - 492, 143, 145, 0, 141, 186, 0, 0, 97, 0, - 0, 577, 110, 114, 116, 112, 120, 111, 0, 126, - 102, 0, 100, 0, 0, 0, 0, 42, 41, 43, - 40, 5, 6, 7, 8, 2, 15, 13, 14, 16, - 9, 10, 11, 12, 3, 17, 36, 19, 24, 25, - 0, 0, 29, 0, 197, 0, 35, 33, 0, 189, - 95, 0, 0, 0, 496, 0, 0, 140, 0, 184, - 0, 190, 44, 48, 51, 54, 59, 62, 64, 66, - 68, 70, 72, 74, 0, 0, 98, 0, 522, 531, - 535, 0, 0, 0, 556, 0, 0, 0, 0, 0, - 0, 0, 0, 44, 77, 90, 0, 509, 0, 155, - 129, 512, 533, 511, 519, 510, 0, 513, 514, 537, - 515, 544, 516, 517, 552, 518, 0, 113, 0, 121, - 0, 504, 128, 0, 0, 104, 0, 101, 37, 38, - 0, 21, 22, 0, 0, 27, 26, 0, 199, 30, - 32, 39, 0, 196, 0, 502, 0, 500, 495, 497, - 0, 92, 144, 142, 187, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 75, 191, 192, 0, 0, 521, - 0, 554, 567, 566, 0, 558, 0, 570, 568, 0, - 0, 0, 551, 520, 80, 81, 83, 82, 85, 86, - 87, 88, 89, 84, 79, 0, 0, 536, 532, 534, - 538, 545, 553, 123, 0, 507, 0, 127, 0, 105, - 4, 0, 23, 20, 31, 198, 0, 503, 0, 498, - 493, 45, 46, 47, 50, 49, 52, 53, 57, 58, - 55, 56, 60, 61, 63, 65, 67, 69, 71, 73, - 0, 193, 581, 0, 579, 523, 0, 0, 0, 0, - 569, 0, 550, 78, 91, 122, 505, 0, 103, 18, - 499, 501, 0, 0, 0, 0, 0, 542, 0, 0, - 0, 0, 561, 560, 563, 529, 546, 506, 508, 0, - 0, 578, 580, 524, 0, 0, 0, 562, 0, 0, - 541, 0, 0, 539, 0, 76, 582, 0, 526, 555, - 525, 0, 564, 0, 529, 528, 530, 548, 543, 0, - 565, 559, 540, 549, 0, 557, 547 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, 8696, -453, -89, -88, -122, -84, -19, -18, - -17, -16, -20, -15, -453, -85, -453, -98, -453, -110, - -119, 2, -453, -453, -453, 4, -453, -453, -453, 189, - 191, 192, -453, -453, -339, -453, -453, -453, -453, 98, - -453, -37, -44, -453, 9, -453, 0, -71, -453, -453, - -453, -453, 261, -453, -453, -453, -452, -137, 20, -68, - -209, -453, -96, -198, -326, -453, -136, -453, -453, -146, - -144, -453, -453, 200, -265, -87, -453, 57, -453, -112, - -453, 59, -453, -453, -453, -453, 61, -453, -453, -453, - -453, -453, -453, -453, -453, 228, -453, -453, -453, -453, - -99 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 434, 435, 436, 621, 437, 438, 439, 440, 441, - 442, 443, 493, 445, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 494, 650, 495, 605, 496, - 552, 497, 337, 524, 413, 498, 339, 340, 341, 371, - 372, 373, 342, 343, 344, 345, 346, 347, 393, 394, - 348, 349, 350, 351, 446, 396, 447, 399, 384, 385, - 448, 354, 355, 356, 455, 389, 453, 454, 546, 547, - 522, 616, 501, 502, 503, 504, 505, 580, 676, 709, - 700, 701, 702, 710, 506, 507, 508, 509, 703, 680, - 510, 511, 704, 724, 512, 513, 514, 656, 584, 658, - 684, 698, 699, 515, 357, 358, 359, 368, 516, 653, - 654 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 353, 542, 336, 550, 338, 481, 457, 363, 484, 352, - 485, 486, 458, 543, 489, 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, 618, 364, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 374, 381, 530, 409, 609, 613, - 521, 615, 474, 449, 617, 655, 549, 678, 562, 563, - 573, 365, 391, 397, 361, 560, 561, 407, 378, 397, - 381, 398, 475, 374, 517, 519, 408, 566, 567, 397, - 476, 375, 459, 392, 539, 678, 518, 366, 460, 382, - 352, 369, 451, 564, 565, 574, 362, 353, 352, 336, - 388, 338, 297, 531, 532, 475, 352, 302, 303, 708, - 375, 551, 523, 674, 375, 536, 716, 675, 589, 352, - 591, 537, -34, 352, 533, 475, 657, 708, 534, 452, - 577, 410, 614, 620, 411, 685, 686, 412, 352, 606, - 500, 606, 606, 376, 719, 665, 377, 381, 526, 499, - 606, 527, 606, 549, 628, 607, 451, 629, 451, 367, - 521, 606, 521, 622, 660, 521, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 293, 294, 295, 624, - 638, 639, 640, 641, 628, 604, 370, 670, 555, 556, - 557, 544, 723, 452, 558, 452, 559, 609, 688, 666, - 352, 667, 352, 383, 352, 606, 662, 606, 689, 634, - 635, 390, 636, 637, 627, 400, 659, 395, 397, 405, - 661, 549, 642, 643, 406, 450, 456, 451, 525, 535, - 540, 475, 545, 554, 568, 569, 571, 572, 718, 570, - 575, 578, 581, 579, 582, 583, 500, 663, 664, 592, - 585, 586, 590, 451, 587, 499, 521, 593, -35, -33, - 619, 623, -28, 651, 452, 609, 669, 652, 673, 606, - 681, 693, 691, 352, 695, 696, 694, 706, -527, 707, - 672, 712, 713, 478, 714, 726, 677, 717, 725, 644, - 452, 645, 648, 646, 690, 647, 553, 360, 649, 352, - 671, 402, 682, 403, 626, 715, 404, 721, 401, 521, - 722, 683, 697, 610, 677, 611, 692, 612, 0, 0, - 500, 451, 0, 0, 500, 387, 711, 0, 551, 499, - 0, 705, 0, 499, 0, 0, 0, 0, 0, 0, - 0, 0, 720, 0, 0, 0, 0, 0, 0, 521, - 0, 0, 0, 0, 0, 0, 0, 0, 452, 679, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 679, 0, 0, - 0, 0, 0, 0, 0, 500, 500, 0, 500, 0, - 0, 0, 0, 0, 499, 499, 0, 499, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 382, - 0, 0, 0, 0, 500, 0, 0, 0, 352, 0, - 0, 0, 0, 499, 0, 500, 0, 0, 0, 0, - 0, 0, 500, 0, 499, 0, 0, 0, 0, 0, - 0, 499, 0, 500, 0, 0, 0, 500, 0, 0, - 0, 0, 499, 500, 0, 0, 499, 0, 0, 0, - 386, 0, 499, 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, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 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, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 296, 0, 0, 0, 0, 0, 0, 0, - 0, 297, 298, 299, 300, 301, 302, 303, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 304, 305, 306, 307, 308, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 310, 0, 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, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, 0, 0, 414, 415, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 477, 0, 478, 479, 0, 0, - 0, 0, 480, 417, 418, 419, 420, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 296, 0, 0, 0, 421, 422, 423, 424, 425, 297, - 298, 299, 300, 301, 302, 303, 481, 482, 483, 484, - 0, 485, 486, 487, 488, 489, 490, 491, 304, 305, - 306, 307, 308, 309, 426, 427, 428, 429, 430, 431, - 432, 433, 310, 492, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, - 0, 414, 415, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 477, 0, 478, 608, 0, 0, 0, 0, - 480, 417, 418, 419, 420, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 296, 0, - 0, 0, 421, 422, 423, 424, 425, 297, 298, 299, - 300, 301, 302, 303, 481, 482, 483, 484, 0, 485, - 486, 487, 488, 489, 490, 491, 304, 305, 306, 307, - 308, 309, 426, 427, 428, 429, 430, 431, 432, 433, - 310, 492, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 414, - 415, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, - 477, 0, 478, 0, 0, 0, 0, 0, 480, 417, - 418, 419, 420, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 296, 0, 0, 0, - 421, 422, 423, 424, 425, 297, 298, 299, 300, 301, - 302, 303, 481, 482, 483, 484, 0, 485, 486, 487, - 488, 489, 490, 491, 304, 305, 306, 307, 308, 309, - 426, 427, 428, 429, 430, 431, 432, 433, 310, 492, - 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 477, 0, - 400, 0, 0, 0, 0, 0, 480, 417, 418, 419, - 420, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 292, 293, 294, 295, 296, 0, 0, 0, 421, 422, - 423, 424, 425, 297, 298, 299, 300, 301, 302, 303, - 481, 482, 483, 484, 0, 485, 486, 487, 488, 489, - 490, 491, 304, 305, 306, 307, 308, 309, 426, 427, - 428, 429, 430, 431, 432, 433, 310, 492, 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, 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, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 477, 0, 0, 0, - 0, 0, 0, 0, 480, 417, 418, 419, 420, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 296, 0, 0, 0, 421, 422, 423, 424, - 425, 297, 298, 299, 300, 301, 302, 303, 481, 482, - 483, 484, 0, 485, 486, 487, 488, 489, 490, 491, - 304, 305, 306, 307, 308, 309, 426, 427, 428, 429, - 430, 431, 432, 433, 310, 492, 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, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, 0, 0, 414, 415, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 480, 417, 418, 419, 420, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 296, 0, 0, 0, 421, 422, 423, 424, 425, 297, - 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 304, 305, - 306, 307, 308, 309, 426, 427, 428, 429, 430, 431, - 432, 433, 310, 0, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, - 0, 414, 415, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 417, 418, 419, 420, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 0, 0, - 0, 0, 421, 422, 423, 424, 425, 297, 298, 299, - 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, - 308, 309, 426, 427, 428, 429, 430, 431, 432, 433, - 310, 0, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 296, 0, 0, 0, - 0, 0, 0, 0, 0, 297, 298, 299, 300, 301, - 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, - 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, - 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 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, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 292, 293, 294, 295, 0, 0, 0, 0, 0, 0, - 0, 0, 380, 297, 298, 299, 300, 301, 302, 303, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 304, 305, 306, 307, 308, 309, 0, 0, - 0, 0, 0, 0, 0, 0, 310, 0, 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, 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, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 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, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 297, 298, 299, 300, 301, 302, 303, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 304, 305, 306, 307, 308, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 310, 0, 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, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, - 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 304, 305, - 306, 307, 308, 309, 0, 0, 0, 0, 0, 0, - 0, 0, 310, 0, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 668, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 297, 298, 299, - 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, - 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, - 310, 0, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 297, 298, 299, 300, 301, - 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, - 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, - 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, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 520, - 687, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 461, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 520, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 576, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 588, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 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, 0, 0, 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, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 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, 0, 0, 414, 415, 0, 444, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 462, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 538, 0, - 0, 541, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 462, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 462, 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, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 631, 632, 633, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 462 -}; - -static const yytype_int16 yycheck[] = -{ - 0, 321, 0, 455, 0, 358, 315, 314, 361, 0, - 363, 364, 321, 333, 367, 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, 524, 314, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, 341, 349, 416, 378, 506, 518, - 408, 520, 397, 384, 523, 580, 453, 656, 297, 298, - 302, 324, 350, 316, 318, 293, 294, 314, 350, 316, - 374, 324, 316, 370, 405, 406, 323, 299, 300, 316, - 324, 341, 315, 371, 442, 684, 323, 350, 321, 349, - 341, 315, 389, 332, 333, 337, 350, 357, 349, 357, - 360, 357, 351, 295, 296, 316, 357, 356, 357, 695, - 370, 456, 323, 317, 374, 315, 702, 321, 488, 370, - 490, 321, 314, 374, 316, 316, 584, 713, 320, 389, - 475, 318, 323, 315, 321, 315, 315, 324, 389, 321, - 400, 321, 321, 321, 315, 614, 324, 451, 321, 400, - 321, 324, 321, 550, 321, 324, 453, 324, 455, 324, - 518, 321, 520, 533, 324, 523, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 339, 340, 341, 537, - 562, 563, 564, 565, 321, 323, 321, 324, 329, 330, - 331, 451, 717, 453, 326, 455, 328, 655, 667, 319, - 451, 321, 453, 332, 455, 321, 322, 321, 322, 558, - 559, 318, 560, 561, 545, 318, 586, 350, 316, 350, - 590, 618, 566, 567, 350, 324, 323, 524, 350, 315, - 314, 316, 350, 350, 336, 335, 301, 303, 707, 334, - 317, 316, 314, 319, 324, 324, 506, 605, 606, 322, - 314, 314, 314, 550, 324, 506, 614, 324, 314, 314, - 350, 350, 315, 317, 524, 723, 317, 350, 314, 321, - 358, 319, 317, 524, 315, 314, 350, 315, 318, 323, - 650, 324, 315, 318, 362, 319, 656, 318, 324, 568, - 550, 569, 572, 570, 673, 571, 458, 296, 573, 550, - 628, 370, 658, 374, 544, 701, 374, 713, 368, 667, - 714, 658, 684, 516, 684, 516, 675, 516, -1, -1, - 580, 618, -1, -1, 584, 357, 696, -1, 673, 580, - -1, 689, -1, 584, -1, -1, -1, -1, -1, -1, - -1, -1, 712, -1, -1, -1, -1, -1, -1, 707, - -1, -1, -1, -1, -1, -1, -1, -1, 618, 656, - -1, -1, -1, -1, -1, -1, -1, 618, -1, -1, - -1, -1, -1, -1, -1, 679, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 684, -1, -1, - -1, -1, -1, -1, -1, 655, 656, -1, 658, -1, - -1, -1, -1, -1, 655, 656, -1, 658, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 679, - -1, -1, -1, -1, 684, -1, -1, -1, 679, -1, - -1, -1, -1, 684, -1, 695, -1, -1, -1, -1, - -1, -1, 702, -1, 695, -1, -1, -1, -1, -1, - -1, 702, -1, 713, -1, -1, -1, 717, -1, -1, - -1, -1, 713, 723, -1, -1, 717, -1, -1, -1, - 0, -1, 723, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, -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, 324, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, 342, -1, -1, -1, -1, -1, -1, -1, - -1, 351, 352, 353, 354, 355, 356, 357, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 370, 371, 372, 373, 374, 375, -1, -1, -1, -1, - -1, -1, -1, -1, 384, -1, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, 295, 296, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, - -1, -1, 324, 325, 326, 327, 328, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - 342, -1, -1, -1, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - -1, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, -1, - -1, 295, 296, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 314, -1, 316, -1, 318, 319, -1, -1, -1, -1, - 324, 325, 326, 327, 328, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, 342, -1, - -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 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, -1, -1, 295, - 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, - 316, -1, 318, -1, -1, -1, -1, -1, 324, 325, - 326, 327, 328, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 338, 339, 340, 341, 342, -1, -1, -1, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, -1, 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, 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, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 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, -1, -1, 295, 296, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 314, -1, 316, -1, - 318, -1, -1, -1, -1, -1, 324, 325, 326, 327, - 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 338, 339, 340, 341, 342, -1, -1, -1, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, -1, 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, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, -1, -1, 295, 296, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 314, -1, 316, -1, -1, -1, - -1, -1, -1, -1, 324, 325, 326, 327, 328, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, 342, -1, -1, -1, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, -1, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, -1, -1, 295, 296, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 324, 325, 326, 327, 328, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - 342, -1, -1, -1, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, -1, - -1, 295, 296, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 325, 326, 327, 328, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, -1, -1, - -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 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, -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, 324, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 338, 339, 340, 341, 342, -1, -1, -1, - -1, -1, -1, -1, -1, 351, 352, 353, 354, 355, - 356, 357, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 370, 371, 372, 373, 374, 375, - -1, -1, -1, -1, -1, -1, -1, -1, 384, -1, - 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, 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, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 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, -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, 324, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 338, 339, 340, 341, -1, -1, -1, -1, -1, -1, - -1, -1, 350, 351, 352, 353, 354, 355, 356, 357, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 370, 371, 372, 373, 374, 375, -1, -1, - -1, -1, -1, -1, -1, -1, 384, -1, 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, 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, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 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, -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, 319, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 351, 352, 353, 354, 355, 356, 357, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 370, 371, 372, 373, 374, 375, -1, -1, -1, -1, - -1, -1, -1, -1, 384, -1, 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, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, -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, 319, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 351, - 352, 353, 354, 355, 356, 357, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 370, 371, - 372, 373, 374, 375, -1, -1, -1, -1, -1, -1, - -1, -1, 384, -1, 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, 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, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 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, -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, 319, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 351, 352, 353, - 354, 355, 356, 357, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 370, 371, 372, 373, - 374, 375, -1, -1, -1, -1, -1, -1, -1, -1, - 384, -1, 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, 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, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 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, -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, 338, 339, 340, 341, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 351, 352, 353, 354, 355, - 356, 357, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 370, 371, 372, 373, 374, 375, - -1, -1, -1, -1, -1, -1, -1, -1, 384, -1, - 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, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, 318, - 319, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, 317, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, 318, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, 317, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 324, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 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, -1, -1, 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, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 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, -1, -1, 295, 296, -1, 383, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 397, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, 445, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 456, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, 475, -1, -1, 393, -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, 542, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 555, 556, 557, 558, 559, 560, 561, 562, 563, - 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, - -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, 673 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = -{ - 0, 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, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 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, 324, 338, 339, 340, 341, 342, 351, 352, 353, - 354, 355, 356, 357, 370, 371, 372, 373, 374, 375, - 384, 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, 442, 443, 446, 447, - 448, 449, 453, 454, 455, 456, 457, 458, 461, 462, - 463, 464, 465, 467, 472, 473, 474, 515, 516, 517, - 473, 318, 350, 314, 314, 324, 350, 324, 518, 315, - 321, 450, 451, 452, 462, 467, 321, 324, 350, 324, - 350, 463, 467, 332, 469, 470, 0, 516, 467, 476, - 318, 350, 371, 459, 460, 350, 466, 316, 324, 468, - 318, 494, 451, 450, 452, 350, 350, 314, 323, 468, - 318, 321, 324, 445, 295, 296, 314, 325, 326, 327, - 328, 346, 347, 348, 349, 350, 376, 377, 378, 379, - 380, 381, 382, 383, 412, 413, 414, 416, 417, 418, - 419, 420, 421, 422, 423, 424, 465, 467, 471, 468, - 324, 462, 467, 477, 478, 475, 323, 315, 321, 315, - 321, 317, 423, 425, 426, 427, 428, 429, 430, 431, - 432, 433, 434, 435, 436, 316, 324, 316, 318, 319, - 324, 358, 359, 360, 361, 363, 364, 365, 366, 367, - 368, 369, 385, 423, 436, 438, 440, 442, 446, 465, - 467, 483, 484, 485, 486, 487, 495, 496, 497, 498, - 501, 502, 505, 506, 507, 514, 519, 468, 323, 468, - 318, 438, 481, 323, 444, 350, 321, 324, 423, 423, - 440, 295, 296, 316, 320, 315, 315, 321, 357, 438, - 314, 423, 321, 333, 467, 350, 479, 480, 319, 478, - 477, 436, 441, 460, 350, 329, 330, 331, 326, 328, - 293, 294, 297, 298, 332, 333, 299, 300, 336, 335, - 334, 301, 303, 302, 337, 317, 317, 436, 316, 319, - 488, 314, 324, 324, 509, 314, 314, 324, 324, 440, - 314, 440, 322, 324, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 323, 439, 321, 324, 319, 484, - 498, 502, 507, 481, 323, 481, 482, 481, 477, 350, - 315, 415, 440, 350, 438, 423, 479, 468, 321, 324, - 319, 423, 423, 423, 425, 425, 426, 426, 427, 427, - 427, 427, 428, 428, 429, 430, 431, 432, 433, 434, - 437, 317, 350, 520, 521, 495, 508, 484, 510, 440, - 324, 440, 322, 438, 438, 481, 319, 321, 319, 317, - 324, 480, 440, 314, 317, 321, 489, 440, 455, 462, - 500, 358, 483, 496, 511, 315, 315, 319, 481, 322, - 441, 317, 521, 319, 350, 315, 314, 500, 512, 513, - 491, 492, 493, 499, 503, 438, 315, 323, 485, 490, - 494, 440, 324, 315, 362, 487, 485, 318, 481, 315, - 440, 490, 491, 495, 504, 324, 319 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = -{ - 0, 411, 412, 413, 413, 413, 413, 413, 413, 413, - 413, 413, 413, 413, 413, 413, 413, 414, 414, 414, - 414, 414, 414, 415, 416, 417, 418, 418, 419, 419, - 420, 420, 421, 422, 422, 422, 423, 423, 423, 423, - 424, 424, 424, 424, 425, 425, 425, 425, 426, 426, - 426, 427, 427, 427, 428, 428, 428, 428, 428, 429, - 429, 429, 430, 430, 431, 431, 432, 432, 433, 433, - 434, 434, 435, 435, 436, 437, 436, 438, 438, 439, - 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, - 440, 440, 441, 442, 442, 442, 442, 442, 442, 442, - 442, 442, 444, 443, 445, 445, 446, 447, 447, 448, - 448, 449, 450, 450, 451, 451, 451, 451, 452, 453, - 453, 453, 453, 453, 454, 454, 454, 454, 454, 455, - 455, 456, 457, 457, 457, 457, 457, 457, 457, 457, - 458, 459, 459, 460, 460, 460, 461, 462, 462, 463, - 463, 463, 463, 463, 463, 463, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 465, 466, 466, 467, 467, - 468, 468, 468, 468, 469, 469, 470, 471, 471, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 473, - 473, 473, 475, 474, 476, 474, 477, 477, 478, 478, - 479, 479, 480, 480, 481, 481, 481, 482, 482, 483, - 484, 484, 485, 485, 485, 485, 485, 485, 485, 485, - 486, 487, 488, 489, 487, 490, 490, 492, 491, 493, - 491, 494, 494, 495, 495, 496, 496, 497, 497, 498, - 499, 499, 500, 500, 501, 501, 503, 502, 504, 504, - 505, 505, 506, 506, 508, 507, 509, 507, 510, 507, - 511, 511, 512, 512, 513, 513, 514, 514, 514, 514, - 514, 515, 515, 516, 516, 516, 518, 517, 519, 520, - 520, 521, 521 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, - 3, 2, 2, 1, 1, 1, 2, 2, 2, 1, - 2, 3, 2, 1, 1, 1, 1, 2, 2, 2, - 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, - 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, - 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 0, 6, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 2, 2, 4, 2, 3, 4, 2, - 3, 4, 0, 6, 2, 3, 2, 1, 1, 2, - 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, - 3, 4, 6, 5, 1, 2, 3, 5, 4, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 3, 1, 3, 1, 1, 1, 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, 4, 1, 1, 3, 2, 3, - 2, 3, 3, 4, 1, 0, 3, 1, 3, 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, 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, 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, 6, 0, 5, 1, 2, 3, 4, - 1, 3, 1, 2, 1, 3, 4, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 0, 0, 5, 1, 1, 0, 2, 0, - 2, 2, 3, 1, 2, 1, 2, 1, 2, 5, - 3, 1, 1, 4, 1, 2, 0, 8, 0, 1, - 3, 2, 1, 2, 0, 6, 0, 8, 0, 7, - 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, - 2, 1, 2, 1, 1, 1, 0, 3, 5, 1, - 3, 1, 4 -}; - - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (pParseContext, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -#ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -#endif - - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, pParseContext); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - FILE *yyo = yyoutput; - YYUSE (yyo); - YYUSE (pParseContext); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep, pParseContext); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, glslang::TParseContext* pParseContext) -{ - unsigned long int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , pParseContext); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext) -{ - YYUSE (yyvaluep); - YYUSE (pParseContext); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yytype); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (glslang::TParseContext* pParseContext) -{ -/* The lookahead symbol. */ -int yychar; - - -/* The semantic value of the lookahead symbol. */ -/* Default value used for initialization, for pacifying older GCCs - or non-GCC compilers. */ -YY_INITIAL_VALUE (static YYSTYPE yyval_default;) -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - - /* Number of syntax errors so far. */ - int yynerrs; - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (&yylval, parseContext); - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 352 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); - } -#line 4172 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 3: -#line 358 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 4: -#line 361 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } -#line 4190 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 5: -#line 366 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 4198 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 6: -#line 369 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4206 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 7: -#line 372 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4215 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 8: -#line 376 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 4223 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 9: -#line 380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 10: -#line 384 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 11: -#line 388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); - } -#line 4250 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 12: -#line 392 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); - } -#line 4259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 13: -#line 396 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 4268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 14: -#line 400 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 4277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 15: -#line 404 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true); - } -#line 4286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 16: -#line 408 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); - } -#line 4295 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 17: -#line 416 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 18: -#line 419 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); - } -#line 4311 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 19: -#line 422 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4319 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 20: -#line 425 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); - } -#line 4327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 21: -#line 428 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 4337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 22: -#line 433 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 4347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 23: -#line 441 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 24: -#line 448 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); - delete (yyvsp[0].interm).function; - } -#line 4365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 25: -#line 455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 4373 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 26: -#line 461 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 4382 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 27: -#line 465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 4391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 28: -#line 472 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 4399 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 29: -#line 475 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 4407 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 30: -#line 481 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - (yyvsp[-1].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-1].interm).function; - (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode); - } -#line 4419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 31: -#line 488 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - (yyvsp[-2].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-2].interm).function; - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - } -#line 4431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 32: -#line 498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 4439 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 33: -#line 506 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 4449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 34: -#line 511 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // Should be a method or subroutine call, but we haven't recognized the arguments yet. - // - (yyval.interm).function = 0; - (yyval.interm).intermNode = 0; - - TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode(); - if (method) { - (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); - (yyval.interm).intermNode = method->getObject(); - } else { - TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode(); - if (symbol) { - parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); - TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); - (yyval.interm).function = function; - } else - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", ""); - } - - if ((yyval.interm).function == 0) { - // error recover - TString* empty = NewPoolTString(""); - (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull); - } - } -#line 4481 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 35: -#line 539 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 4491 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 36: -#line 548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode()) - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); - } -#line 4502 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 37: -#line 554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 4511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 38: -#line 558 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 4520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 39: -#line 562 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm).op != EOpNull) { - char errorOp[2] = {0, 0}; - switch((yyvsp[-1].interm).op) { - case EOpNegative: errorOp[0] = '-'; break; - case EOpLogicalNot: errorOp[0] = '!'; break; - case EOpBitwiseNot: errorOp[0] = '~'; break; - default: break; // some compilers want this - } - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode)); - } else { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } - } -#line 4541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 40: -#line 582 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } -#line 4547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 41: -#line 583 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } -#line 4553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 42: -#line 584 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } -#line 4559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 43: -#line 585 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } -#line 4566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 44: -#line 591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 45: -#line 592 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 46: -#line 597 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4592 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 47: -#line 602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 48: -#line 611 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 49: -#line 612 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 50: -#line 617 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 51: -#line 625 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4635 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 52: -#line 626 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 53: -#line 632 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4657 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 54: -#line 641 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4663 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 55: -#line 642 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4673 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 56: -#line 647 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4683 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 57: -#line 652 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 58: -#line 657 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 59: -#line 665 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 60: -#line 666 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4723 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 61: -#line 675 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 62: -#line 687 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4743 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 63: -#line 688 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4754 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 64: -#line 697 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4760 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 65: -#line 698 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 66: -#line 707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 67: -#line 708 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 4788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 68: -#line 717 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4794 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 69: -#line 718 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4804 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 70: -#line 726 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 71: -#line 727 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4820 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 72: -#line 735 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 73: -#line 736 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 4836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 74: -#line 744 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 75: -#line 745 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.controlFlowNestingLevel; - } -#line 4850 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 76: -#line 748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.controlFlowNestingLevel; - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 4867 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 77: -#line 763 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4873 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 78: -#line 764 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); - parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.storage16BitAssignmentCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].interm).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } - } -#line 4891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 79: -#line 780 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAssign; - } -#line 4900 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 80: -#line 784 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpMulAssign; - } -#line 4909 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 81: -#line 788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpDivAssign; - } -#line 4918 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 82: -#line 792 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpModAssign; - } -#line 4928 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 83: -#line 797 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAddAssign; - } -#line 4937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 84: -#line 801 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpSubAssign; - } -#line 4946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 85: -#line 805 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; - } -#line 4955 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 86: -#line 809 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; - } -#line 4964 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 87: -#line 813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; - } -#line 4973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 88: -#line 817 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; - } -#line 4982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 89: -#line 821 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; - } -#line 4991 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 90: -#line 828 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 4999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 91: -#line 831 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString()); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 5012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 92: -#line 842 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 5021 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 93: -#line 849 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); - (yyval.interm.intermNode) = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } -#line 5031 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 94: -#line 854 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) - (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode; - } -#line 5041 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 95: -#line 859 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); - // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope - parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision); - (yyval.interm.intermNode) = 0; - } -#line 5053 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 96: -#line 866 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); - (yyval.interm.intermNode) = 0; - } -#line 5062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 97: -#line 870 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 5071 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 98: -#line 874 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); - (yyval.interm.intermNode) = 0; - } -#line 5080 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 99: -#line 878 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); - parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); - (yyval.interm.intermNode) = 0; - } -#line 5090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 100: -#line 883 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); - parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 5100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 101: -#line 888 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); - (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); - parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList)); - (yyval.interm.intermNode) = 0; - } -#line 5111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 102: -#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } -#line 5117 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 103: -#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.structNestingLevel; - parseContext.blockName = (yyvsp[-4].lex).string; - parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier); - parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers); - parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier; - (yyval.interm).loc = (yyvsp[-5].interm.type).loc; - (yyval.interm).typeList = (yyvsp[-1].interm.typeList); - } -#line 5131 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 104: -#line 908 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.identifierList) = new TIdentifierList; - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 5140 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 105: -#line 912 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 5149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 106: -#line 919 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).function = (yyvsp[-1].interm.function); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 5158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 107: -#line 926 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 5166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 108: -#line 929 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 5174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 109: -#line 936 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // Add the parameter - (yyval.interm.function) = (yyvsp[-1].interm.function); - if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid) - (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param); - else - delete (yyvsp[0].interm).param.type; - } -#line 5187 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 110: -#line 944 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", ""); - delete (yyvsp[0].interm).param.type; - } else { - // Add the parameter - (yyval.interm.function) = (yyvsp[-2].interm.function); - (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); - } - } -#line 5209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 111: -#line 964 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { - parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", - GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), ""); - } - if ((yyvsp[-2].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type((yyvsp[-2].interm.type)); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction((yyvsp[-1].lex).string); - - // Make the function - function = new TFunction((yyvsp[-1].lex).string, type); - (yyval.interm.function) = function; - } -#line 5233 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 112: -#line 987 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes); - } - if ((yyvsp[-1].interm.type).basicType == EbtVoid) { - parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), ""); - } - parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string); - - TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))}; - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).param = param; - } -#line 5253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 113: -#line 1002 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - TType* type = new TType((yyvsp[-2].interm.type)); - type->transferArraySizes((yyvsp[0].interm).arraySizes); - type->copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, type->getArraySizes()); - parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes); - parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string); - - TParameter param = { (yyvsp[-1].lex).string, type }; - - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).param = param; - } -#line 5277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 114: -#line 1027 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - - } -#line 5293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 115: -#line 1038 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - } -#line 5305 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 116: -#line 1048 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - } -#line 5320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 117: -#line 1058 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); - } -#line 5332 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 118: -#line 1068 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; - (yyval.interm).param = param; - if ((yyvsp[0].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); - } -#line 5343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 119: -#line 1077 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 5351 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 120: -#line 1080 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-2].interm); - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); - } -#line 5360 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 121: -#line 1084 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-3].interm); - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); - } -#line 5369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 122: -#line 1088 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-5].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 5379 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 123: -#line 1093 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-4].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 5389 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 124: -#line 1101 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[0].interm.type); - (yyval.interm).intermNode = 0; - - parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); - - } -#line 5401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 125: -#line 1108 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-1].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); - } -#line 5411 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 126: -#line 1113 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-2].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); - } -#line 5421 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 127: -#line 1118 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-4].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 5431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 128: -#line 1123 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).type = (yyvsp[-3].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 5441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 129: -#line 1132 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - - parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type)); - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier); - } -#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 130: -#line 1142 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); - parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); - - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - - if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier)) - (yyvsp[0].interm.type).arraySizes = nullptr; - - parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier); - - (yyval.interm.type) = (yyvsp[0].interm.type); - - if (! (yyval.interm.type).qualifier.isInterpolation() && - ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) || - (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) - (yyval.interm.type).qualifier.smooth = true; - } -#line 5485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 131: -#line 1169 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); - parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.invariant = true; - } -#line 5496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 132: -#line 1178 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.smooth = true; - } -#line 5508 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 133: -#line 1185 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.flat = true; - } -#line 5520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 134: -#line 1193 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nopersp = true; - } -#line 5532 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 135: -#line 1200 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.explicitInterp = true; - } -#line 5544 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 136: -#line 1207 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.pervertexNV = true; - } -#line 5557 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 137: -#line 1215 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV"); - // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. - if (parseContext.language == EShLangFragment) - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perPrimitiveNV = true; - } -#line 5572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 138: -#line 1225 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV"); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangMeshNV, "perviewNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perViewNV = true; - } -#line 5584 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 139: -#line 1232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perTaskNV = true; - } -#line 5596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 140: -#line 1243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - } -#line 5604 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 141: -#line 1249 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5612 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 142: -#line 1252 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-2].interm.type); - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 5622 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 143: -#line 1259 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); - } -#line 5631 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 144: -#line 1263 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[-2].lex).loc); - parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); - } -#line 5640 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 145: -#line 1267 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { // because "shared" is both an identifier and a keyword - (yyval.interm.type).init((yyvsp[0].lex).loc); - TString strShared("shared"); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); - } -#line 5650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 146: -#line 1276 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.noContraction = true; - } -#line 5661 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 147: -#line 1286 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 148: -#line 1289 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - if ((yyval.interm.type).basicType == EbtVoid) - (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType; - - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 5682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 149: -#line 1300 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 150: -#line 1303 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 151: -#line 1306 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5707 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 152: -#line 1310 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 153: -#line 1314 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 154: -#line 1319 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5734 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 155: -#line 1323 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5742 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 156: -#line 1330 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant - } -#line 5751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 157: -#line 1334 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqInOut; - } -#line 5761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 158: -#line 1339 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "in"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqIn; - } -#line 5772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 159: -#line 1345 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "out"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqOut; - } -#line 5783 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 160: -#line 1351 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck((yyvsp[0].lex).loc, "centroid"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.centroid = true; - } -#line 5795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 161: -#line 1358 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqUniform; - } -#line 5805 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 162: -#line 1363 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshNVMask | EShLangTaskNVMask), "shared"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqShared; - } -#line 5818 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 163: -#line 1371 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqBuffer; - } -#line 5828 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 164: -#line 1377 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "attribute"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 5845 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 165: -#line 1389 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "varying"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - if (parseContext.language == EShLangVertex) - (yyval.interm.type).qualifier.storage = EvqVaryingOut; - else - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 5864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 166: -#line 1403 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.patch = true; - } -#line 5875 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 167: -#line 1409 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.sample = true; - } -#line 5885 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 168: -#line 1414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqHitAttrNV; - } -#line 5898 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 169: -#line 1422 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadNV; - } -#line 5911 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 170: -#line 1430 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadInNV; - } -#line 5924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 171: -#line 1438 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataNV; - } -#line 5937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 172: -#line 1446 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataInNV; - } -#line 5949 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 173: -#line 1453 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.coherent = true; - } -#line 5958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 174: -#line 1457 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); - (yyval.interm.type).qualifier.devicecoherent = true; - } -#line 5968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 175: -#line 1462 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); - (yyval.interm.type).qualifier.queuefamilycoherent = true; - } -#line 5978 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 176: -#line 1467 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); - (yyval.interm.type).qualifier.workgroupcoherent = true; - } -#line 5988 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 177: -#line 1472 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); - (yyval.interm.type).qualifier.subgroupcoherent = true; - } -#line 5998 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 178: -#line 1477 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); - (yyval.interm.type).qualifier.nonprivate = true; - } -#line 6008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 179: -#line 1482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.volatil = true; - } -#line 6017 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 180: -#line 1486 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.restrict = true; - } -#line 6026 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 181: -#line 1490 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.readonly = true; - } -#line 6035 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 182: -#line 1494 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.writeonly = true; - } -#line 6044 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 183: -#line 1498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - } -#line 6055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 184: -#line 1504 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[-3].lex).loc); - } -#line 6066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 185: -#line 1515 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nonUniform = true; - } -#line 6075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 186: -#line 1522 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // TODO - } -#line 6083 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 187: -#line 1525 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // TODO: 4.0 semantics: subroutines - // 1) make sure each identifier is a type declared earlier with SUBROUTINE - // 2) save all of the identifiers for future comparison with the declared function - } -#line 6093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 188: -#line 1534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters); - } -#line 6103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 189: -#line 1539 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); - (yyval.interm.type) = (yyvsp[-2].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters); - (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; - } -#line 6115 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 190: -#line 1549 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - (yyval.interm).arraySizes->addInnerSize(); - } -#line 6125 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 191: -#line 1554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm).loc = (yyvsp[-2].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 6138 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 192: -#line 1562 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-2].interm); - (yyval.interm).arraySizes->addInnerSize(); - } -#line 6147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 193: -#line 1566 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm) = (yyvsp[-3].interm); - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 6159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 194: -#line 1576 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters); - } -#line 6167 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 195: -#line 1579 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeParameters) = 0; - } -#line 6175 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 196: -#line 1585 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters); - } -#line 6183 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 197: -#line 1591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeParameters) = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); - (yyval.interm.typeParameters)->addInnerSize(size); - } -#line 6195 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 198: -#line 1598 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters); - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); - (yyval.interm.typeParameters)->addInnerSize(size); - } -#line 6207 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 199: -#line 1608 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtVoid; - } -#line 6216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 200: -#line 1612 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 6225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 201: -#line 1616 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 6234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 202: -#line 1620 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 6244 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 203: -#line 1625 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - } -#line 6253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 204: -#line 1629 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 6263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 205: -#line 1634 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 6273 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 206: -#line 1639 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 6283 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 207: -#line 1644 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(2); - } -#line 6293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 208: -#line 1649 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(3); - } -#line 6303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 209: -#line 1654 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(4); - } -#line 6313 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 210: -#line 1659 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 6323 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 211: -#line 1664 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 6333 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 212: -#line 1669 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 6343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 213: -#line 1674 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 6354 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 214: -#line 1680 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 6365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 215: -#line 1686 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 6376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 216: -#line 1692 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 217: -#line 1697 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6396 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 218: -#line 1702 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 219: -#line 1707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 6416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 220: -#line 1712 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 6426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 221: -#line 1717 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 6436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 222: -#line 1722 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 6446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 223: -#line 1727 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 6456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 224: -#line 1732 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 6466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 225: -#line 1737 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 6476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 226: -#line 1742 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 6486 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 227: -#line 1747 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 6496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 228: -#line 1753 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 6506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 229: -#line 1758 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - } -#line 6516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 230: -#line 1763 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 6526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 231: -#line 1768 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 6536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 232: -#line 1773 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - } -#line 6546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 233: -#line 1778 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - } -#line 6556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 234: -#line 1783 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - } -#line 6566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 235: -#line 1788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - } -#line 6576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 236: -#line 1793 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 6586 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 237: -#line 1798 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 6596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 238: -#line 1803 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - } -#line 6606 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 239: -#line 1808 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - } -#line 6616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 240: -#line 1813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 6627 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 241: -#line 1819 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 6638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 242: -#line 1825 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 6649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 243: -#line 1831 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(2); - } -#line 6660 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 244: -#line 1837 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(3); - } -#line 6671 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 245: -#line 1843 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(4); - } -#line 6682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 246: -#line 1849 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 6693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 247: -#line 1855 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 6704 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 248: -#line 1861 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 6715 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 249: -#line 1867 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 6726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 250: -#line 1873 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 6737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 251: -#line 1879 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 6748 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 252: -#line 1885 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(2); - } -#line 6759 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 253: -#line 1891 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(3); - } -#line 6770 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 254: -#line 1897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(4); - } -#line 6781 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 255: -#line 1903 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(2); - } -#line 6792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 256: -#line 1909 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(3); - } -#line 6803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 257: -#line 1915 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(4); - } -#line 6814 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 258: -#line 1921 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 6825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 259: -#line 1927 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 6836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 260: -#line 1933 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 6847 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 261: -#line 1939 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(2); - } -#line 6858 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 262: -#line 1945 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(3); - } -#line 6869 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 263: -#line 1951 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(4); - } -#line 6880 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 264: -#line 1957 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(2); - } -#line 6891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 265: -#line 1963 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(3); - } -#line 6902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 266: -#line 1969 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(4); - } -#line 6913 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 267: -#line 1975 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(2); - } -#line 6924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 268: -#line 1981 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(3); - } -#line 6935 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 269: -#line 1987 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(4); - } -#line 6946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 270: -#line 1993 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 6957 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 271: -#line 1999 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 6968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 272: -#line 2005 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 6979 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 273: -#line 2011 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(2); - } -#line 6990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 274: -#line 2017 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(3); - } -#line 7001 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 275: -#line 2023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(4); - } -#line 7012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 276: -#line 2029 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7023 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 277: -#line 2035 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 278: -#line 2041 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7045 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 279: -#line 2047 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 280: -#line 2053 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7067 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 281: -#line 2059 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7078 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 282: -#line 2065 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7089 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 283: -#line 2071 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 284: -#line 2077 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 285: -#line 2083 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 286: -#line 2089 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7133 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 287: -#line 2095 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7144 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 288: -#line 2101 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 289: -#line 2107 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 290: -#line 2113 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 291: -#line 2119 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7188 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 292: -#line 2125 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7199 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 293: -#line 2131 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7210 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 294: -#line 2137 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7221 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 295: -#line 2143 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 296: -#line 2149 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7243 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 297: -#line 2155 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7254 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 298: -#line 2161 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7265 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 299: -#line 2167 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 300: -#line 2173 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7287 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 301: -#line 2179 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7298 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 302: -#line 2185 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7309 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 303: -#line 2191 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 304: -#line 2197 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7331 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 305: -#line 2203 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7342 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 306: -#line 2209 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7353 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 307: -#line 2215 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 308: -#line 2221 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7375 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 309: -#line 2227 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 310: -#line 2233 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7397 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 311: -#line 2239 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7408 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 312: -#line 2245 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 313: -#line 2251 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7430 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 314: -#line 2257 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 315: -#line 2263 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7452 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 316: -#line 2269 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7463 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 317: -#line 2275 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 318: -#line 2281 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 319: -#line 2287 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 320: -#line 2293 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7507 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 321: -#line 2299 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7518 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 322: -#line 2305 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 323: -#line 2311 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7540 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 324: -#line 2317 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAccStructNV; - } -#line 7549 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 325: -#line 2321 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAtomicUint; - } -#line 7559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 326: -#line 2326 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D); - } -#line 7569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 327: -#line 2332 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - } -#line 7579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 328: -#line 2337 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd3D); - } -#line 7589 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 329: -#line 2342 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube); - } -#line 7599 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 330: -#line 2347 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); - } -#line 7609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 331: -#line 2352 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); - } -#line 7619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 332: -#line 2357 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); - } -#line 7629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 333: -#line 2362 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); - } -#line 7639 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 334: -#line 2368 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); - } -#line 7649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 335: -#line 2373 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); - } -#line 7659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 336: -#line 2378 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); - } -#line 7669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 337: -#line 2383 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); - } -#line 7679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 338: -#line 2388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); - } -#line 7689 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 339: -#line 2393 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); - } -#line 7700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 340: -#line 2399 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); - } -#line 7711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 341: -#line 2405 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); - } -#line 7722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 342: -#line 2411 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); - } -#line 7733 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 343: -#line 2417 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); - } -#line 7744 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 344: -#line 2423 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); - } -#line 7755 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 345: -#line 2429 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); - } -#line 7766 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 346: -#line 2435 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); - } -#line 7777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 347: -#line 2441 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); - } -#line 7788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 348: -#line 2447 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); - } -#line 7799 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 349: -#line 2453 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); - } -#line 7810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 350: -#line 2459 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); - } -#line 7821 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 351: -#line 2465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); - } -#line 7832 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 352: -#line 2471 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D); - } -#line 7842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 353: -#line 2477 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D); - } -#line 7852 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 354: -#line 2482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd3D); - } -#line 7862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 355: -#line 2487 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube); - } -#line 7872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 356: -#line 2492 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); - } -#line 7882 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 357: -#line 2497 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D); - } -#line 7892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 358: -#line 2502 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd3D); - } -#line 7902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 359: -#line 2507 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube); - } -#line 7912 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 360: -#line 2513 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); - } -#line 7922 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 361: -#line 2518 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); - } -#line 7932 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 362: -#line 2523 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D); - } -#line 7942 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 363: -#line 2528 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); - } -#line 7952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 364: -#line 2533 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); - } -#line 7962 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 365: -#line 2538 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); - } -#line 7972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 366: -#line 2543 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); - } -#line 7982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 367: -#line 2548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); - } -#line 7992 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 368: -#line 2554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); - } -#line 8002 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 369: -#line 2559 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); - } -#line 8012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 370: -#line 2564 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); - } -#line 8022 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 371: -#line 2569 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); - } -#line 8032 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 372: -#line 2574 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); - } -#line 8042 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 373: -#line 2579 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); - } -#line 8052 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 374: -#line 2584 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); - } -#line 8062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 375: -#line 2589 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); - } -#line 8072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 376: -#line 2594 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); - } -#line 8082 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 377: -#line 2599 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); - } -#line 8092 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 378: -#line 2604 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); - } -#line 8102 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 379: -#line 2609 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); - } -#line 8112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 380: -#line 2614 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); - } -#line 8122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 381: -#line 2619 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(false); - } -#line 8132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 382: -#line 2624 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(true); - } -#line 8142 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 383: -#line 2630 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect); - } -#line 8152 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 384: -#line 2635 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); - } -#line 8162 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 385: -#line 2640 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); - } -#line 8173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 386: -#line 2646 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); - } -#line 8184 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 387: -#line 2652 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdRect); - } -#line 8194 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 388: -#line 2657 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdRect); - } -#line 8204 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 389: -#line 2662 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); - } -#line 8214 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 390: -#line 2667 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); - } -#line 8225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 391: -#line 2673 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); - } -#line 8235 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 392: -#line 2678 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); - } -#line 8245 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 393: -#line 2683 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); - } -#line 8255 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 394: -#line 2688 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); - } -#line 8266 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 395: -#line 2694 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); - } -#line 8276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 396: -#line 2699 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); - } -#line 8286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 397: -#line 2704 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); - } -#line 8296 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 398: -#line 2709 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); - } -#line 8307 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 399: -#line 2715 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); - } -#line 8317 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 400: -#line 2720 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); - } -#line 8327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 401: -#line 2725 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); - } -#line 8337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 402: -#line 2730 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); - } -#line 8348 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 403: -#line 2736 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); - } -#line 8359 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 404: -#line 2742 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); - } -#line 8370 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 405: -#line 2748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); - } -#line 8381 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 406: -#line 2754 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); - } -#line 8391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 407: -#line 2759 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); - } -#line 8402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 408: -#line 2765 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); - } -#line 8413 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 409: -#line 2771 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); - } -#line 8424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 410: -#line 2777 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); - } -#line 8434 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 411: -#line 2782 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); - } -#line 8444 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 412: -#line 2787 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); - } -#line 8454 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 413: -#line 2792 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); - } -#line 8464 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 414: -#line 2797 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); - } -#line 8474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 415: -#line 2802 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); - } -#line 8485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 416: -#line 2808 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); - } -#line 8495 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 417: -#line 2813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); - } -#line 8505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 418: -#line 2818 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); - } -#line 8515 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 419: -#line 2823 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); - } -#line 8526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 420: -#line 2829 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); - } -#line 8536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 421: -#line 2834 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); - } -#line 8546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 422: -#line 2839 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); - } -#line 8556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 423: -#line 2844 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); - } -#line 8567 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 424: -#line 2850 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); - } -#line 8577 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 425: -#line 2855 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); - } -#line 8587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 426: -#line 2860 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); - } -#line 8597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 427: -#line 2865 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); - } -#line 8608 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 428: -#line 2871 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); - } -#line 8618 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 429: -#line 2876 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); - } -#line 8628 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 430: -#line 2881 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); - } -#line 8638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 431: -#line 2886 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); - } -#line 8649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 432: -#line 2892 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); - } -#line 8659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 433: -#line 2897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); - } -#line 8669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 434: -#line 2902 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); - } -#line 8679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 435: -#line 2907 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); - } -#line 8690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 436: -#line 2913 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); - } -#line 8700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 437: -#line 2918 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); - } -#line 8710 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 438: -#line 2923 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); - } -#line 8720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 439: -#line 2928 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); - } -#line 8731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 440: -#line 2934 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); - } -#line 8741 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 441: -#line 2939 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); - } -#line 8751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 442: -#line 2944 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); - } -#line 8761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 443: -#line 2949 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); - } -#line 8772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 444: -#line 2955 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); - } -#line 8782 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 445: -#line 2960 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); - } -#line 8792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 446: -#line 2965 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); - } -#line 8802 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 447: -#line 2970 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); - } -#line 8813 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 448: -#line 2976 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); - } -#line 8823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 449: -#line 2981 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); - } -#line 8833 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 450: -#line 2986 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); - } -#line 8843 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 451: -#line 2991 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); - } -#line 8854 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 452: -#line 2997 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); - } -#line 8864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 453: -#line 3002 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); - } -#line 8874 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 454: -#line 3007 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); - } -#line 8884 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 455: -#line 3012 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); - } -#line 8895 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 456: -#line 3018 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); - } -#line 8905 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 457: -#line 3023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); - } -#line 8915 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 458: -#line 3028 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); - } -#line 8925 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 459: -#line 3033 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); - } -#line 8936 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 460: -#line 3039 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); - } -#line 8946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 461: -#line 3044 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); - } -#line 8956 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 462: -#line 3049 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); - } -#line 8966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 463: -#line 3054 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); - } -#line 8977 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 464: -#line 3060 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); - } -#line 8987 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 465: -#line 3065 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); - } -#line 8997 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 466: -#line 3070 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); - } -#line 9007 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 467: -#line 3075 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); - } -#line 9018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 468: -#line 3081 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); - } -#line 9028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 469: -#line 3086 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); - } -#line 9038 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 470: -#line 3091 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); - } -#line 9048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 471: -#line 3096 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); - } -#line 9059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 472: -#line 3102 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); - } -#line 9069 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 473: -#line 3107 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); - } -#line 9079 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 474: -#line 3112 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { // GL_OES_EGL_image_external - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - (yyval.interm.type).sampler.external = true; - } -#line 9090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 475: -#line 3118 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { // GL_EXT_YUV_target - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - (yyval.interm.type).sampler.yuv = true; - } -#line 9101 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 476: -#line 3124 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat); - } -#line 9112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 477: -#line 3130 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat, true); - } -#line 9123 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 478: -#line 3136 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16); - } -#line 9135 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 479: -#line 3143 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); - } -#line 9147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 480: -#line 3150 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt); - } -#line 9158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 481: -#line 3156 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt, true); - } -#line 9169 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 482: -#line 3162 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint); - } -#line 9180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 483: -#line 3168 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint, true); - } -#line 9191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 484: -#line 3174 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.fcoopmatCheck((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).coopmat = true; - } -#line 9202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 485: -#line 3180 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).coopmat = true; - } -#line 9213 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 486: -#line 3186 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).coopmat = true; - } -#line 9224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 487: -#line 3193 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); - } -#line 9234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 488: -#line 3198 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) { - const TType& structure = variable->getType(); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = &structure; - } else - parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); - } -#line 9252 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 489: -#line 3214 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); - } -#line 9262 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 490: -#line 3219 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); - } -#line 9272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 491: -#line 3224 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); - } -#line 9282 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 492: -#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } -#line 9288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 493: -#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); - parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); - TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true); - if (! parseContext.symbolTable.insert(*userTypeDef)) - parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct"); - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 9304 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 494: -#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } -#line 9310 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 495: -#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); - (yyval.interm.type).init((yyvsp[-4].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 9322 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 496: -#line 3253 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = (yyvsp[0].interm.typeList); - } -#line 9330 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 497: -#line 3256 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { - for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { - if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName()) - parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str()); - } - (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); - } - } -#line 9345 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 498: -#line 3269 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 9372 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 499: -#line 3291 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.memberQualifierCheck((yyvsp[-3].interm.type)); - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 9401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 500: -#line 3318 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList) = new TTypeList; - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 9410 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 501: -#line 3322 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 9418 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 502: -#line 3328 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); - } -#line 9428 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 503: -#line 3333 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); - - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); - (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); - } -#line 9441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 504: -#line 3344 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 9449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 505: -#line 3348 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - } -#line 9460 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 506: -#line 3354 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 9471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 507: -#line 3365 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); - } -#line 9479 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 508: -#line 3368 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - } -#line 9487 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 509: -#line 3375 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9493 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 510: -#line 3379 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9499 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 511: -#line 3380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 512: -#line 3386 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 513: -#line 3387 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9517 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 514: -#line 3388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 515: -#line 3389 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 516: -#line 3390 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9535 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 517: -#line 3391 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 518: -#line 3392 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 519: -#line 3394 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 520: -#line 3400 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote"); - parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc); - } -#line 9563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 521: -#line 3409 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = 0; } -#line 9569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 522: -#line 3410 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } -#line 9578 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 523: -#line 3414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } -#line 9587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 524: -#line 3418 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) - (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); - } -#line 9597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 525: -#line 3426 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 526: -#line 3427 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 527: -#line 3431 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.controlFlowNestingLevel; - } -#line 9617 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 528: -#line 3434 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 529: -#line 3438 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 530: -#line 3443 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9647 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 531: -#line 3452 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - } -#line 9655 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 532: -#line 3455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) - (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); - } -#line 9665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 533: -#line 3463 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } - } -#line 9678 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 534: -#line 3471 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } else - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 9691 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 535: -#line 3482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = 0; } -#line 9697 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 536: -#line 3483 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { (yyval.interm.intermNode) = static_cast((yyvsp[-1].interm.intermTypedNode)); } -#line 9703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 537: -#line 3487 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 538: -#line 3491 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 539: -#line 3498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); - } -#line 9729 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 540: -#line 3505 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); - } -#line 9738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 541: -#line 3509 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 9747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 542: -#line 3517 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); - } -#line 9756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 543: -#line 3521 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); - - TType type((yyvsp[-3].interm.type)); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - if (initNode) - (yyval.interm.intermTypedNode) = initNode->getAsTyped(); - else - (yyval.interm.intermTypedNode) = 0; - } -#line 9771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 544: -#line 3534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9779 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 545: -#line 3538 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 546: -#line 3545 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // start new switch sequence on the switch stack - ++parseContext.controlFlowNestingLevel; - ++parseContext.statementNestingLevel; - parseContext.switchSequenceStack.push_back(new TIntermSequence); - parseContext.switchLevel.push_back(parseContext.statementNestingLevel); - parseContext.symbolTable.push(); - } -#line 9801 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 547: -#line 3553 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); - delete parseContext.switchSequenceStack.back(); - parseContext.switchSequenceStack.pop_back(); - parseContext.switchLevel.pop_back(); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9815 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 548: -#line 3565 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - } -#line 9823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 549: -#line 3568 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9831 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 550: -#line 3574 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", ""); - else { - parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case"); - parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); - } - } -#line 9848 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 551: -#line 3586 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", ""); - else - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); - } -#line 9862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 552: -#line 3598 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 553: -#line 3602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9879 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 554: -#line 3609 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 555: -#line 3617 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9904 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 556: -#line 3624 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 557: -#line 3629 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); - - parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9930 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 558: -#line 3640 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 9941 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 559: -#line 3646 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); - TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast((yyvsp[-2].interm.nodePair).node1), reinterpret_cast((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc); - if (! parseContext.limits.nonInductiveForLoops) - parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc); - (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 9958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 560: -#line 3661 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 561: -#line 3664 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 9974 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 562: -#line 3670 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 9982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 563: -#line 3673 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermTypedNode) = 0; - } -#line 9990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 564: -#line 3679 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 9999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 565: -#line 3683 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); - } -#line 10008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 566: -#line 3690 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (parseContext.loopNestingLevel <= 0) - parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); - } -#line 10018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 567: -#line 3695 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) - parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); - } -#line 10028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 568: -#line 3700 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); - if (parseContext.currentFunctionType->getBasicType() != EbtVoid) - parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", ""); - if (parseContext.inMain) - parseContext.postEntryPointReturn = true; - } -#line 10040 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 569: -#line 3707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); - } -#line 10048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 570: -#line 3710 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); - } -#line 10057 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 571: -#line 3719 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } -#line 10066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 572: -#line 3723 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - if ((yyvsp[0].interm.intermNode) != nullptr) { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } - } -#line 10077 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 573: -#line 3732 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 10085 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 574: -#line 3735 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 10093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 575: -#line 3739 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); - parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); - (yyval.interm.intermNode) = nullptr; - } -#line 10103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 576: -#line 3748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); - (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); - } -#line 10112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 577: -#line 3752 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - // May be best done as post process phase on intermediate code - if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) - parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str()); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode)); - parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc); - (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); - (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug); - (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); - } -#line 10132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 578: -#line 3771 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); - parseContext.requireExtensions((yyvsp[-4].lex).loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); - } -#line 10141 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 579: -#line 3777 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = (yyvsp[0].interm.attributes); - } -#line 10149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 580: -#line 3780 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); - } -#line 10157 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 581: -#line 3785 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); - } -#line 10165 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 582: -#line 3788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); - } -#line 10173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - -#line 10177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (pParseContext, YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (pParseContext, yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, pParseContext); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp, pParseContext); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (pParseContext, YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, pParseContext); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, pParseContext); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - return yyresult; -} -#line 3793 "MachineIndependent/glslang.y" /* yacc.c:1906 */ - diff --git a/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h deleted file mode 100644 index f4f411473..000000000 --- a/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h +++ /dev/null @@ -1,512 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - - 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 3 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. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token type. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - CONST = 258, - BOOL = 259, - INT = 260, - UINT = 261, - FLOAT = 262, - BVEC2 = 263, - BVEC3 = 264, - BVEC4 = 265, - IVEC2 = 266, - IVEC3 = 267, - IVEC4 = 268, - UVEC2 = 269, - UVEC3 = 270, - UVEC4 = 271, - VEC2 = 272, - VEC3 = 273, - VEC4 = 274, - MAT2 = 275, - MAT3 = 276, - MAT4 = 277, - MAT2X2 = 278, - MAT2X3 = 279, - MAT2X4 = 280, - MAT3X2 = 281, - MAT3X3 = 282, - MAT3X4 = 283, - MAT4X2 = 284, - MAT4X3 = 285, - MAT4X4 = 286, - SAMPLER2D = 287, - SAMPLER3D = 288, - SAMPLERCUBE = 289, - SAMPLER2DSHADOW = 290, - SAMPLERCUBESHADOW = 291, - SAMPLER2DARRAY = 292, - SAMPLER2DARRAYSHADOW = 293, - ISAMPLER2D = 294, - ISAMPLER3D = 295, - ISAMPLERCUBE = 296, - ISAMPLER2DARRAY = 297, - USAMPLER2D = 298, - USAMPLER3D = 299, - USAMPLERCUBE = 300, - USAMPLER2DARRAY = 301, - SAMPLER = 302, - SAMPLERSHADOW = 303, - TEXTURE2D = 304, - TEXTURE3D = 305, - TEXTURECUBE = 306, - TEXTURE2DARRAY = 307, - ITEXTURE2D = 308, - ITEXTURE3D = 309, - ITEXTURECUBE = 310, - ITEXTURE2DARRAY = 311, - UTEXTURE2D = 312, - UTEXTURE3D = 313, - UTEXTURECUBE = 314, - UTEXTURE2DARRAY = 315, - ATTRIBUTE = 316, - VARYING = 317, - FLOAT16_T = 318, - FLOAT32_T = 319, - DOUBLE = 320, - FLOAT64_T = 321, - INT64_T = 322, - UINT64_T = 323, - INT32_T = 324, - UINT32_T = 325, - INT16_T = 326, - UINT16_T = 327, - INT8_T = 328, - UINT8_T = 329, - I64VEC2 = 330, - I64VEC3 = 331, - I64VEC4 = 332, - U64VEC2 = 333, - U64VEC3 = 334, - U64VEC4 = 335, - I32VEC2 = 336, - I32VEC3 = 337, - I32VEC4 = 338, - U32VEC2 = 339, - U32VEC3 = 340, - U32VEC4 = 341, - I16VEC2 = 342, - I16VEC3 = 343, - I16VEC4 = 344, - U16VEC2 = 345, - U16VEC3 = 346, - U16VEC4 = 347, - I8VEC2 = 348, - I8VEC3 = 349, - I8VEC4 = 350, - U8VEC2 = 351, - U8VEC3 = 352, - U8VEC4 = 353, - DVEC2 = 354, - DVEC3 = 355, - DVEC4 = 356, - DMAT2 = 357, - DMAT3 = 358, - DMAT4 = 359, - F16VEC2 = 360, - F16VEC3 = 361, - F16VEC4 = 362, - F16MAT2 = 363, - F16MAT3 = 364, - F16MAT4 = 365, - F32VEC2 = 366, - F32VEC3 = 367, - F32VEC4 = 368, - F32MAT2 = 369, - F32MAT3 = 370, - F32MAT4 = 371, - F64VEC2 = 372, - F64VEC3 = 373, - F64VEC4 = 374, - F64MAT2 = 375, - F64MAT3 = 376, - F64MAT4 = 377, - DMAT2X2 = 378, - DMAT2X3 = 379, - DMAT2X4 = 380, - DMAT3X2 = 381, - DMAT3X3 = 382, - DMAT3X4 = 383, - DMAT4X2 = 384, - DMAT4X3 = 385, - DMAT4X4 = 386, - F16MAT2X2 = 387, - F16MAT2X3 = 388, - F16MAT2X4 = 389, - F16MAT3X2 = 390, - F16MAT3X3 = 391, - F16MAT3X4 = 392, - F16MAT4X2 = 393, - F16MAT4X3 = 394, - F16MAT4X4 = 395, - F32MAT2X2 = 396, - F32MAT2X3 = 397, - F32MAT2X4 = 398, - F32MAT3X2 = 399, - F32MAT3X3 = 400, - F32MAT3X4 = 401, - F32MAT4X2 = 402, - F32MAT4X3 = 403, - F32MAT4X4 = 404, - F64MAT2X2 = 405, - F64MAT2X3 = 406, - F64MAT2X4 = 407, - F64MAT3X2 = 408, - F64MAT3X3 = 409, - F64MAT3X4 = 410, - F64MAT4X2 = 411, - F64MAT4X3 = 412, - F64MAT4X4 = 413, - ATOMIC_UINT = 414, - ACCSTRUCTNV = 415, - FCOOPMATNV = 416, - ICOOPMATNV = 417, - UCOOPMATNV = 418, - SAMPLERCUBEARRAY = 419, - SAMPLERCUBEARRAYSHADOW = 420, - ISAMPLERCUBEARRAY = 421, - USAMPLERCUBEARRAY = 422, - SAMPLER1D = 423, - SAMPLER1DARRAY = 424, - SAMPLER1DARRAYSHADOW = 425, - ISAMPLER1D = 426, - SAMPLER1DSHADOW = 427, - SAMPLER2DRECT = 428, - SAMPLER2DRECTSHADOW = 429, - ISAMPLER2DRECT = 430, - USAMPLER2DRECT = 431, - SAMPLERBUFFER = 432, - ISAMPLERBUFFER = 433, - USAMPLERBUFFER = 434, - SAMPLER2DMS = 435, - ISAMPLER2DMS = 436, - USAMPLER2DMS = 437, - SAMPLER2DMSARRAY = 438, - ISAMPLER2DMSARRAY = 439, - USAMPLER2DMSARRAY = 440, - SAMPLEREXTERNALOES = 441, - SAMPLEREXTERNAL2DY2YEXT = 442, - ISAMPLER1DARRAY = 443, - USAMPLER1D = 444, - USAMPLER1DARRAY = 445, - F16SAMPLER1D = 446, - F16SAMPLER2D = 447, - F16SAMPLER3D = 448, - F16SAMPLER2DRECT = 449, - F16SAMPLERCUBE = 450, - F16SAMPLER1DARRAY = 451, - F16SAMPLER2DARRAY = 452, - F16SAMPLERCUBEARRAY = 453, - F16SAMPLERBUFFER = 454, - F16SAMPLER2DMS = 455, - F16SAMPLER2DMSARRAY = 456, - F16SAMPLER1DSHADOW = 457, - F16SAMPLER2DSHADOW = 458, - F16SAMPLER1DARRAYSHADOW = 459, - F16SAMPLER2DARRAYSHADOW = 460, - F16SAMPLER2DRECTSHADOW = 461, - F16SAMPLERCUBESHADOW = 462, - F16SAMPLERCUBEARRAYSHADOW = 463, - IMAGE1D = 464, - IIMAGE1D = 465, - UIMAGE1D = 466, - IMAGE2D = 467, - IIMAGE2D = 468, - UIMAGE2D = 469, - IMAGE3D = 470, - IIMAGE3D = 471, - UIMAGE3D = 472, - IMAGE2DRECT = 473, - IIMAGE2DRECT = 474, - UIMAGE2DRECT = 475, - IMAGECUBE = 476, - IIMAGECUBE = 477, - UIMAGECUBE = 478, - IMAGEBUFFER = 479, - IIMAGEBUFFER = 480, - UIMAGEBUFFER = 481, - IMAGE1DARRAY = 482, - IIMAGE1DARRAY = 483, - UIMAGE1DARRAY = 484, - IMAGE2DARRAY = 485, - IIMAGE2DARRAY = 486, - UIMAGE2DARRAY = 487, - IMAGECUBEARRAY = 488, - IIMAGECUBEARRAY = 489, - UIMAGECUBEARRAY = 490, - IMAGE2DMS = 491, - IIMAGE2DMS = 492, - UIMAGE2DMS = 493, - IMAGE2DMSARRAY = 494, - IIMAGE2DMSARRAY = 495, - UIMAGE2DMSARRAY = 496, - F16IMAGE1D = 497, - F16IMAGE2D = 498, - F16IMAGE3D = 499, - F16IMAGE2DRECT = 500, - F16IMAGECUBE = 501, - F16IMAGE1DARRAY = 502, - F16IMAGE2DARRAY = 503, - F16IMAGECUBEARRAY = 504, - F16IMAGEBUFFER = 505, - F16IMAGE2DMS = 506, - F16IMAGE2DMSARRAY = 507, - TEXTURECUBEARRAY = 508, - ITEXTURECUBEARRAY = 509, - UTEXTURECUBEARRAY = 510, - TEXTURE1D = 511, - ITEXTURE1D = 512, - UTEXTURE1D = 513, - TEXTURE1DARRAY = 514, - ITEXTURE1DARRAY = 515, - UTEXTURE1DARRAY = 516, - TEXTURE2DRECT = 517, - ITEXTURE2DRECT = 518, - UTEXTURE2DRECT = 519, - TEXTUREBUFFER = 520, - ITEXTUREBUFFER = 521, - UTEXTUREBUFFER = 522, - TEXTURE2DMS = 523, - ITEXTURE2DMS = 524, - UTEXTURE2DMS = 525, - TEXTURE2DMSARRAY = 526, - ITEXTURE2DMSARRAY = 527, - UTEXTURE2DMSARRAY = 528, - F16TEXTURE1D = 529, - F16TEXTURE2D = 530, - F16TEXTURE3D = 531, - F16TEXTURE2DRECT = 532, - F16TEXTURECUBE = 533, - F16TEXTURE1DARRAY = 534, - F16TEXTURE2DARRAY = 535, - F16TEXTURECUBEARRAY = 536, - F16TEXTUREBUFFER = 537, - F16TEXTURE2DMS = 538, - F16TEXTURE2DMSARRAY = 539, - SUBPASSINPUT = 540, - SUBPASSINPUTMS = 541, - ISUBPASSINPUT = 542, - ISUBPASSINPUTMS = 543, - USUBPASSINPUT = 544, - USUBPASSINPUTMS = 545, - F16SUBPASSINPUT = 546, - F16SUBPASSINPUTMS = 547, - LEFT_OP = 548, - RIGHT_OP = 549, - INC_OP = 550, - DEC_OP = 551, - LE_OP = 552, - GE_OP = 553, - EQ_OP = 554, - NE_OP = 555, - AND_OP = 556, - OR_OP = 557, - XOR_OP = 558, - MUL_ASSIGN = 559, - DIV_ASSIGN = 560, - ADD_ASSIGN = 561, - MOD_ASSIGN = 562, - LEFT_ASSIGN = 563, - RIGHT_ASSIGN = 564, - AND_ASSIGN = 565, - XOR_ASSIGN = 566, - OR_ASSIGN = 567, - SUB_ASSIGN = 568, - LEFT_PAREN = 569, - RIGHT_PAREN = 570, - LEFT_BRACKET = 571, - RIGHT_BRACKET = 572, - LEFT_BRACE = 573, - RIGHT_BRACE = 574, - DOT = 575, - COMMA = 576, - COLON = 577, - EQUAL = 578, - SEMICOLON = 579, - BANG = 580, - DASH = 581, - TILDE = 582, - PLUS = 583, - STAR = 584, - SLASH = 585, - PERCENT = 586, - LEFT_ANGLE = 587, - RIGHT_ANGLE = 588, - VERTICAL_BAR = 589, - CARET = 590, - AMPERSAND = 591, - QUESTION = 592, - INVARIANT = 593, - HIGH_PRECISION = 594, - MEDIUM_PRECISION = 595, - LOW_PRECISION = 596, - PRECISION = 597, - PACKED = 598, - RESOURCE = 599, - SUPERP = 600, - FLOATCONSTANT = 601, - INTCONSTANT = 602, - UINTCONSTANT = 603, - BOOLCONSTANT = 604, - IDENTIFIER = 605, - TYPE_NAME = 606, - CENTROID = 607, - IN = 608, - OUT = 609, - INOUT = 610, - STRUCT = 611, - VOID = 612, - WHILE = 613, - BREAK = 614, - CONTINUE = 615, - DO = 616, - ELSE = 617, - FOR = 618, - IF = 619, - DISCARD = 620, - RETURN = 621, - SWITCH = 622, - CASE = 623, - DEFAULT = 624, - UNIFORM = 625, - SHARED = 626, - BUFFER = 627, - FLAT = 628, - SMOOTH = 629, - LAYOUT = 630, - DOUBLECONSTANT = 631, - INT16CONSTANT = 632, - UINT16CONSTANT = 633, - FLOAT16CONSTANT = 634, - INT32CONSTANT = 635, - UINT32CONSTANT = 636, - INT64CONSTANT = 637, - UINT64CONSTANT = 638, - SUBROUTINE = 639, - DEMOTE = 640, - PAYLOADNV = 641, - PAYLOADINNV = 642, - HITATTRNV = 643, - CALLDATANV = 644, - CALLDATAINNV = 645, - PATCH = 646, - SAMPLE = 647, - NONUNIFORM = 648, - COHERENT = 649, - VOLATILE = 650, - RESTRICT = 651, - READONLY = 652, - WRITEONLY = 653, - DEVICECOHERENT = 654, - QUEUEFAMILYCOHERENT = 655, - WORKGROUPCOHERENT = 656, - SUBGROUPCOHERENT = 657, - NONPRIVATE = 658, - NOPERSPECTIVE = 659, - EXPLICITINTERPAMD = 660, - PERVERTEXNV = 661, - PERPRIMITIVENV = 662, - PERVIEWNV = 663, - PERTASKNV = 664, - PRECISE = 665 - }; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -union YYSTYPE -{ -#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */ - - struct { - glslang::TSourceLoc loc; - union { - glslang::TString *string; - int i; - unsigned int u; - long long i64; - unsigned long long u64; - bool b; - double d; - }; - glslang::TSymbol* symbol; - } lex; - struct { - glslang::TSourceLoc loc; - glslang::TOperator op; - union { - TIntermNode* intermNode; - glslang::TIntermNodePair nodePair; - glslang::TIntermTyped* intermTypedNode; - glslang::TAttributes* attributes; - }; - union { - glslang::TPublicType type; - glslang::TFunction* function; - glslang::TParameter param; - glslang::TTypeLoc typeLine; - glslang::TTypeList* typeList; - glslang::TArraySizes* arraySizes; - glslang::TIdentifierList* identifierList; - }; - glslang::TArraySizes* typeParameters; - } interm; - -#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */ -}; - -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - - -int yyparse (glslang::TParseContext* pParseContext); - -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/libraries/glslang/glslang/OSDependent/Unix/CMakeLists.txt b/libraries/glslang/glslang/OSDependent/Unix/CMakeLists.txt deleted file mode 100644 index 9994314fd..000000000 --- a/libraries/glslang/glslang/OSDependent/Unix/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -add_library(OSDependent STATIC ossource.cpp ../osinclude.h) -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -# Link pthread -set(CMAKE_THREAD_PREFER_PTHREAD ON) -if(${CMAKE_VERSION} VERSION_LESS "3.1.0" OR CMAKE_CROSSCOMPILING) - # Needed as long as we support CMake 2.8 for Ubuntu 14.04, - # which does not support the recommended Threads::Threads target. - # https://cmake.org/cmake/help/v2.8.12/cmake.html#module:FindThreads - # Also needed when cross-compiling to work around - # https://gitlab.kitware.com/cmake/cmake/issues/16920 - find_package(Threads) - target_link_libraries(OSDependent ${CMAKE_THREAD_LIBS_INIT}) -else() - # This is the recommended way, so we use it for 3.1+. - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads) - target_link_libraries(OSDependent Threads::Threads) -endif() - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OSDependent EXPORT OSDependentTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/glslang/glslang/OSDependent/Web/CMakeLists.txt b/libraries/glslang/glslang/OSDependent/Web/CMakeLists.txt deleted file mode 100644 index e8238c350..000000000 --- a/libraries/glslang/glslang/OSDependent/Web/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_executable(glslang.js "glslang.js.cpp") -glslang_set_link_args(glslang.js) -target_link_libraries(glslang.js glslang SPIRV) -if(EMSCRIPTEN) - set_target_properties(glslang.js PROPERTIES - OUTPUT_NAME "glslang" - SUFFIX ".js") - em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js") - - target_link_options(glslang.js PRIVATE - "SHELL:--bind -s MODULARIZE=1") - if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - target_link_options(glslang.js PRIVATE - "SHELL:-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") - else() - target_link_options(glslang.js PRIVATE - "SHELL:-s ENVIRONMENT=web,worker") - endif() - - if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - add_custom_command(TARGET glslang.js POST_BUILD - COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) - endif() -endif(EMSCRIPTEN) diff --git a/libraries/glslang/glslang/OSDependent/Web/glslang.pre.js b/libraries/glslang/glslang/OSDependent/Web/glslang.pre.js deleted file mode 100644 index 7d3fd0234..000000000 --- a/libraries/glslang/glslang/OSDependent/Web/glslang.pre.js +++ /dev/null @@ -1,45 +0,0 @@ -Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) { - gen_debug = !!gen_debug; - - var shader_stage_int; - if (shader_stage === 'vertex') { - shader_stage_int = 0; - } else if (shader_stage === 'fragment') { - shader_stage_int = 4; - } else if (shader_stage === 'compute') { - shader_stage_int = 5; - } else { - throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'"); - } - - var p_output = Module['_malloc'](4); - var p_output_len = Module['_malloc'](4); - var id = ccall('convert_glsl_to_spirv', - 'number', - ['string', 'number', 'boolean', 'number', 'number'], - [glsl, shader_stage_int, gen_debug, p_output, p_output_len]); - var output = getValue(p_output, 'i32'); - var output_len = getValue(p_output_len, 'i32'); - Module['_free'](p_output); - Module['_free'](p_output_len); - - if (id === 0) { - throw new Error('GLSL compilation failed'); - } - - var ret = {}; - var outputIndexU32 = output / 4; - ret['data'] = Module['HEAPU32'].subarray(outputIndexU32, outputIndexU32 + output_len); - ret['free'] = function() { - Module['_destroy_output_buffer'](id); - }; - - return ret; -}; - -Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) { - var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug); - var ret = compiled['data'].slice() - compiled['free'](); - return ret; -}; diff --git a/libraries/glslang/glslang/OSDependent/Windows/CMakeLists.txt b/libraries/glslang/glslang/OSDependent/Windows/CMakeLists.txt deleted file mode 100644 index c050ef61d..000000000 --- a/libraries/glslang/glslang/OSDependent/Windows/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(SOURCES ossource.cpp ../osinclude.h) - -add_library(OSDependent STATIC ${SOURCES}) -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -# MinGW GCC complains about function pointer casts to void*. -# Turn that off with -fpermissive. -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - target_compile_options(OSDependent PRIVATE -fpermissive) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - install(TARGETS OSDependent EXPORT OSDependentTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(EXPORT OSDependentTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/glslang/glslang/updateGrammar b/libraries/glslang/glslang/updateGrammar deleted file mode 100644 index 9384db948..000000000 --- a/libraries/glslang/glslang/updateGrammar +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -if [ "$1" = 'web' ] -then - m4 -P -DGLSLANG_WEB MachineIndependent/glslang.m4 > MachineIndependent/glslang.y -elif [ "$#" -eq 0 ] -then - m4 -P MachineIndependent/glslang.m4 > MachineIndependent/glslang.y -else - echo usage: - echo $0 web - echo $0 - exit -fi - -bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp diff --git a/libraries/glslang/spirv/CMakeLists.txt b/libraries/glslang/spirv/CMakeLists.txt deleted file mode 100644 index 16df27d7b..000000000 --- a/libraries/glslang/spirv/CMakeLists.txt +++ /dev/null @@ -1,118 +0,0 @@ -cmake_minimum_required( VERSION 3.1.0 ) - -make_release_only() -use_fast_math() - -# Request C++11 -if(${CMAKE_VERSION} VERSION_LESS 3.1) - # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD - # remove this block once CMake >=3.1 has fixated in the ecosystem - add_compile_options(-std=c++11) -else() - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) -endif() - -set(SOURCES - GlslangToSpv.cpp - InReadableOrder.cpp - Logger.cpp - SpvBuilder.cpp - SpvPostProcess.cpp - doc.cpp - SpvTools.cpp - disassemble.cpp) - -set(SPVREMAP_SOURCES - SPVRemapper.cpp - doc.cpp) - -set(HEADERS - bitutils.h - spirv.hpp - GLSL.std.450.h - GLSL.ext.EXT.h - GLSL.ext.KHR.h - GlslangToSpv.h - hex_float.h - Logger.h - SpvBuilder.h - spvIR.h - doc.h - SpvTools.h - disassemble.h - GLSL.ext.AMD.h - GLSL.ext.NV.h) - -set(SPVREMAP_HEADERS - SPVRemapper.h - doc.h) - -add_library(SPIRV STATIC ${LIB_TYPE} ${SOURCES} ${HEADERS}) -set_property(TARGET SPIRV PROPERTY FOLDER glslang) -set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON) -target_include_directories(SPIRV PUBLIC - $ - $) - -if (ENABLE_SPVREMAPPER) - add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) - set_property(TARGET SPVRemapper PROPERTY FOLDER glslang) - set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON) -endif() - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(SPIRV PROPERTIES PREFIX "") - if (ENABLE_SPVREMAPPER) - set_target_properties(SPVRemapper PROPERTIES PREFIX "") - endif() -endif() - -if(ENABLE_OPT) - target_include_directories(SPIRV - PRIVATE ${spirv-tools_SOURCE_DIR}/include - PRIVATE ${spirv-tools_SOURCE_DIR}/source - ) - target_link_libraries(SPIRV glslang SPIRV-Tools-opt) - target_include_directories(SPIRV PUBLIC - $ - $) -else() - target_link_libraries(SPIRV glslang) -endif(ENABLE_OPT) - -if(WIN32) - source_group("Source" FILES ${SOURCES} ${HEADERS}) - source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) -endif(WIN32) - -if(ENABLE_GLSLANG_INSTALL) - if(BUILD_SHARED_LIBS) - if (ENABLE_SPVREMAPPER) - install(TARGETS SPVRemapper EXPORT SPVRemapperTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - install(TARGETS SPIRV EXPORT SPIRVTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - else() - if (ENABLE_SPVREMAPPER) - install(TARGETS SPVRemapper EXPORT SPVRemapperTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - install(TARGETS SPIRV EXPORT SPIRVTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - - if (ENABLE_SPVREMAPPER) - install(EXPORT SPVRemapperTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - endif() - - install(EXPORT SPIRVTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - - install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/) - install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/) -endif(ENABLE_GLSLANG_INSTALL) diff --git a/libraries/lzma/C/7z.h b/libraries/lzma/C/7z.h index 6c7886e38..304f75ffc 100644 --- a/libraries/lzma/C/7z.h +++ b/libraries/lzma/C/7z.h @@ -1,5 +1,5 @@ /* 7z.h -- 7z interface -2017-04-03 : Igor Pavlov : Public domain */ +2018-07-02 : Igor Pavlov : Public domain */ #ifndef __7Z_H #define __7Z_H @@ -91,6 +91,8 @@ typedef struct UInt64 *CoderUnpackSizes; // for all coders in all folders Byte *CodersData; + + UInt64 RangeLimit; } CSzAr; UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); diff --git a/libraries/lzma/C/7zArcIn.c b/libraries/lzma/C/7zArcIn.c index f74d0fad5..0d9dec41e 100644 --- a/libraries/lzma/C/7zArcIn.c +++ b/libraries/lzma/C/7zArcIn.c @@ -1,5 +1,5 @@ /* 7zArcIn.c -- 7z Input functions -2018-12-31 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -75,7 +75,7 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) return SZ_OK; } -void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) +static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; @@ -83,7 +83,7 @@ void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } -void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) +static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; @@ -105,6 +105,8 @@ static void SzAr_Init(CSzAr *p) p->CoderUnpackSizes = NULL; p->CodersData = NULL; + + p->RangeLimit = 0; } static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) @@ -502,7 +504,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) return SZ_ERROR_ARCHIVE; if (propsSize >= 0x80) return SZ_ERROR_UNSUPPORTED; - coder->PropsOffset = sd->Data - dataStart; + coder->PropsOffset = (size_t)(sd->Data - dataStart); coder->PropsSize = (Byte)propsSize; sd->Data += (size_t)propsSize; sd->Size -= (size_t)propsSize; @@ -677,7 +679,7 @@ static SRes ReadUnpackInfo(CSzAr *p, { UInt32 numCoders, ci, numInStreams = 0; - p->FoCodersOffsets[fo] = sd.Data - startBufPtr; + p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr); RINOK(SzReadNumber32(&sd, &numCoders)); if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) @@ -797,7 +799,7 @@ static SRes ReadUnpackInfo(CSzAr *p, p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; { - size_t dataSize = sd.Data - startBufPtr; + 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); @@ -885,7 +887,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) numSubDigests += numStreams; } - ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; + ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data); continue; } if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) @@ -907,7 +909,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { ssi->sdSizes.Data = sd->Data; RINOK(SkipNumbers(sd, numUnpackSizesInData)); - ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; + ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data); RINOK(ReadID(sd, &type)); } @@ -919,7 +921,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { ssi->sdCRCs.Data = sd->Data; RINOK(SkipBitUi32s(sd, numSubDigests)); - ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; + ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); } else { @@ -947,7 +949,11 @@ static SRes SzReadStreamsInfo(CSzAr *p, if (type == k7zIdPackInfo) { RINOK(ReadNumber(sd, dataOffset)); + if (*dataOffset > p->RangeLimit) + return SZ_ERROR_ARCHIVE; RINOK(ReadPackInfo(p, sd, alloc)); + if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset) + return SZ_ERROR_ARCHIVE; RINOK(ReadID(sd, &type)); } if (type == k7zIdUnpackInfo) @@ -1028,12 +1034,12 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size return SZ_ERROR_ARCHIVE; for (p = data + pos; #ifdef _WIN32 - *(const UInt16 *)p != 0 + *(const UInt16 *)(const void *)p != 0 #else p[0] != 0 || p[1] != 0 #endif ; p += 2); - pos = p - data + 2; + pos = (size_t)(p - data) + 2; *offsets++ = (pos >> 1); } while (--numFiles); @@ -1133,6 +1139,8 @@ static SRes SzReadHeader2( SRes res; SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, p->startPosAfterHeader, &tempAr, allocTemp); *numTempBufs = tempAr.NumFolders; @@ -1526,11 +1534,13 @@ static SRes SzArEx_Open2( nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; + p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; + p->db.RangeLimit = nextHeaderOffset; + nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; @@ -1543,13 +1553,13 @@ static SRes SzArEx_Open2( { Int64 pos = 0; RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < startArcPos + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + 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, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1575,6 +1585,8 @@ static SRes SzArEx_Open2( Buf_Init(&tempBuf); SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); SzAr_Free(&tempAr, allocTemp); diff --git a/libraries/lzma/C/7zCrc.c b/libraries/lzma/C/7zCrc.c index b4d84f023..f186324dd 100644 --- a/libraries/lzma/C/7zCrc.c +++ b/libraries/lzma/C/7zCrc.c @@ -1,5 +1,5 @@ /* 7zCrc.c -- CRC32 init -2017-06-06 : Igor Pavlov : Public domain */ +2021-04-01 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -26,8 +26,20 @@ 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; +extern +CRC_FUNC g_CrcUpdateT0_32; +CRC_FUNC g_CrcUpdateT0_32; +extern +CRC_FUNC g_CrcUpdateT0_64; +CRC_FUNC g_CrcUpdateT0_64; +extern +CRC_FUNC g_CrcUpdate; CRC_FUNC g_CrcUpdate; UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; @@ -44,6 +56,7 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) #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) { const Byte *p = (const Byte *)data; @@ -53,6 +66,166 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U return v; } + +/* ---------- hardware CRC ---------- */ + +#ifdef MY_CPU_LE + +#if defined(MY_CPU_ARM_OR_ARM64) + +// #pragma message("ARM*") + + #if defined(_MSC_VER) + #if defined(MY_CPU_ARM64) + #if (_MSC_VER >= 1910) + #define USE_ARM64_CRC + #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 + #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) + #endif + #endif + #if defined(__ARM_FEATURE_CRC32) + #define USE_ARM64_CRC + #include + #endif + #endif + +#else + +// no hardware CRC + +// #define USE_CRC_EMU + +#ifdef USE_CRC_EMU + +#pragma message("ARM64 CRC emulation") + +MY_FORCE_INLINE +UInt32 __crc32b(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32w(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32d(UInt32 v, UInt64 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +#endif // USE_CRC_EMU + +#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE) + + + +#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#define T0_32_UNROLL_BYTES (4 * 4) +#define T0_64_UNROLL_BYTES (4 * 8) + +#ifndef ATTRIB_CRC +#define ATTRIB_CRC +#endif +// #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); +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_32_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_32_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +ATTRIB_CRC +UInt32 MY_FAST_CALL 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) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_64_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_64_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#endif // MY_CPU_LE + + + + void MY_FAST_CALL CrcGenerateTable() { UInt32 i; @@ -123,6 +296,27 @@ void MY_FAST_CALL CrcGenerateTable() } } #endif + #endif + #ifdef MY_CPU_LE + #ifdef USE_ARM64_CRC + if (CPU_IsSupported_CRC32()) + { + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = + #if defined(MY_CPU_ARM) + CrcUpdateT0_32; + #else + CrcUpdateT0_64; + #endif + } + #endif + + #ifdef USE_CRC_EMU + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = CrcUpdateT0_64; + #endif #endif } diff --git a/libraries/lzma/C/7zCrcOpt.c b/libraries/lzma/C/7zCrcOpt.c index 73beba298..69fad9ca2 100644 --- a/libraries/lzma/C/7zCrcOpt.c +++ b/libraries/lzma/C/7zCrcOpt.c @@ -1,5 +1,5 @@ /* 7zCrcOpt.c -- CRC32 calculation -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -9,6 +9,7 @@ #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) { const Byte *p = (const Byte *)data; @@ -16,7 +17,7 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U v = CRC_UPDATE_BYTE_2(v, *p); for (; size >= 4; size -= 4, p += 4) { - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x300)[((v ) & 0xFF)] ^ (table + 0x200)[((v >> 8) & 0xFF)] @@ -28,6 +29,7 @@ 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) { const Byte *p = (const Byte *)data; @@ -36,13 +38,13 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U for (; size >= 8; size -= 8, p += 8) { UInt32 d; - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x700)[((v ) & 0xFF)] ^ (table + 0x600)[((v >> 8) & 0xFF)] ^ (table + 0x500)[((v >> 16) & 0xFF)] ^ (table + 0x400)[((v >> 24))]; - d = *((const UInt32 *)p + 1); + d = *((const UInt32 *)(const void *)p + 1); v ^= (table + 0x300)[((d ) & 0xFF)] ^ (table + 0x200)[((d >> 8) & 0xFF)] @@ -72,7 +74,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co v = CRC_UPDATE_BYTE_2_BE(v, *p); for (; size >= 4; size -= 4, p += 4) { - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x000)[((v ) & 0xFF)] ^ (table + 0x100)[((v >> 8) & 0xFF)] @@ -94,13 +96,13 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, co for (; size >= 8; size -= 8, p += 8) { UInt32 d; - v ^= *(const UInt32 *)p; + v ^= *(const UInt32 *)(const void *)p; v = (table + 0x400)[((v ) & 0xFF)] ^ (table + 0x500)[((v >> 8) & 0xFF)] ^ (table + 0x600)[((v >> 16) & 0xFF)] ^ (table + 0x700)[((v >> 24))]; - d = *((const UInt32 *)p + 1); + d = *((const UInt32 *)(const void *)p + 1); v ^= (table + 0x000)[((d ) & 0xFF)] ^ (table + 0x100)[((d >> 8) & 0xFF)] diff --git a/libraries/lzma/C/7zDec.c b/libraries/lzma/C/7zDec.c index 7c4635211..fbfd016e1 100644 --- a/libraries/lzma/C/7zDec.c +++ b/libraries/lzma/C/7zDec.c @@ -1,5 +1,5 @@ /* 7zDec.c -- Decoding from 7z folder -2019-02-02 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -21,17 +21,20 @@ #endif #define k_Copy 0 -#define k_Delta 3 +#ifndef _7Z_NO_METHOD_LZMA2 #define k_LZMA2 0x21 +#endif #define k_LZMA 0x30101 -#define k_BCJ 0x3030103 #define k_BCJ2 0x303011B +#ifndef _7Z_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 @@ -56,7 +59,7 @@ static Byte ReadByte(const IByteIn *pp) return *p->cur++; if (p->res == SZ_OK) { - size_t size = p->cur - p->begin; + size_t size = (size_t)(p->cur - p->begin); p->processed += size; p->res = ILookInStream_Skip(p->inStream, size); size = (1 << 25); @@ -101,28 +104,32 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, c Ppmd7_Init(&ppmd, order); } { - CPpmd7z_RangeDec rc; - Ppmd7z_RangeDec_CreateVTable(&rc); - rc.Stream = &s.vt; - if (!Ppmd7z_RangeDec_Init(&rc)) + ppmd.rc.dec.Stream = &s.vt; + if (!Ppmd7z_RangeDec_Init(&ppmd.rc.dec)) res = SZ_ERROR_DATA; - else if (s.extra) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else + else if (!s.extra) { - SizeT i; - for (i = 0; i < outSize; i++) + Byte *buf = outBuffer; + const Byte *lim = buf + outSize; + for (; buf != lim; buf++) { - int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt); + int sym = Ppmd7z_DecodeSymbol(&ppmd); if (s.extra || sym < 0) break; - outBuffer[i] = (Byte)sym; + *buf = (Byte)sym; } - if (i != outSize) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + if (buf != lim) res = SZ_ERROR_DATA; + else if (!Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) + { + /* if (Ppmd7z_DecodeSymbol(&ppmd) != PPMD7_SYM_END || !Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) */ + res = SZ_ERROR_DATA; + } } + if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (size_t)(s.cur - s.begin) != inSize) + res = SZ_ERROR_DATA; } Ppmd7_Free(&ppmd, allocMain); return res; @@ -365,7 +372,9 @@ 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, diff --git a/libraries/lzma/C/7zStream.c b/libraries/lzma/C/7zStream.c index 6b5aa1621..28a14604f 100644 --- a/libraries/lzma/C/7zStream.c +++ b/libraries/lzma/C/7zStream.c @@ -1,5 +1,5 @@ /* 7zStream.c -- 7z Stream functions -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -37,7 +37,7 @@ SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) { - Int64 t = offset; + Int64 t = (Int64)offset; return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); } diff --git a/libraries/lzma/C/7zTypes.h b/libraries/lzma/C/7zTypes.h index 65b3af63c..fe4fde3ff 100644 --- a/libraries/lzma/C/7zTypes.h +++ b/libraries/lzma/C/7zTypes.h @@ -1,11 +1,13 @@ /* 7zTypes.h -- Basic types -2018-08-04 : Igor Pavlov : Public domain */ +2021-12-25 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #ifdef _WIN32 /* #include */ +#else +#include #endif #include @@ -43,18 +45,116 @@ EXTERN_C_BEGIN typedef int SRes; +#ifdef _MSC_VER + #if _MSC_VER > 1200 + #define MY_ALIGN(n) __declspec(align(n)) + #else + #define MY_ALIGN(n) + #endif +#else + #define MY_ALIGN(n) __attribute__ ((aligned(n))) +#endif + + #ifdef _WIN32 /* typedef DWORD WRes; */ typedef unsigned WRes; #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) -#else +// #define MY_HRES_ERROR__INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) +#else // _WIN32 + +// #define ENV_HAVE_LSTAT typedef int WRes; -#define MY__FACILITY_WIN32 7 -#define MY__FACILITY__WRes MY__FACILITY_WIN32 -#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) + +// (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_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \ + ( (HRESULT)(x) & 0x0000FFFF) \ + | (MY__FACILITY__WRes << 16) \ + | (HRESULT)0x80000000 )) + +#define MY_SRes_HRESULT_FROM_WRes(x) \ + ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x)) + +// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno) +#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x) + +/* +#define ERROR_FILE_NOT_FOUND 2L +#define ERROR_ACCESS_DENIED 5L +#define ERROR_NO_MORE_FILES 18L +#define ERROR_LOCK_VIOLATION 33L +#define ERROR_FILE_EXISTS 80L +#define ERROR_DISK_FULL 112L +#define ERROR_NEGATIVE_SEEK 131L +#define ERROR_ALREADY_EXISTS 183L +#define ERROR_DIRECTORY 267L +#define ERROR_TOO_MANY_POSTS 298L + +#define ERROR_INTERNAL_ERROR 1359L +#define ERROR_INVALID_REPARSE_DATA 4392L +#define ERROR_REPARSE_TAG_INVALID 4393L +#define ERROR_REPARSE_TAG_MISMATCH 4394L +*/ + +// we use errno equivalents for some WIN32 errors: + +#define ERROR_INVALID_PARAMETER EINVAL +#define ERROR_INVALID_FUNCTION EINVAL +#define ERROR_ALREADY_EXISTS EEXIST +#define ERROR_FILE_EXISTS EEXIST +#define ERROR_PATH_NOT_FOUND ENOENT +#define ERROR_FILE_NOT_FOUND ENOENT +#define ERROR_DISK_FULL ENOSPC +// #define ERROR_INVALID_HANDLE EBADF + +// we use FACILITY_WIN32 for errors that has no errno equivalent +// Too many posts were made to a semaphore. +#define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL) +#define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L) +#define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L) + +// 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) + +/* +// 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) +*/ + +// 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 +#define FILE_ATTRIBUTE_HIDDEN 0x0002 +#define FILE_ATTRIBUTE_SYSTEM 0x0004 +#define FILE_ATTRIBUTE_DIRECTORY 0x0010 +#define FILE_ATTRIBUTE_ARCHIVE 0x0020 +#define FILE_ATTRIBUTE_DEVICE 0x0040 +#define FILE_ATTRIBUTE_NORMAL 0x0080 +#define FILE_ATTRIBUTE_TEMPORARY 0x0100 +#define FILE_ATTRIBUTE_SPARSE_FILE 0x0200 +#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400 +#define FILE_ATTRIBUTE_COMPRESSED 0x0800 +#define FILE_ATTRIBUTE_OFFLINE 0x1000 +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000 +#define FILE_ATTRIBUTE_ENCRYPTED 0x4000 + +#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */ #endif @@ -63,6 +163,10 @@ typedef int WRes; #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif +#ifndef RINOK_WRes +#define RINOK_WRes(x) { WRes __result__ = (x); if (__result__ != 0) return __result__; } +#endif + typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; @@ -75,6 +179,40 @@ typedef int Int32; typedef unsigned int UInt32; #endif + +#ifndef _WIN32 + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +#define VOID void + +#define HRESULT LONG + +typedef void *LPVOID; +// typedef void VOID; +// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; +// gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits) +typedef long INT_PTR; +typedef unsigned long UINT_PTR; +typedef long LONG_PTR; +typedef unsigned long DWORD_PTR; + +typedef size_t SIZE_T; + +#endif // _WIN32 + + +#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. @@ -128,25 +266,37 @@ typedef int BoolInt; #define MY_CDECL __cdecl #define MY_FAST_CALL __fastcall -#else +#else // _MSC_VER -#define MY_NO_INLINE -#define MY_FORCE_INLINE -#define MY_CDECL -#define MY_FAST_CALL - -/* inline keyword : for C++ / C99 */ - -/* GCC, clang: */ -/* -#if defined (__GNUC__) && (__GNUC__ >= 4) -#define MY_FORCE_INLINE __attribute__((always_inline)) +#if (defined(__GNUC__) && (__GNUC__ >= 4)) \ + || (defined(__clang__) && (__clang_major__ >= 4)) \ + || defined(__INTEL_COMPILER) \ + || defined(__xlC__) #define MY_NO_INLINE __attribute__((noinline)) +// #define MY_FORCE_INLINE __attribute__((always_inline)) inline +#else +#define MY_NO_INLINE #endif -*/ +#define MY_FORCE_INLINE + + +#define MY_CDECL + +#if defined(_M_IX86) \ + || defined(__i386__) +// #define MY_FAST_CALL __attribute__((fastcall)) +// #define MY_FAST_CALL __attribute__((cdecl)) +#define MY_FAST_CALL +#elif defined(MY_CPU_AMD64) +// #define MY_FAST_CALL __attribute__((ms_abi)) +#define MY_FAST_CALL +#else +#define MY_FAST_CALL #endif +#endif // _MSC_VER + /* The following interfaces use first parameter as pointer to structure */ @@ -335,12 +485,11 @@ struct ISzAlloc GCC 4.8.1 : classes with non-public variable members" */ -#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) - +#define MY_container_of(ptr, type, m) ((type *)(void *)((char *)(void *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) #endif -#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) +#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) /* #define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) @@ -353,6 +502,7 @@ struct ISzAlloc */ +#define MY_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) #ifdef _WIN32 diff --git a/libraries/lzma/C/7zVersion.h b/libraries/lzma/C/7zVersion.h index c176823a4..e9363d37b 100644 --- a/libraries/lzma/C/7zVersion.h +++ b/libraries/lzma/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 19 -#define MY_VER_MINOR 00 +#define MY_VER_MAJOR 21 +#define MY_VER_MINOR 07 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "19.00" +#define MY_VERSION_NUMBERS "21.07" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,12 +10,12 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2019-02-21" +#define MY_DATE "2021-12-26" #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-2018 Igor Pavlov" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2021 Igor Pavlov" #ifdef USE_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR diff --git a/libraries/lzma/C/Bcj2.c b/libraries/lzma/C/Bcj2.c index 9a0046a65..c7b956708 100644 --- a/libraries/lzma/C/Bcj2.c +++ b/libraries/lzma/C/Bcj2.c @@ -1,5 +1,5 @@ /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) -2018-04-28 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -123,7 +123,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; const Byte *srcLim; Byte *dest; - SizeT num = p->lims[BCJ2_STREAM_MAIN] - src; + SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); if (num == 0) { @@ -134,7 +134,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) dest = p->dest; if (num > (SizeT)(p->destLim - dest)) { - num = p->destLim - dest; + num = (SizeT)(p->destLim - dest); if (num == 0) { p->state = BCJ2_DEC_STATE_ORIG; @@ -168,7 +168,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) break; } - num = src - p->bufs[BCJ2_STREAM_MAIN]; + num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); if (src == srcLim) { @@ -228,7 +228,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p) p->ip += 4; val -= p->ip; dest = p->dest; - rem = p->destLim - dest; + rem = (SizeT)(p->destLim - dest); if (rem < 4) { diff --git a/libraries/lzma/C/Bra.c b/libraries/lzma/C/Bra.c index aed17e330..3b854d9ca 100644 --- a/libraries/lzma/C/Bra.c +++ b/libraries/lzma/C/Bra.c @@ -1,5 +1,5 @@ /* Bra.c -- Converters for RISC code -2017-04-04 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -22,7 +22,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; if (p[-1] == 0xEB) break; @@ -43,7 +43,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; if (p[-1] == 0xEB) break; @@ -78,7 +78,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 b3; if (p > lim) - return p - data; + return (SizeT)(p - data); b1 = p[1]; b3 = p[3]; p += 2; @@ -113,7 +113,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 b3; if (p > lim) - return p - data; + return (SizeT)(p - data); b1 = p[1]; b3 = p[3]; p += 2; @@ -162,7 +162,7 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); p += 4; /* if ((v & 0xFC000003) == 0x48000001) */ if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) @@ -196,7 +196,7 @@ SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) for (;;) { if (p >= lim) - return p - data; + return (SizeT)(p - data); /* v = GetBe32(p); p += 4; diff --git a/libraries/lzma/C/Bra86.c b/libraries/lzma/C/Bra86.c index 93ed4d762..10a0fbd16 100644 --- a/libraries/lzma/C/Bra86.c +++ b/libraries/lzma/C/Bra86.c @@ -1,5 +1,5 @@ /* Bra86.c -- Converter for x86 code (BCJ) -2017-04-03 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -25,7 +25,7 @@ SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding break; { - SizeT d = (SizeT)(p - data - pos); + SizeT d = (SizeT)(p - data) - pos; pos = (SizeT)(p - data); if (p >= limit) { diff --git a/libraries/lzma/C/Compiler.h b/libraries/lzma/C/Compiler.h index 0cc409d8a..a9816fa5a 100644 --- a/libraries/lzma/C/Compiler.h +++ b/libraries/lzma/C/Compiler.h @@ -1,9 +1,13 @@ /* Compiler.h -2017-04-03 : Igor Pavlov : Public domain */ +2021-01-05 : Igor Pavlov : Public domain */ #ifndef __7Z_COMPILER_H #define __7Z_COMPILER_H + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wunused-private-field" + #endif + #ifdef _MSC_VER #ifdef UNDER_CE @@ -25,6 +29,12 @@ #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information #endif + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma clang diagnostic ignored "-Wmicrosoft-exception-spec" + // #pragma clang diagnostic ignored "-Wreserved-id-macro" + #endif + #endif #define UNUSED_VAR(x) (void)x; diff --git a/libraries/lzma/C/CpuArch.c b/libraries/lzma/C/CpuArch.c index 02e482e08..fa9afe397 100644 --- a/libraries/lzma/C/CpuArch.c +++ b/libraries/lzma/C/CpuArch.c @@ -1,5 +1,5 @@ /* CpuArch.c -- CPU specific code -2018-02-18: Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -55,6 +55,47 @@ static UInt32 CheckFlag(UInt32 flag) #define CHECK_CPUID_IS_SUPPORTED #endif +#ifndef USE_ASM + #ifdef _MSC_VER + #if _MSC_VER >= 1600 + #define MY__cpuidex __cpuidex + #else + +/* + __cpuid (function == 4) 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). + 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 + 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() !!! +*/ + +static +MY_NO_INLINE +void MY_FAST_CALL MY__cpuidex_HACK(UInt32 subFunction, int *CPUInfo, UInt32 function) +{ + UNUSED_VAR(subFunction); + __cpuid(CPUInfo, function); +} + + #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 +#endif + + + + void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) { #ifdef USE_ASM @@ -99,18 +140,20 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) #endif "=c" (*c) , "=d" (*d) - : "0" (function)) ; + : "0" (function), "c"(0) ) ; #endif #else int CPUInfo[4]; - __cpuid(CPUInfo, function); - *a = CPUInfo[0]; - *b = CPUInfo[1]; - *c = CPUInfo[2]; - *d = CPUInfo[3]; + + MY__cpuidex(CPUInfo, (int)function, 0); + + *a = (UInt32)CPUInfo[0]; + *b = (UInt32)CPUInfo[1]; + *c = (UInt32)CPUInfo[2]; + *d = (UInt32)CPUInfo[3]; #endif } @@ -174,7 +217,7 @@ BoolInt CPU_Is_InOrder() } #if !defined(MY_CPU_AMD64) && defined(_WIN32) -#include +#include static BoolInt CPU_Sys_Is_SSE_Supported() { OSVERSIONINFO vi; @@ -188,13 +231,101 @@ static BoolInt CPU_Sys_Is_SSE_Supported() #define CHECK_SYS_SSE_SUPPORT #endif -BoolInt CPU_Is_Aes_Supported() + +static UInt32 X86_CPUID_ECX_Get_Flags() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return 0; + return p.c; +} + +BoolInt CPU_IsSupported_AES() +{ + return (X86_CPUID_ECX_Get_Flags() >> 25) & 1; +} + +BoolInt CPU_IsSupported_SSSE3() +{ + return (X86_CPUID_ECX_Get_Flags() >> 9) & 1; +} + +BoolInt CPU_IsSupported_SSE41() +{ + return (X86_CPUID_ECX_Get_Flags() >> 19) & 1; +} + +BoolInt CPU_IsSupported_SHA() { Cx86cpuid p; CHECK_SYS_SSE_SUPPORT if (!x86cpuid_CheckAndRead(&p)) return False; - return (p.c >> 25) & 1; + + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + return (d[1] >> 29) & 1; + } +} + +// #include + +#ifdef _WIN32 +#include +#endif + +BoolInt CPU_IsSupported_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5); // avx2 + } +} + +BoolInt CPU_IsSupported_VAES_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5) // avx2 + // & (d[1] >> 31) // avx512vl + & (d[2] >> 9); // vaes // VEX-256/EVEX + } } BoolInt CPU_IsSupported_PageGB() @@ -215,4 +346,133 @@ BoolInt CPU_IsSupported_PageGB() } } + +#elif defined(MY_CPU_ARM_OR_ARM64) + +#ifdef _WIN32 + +#include + +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; } + +#else + +#if defined(__APPLE__) + +/* +#include +#include +static void Print_sysctlbyname(const char *name) +{ + size_t bufSize = 256; + char buf[256]; + int res = sysctlbyname(name, &buf, &bufSize, NULL, 0); + { + int i; + printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize); + for (i = 0; i < 20; i++) + printf(" %2x", (unsigned)(Byte)buf[i]); + + } +} +*/ + +static BoolInt My_sysctlbyname_Get_BoolInt(const char *name) +{ + UInt32 val = 0; + if (My_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"); +} + +BoolInt CPU_IsSupported_NEON(void) +{ + return My_sysctlbyname_Get_BoolInt("hw.optional.neon"); +} + +#ifdef MY_CPU_ARM64 +#define APPLE_CRYPTO_SUPPORT_VAL 1 +#else +#define APPLE_CRYPTO_SUPPORT_VAL 0 +#endif + +BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } + + +#else // __APPLE__ + +#include + +#define USE_HWCAP + +#ifdef USE_HWCAP + +#include + + #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ + BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; } + +#ifdef MY_CPU_ARM64 + #define MY_HWCAP_CHECK_FUNC(name) \ + MY_HWCAP_CHECK_FUNC_2(name, name) + MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) +// MY_HWCAP_CHECK_FUNC (ASIMD) +#elif defined(MY_CPU_ARM) + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; } + MY_HWCAP_CHECK_FUNC_2(NEON, NEON) +#endif + +#else // USE_HWCAP + + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return 0; } + MY_HWCAP_CHECK_FUNC(NEON) + +#endif // USE_HWCAP + +MY_HWCAP_CHECK_FUNC (CRC32) +MY_HWCAP_CHECK_FUNC (SHA1) +MY_HWCAP_CHECK_FUNC (SHA2) +MY_HWCAP_CHECK_FUNC (AES) + +#endif // __APPLE__ +#endif // _WIN32 + +#endif // MY_CPU_ARM_OR_ARM64 + + + +#ifdef __APPLE__ + +#include + +int My_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) +{ + size_t bufSize = sizeof(*val); + int res = My_sysctlbyname_Get(name, val, &bufSize); + if (res == 0 && bufSize != sizeof(*val)) + return EFAULT; + return res; +} + #endif diff --git a/libraries/lzma/C/CpuArch.h b/libraries/lzma/C/CpuArch.h index bd4293880..529d3a502 100644 --- a/libraries/lzma/C/CpuArch.h +++ b/libraries/lzma/C/CpuArch.h @@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code -2018-02-18 : Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H @@ -14,6 +14,10 @@ MY_CPU_BE means that CPU is BIG ENDIAN. If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. + +MY_CPU_64BIT means that processor can work with 64-bit registers. + MY_CPU_64BIT can be used to select fast code branch + MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) */ #if defined(_M_X64) \ @@ -24,8 +28,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define MY_CPU_AMD64 #ifdef __ILP32__ #define MY_CPU_NAME "x32" + #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "x64" + #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT #endif @@ -35,7 +41,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem || defined(__i386__) #define MY_CPU_X86 #define MY_CPU_NAME "x86" - #define MY_CPU_32BIT + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 #endif @@ -59,8 +66,14 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem || defined(__THUMBEL__) \ || defined(__THUMBEB__) #define MY_CPU_ARM - #define MY_CPU_NAME "arm" - #define MY_CPU_32BIT + + #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) + #define MY_CPU_NAME "armt" + #else + #define MY_CPU_NAME "arm" + #endif + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 #endif @@ -84,17 +97,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #if defined(__ppc64__) \ - || defined(__powerpc64__) + || defined(__powerpc64__) \ + || defined(__ppc__) \ + || defined(__powerpc__) \ + || defined(__PPC__) \ + || defined(_POWER) + +#if defined(__ppc64__) \ + || defined(__powerpc64__) \ + || defined(_LP64) \ + || defined(__64BIT__) #ifdef __ILP32__ #define MY_CPU_NAME "ppc64-32" + #define MY_CPU_SIZEOF_POINTER 4 #else #define MY_CPU_NAME "ppc64" + #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT -#elif defined(__ppc__) \ - || defined(__powerpc__) +#else #define MY_CPU_NAME "ppc" - #define MY_CPU_32BIT + #define MY_CPU_SIZEOF_POINTER 4 + /* #define MY_CPU_32BIT */ +#endif #endif @@ -111,6 +136,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define MY_CPU_X86_OR_AMD64 #endif +#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64) +#define MY_CPU_ARM_OR_ARM64 +#endif + #ifdef _WIN32 @@ -170,6 +199,40 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #error Stop_Compiling_Bad_32_64_BIT #endif +#ifdef __SIZEOF_POINTER__ + #ifdef MY_CPU_SIZEOF_POINTER + #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__ + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE + #endif + #else + #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__ + #endif +#endif + +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +#if defined (_LP64) + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE +#endif +#endif + +#ifdef _MSC_VER + #if _MSC_VER >= 1300 + #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1)) + #define MY_CPU_pragma_pop __pragma(pack(pop)) + #else + #define MY_CPU_pragma_pack_push_1 + #define MY_CPU_pragma_pop + #endif +#else + #ifdef __xlC__ + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)") + #define MY_CPU_pragma_pop _Pragma("pack()") + #else + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)") + #define MY_CPU_pragma_pop _Pragma("pack(pop)") + #endif +#endif + #ifndef MY_CPU_NAME #ifdef MY_CPU_LE @@ -189,8 +252,12 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #ifdef MY_CPU_LE #if defined(MY_CPU_X86_OR_AMD64) \ - || defined(MY_CPU_ARM64) \ - || defined(__ARM_FEATURE_UNALIGNED) + || defined(MY_CPU_ARM64) + #define MY_CPU_LE_UNALIGN + #define MY_CPU_LE_UNALIGN_64 + #elif defined(__ARM_FEATURE_UNALIGNED) + /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. + So we can't use unaligned 64-bit operations. */ #define MY_CPU_LE_UNALIGN #endif #endif @@ -200,11 +267,15 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#ifdef MY_CPU_LE_UNALIGN_64 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) +#endif -#define SetUi16(p, v) { *(UInt16 *)(p) = (v); } -#define SetUi32(p, v) { *(UInt32 *)(p) = (v); } -#define SetUi64(p, v) { *(UInt64 *)(p) = (v); } +#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 @@ -218,8 +289,6 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) -#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) - #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ _ppp_[0] = (Byte)_vvv_; \ _ppp_[1] = (Byte)(_vvv_ >> 8); } @@ -230,19 +299,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem _ppp_[2] = (Byte)(_vvv_ >> 16); \ _ppp_[3] = (Byte)(_vvv_ >> 24); } +#endif + + +#ifndef MY_CPU_LE_UNALIGN_64 + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ SetUi32(_ppp2_ , (UInt32)_vvv2_); \ SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } #endif + + + #ifdef __has_builtin #define MY__has_builtin(x) __has_builtin(x) #else #define MY__has_builtin(x) 0 #endif -#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) +#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 */ @@ -253,8 +332,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem #pragma intrinsic(_byteswap_uint64) /* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ -#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(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) @@ -262,9 +341,9 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) -/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ -#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) +/* #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) @@ -325,10 +404,37 @@ int x86cpuid_GetFirm(const Cx86cpuid *p); #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) #define x86cpuid_GetStepping(ver) (ver & 0xF) -BoolInt CPU_Is_InOrder(); -BoolInt CPU_Is_Aes_Supported(); -BoolInt CPU_IsSupported_PageGB(); +BoolInt CPU_Is_InOrder(void); +BoolInt CPU_IsSupported_AES(void); +BoolInt CPU_IsSupported_AVX2(void); +BoolInt CPU_IsSupported_VAES_AVX2(void); +BoolInt CPU_IsSupported_SSSE3(void); +BoolInt CPU_IsSupported_SSE41(void); +BoolInt CPU_IsSupported_SHA(void); +BoolInt CPU_IsSupported_PageGB(void); + +#elif defined(MY_CPU_ARM_OR_ARM64) + +BoolInt CPU_IsSupported_CRC32(void); +BoolInt CPU_IsSupported_NEON(void); + +#if defined(_WIN32) +BoolInt CPU_IsSupported_CRYPTO(void); +#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO +#else +BoolInt CPU_IsSupported_SHA1(void); +BoolInt CPU_IsSupported_SHA2(void); +BoolInt CPU_IsSupported_AES(void); +#endif + +#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); #endif EXTERN_C_END diff --git a/libraries/lzma/C/Delta.c b/libraries/lzma/C/Delta.c index e3edd21ed..c4a4499fe 100644 --- a/libraries/lzma/C/Delta.c +++ b/libraries/lzma/C/Delta.c @@ -1,5 +1,5 @@ /* Delta.c -- Delta converter -2009-05-26 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -12,53 +12,158 @@ void Delta_Init(Byte *state) state[i] = 0; } -static void MyMemCpy(Byte *dest, const Byte *src, unsigned size) -{ - unsigned i; - for (i = 0; i < size; i++) - dest[i] = src[i]; -} void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) { - Byte buf[DELTA_STATE_SIZE]; - unsigned j = 0; - MyMemCpy(buf, state, delta); + Byte temp[DELTA_STATE_SIZE]; + + if (size == 0) + return; + { - SizeT i; - for (i = 0; i < size;) + unsigned i = 0; + do + temp[i] = state[i]; + while (++i != delta); + } + + if (size <= delta) + { + unsigned i = 0, k; + do { - for (j = 0; j < delta && i < size; i++, j++) + Byte b = *data; + *data++ = (Byte)(b - temp[i]); + temp[i] = b; + } + while (++i != size); + + k = 0; + + do + { + if (i == delta) + i = 0; + state[k] = temp[i++]; + } + while (++k != delta); + + return; + } + + { + Byte *p = data + size - delta; + { + unsigned i = 0; + do + state[i] = *p++; + while (++i != delta); + } + { + const Byte *lim = data + delta; + ptrdiff_t dif = -(ptrdiff_t)delta; + + if (((ptrdiff_t)size + dif) & 1) { - Byte b = data[i]; - data[i] = (Byte)(b - buf[j]); - buf[j] = b; + --p; *p = (Byte)(*p - p[dif]); } + + while (p != lim) + { + --p; *p = (Byte)(*p - p[dif]); + --p; *p = (Byte)(*p - p[dif]); + } + + dif = -dif; + + do + { + --p; *p = (Byte)(*p - temp[--dif]); + } + while (dif != 0); } } - if (j == delta) - j = 0; - MyMemCpy(state, buf + j, delta - j); - MyMemCpy(state + delta - j, buf, j); } + void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) { - Byte buf[DELTA_STATE_SIZE]; - unsigned j = 0; - MyMemCpy(buf, state, delta); + unsigned i; + const Byte *lim; + + if (size == 0) + return; + + i = 0; + lim = data + size; + + if (size <= delta) { - SizeT i; - for (i = 0; i < size;) + do + *data = (Byte)(*data + state[i++]); + while (++data != lim); + + for (; delta != i; state++, delta--) + *state = state[i]; + data -= i; + } + else + { + /* + #define B(n) b ## n + #define I(n) Byte B(n) = state[n]; + #define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); } + #define F(n) if (data != lim) { U(n) } + + if (delta == 1) { - for (j = 0; j < delta && i < size; i++, j++) + I(0) + if ((lim - data) & 1) { U(0) } + while (data != lim) { U(0) U(0) } + data -= 1; + } + else if (delta == 2) + { + I(0) I(1) + lim -= 1; while (data < lim) { U(0) U(1) } + lim += 1; F(0) + data -= 2; + } + else if (delta == 3) + { + I(0) I(1) I(2) + lim -= 2; while (data < lim) { U(0) U(1) U(2) } + lim += 2; F(0) F(1) + data -= 3; + } + else if (delta == 4) + { + I(0) I(1) I(2) I(3) + lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) } + lim += 3; F(0) F(1) F(2) + data -= 4; + } + else + */ + { + do { - buf[j] = data[i] = (Byte)(buf[j] + data[i]); + *data = (Byte)(*data + state[i++]); + data++; + } + while (i != delta); + + { + ptrdiff_t dif = -(ptrdiff_t)delta; + do + *data = (Byte)(*data + data[dif]); + while (++data != lim); + data += dif; } } } - if (j == delta) - j = 0; - MyMemCpy(state, buf + j, delta - j); - MyMemCpy(state + delta - j, buf, j); + + do + *state++ = *data; + while (++data != lim); } diff --git a/libraries/lzma/C/LzFind.c b/libraries/lzma/C/LzFind.c index df55e86c1..1b73c2848 100644 --- a/libraries/lzma/C/LzFind.c +++ b/libraries/lzma/C/LzFind.c @@ -1,20 +1,69 @@ /* LzFind.c -- Match finder for LZ algorithms -2018-07-08 : Igor Pavlov : Public domain */ +2021-11-29 : Igor Pavlov : Public domain */ #include "Precomp.h" #include +// #include +#include "CpuArch.h" #include "LzFind.h" #include "LzHash.h" -#define kEmptyHashValue 0 -#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) -#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ -#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1)) -#define kMaxHistorySize ((UInt32)7 << 29) +#define kBlockMoveAlign (1 << 7) // alignment for memmove() +#define kBlockSizeAlign (1 << 16) // alignment for block allocation +#define kBlockSizeReserveMin (1 << 24) // it's 1/256 from 4 GB dictinary + +#define kEmptyHashValue 0 + +#define kMaxValForNormalize ((UInt32)0) +// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xFFF) // for debug + +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#define GET_AVAIL_BYTES(p) \ + Inline_MatchFinder_GetNumAvailableBytes(p) + + +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +#define kFix5HashSize kFix4HashSize + +/* + HASH2_CALC: + if (hv) match, then cur[0] and cur[1] also match +*/ +#define HASH2_CALC hv = GetUi16(cur); + +// (crc[0 ... 255] & 0xFF) provides one-to-one correspondence to [0 ... 255] + +/* + HASH3_CALC: + if (cur[0]) and (h2) match, then cur[1] also match + if (cur[0]) and (hv) match, then cur[1] and cur[2] also match +*/ +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + hv = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + temp ^= (p->crc[cur[3]] << kLzHash_CrcShift_1); \ + /* h4 = temp & p->hash4Mask; */ /* (kHash4Size - 1); */ \ + hv = (temp ^ (p->crc[cur[4]] << kLzHash_CrcShift_2)) & p->hashMask; } + +#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; -#define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) { @@ -25,46 +74,57 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) } } -/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ -static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc) +static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr alloc) { - UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; - if (p->directInput) - { - p->blockSize = blockSize; - return 1; - } + if (blockSize == 0) + return 0; if (!p->bufferBase || p->blockSize != blockSize) { + // size_t blockSizeT; LzInWindow_Free(p, alloc); p->blockSize = blockSize; - p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize); + // blockSizeT = blockSize; + + // printf("\nblockSize = 0x%x\n", blockSize); + /* + #if defined _WIN64 + // we can allocate 4GiB, but still use UInt32 for (p->blockSize) + // we use UInt32 type for (p->blockSize), because + // we don't want to wrap over 4 GiB, + // when we use (p->streamPos - p->pos) that is UInt32. + if (blockSize >= (UInt32)0 - (UInt32)kBlockSizeAlign) + { + blockSizeT = ((size_t)1 << 32); + printf("\nchanged to blockSizeT = 4GiB\n"); + } + #endif + */ + + p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); + // printf("\nbufferBase = %p\n", p->bufferBase); + // return 0; // for debug } return (p->bufferBase != NULL); } -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) -{ - p->posLimit -= subValue; - p->pos -= subValue; - p->streamPos -= subValue; -} +MY_NO_INLINE static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; - /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */ + /* We use (p->streamPos - p->pos) value. + (p->streamPos < p->pos) is allowed. */ if (p->directInput) { - UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos); + UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p); if (curSize > p->directInputRem) curSize = (UInt32)p->directInputRem; p->directInputRem -= curSize; @@ -76,10 +136,22 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) for (;;) { - Byte *dest = p->buffer + (p->streamPos - p->pos); - size_t size = (p->bufferBase + p->blockSize - dest); + Byte *dest = p->buffer + GET_AVAIL_BYTES(p); + size_t size = (size_t)(p->bufferBase + p->blockSize - dest); if (size == 0) + { + /* we call ReadBlock() after NeedMove() and MoveBlock(). + NeedMove() and MoveBlock() povide more than (keepSizeAfter) + to the end of (blockSize). + So we don't execute this branch in normal code flow. + We can go here, if we will call ReadBlock() before NeedMove(), MoveBlock(). + */ + // p->result = SZ_ERROR_FAIL; // we can show error here return; + } + + // #define kRead 3 + // if (size > kRead) size = kRead; // for debug p->result = ISeqInStream_Read(p->stream, dest, &size); if (p->result != SZ_OK) @@ -90,41 +162,52 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) return; } p->streamPos += (UInt32)size; - if (p->streamPos - p->pos > p->keepSizeAfter) + if (GET_AVAIL_BYTES(p) > p->keepSizeAfter) return; + /* here and in another (p->keepSizeAfter) checks we keep on 1 byte more than was requested by Create() function + (GET_AVAIL_BYTES(p) >= p->keepSizeAfter) - minimal required size */ } + + // on exit: (p->result != SZ_OK || p->streamEndWasReached || GET_AVAIL_BYTES(p) > p->keepSizeAfter) } + + +MY_NO_INLINE void MatchFinder_MoveBlock(CMatchFinder *p) { + const size_t offset = (size_t)(p->buffer - p->bufferBase) - p->keepSizeBefore; + const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore; + p->buffer = p->bufferBase + keepBefore; memmove(p->bufferBase, - p->buffer - p->keepSizeBefore, - (size_t)(p->streamPos - p->pos) + p->keepSizeBefore); - p->buffer = p->bufferBase + p->keepSizeBefore; + p->bufferBase + (offset & ~((size_t)kBlockMoveAlign - 1)), + keepBefore + (size_t)GET_AVAIL_BYTES(p)); } +/* We call MoveBlock() before ReadBlock(). + So MoveBlock() can be wasteful operation, if the whole input data + can fit in current block even without calling MoveBlock(). + in important case where (dataSize <= historySize) + condition (p->blockSize > dataSize + p->keepSizeAfter) is met + So there is no MoveBlock() in that case case. +*/ + int MatchFinder_NeedMove(CMatchFinder *p) { if (p->directInput) return 0; - /* if (p->streamEndWasReached) return 0; */ + if (p->streamEndWasReached || p->result != SZ_OK) + return 0; return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { - if (p->streamEndWasReached) - return; - if (p->keepSizeAfter >= p->streamPos - p->pos) + if (p->keepSizeAfter >= GET_AVAIL_BYTES(p)) MatchFinder_ReadBlock(p); } -static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) -{ - if (MatchFinder_NeedMove(p)) - MatchFinder_MoveBlock(p); - MatchFinder_ReadBlock(p); -} + static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { @@ -175,39 +258,74 @@ static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); } +#if (kBlockSizeReserveMin < kBlockSizeAlign * 2) + #error Stop_Compiling_Bad_Reserve +#endif + + + +static UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize) +{ + UInt32 blockSize = (p->keepSizeBefore + p->keepSizeAfter); + /* + if (historySize > kMaxHistorySize) + return 0; + */ + // printf("\nhistorySize == 0x%x\n", historySize); + + if (p->keepSizeBefore < historySize || blockSize < p->keepSizeBefore) // if 32-bit overflow + return 0; + + { + const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)kBlockSizeAlign; + const UInt32 rem = kBlockSizeMax - blockSize; + const UInt32 reserve = (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)) + + (1 << 12) + kBlockMoveAlign + kBlockSizeAlign; // do not overflow 32-bit here + if (blockSize >= kBlockSizeMax + || rem < kBlockSizeReserveMin) // we reject settings that will be slow + return 0; + if (reserve >= rem) + blockSize = kBlockSizeMax; + else + { + blockSize += reserve; + blockSize &= ~(UInt32)(kBlockSizeAlign - 1); + } + } + // printf("\n LzFind_blockSize = %x\n", blockSize); + // printf("\n LzFind_blockSize = %d\n", blockSize >> 20); + return blockSize; +} + + int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { - UInt32 sizeReserv; - - if (historySize > kMaxHistorySize) - { - MatchFinder_Free(p, alloc); - return 0; - } - - sizeReserv = historySize >> 1; - if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3; - else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2; - - sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); - + /* we need one additional byte in (p->keepSizeBefore), + since we use MoveBlock() after (p->pos++) and before dictionary using */ + // keepAddBufferBefore = (UInt32)0xFFFFFFFF - (1 << 22); // for debug p->keepSizeBefore = historySize + keepAddBufferBefore + 1; - p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; - - /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ - - if (LzInWindow_Create(p, sizeReserv, alloc)) + + keepAddBufferAfter += matchMaxLen; + /* we need (p->keepSizeAfter >= p->numHashBytes) */ + if (keepAddBufferAfter < p->numHashBytes) + keepAddBufferAfter = p->numHashBytes; + // keepAddBufferAfter -= 2; // for debug + p->keepSizeAfter = keepAddBufferAfter; + + if (p->directInput) + p->blockSize = 0; + if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc)) { - UInt32 newCyclicBufferSize = historySize + 1; + const UInt32 newCyclicBufferSize = historySize + 1; // do not change it UInt32 hs; p->matchMaxLen = matchMaxLen; { + // UInt32 hs4; p->fixedHashSize = 0; - if (p->numHashBytes == 2) - hs = (1 << 16) - 1; - else + hs = (1 << 16) - 1; + if (p->numHashBytes != 2) { hs = historySize; if (hs > p->expectedDataSize) @@ -218,9 +336,9 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); + // we propagated 16 bits in (hs). Low 16 bits must be set later hs >>= 1; - hs |= 0xFFFF; /* don't change it! It's required for Deflate */ - if (hs > (1 << 24)) + if (hs >= (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; @@ -228,12 +346,30 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs >>= 1; /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ } + + // hs = ((UInt32)1 << 25) - 1; // for test + + // (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; } p->hashMask = hs; hs++; + + /* + hs4 = (1 << 20); + if (hs4 > hs) + hs4 = hs; + // hs4 = (1 << 16); // for test + p->hash4Mask = hs4 - 1; + */ + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; - if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; hs += p->fixedHashSize; } @@ -242,13 +378,17 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, size_t numSons; p->historySize = historySize; p->hashSizeSum = hs; - p->cyclicBufferSize = newCyclicBufferSize; + p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1) numSons = newCyclicBufferSize; if (p->btMode) numSons <<= 1; newSize = hs + numSons; + // 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) return 1; @@ -268,33 +408,43 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, return 0; } + static void MatchFinder_SetLimits(CMatchFinder *p) { - UInt32 limit = kMaxValForNormalize - p->pos; - UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + UInt32 k; + UInt32 n = kMaxValForNormalize - p->pos; + if (n == 0) + n = (UInt32)(Int32)-1; // we allow (pos == 0) at start even with (kMaxValForNormalize == 0) - if (limit2 < limit) - limit = limit2; - limit2 = p->streamPos - p->pos; - - if (limit2 <= p->keepSizeAfter) + k = p->cyclicBufferSize - p->cyclicBufferPos; + if (k < n) + n = k; + + k = GET_AVAIL_BYTES(p); { - if (limit2 > 0) - limit2 = 1; + const UInt32 ksa = p->keepSizeAfter; + UInt32 mm = p->matchMaxLen; + if (k > ksa) + k -= ksa; // we must limit exactly to keepSizeAfter for ReadBlock + else if (k >= mm) + { + // the limitation for (p->lenLimit) update + k -= mm; // optimization : to reduce the number of checks + k++; + // k = 1; // non-optimized version : for debug + } + else + { + mm = k; + if (k != 0) + k = 1; + } + p->lenLimit = mm; } - else - limit2 -= p->keepSizeAfter; + if (k < n) + n = k; - if (limit2 < limit) - limit = limit2; - - { - UInt32 lenLimit = p->streamPos - p->pos; - if (lenLimit > p->matchMaxLen) - lenLimit = p->matchMaxLen; - p->lenLimit = lenLimit; - } - p->posLimit = p->pos + limit; + p->posLimit = p->pos + n; } @@ -302,7 +452,7 @@ void MatchFinder_Init_LowHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash; - size_t numItems = p->fixedHashSize; + const size_t numItems = p->fixedHashSize; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } @@ -312,72 +462,322 @@ void MatchFinder_Init_HighHash(CMatchFinder *p) { size_t i; CLzRef *items = p->hash + p->fixedHashSize; - size_t numItems = (size_t)p->hashMask + 1; + const size_t numItems = (size_t)p->hashMask + 1; for (i = 0; i < numItems; i++) items[i] = kEmptyHashValue; } -void MatchFinder_Init_3(CMatchFinder *p, int readData) +void MatchFinder_Init_4(CMatchFinder *p) { - p->cyclicBufferPos = 0; p->buffer = p->bufferBase; - p->pos = - p->streamPos = p->cyclicBufferSize; + { + /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker. + the code in CMatchFinderMt expects (pos = 1) */ + p->pos = + p->streamPos = + 1; // it's smallest optimal value. do not change it + // 0; // for debug + } p->result = SZ_OK; p->streamEndWasReached = 0; - - if (readData) - MatchFinder_ReadBlock(p); - - MatchFinder_SetLimits(p); } +// (CYC_TO_POS_OFFSET == 0) is expected by some optimized code +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug + void MatchFinder_Init(CMatchFinder *p) { MatchFinder_Init_HighHash(p); MatchFinder_Init_LowHash(p); - MatchFinder_Init_3(p, True); + MatchFinder_Init_4(p); + // if (readData) + MatchFinder_ReadBlock(p); + + /* if we init (cyclicBufferPos = pos), then we can use one variable + instead of both (cyclicBufferPos) and (pos) : only before (cyclicBufferPos) wrapping */ + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); // init with relation to (pos) + // p->cyclicBufferPos = 0; // smallest value + // p->son[0] = p->son[1] = 0; // unused: we can init skipped record for speculated accesses. + MatchFinder_SetLimits(p); } - -static UInt32 MatchFinder_GetSubValue(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"))) + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1600) + #define USE_SATUR_SUB_128 + #if (_MSC_VER >= 1900) + #define USE_AVX2 + #include // avx + #endif + #endif + #endif + +// #elif defined(MY_CPU_ARM_OR_ARM64) +#elif defined(MY_CPU_ARM64) + + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) + #define USE_SATUR_SUB_128 + #ifdef MY_CPU_ARM64 + // #define ATTRIB_SSE41 __attribute__((__target__(""))) + #else + // #define ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif + + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1910) + #define USE_SATUR_SUB_128 + #endif + #endif + + #if defined(_MSC_VER) && defined(MY_CPU_ARM64) + #include + #else + #include + #endif + +#endif + +/* +#ifndef ATTRIB_SSE41 + #define ATTRIB_SSE41 +#endif +#ifndef ATTRIB_AVX2 + #define ATTRIB_AVX2 +#endif +*/ + +#ifdef USE_SATUR_SUB_128 + +// #define _SHOW_HW_STATUS + +#ifdef _SHOW_HW_STATUS +#include +#define _PRF(x) x +_PRF(;) +#else +#define _PRF(x) +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +#ifdef MY_CPU_ARM64 +// #define FORCE_SATUR_SUB_128 +#endif + +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 + +#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 + +#endif + + + +MY_NO_INLINE +static +#ifdef ATTRIB_SSE41 +ATTRIB_SSE41 +#endif +void +MY_FAST_CALL +LzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim) { - return (p->pos - p->historySize - 1) & kNormalizeMask; + 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 + do + { + SASUB_128(0) + SASUB_128(1) + SASUB_128(2) + SASUB_128(3) + items += 4 * 4; + } + while (items != lim); } + + +#ifdef USE_AVX2 + +#include // avx + +#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 + +MY_NO_INLINE +static +#ifdef ATTRIB_AVX2 +ATTRIB_AVX2 +#endif +void +MY_FAST_CALL +LzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + __m256i sub2 = _mm256_set_epi32( + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + do + { + SASUB_256(0) + SASUB_256(1) + items += 2 * 8; + } + while (items != lim); +} +#endif // USE_AVX2 + +#ifndef FORCE_SATUR_SUB_128 +typedef void (MY_FAST_CALL *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 // USE_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; + +#ifdef FORCE_SATUR_SUB_128 + +#define DEFAULT_SaturSub LzFind_SaturSub_128 + +#else + +#define DEFAULT_SaturSub LzFind_SaturSub_32 + +MY_NO_INLINE +static +void +MY_FAST_CALL +LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + 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; + } + while (items != lim); +} + +#endif + + +MY_NO_INLINE void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) { - size_t i; - for (i = 0; i < numItems; i++) + #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--) { - UInt32 value = items[i]; - if (value <= subValue) - value = kEmptyHashValue; - else - value -= subValue; - items[i] = value; + UInt32 v; + 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; + if (items != lim) + { + #if defined(USE_SATUR_SUB_128) && !defined(FORCE_SATUR_SUB_128) + if (g_LzFind_SaturSub) + g_LzFind_SaturSub(subValue, items, lim); + else + #endif + DEFAULT_SaturSub(subValue, items, lim); + } + items = lim; + } + + + for (; numItems != 0; numItems--) + { + UInt32 v; + SASUB_32(0); + items++; } } -static void MatchFinder_Normalize(CMatchFinder *p) -{ - UInt32 subValue = MatchFinder_GetSubValue(p); - MatchFinder_Normalize3(subValue, p->hash, p->numRefs); - MatchFinder_ReduceOffsets(p, subValue); -} +// call MatchFinder_CheckLimits() only after (p->pos++) update + MY_NO_INLINE static void MatchFinder_CheckLimits(CMatchFinder *p) { + if (// !p->streamEndWasReached && p->result == SZ_OK && + p->keepSizeAfter == GET_AVAIL_BYTES(p)) + { + // we try to read only in exact state (p->keepSizeAfter == GET_AVAIL_BYTES(p)) + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); + } + if (p->pos == kMaxValForNormalize) - MatchFinder_Normalize(p); - if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) - MatchFinder_CheckAndMoveAndRead(p); + if (GET_AVAIL_BYTES(p) >= p->numHashBytes) // optional optimization for last bytes of data. + /* + if we disable normalization for last bytes of data, and + if (data_size == 4 GiB), we don't call wastfull normalization, + but (pos) will be wrapped over Zero (0) in that case. + And we cannot resume later to normal operation + */ + { + // MatchFinder_Normalize(p); + /* after normalization we need (p->pos >= p->historySize + 1); */ + /* we can reduce subValue to aligned value, if want to keep alignment + of (p->pos) and (p->buffer) for speculated accesses. */ + 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); + } + if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); } @@ -386,9 +786,9 @@ static void MatchFinder_CheckLimits(CMatchFinder *p) (lenLimit > maxLen) */ MY_FORCE_INLINE -static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, unsigned maxLen) +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) { /* son[_cyclicBufferPos] = curMatch; @@ -396,7 +796,7 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) - return distances; + return d; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; @@ -409,10 +809,10 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos if (maxLen < len) { maxLen = len; - *distances++ = len; - *distances++ = delta - 1; + *d++ = len; + *d++ = delta - 1; if (len == lenLimit) - return distances; + return d; } } } @@ -421,35 +821,41 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos const Byte *lim = cur + lenLimit; son[_cyclicBufferPos] = curMatch; + do { - UInt32 delta = pos - curMatch; + UInt32 delta; + + if (curMatch == 0) + break; + // if (curMatch2 >= curMatch) return NULL; + delta = pos - curMatch; if (delta >= _cyclicBufferSize) break; { ptrdiff_t diff; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; - diff = (ptrdiff_t)0 - delta; - if (cur[maxLen] == cur[maxLen + diff]) + diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) { const Byte *c = cur; while (*c == c[diff]) { if (++c == lim) { - distances[0] = (UInt32)(lim - cur); - distances[1] = delta - 1; - return distances + 2; + d[0] = (UInt32)(lim - cur); + d[1] = delta - 1; + return d + 2; } } { - unsigned len = (unsigned)(c - cur); + const unsigned len = (unsigned)(c - cur); if (maxLen < len) { maxLen = len; - distances[0] = (UInt32)len; - distances[1] = delta - 1; - distances += 2; + d[0] = (UInt32)len; + d[1] = delta - 1; + d += 2; } } } @@ -457,31 +863,36 @@ static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos } while (--cutValue); - return distances; + return d; } MY_FORCE_INLINE UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *d, UInt32 maxLen) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; - for (;;) + + UInt32 cmCheck; + + // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (cmCheck < curMatch) + do { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return distances; - } + const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; unsigned len = (len0 < len1 ? len0 : len1); - UInt32 pair0 = pair[0]; + const UInt32 pair0 = pair[0]; if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) @@ -491,48 +902,60 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt if (maxLen < len) { maxLen = (UInt32)len; - *distances++ = (UInt32)len; - *distances++ = delta - 1; + *d++ = (UInt32)len; + *d++ = delta - 1; if (len == lenLimit) { *ptr1 = pair0; *ptr0 = pair[1]; - return distances; + return d; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; + // const UInt32 curMatch2 = pair[1]; + // if (curMatch2 >= curMatch) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + // curMatch = curMatch2; + curMatch = pair[1]; ptr1 = pair + 1; - curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; + curMatch = pair[0]; ptr0 = pair; - curMatch = *ptr0; len0 = len; } } } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return d; } + static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); unsigned len0 = 0, len1 = 0; - for (;;) + + UInt32 cmCheck; + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (// curMatch >= pos || // failure + cmCheck < curMatch) + do { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return; - } + const UInt32 delta = pos - curMatch; { CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; @@ -554,80 +977,108 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const if (pb[len] < cur[len]) { *ptr1 = curMatch; + curMatch = pair[1]; ptr1 = pair + 1; - curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; + curMatch = pair[0]; ptr0 = pair; - curMatch = *ptr0; len0 = len; } } } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return; } + #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ - if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + { const UInt32 pos1 = p->pos + 1; p->pos = pos1; if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } -#define MOVE_POS_RET MOVE_POS return (UInt32)offset; +#define MOVE_POS_RET MOVE_POS return distances; -static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } +MY_NO_INLINE +static void MatchFinder_MovePos(CMatchFinder *p) +{ + /* we go here at the end of stream data, when (avail < num_hash_bytes) + We don't update sons[cyclicBufferPos << btMode]. + So (sons) record will contain junk. And we cannot resume match searching + to normal operation, even if we will provide more input data in buffer. + p->sons[p->cyclicBufferPos << p->btMode] = 0; // kEmptyHashValue + if (p->btMode) + p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0; // kEmptyHashValue + */ + MOVE_POS; +} #define GET_MATCHES_HEADER2(minLen, ret_op) \ - unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ + unsigned lenLimit; UInt32 hv; Byte *cur; UInt32 curMatch; \ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; -#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) -#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) +#define SKIP_HEADER(minLen) do { GET_MATCHES_HEADER2(minLen, continue) -#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue +#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 GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ + distances = func(MF_PARAMS(p), \ + distances, (UInt32)_maxLen_); MOVE_POS_RET; + +#define GET_MATCHES_FOOTER_BT(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) + +#define GET_MATCHES_FOOTER_HC(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, Hc_GetMatchesSpec) -#define GET_MATCHES_FOOTER(offset, maxLen) \ - offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \ - distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET; -#define SKIP_FOOTER \ - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; #define UPDATE_maxLen { \ - ptrdiff_t diff = (ptrdiff_t)0 - d2; \ + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)d2; \ const Byte *c = cur + maxLen; \ const Byte *lim = cur + lenLimit; \ for (; c != lim; c++) if (*(c + diff) != *c) break; \ maxLen = (unsigned)(c - cur); } -static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 1) + GET_MATCHES_FOOTER_BT(1) } -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 2) + GET_MATCHES_FOOTER_BT(2) } -static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +#define SET_mmm \ + mmm = p->cyclicBufferSize; \ + if (pos < mmm) \ + mmm = pos; + + +static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, d2, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(3) @@ -643,29 +1094,32 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) hash[h2] = pos; (hash + kFix3HashSize)[hv] = pos; - maxLen = 2; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + maxLen = 2; + + if (d2 < mmm && *(cur - d2) == *cur) { UPDATE_maxLen distances[0] = (UInt32)maxLen; distances[1] = d2 - 1; - offset = 2; + distances += 2; if (maxLen == lenLimit) { - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); + SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET; } } - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, h3, d2, d3, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) @@ -676,53 +1130,63 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; - curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; (hash + kFix4HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm + + maxLen = 3; - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + for (;;) { - maxLen = 2; - distances[0] = 2; - distances[1] = d2 - 1; - offset = 2; - } + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; - if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - maxLen = 3; - distances[(size_t)offset + 1] = d3 - 1; - offset += 2; - d2 = d3; - } - - if (offset != 0) - { UPDATE_maxLen - distances[(size_t)offset - 2] = (UInt32)maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { - SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; + SkipMatchesSpec(MF_PARAMS(p)); + MOVE_POS_RET } + break; } - if (maxLen < 3) - maxLen = 3; - - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -/* -static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos; + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 *hash; GET_MATCHES_HEADER(5) @@ -733,73 +1197,69 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; - d4 = pos - (hash + kFix4HashSize)[h4]; + // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; - (hash + kFix4HashSize)[h4] = pos; + // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + maxLen = 4; + + for (;;) { - distances[0] = maxLen = 2; - distances[1] = d2 - 1; - offset = 2; - if (*(cur - d2 + 2) == cur[2]) - distances[0] = maxLen = 3; - else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + if (d2 < mmm && *(cur - d2) == *cur) { - distances[2] = maxLen = 3; - distances[3] = d3 - 1; - offset = 4; + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; d2 = d3; } - } - else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - distances[0] = maxLen = 3; - distances[1] = d3 - 1; - offset = 2; - d2 = d3; - } - - if (d2 != d4 && d4 < p->cyclicBufferSize - && *(cur - d4) == *cur - && *(cur - d4 + 3) == *(cur + 3)) - { - maxLen = 4; - distances[(size_t)offset + 1] = d4 - 1; - offset += 2; - d2 = d4; - } - - if (offset != 0) - { + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; UPDATE_maxLen - distances[(size_t)offset - 2] = maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS_RET; } + break; } - - if (maxLen < 4) - maxLen = 4; - GET_MATCHES_FOOTER(offset, maxLen) + GET_MATCHES_FOOTER_BT(maxLen) } -*/ -static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { + UInt32 mmm; UInt32 h2, h3, d2, d3, pos; - unsigned maxLen, offset; + unsigned maxLen; UInt32 *hash; GET_MATCHES_HEADER(4) @@ -816,48 +1276,57 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) (hash + kFix3HashSize)[h3] = pos; (hash + kFix4HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) - { - maxLen = 2; - distances[0] = 2; - distances[1] = d2 - 1; - offset = 2; - } - - if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - maxLen = 3; - distances[(size_t)offset + 1] = d3 - 1; - offset += 2; - d2 = d3; - } - - if (offset != 0) + maxLen = 3; + + for (;;) { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + UPDATE_maxLen - distances[(size_t)offset - 2] = (UInt32)maxLen; + distances[-2] = (UInt32)maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } + break; } - if (maxLen < 3) - maxLen = 3; - - offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(maxLen); } -/* -static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 *hash; GET_MATCHES_HEADER(5) @@ -865,242 +1334,237 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) hash = p->hash; pos = p->pos; - + d2 = pos - hash [h2]; d3 = pos - (hash + kFix3HashSize)[h3]; - d4 = pos - (hash + kFix4HashSize)[h4]; + // d4 = pos - (hash + kFix4HashSize)[h4]; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = pos; (hash + kFix3HashSize)[h3] = pos; - (hash + kFix4HashSize)[h4] = pos; + // (hash + kFix4HashSize)[h4] = pos; (hash + kFix5HashSize)[hv] = pos; - maxLen = 0; - offset = 0; + SET_mmm + + maxLen = 4; - if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + for (;;) { - distances[0] = maxLen = 2; - distances[1] = d2 - 1; - offset = 2; - if (*(cur - d2 + 2) == cur[2]) - distances[0] = maxLen = 3; - else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + if (d2 < mmm && *(cur - d2) == *cur) { - distances[2] = maxLen = 3; - distances[3] = d3 - 1; - offset = 4; + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; d2 = d3; } - } - else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) - { - distances[0] = maxLen = 3; - distances[1] = d3 - 1; - offset = 2; - d2 = d3; - } - - if (d2 != d4 && d4 < p->cyclicBufferSize - && *(cur - d4) == *cur - && *(cur - d4 + 3) == *(cur + 3)) - { - maxLen = 4; - distances[(size_t)offset + 1] = d4 - 1; - offset += 2; - d2 = d4; - } - - if (offset != 0) - { + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; UPDATE_maxLen - distances[(size_t)offset - 2] = maxLen; + distances[-2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } + break; } - if (maxLen < 4) - maxLen = 4; - - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(maxLen); } -*/ -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) + +UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { - unsigned offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances, 2) - (distances)); - MOVE_POS_RET + GET_MATCHES_FOOTER_HC(2) } + static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(2) { - SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(3) { - SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hv]; p->hash[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(3) { UInt32 h2; UInt32 *hash; - SKIP_HEADER(3) HASH3_CALC; hash = p->hash; curMatch = (hash + kFix3HashSize)[hv]; hash[h2] = (hash + kFix3HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(4) { UInt32 h2, h3; UInt32 *hash; - SKIP_HEADER(4) HASH4_CALC; hash = p->hash; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = (hash + kFix4HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } -/* static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do + SKIP_HEADER(5) { - UInt32 h2, h3, h4; + UInt32 h2, h3; UInt32 *hash; - SKIP_HEADER(5) HASH5_CALC; hash = p->hash; curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = - (hash + kFix4HashSize)[h4] = + // (hash + kFix4HashSize)[h4] = (hash + kFix5HashSize)[hv] = p->pos; - SKIP_FOOTER } - while (--num != 0); + SKIP_FOOTER } -*/ + + +#define HC_SKIP_HEADER(minLen) \ + do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \ + Byte *cur; \ + UInt32 *hash; \ + UInt32 *son; \ + UInt32 pos = p->pos; \ + UInt32 num2 = num; \ + /* (p->pos == p->posLimit) is not allowed here !!! */ \ + { const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \ + num -= num2; \ + { const UInt32 cycPos = p->cyclicBufferPos; \ + son = p->son + cycPos; \ + p->cyclicBufferPos = cycPos + num2; } \ + cur = p->buffer; \ + hash = p->hash; \ + do { \ + UInt32 curMatch; \ + UInt32 hv; + + +#define HC_SKIP_FOOTER \ + cur++; pos++; *son++ = curMatch; \ + } while (--num2); \ + p->buffer = cur; \ + p->pos = pos; \ + if (pos == p->posLimit) MatchFinder_CheckLimits(p); \ + }} while(num); \ + static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do - { + HC_SKIP_HEADER(4) + UInt32 h2, h3; - UInt32 *hash; - SKIP_HEADER(4) HASH4_CALC; - hash = p->hash; curMatch = (hash + kFix4HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = - (hash + kFix4HashSize)[hv] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); + (hash + kFix4HashSize)[hv] = pos; + + HC_SKIP_FOOTER } -/* + static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do - { - UInt32 h2, h3, h4; - UInt32 *hash; - SKIP_HEADER(5) - HASH5_CALC; - hash = p->hash; - curMatch = hash + kFix5HashSize)[hv]; + HC_SKIP_HEADER(5) + + UInt32 h2, h3; + HASH5_CALC + curMatch = (hash + kFix5HashSize)[hv]; hash [h2] = (hash + kFix3HashSize)[h3] = - (hash + kFix4HashSize)[h4] = - (hash + kFix5HashSize)[hv] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); + // (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = pos; + + HC_SKIP_FOOTER } -*/ + void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { - do - { - SKIP_HEADER(3) + HC_SKIP_HEADER(3) + HASH_ZIP_CALC; - curMatch = p->hash[hv]; - p->hash[hv] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); + curMatch = hash[hv]; + hash[hv] = pos; + + HC_SKIP_FOOTER } -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { - /* if (p->numHashBytes <= 4) */ + if (p->numHashBytes <= 4) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } - /* else { vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; } - */ } else if (p->numHashBytes == 2) { @@ -1112,16 +1576,53 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } - else /* if (p->numHashBytes == 4) */ + else if (p->numHashBytes == 4) { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } - /* else { vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; } - */ +} + + + +void LzFindPrepare() +{ + #ifndef FORCE_SATUR_SUB_128 + #ifdef USE_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")); + f = LzFind_SaturSub_128; + } + // f = 0; // for debug + } + #else // MY_CPU_ARM_OR_ARM64 + if (CPU_IsSupported_SSE41()) + { + // #pragma message ("=== LzFind SSE41") + _PRF(printf("\n=== LzFind SSE41\n")); + f = LzFind_SaturSub_128; + + #ifdef USE_AVX2 + if (CPU_IsSupported_AVX2()) + { + // #pragma message ("=== LzFind AVX2") + _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 } diff --git a/libraries/lzma/C/LzFind.h b/libraries/lzma/C/LzFind.h index 42c13be15..eea873ff6 100644 --- a/libraries/lzma/C/LzFind.h +++ b/libraries/lzma/C/LzFind.h @@ -1,5 +1,5 @@ /* LzFind.h -- Match finder for LZ algorithms -2017-06-10 : Igor Pavlov : Public domain */ +2021-07-13 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_H #define __LZ_FIND_H @@ -15,7 +15,7 @@ typedef struct _CMatchFinder Byte *buffer; UInt32 pos; UInt32 posLimit; - UInt32 streamPos; + UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */ UInt32 lenLimit; UInt32 cyclicBufferPos; @@ -51,17 +51,19 @@ typedef struct _CMatchFinder UInt64 expectedDataSize; } CMatchFinder; -#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer) -#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((p)->streamPos - (p)->pos)) +/* #define Inline_MatchFinder_IsFinishedOK(p) \ ((p)->streamEndWasReached \ && (p)->streamPos == (p)->pos \ && (!(p)->directInput || (p)->directInputRem == 0)) +*/ int MatchFinder_NeedMove(CMatchFinder *p); -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */ void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); @@ -76,10 +78,21 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 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); +// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +/* +#define Inline_MatchFinder_InitPos(p, val) \ + (p)->pos = (val); \ + (p)->streamPos = (val); +*/ + +#define Inline_MatchFinder_ReduceOffsets(p, subValue) \ + (p)->pos -= (subValue); \ + (p)->streamPos -= (subValue); + UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* @@ -91,7 +104,7 @@ Conditions: typedef void (*Mf_Init_Func)(void *object); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); -typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder @@ -101,21 +114,23 @@ typedef struct _IMatchFinder Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; -} IMatchFinder; +} IMatchFinder2; -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable); void MatchFinder_Init_LowHash(CMatchFinder *p); void MatchFinder_Init_HighHash(CMatchFinder *p); -void MatchFinder_Init_3(CMatchFinder *p, int readData); +void MatchFinder_Init_4(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p); -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void LzFindPrepare(void); + EXTERN_C_END #endif diff --git a/libraries/lzma/C/LzFindMt.c b/libraries/lzma/C/LzFindMt.c index bb0f42c30..4e67fc3f2 100644 --- a/libraries/lzma/C/LzFindMt.c +++ b/libraries/lzma/C/LzFindMt.c @@ -1,97 +1,215 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2018-12-29 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #include "Precomp.h" -#include "LzHash.h" +// #include +#include "CpuArch.h" + +#include "LzHash.h" #include "LzFindMt.h" +// #define LOG_ITERS + +// #define LOG_THREAD + +#ifdef LOG_THREAD +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef LOG_ITERS +#include +extern UInt64 g_NumIters_Tree; +extern UInt64 g_NumIters_Loop; +extern UInt64 g_NumIters_Bytes; +#define LOG_ITER(x) x +#else +#define LOG_ITER(x) +#endif + +#define kMtHashBlockSize ((UInt32)1 << 17) +#define kMtHashNumBlocks (1 << 1) + +#define GET_HASH_BLOCK_OFFSET(i) (((i) & (kMtHashNumBlocks - 1)) * kMtHashBlockSize) + +#define kMtBtBlockSize ((UInt32)1 << 16) +#define kMtBtNumBlocks (1 << 4) + +#define GET_BT_BLOCK_OFFSET(i) (((i) & (kMtBtNumBlocks - 1)) * (size_t)kMtBtBlockSize) + +/* + HASH functions: + We use raw 8/16 bits from a[1] and a[2], + xored with crc(a[0]) and crc(a[3]). + We check a[0], a[3] only. We don't need to compare a[1] and a[2] in matches. + our crc() function provides one-to-one correspondence for low 8-bit values: + (crc[0...0xFF] & 0xFF) <-> [0...0xFF] +*/ + +#define MF(mt) ((mt)->MatchFinder) +#define MF_CRC (p->crc) + +// #define MF(mt) (&(mt)->MatchFinder) +// #define MF_CRC (p->MatchFinder.crc) + +#define MT_HASH2_CALC \ + h2 = (MF_CRC[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = MF_CRC[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +/* +#define MT_HASH3_CALC__NO_2 { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define __MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + h4 = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hash4Mask; } + // (kHash4Size - 1); +*/ + + +MY_NO_INLINE static void MtSync_Construct(CMtSync *p) { + p->affinity = 0; p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); - Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } -static void MtSync_GetNextBlock(CMtSync *p) + +#define DEBUG_BUFFER_LOCK // define it to debug lock state + +#ifdef DEBUG_BUFFER_LOCK +#include +#define BUFFER_MUST_BE_LOCKED(p) if (!(p)->csWasEntered) exit(1); +#define BUFFER_MUST_BE_UNLOCKED(p) if ( (p)->csWasEntered) exit(1); +#else +#define BUFFER_MUST_BE_LOCKED(p) +#define BUFFER_MUST_BE_UNLOCKED(p) +#endif + +#define LOCK_BUFFER(p) { \ + BUFFER_MUST_BE_UNLOCKED(p); \ + CriticalSection_Enter(&(p)->cs); \ + (p)->csWasEntered = True; } + +#define UNLOCK_BUFFER(p) { \ + BUFFER_MUST_BE_LOCKED(p); \ + CriticalSection_Leave(&(p)->cs); \ + (p)->csWasEntered = False; } + + +MY_NO_INLINE +static UInt32 MtSync_GetNextBlock(CMtSync *p) { + UInt32 numBlocks = 0; if (p->needStart) { + BUFFER_MUST_BE_UNLOCKED(p) p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; - Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); - Event_Set(&p->canStart); - Event_Wait(&p->wasStarted); - - // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder); } else { - CriticalSection_Leave(&p->cs); - p->csWasEntered = False; - p->numProcessedBlocks++; + UNLOCK_BUFFER(p) + // we free current block + numBlocks = p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } + + // buffer is UNLOCKED here Semaphore_Wait(&p->filledSemaphore); - CriticalSection_Enter(&p->cs); - p->csWasEntered = True; + LOCK_BUFFER(p); + return numBlocks; } -/* MtSync_StopWriting must be called if Writing was started */ +/* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */ + +MY_NO_INLINE static void MtSync_StopWriting(CMtSync *p) { - UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; - p->stopWriting = True; + + PRF(printf("\nMtSync_StopWriting %p\n", p)); + if (p->csWasEntered) { - CriticalSection_Leave(&p->cs); - p->csWasEntered = False; + /* we don't use buffer in this thread after StopWriting(). + So we UNLOCK buffer. + And we restore default UNLOCKED state for stopped thread */ + UNLOCK_BUFFER(p) } - Semaphore_Release1(&p->freeSemaphore); - - Event_Wait(&p->wasStopped); - while (myNumBlocks++ != p->numProcessedBlocks) - { - Semaphore_Wait(&p->filledSemaphore); - Semaphore_Release1(&p->freeSemaphore); - } + /* We send (p->stopWriting) message and release freeSemaphore + to free current block. + So the thread will see (p->stopWriting) at some + iteration after Wait(freeSemaphore). + The thread doesn't need to fill all avail free blocks, + so we can get fast thread stop. + */ + + p->stopWriting = True; + Semaphore_Release1(&p->freeSemaphore); // check semaphore count !!! + + PRF(printf("\nMtSync_StopWriting %p : Event_Wait(&p->wasStopped)\n", p)); + Event_Wait(&p->wasStopped); + PRF(printf("\nMtSync_StopWriting %p : Event_Wait() finsihed\n", p)); + + /* 21.03 : we don't restore samaphore counters here. + We will recreate and reinit samaphores in next start */ + p->needStart = True; } + +MY_NO_INLINE static void MtSync_Destruct(CMtSync *p) { + PRF(printf("\nMtSync_Destruct %p\n", p)); + if (Thread_WasCreated(&p->thread)) { + /* we want thread to be in Stopped state before sending EXIT command. + note: stop(btSync) will stop (htSync) also */ MtSync_StopWriting(p); + /* thread in Stopped state here : (p->needStart == true) */ p->exit = True; - if (p->needStart) - Event_Set(&p->canStart); - Thread_Wait(&p->thread); - Thread_Close(&p->thread); + // if (p->needStart) // it's (true) + Event_Set(&p->canStart); // we send EXIT command to thread + Thread_Wait_Close(&p->thread); // we wait thread finishing } + if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } + p->csWasEntered = False; Event_Close(&p->canStart); - Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); @@ -99,80 +217,251 @@ static void MtSync_Destruct(CMtSync *p) p->wasCreated = False; } -#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } -static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +// #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) + + +// call it before each new file (when new starting is required): +MY_NO_INLINE +static SRes MtSync_Init(CMtSync *p, UInt32 numBlocks) { + WRes wres; + // BUFFER_MUST_BE_UNLOCKED(p) + if (!p->needStart || p->csWasEntered) + return SZ_ERROR_FAIL; + wres = Semaphore_OptCreateInit(&p->freeSemaphore, numBlocks, numBlocks); + if (wres == 0) + wres = Semaphore_OptCreateInit(&p->filledSemaphore, 0, numBlocks); + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) +{ + WRes wres; + if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; + p->csWasEntered = False; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); - RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); - - RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); - RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; - - RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->exit = True; /* p->exit is unused before (canStart) Event. + But in case of some unexpected code failure we will get fast exit from thread */ + + // return ERROR_TOO_MANY_POSTS; // for debug + // return EINVAL; // for debug + + if (p->affinity != 0) + wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); + else + wres = Thread_Create(&p->thread, startAddress, obj); + + RINOK_THREAD(wres); p->wasCreated = True; return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) + +MY_NO_INLINE +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) { - SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); - if (res != SZ_OK) - MtSync_Destruct(p); - return res; + const WRes wres = MtSync_Create_WRes(p, startAddress, obj); + if (wres == 0) + return 0; + MtSync_Destruct(p); + return MY_SRes_HRESULT_FROM_WRes(wres); } -void MtSync_Init(CMtSync *p) { p->needStart = True; } + +// ---------- HASH THREAD ---------- #define kMtMaxValForNormalize 0xFFFFFFFF +// #define kMtMaxValForNormalize ((1 << 21)) // for debug +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#ifdef MY_CPU_LE_UNALIGN + #define GetUi24hi_from32(p) ((UInt32)GetUi32(p) >> 8) +#else + #define GetUi24hi_from32(p) ((p)[1] ^ ((UInt32)(p)[2] << 8) ^ ((UInt32)(p)[3] << 16)) +#endif + +#define GetHeads_DECL(name) \ + static void GetHeads ## name(const Byte *p, UInt32 pos, \ + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) + +#define GetHeads_LOOP(v) \ + for (; numHeads != 0; numHeads--) { \ + const UInt32 value = (v); \ + p++; \ + *heads++ = pos - hash[value]; \ + hash[value] = pos++; } #define DEF_GetHeads2(name, v, action) \ - static void GetHeads ## name(const Byte *p, UInt32 pos, \ - UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ - { action; for (; numHeads != 0; numHeads--) { \ - const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } - + GetHeads_DECL(name) { action \ + GetHeads_LOOP(v) } + #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) -DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) -DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) -DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) -DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) -/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ +DEF_GetHeads2(2, GetUi16(p), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +DEF_GetHeads(3, (crc[p[0]] ^ GetUi16(p + 1)) & hashMask) +DEF_GetHeads2(3b, GetUi16(p) ^ ((UInt32)(p)[2] << 16), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +// BT3 is not good for crc collisions for big hashMask values. + +/* +GetHeads_DECL(3b) +{ + UNUSED_VAR(hashMask); + UNUSED_VAR(crc); + { + const Byte *pLim = p + numHeads; + if (numHeads == 0) + return; + pLim--; + while (p < pLim) + { + UInt32 v1 = GetUi32(p); + UInt32 v0 = v1 & 0xFFFFFF; + UInt32 h0, h1; + p += 2; + v1 >>= 8; + h0 = hash[v0]; hash[v0] = pos; heads[0] = pos - h0; pos++; + h1 = hash[v1]; hash[v1] = pos; heads[1] = pos - h1; pos++; + heads += 2; + } + if (p == pLim) + { + UInt32 v0 = GetUi16(p) ^ ((UInt32)(p)[2] << 16); + *heads = pos - hash[v0]; + hash[v0] = pos; + } + } +} +*/ + +/* +GetHeads_DECL(4) +{ + unsigned sh = 0; + UNUSED_VAR(crc) + while ((hashMask & 0x80000000) == 0) + { + hashMask <<= 1; + sh++; + } + GetHeads_LOOP((GetUi32(p) * 0xa54a1) >> sh) +} +#define GetHeads4b GetHeads4 +*/ + +#define USE_GetHeads_LOCAL_CRC + +#ifdef USE_GetHeads_LOCAL_CRC + +GetHeads_DECL(4) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + // crc1[i] = rotlFixed(v, 8) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(4b) +{ + UInt32 crc0[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + crc0[i] = crc[i] & hashMask; + } + GetHeads_LOOP(crc0[p[0]] ^ GetUi24hi_from32(p)) +} + +GetHeads_DECL(5) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + UInt32 crc2[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + crc2[i] = (v << kLzHash_CrcShift_2) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ crc2[p[4]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(5b) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[4]] ^ GetUi24hi_from32(p)) +} + +#else + +DEF_GetHeads(4, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (UInt32)GetUi16(p+1)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ GetUi24hi_from32(p)) & hashMask) +DEF_GetHeads(5, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (crc[p[4]] << kLzHash_CrcShift_2) ^ (UInt32)GetUi16(p + 1)) & hashMask) +DEF_GetHeads(5b, (crc[p[0]] ^ (crc[p[4]] << kLzHash_CrcShift_1) ^ GetUi24hi_from32(p)) & hashMask) + +#endif + static void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; + PRF(printf("\nHashThreadFunc\n")); + for (;;) { - UInt32 numProcessedBlocks = 0; + UInt32 blockIndex = 0; + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart)\n")); Event_Wait(&p->canStart); - Event_Set(&p->wasStarted); + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart) : after \n")); + if (p->exit) + { + PRF(printf("\nHashThreadFunc : exit \n")); + return; + } - MatchFinder_Init_HighHash(mt->MatchFinder); + MatchFinder_Init_HighHash(MF(mt)); for (;;) { - if (p->exit) - return; - if (p->stopWriting) - { - p->numProcessedBlocks = numProcessedBlocks; - Event_Set(&p->wasStopped); - break; - } + PRF(printf("Hash thread block = %d pos = %d\n", (unsigned)blockIndex, mt->MatchFinder->pos)); { - CMatchFinder *mf = mt->MatchFinder; + CMatchFinder *mf = MF(mt); if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); @@ -185,194 +474,178 @@ static void HashThreadFunc(CMatchFinderMt *mt) mt->pointerToCurPos -= offset; mt->buffer -= offset; } - CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); + CriticalSection_Leave(&mt->btSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); + if (p->exit) // exit is unexpected here. But we check it here for some failure case + return; + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + MatchFinder_ReadIfRequired(mf); - if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { - UInt32 subValue = (mf->pos - mf->historySize - 1); - MatchFinder_ReduceOffsets(mf, subValue); - MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); - } - { - UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; - UInt32 num = mf->streamPos - mf->pos; + UInt32 *heads = mt->hashBuf + GET_HASH_BLOCK_OFFSET(blockIndex++); + UInt32 num = Inline_MatchFinder_GetNumAvailableBytes(mf); heads[0] = 2; heads[1] = num; + + /* heads[1] contains the number of avail bytes: + if (avail < mf->numHashBytes) : + { + it means that stream was finished + HASH_THREAD and BT_TREAD must move position for heads[1] (avail) bytes. + HASH_THREAD doesn't stop, + HASH_THREAD fills only the header (2 numbers) for all next blocks: + {2, NumHashBytes - 1}, {2,0}, {2,0}, ... , {2,0} + } + else + { + HASH_THREAD and BT_TREAD must move position for (heads[0] - 2) bytes; + } + */ + if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; - mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + + if (mf->pos > (UInt32)kMtMaxValForNormalize - num) + { + const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + Inline_MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); + } + heads[0] = 2 + num; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); } - mf->pos += num; + + mf->pos += num; // wrap over zero is allowed at the end of stream mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); - } - } + } // for() processing end + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); + } // for() thread end } -static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) -{ - MtSync_GetNextBlock(&p->hashSync); - p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; - p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; - p->hashNumAvail = p->hashBuf[p->hashBufPos++]; -} -#define kEmptyHashValue 0 + + +// ---------- BT THREAD ---------- + +/* we use one variable instead of two (cyclicBufferPos == pos) before CyclicBuf wrap. + here we define fixed offset of (p->pos) from (p->cyclicBufferPos) */ +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug #define MFMT_GM_INLINE #ifdef MFMT_GM_INLINE /* - we use size_t for _cyclicBufferPos instead of UInt32 + we use size_t for (pos) instead of UInt32 to eliminate "movsx" BUG in old MSVC x64 compiler. */ -MY_NO_INLINE -static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, - size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, - UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes) -{ - do - { - UInt32 *_distances = ++distances; - UInt32 delta = *hash++; - CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); - unsigned len0 = 0, len1 = 0; - UInt32 cutValue = _cutValue; - unsigned maxLen = (unsigned)_maxLen; - - /* - if (size > 1) - { - UInt32 delta = *hash; - if (delta < _cyclicBufferSize) - { - UInt32 cyc1 = _cyclicBufferPos + 1; - CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1); - Byte b = *(cur + 1 - delta); - _distances[0] = pair[0]; - _distances[1] = b; - } - } - */ - if (cutValue == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - } - else - for(;;) - { - { - CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - unsigned len = (len0 < len1 ? len0 : len1); - UInt32 pair0 = *pair; - if (pb[len] == cur[len]) - { - if (++len != lenLimit && pb[len] == cur[len]) - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - maxLen = len; - *distances++ = (UInt32)len; - *distances++ = delta - 1; - if (len == lenLimit) - { - UInt32 pair1 = pair[1]; - *ptr1 = pair0; - *ptr0 = pair1; - break; - } - } - } - { - UInt32 curMatch = pos - delta; - // delta = pos - *pair; - // delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31]; - if (pb[len] < cur[len]) - { - delta = pos - pair[1]; - *ptr1 = curMatch; - ptr1 = pair + 1; - len1 = len; - } - else - { - delta = pos - *pair; - *ptr0 = curMatch; - ptr0 = pair; - len0 = len; - } - } - } - if (--cutValue == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - break; - } - } - pos++; - _cyclicBufferPos++; - cur++; - { - UInt32 num = (UInt32)(distances - _distances); - _distances[-1] = num; - } - } - while (distances < limit && --size != 0); - *posRes = pos; - return distances; -} +UInt32 * MY_FAST_CALL 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); #endif - -static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +static void BtGetMatches(CMatchFinderMt *p, UInt32 *d) { UInt32 numProcessed = 0; UInt32 curPos = 2; - UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2 - distances[1] = p->hashNumAvail; + /* GetMatchesSpec() functions don't create (len = 1) + in [len, dist] match pairs, if (p->numHashBytes >= 2) + Also we suppose here that (matchMaxLen >= 2). + So the following code for (reserve) is not required + UInt32 reserve = (p->matchMaxLen * 2); + const UInt32 kNumHashBytes_Max = 5; // BT_HASH_BYTES_MAX + if (reserve < kNumHashBytes_Max - 1) + reserve = kNumHashBytes_Max - 1; + const UInt32 limit = kMtBtBlockSize - (reserve); + */ + + const UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + + d[1] = p->hashNumAvail; + + if (p->failure_BT) + { + // printf("\n == 1 BtGetMatches() p->failure_BT\n"); + d[0] = 0; + // d[1] = 0; + return; + } while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { - MatchFinderMt_GetNextBlock_Hash(p); - distances[1] = numProcessed + p->hashNumAvail; - if (p->hashNumAvail >= p->numHashBytes) + // MatchFinderMt_GetNextBlock_Hash(p); + UInt32 avail; + { + const UInt32 bi = MtSync_GetNextBlock(&p->hashSync); + const UInt32 k = GET_HASH_BLOCK_OFFSET(bi); + const UInt32 *h = p->hashBuf + k; + avail = h[1]; + p->hashBufPosLimit = k + h[0]; + p->hashNumAvail = avail; + p->hashBufPos = k + 2; + } + + { + /* we must prevent UInt32 overflow for avail total value, + if avail was increased with new hash block */ + UInt32 availSum = numProcessed + avail; + if (availSum < numProcessed) + availSum = (UInt32)(Int32)-1; + d[1] = availSum; + } + + if (avail >= p->numHashBytes) continue; - distances[0] = curPos + p->hashNumAvail; - distances += curPos; - for (; p->hashNumAvail != 0; p->hashNumAvail--) - *distances++ = 0; + + // if (p->hashBufPos != p->hashBufPosLimit) exit(1); + + /* (avail < p->numHashBytes) + It means that stream was finished. + And (avail) - is a number of remaining bytes, + we fill (d) for (avail) bytes for LZ_THREAD (receiver). + but we don't update (p->pos) and (p->cyclicBufferPos) here in BT_THREAD */ + + /* here we suppose that we have space enough: + (kMtBtBlockSize - curPos >= p->hashNumAvail) */ + p->hashNumAvail = 0; + d[0] = curPos + avail; + d += curPos; + for (; avail != 0; avail--) + *d++ = 0; return; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; - UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; + UInt32 lenLimit = p->matchMaxLen; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { @@ -384,10 +657,18 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) size = size2; } + if (pos > (UInt32)kMtMaxValForNormalize - size) + { + const UInt32 subValue = (pos - p->cyclicBufferSize); // & ~(UInt32)(kNormalizeAlign - 1); + pos -= subValue; + p->pos = pos; + MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); + } + #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { - UInt32 *startDistances = distances + curPos; + UInt32 *startDistances = d + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); @@ -399,81 +680,112 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) } #else { - UInt32 posRes; - curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, - distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, - distances + limit, - size, &posRes) - distances); - p->hashBufPos += posRes - pos; - cyclicBufferPos += posRes - pos; - p->buffer += posRes - pos; - pos = posRes; + UInt32 posRes = pos; + const UInt32 *d_end; + { + d_end = GetMatchesSpecN_2( + p->buffer + lenLimit - 1, + pos, p->buffer, p->son, p->cutValue, d + curPos, + p->numHashBytes - 1, p->hashBuf + p->hashBufPos, + d + limit, p->hashBuf + p->hashBufPos + size, + cyclicBufferPos, p->cyclicBufferSize, + &posRes); + } + { + if (!d_end) + { + // printf("\n == 2 BtGetMatches() p->failure_BT\n"); + // internal data failure + p->failure_BT = True; + d[0] = 0; + // d[1] = 0; + return; + } + } + curPos = (UInt32)(d_end - d); + { + const UInt32 processed = posRes - pos; + pos = posRes; + p->hashBufPos += processed; + cyclicBufferPos += processed; + p->buffer += processed; + } } #endif - numProcessed += pos - p->pos; - p->hashNumAvail -= pos - p->pos; - p->pos = pos; + { + const UInt32 processed = pos - p->pos; + numProcessed += processed; + p->hashNumAvail -= processed; + p->pos = pos; + } if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } - distances[0] = curPos; + d[0] = curPos; } + static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; + + BUFFER_MUST_BE_UNLOCKED(sync) + if (!sync->needStart) { - CriticalSection_Enter(&sync->cs); - sync->csWasEntered = True; + LOCK_BUFFER(sync) } - BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + BtGetMatches(p, p->btBuf + GET_BT_BLOCK_OFFSET(globalBlockIndex)); + + /* We suppose that we have called GetNextBlock() from start. + So buffer is LOCKED */ - if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) - { - UInt32 subValue = p->pos - p->cyclicBufferSize; - MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); - p->pos -= subValue; - } - - if (!sync->needStart) - { - CriticalSection_Leave(&sync->cs); - sync->csWasEntered = False; - } + UNLOCK_BUFFER(sync) } -void BtThreadFunc(CMatchFinderMt *mt) + +MY_NO_INLINE +static void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); - Event_Set(&p->wasStarted); + for (;;) { + PRF(printf(" BT thread block = %d pos = %d\n", (unsigned)blockIndex, mt->pos)); + /* (p->exit == true) is possible after (p->canStart) at first loop iteration + and is unexpected after more Wait(freeSemaphore) iterations */ if (p->exit) return; - if (p->stopWriting) - { - p->numProcessedBlocks = blockIndex; - MtSync_StopWriting(&mt->hashSync); - Event_Set(&p->wasStopped); - break; - } + Semaphore_Wait(&p->freeSemaphore); + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); } + + // we stop HASH_THREAD here + MtSync_StopWriting(&mt->hashSync); + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); } } + void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = NULL; @@ -489,16 +801,39 @@ static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) { - MtSync_Destruct(&p->hashSync); + /* + HASH_THREAD can use CriticalSection(s) btSync.cs and hashSync.cs. + So we must be sure that HASH_THREAD will not use CriticalSection(s) + after deleting CriticalSection here. + + we call ReleaseStream(p) + that calls StopWriting(btSync) + that calls StopWriting(hashSync), if it's required to stop HASH_THREAD. + after StopWriting() it's safe to destruct MtSync(s) in any order */ + + MatchFinderMt_ReleaseStream(p); + MtSync_Destruct(&p->btSync); + MtSync_Destruct(&p->hashSync); + + LOG_ITER( + printf("\nTree %9d * %7d iter = %9d = sum : bytes = %9d\n", + (UInt32)(g_NumIters_Tree / 1000), + (UInt32)(((UInt64)g_NumIters_Loop * 1000) / (g_NumIters_Tree + 1)), + (UInt32)(g_NumIters_Loop / 1000), + (UInt32)(g_NumIters_Bytes / 1000) + )); + MatchFinderMt_FreeMem(p, alloc); } + #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) -static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } -static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) + +static THREAD_FUNC_DECL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_DECL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; unsigned i = 0; @@ -509,16 +844,17 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) return 0; } + SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) { - CMatchFinder *mf = p->MatchFinder; + CMatchFinder *mf = MF(p); p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (!p->hashBuf) { - p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, ((size_t)kHashBufferSize + (size_t)kBtBufferSize) * sizeof(UInt32)); if (!p->hashBuf) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; @@ -528,253 +864,457 @@ 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, kMtHashNumBlocks)); - RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)); return SZ_OK; } -/* Call it after ReleaseStream / SetStream */ + +SRes MatchFinderMt_InitMt(CMatchFinderMt *p) +{ + RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)); + return MtSync_Init(&p->btSync, kMtBtNumBlocks); +} + + static void MatchFinderMt_Init(CMatchFinderMt *p) { - CMatchFinder *mf = p->MatchFinder; + CMatchFinder *mf = MF(p); p->btBufPos = - p->btBufPosLimit = 0; + p->btBufPosLimit = NULL; p->hashBufPos = p->hashBufPosLimit = 0; + p->hashNumAvail = 0; // 21.03 + + p->failure_BT = False; /* Init without data reading. We don't want to read data in this thread */ - MatchFinder_Init_3(mf, False); + MatchFinder_Init_4(mf); + MatchFinder_Init_LowHash(mf); p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; - p->lzPos = p->historySize + 1; + p->failure_LZ_BT = False; + // p->failure_LZ_LZ = False; + + p->lzPos = + 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; + // p->hash4Mask = mf->hash4Mask; p->crc = mf->crc; + // memcpy(p->crc, mf->crc, sizeof(mf->crc)); p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; - p->pos = mf->pos; - p->buffer = mf->buffer; - p->cyclicBufferPos = mf->cyclicBufferPos; + + /* (mf->pos) and (mf->streamPos) were already initialized to 1 in MatchFinder_Init_4() */ + // mf->streamPos = mf->pos = 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug + + /* we must init (p->pos = mf->pos) for BT, because + BT code needs (p->pos == delta_value_for_empty_hash_record == mf->pos) */ + p->pos = mf->pos; // do not change it + + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); p->cyclicBufferSize = mf->cyclicBufferSize; + p->buffer = mf->buffer; p->cutValue = mf->cutValue; + // p->son[0] = p->son[1] = 0; // unused: to init skipped record for speculated accesses. } + /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { + // Sleep(1); // for debug MtSync_StopWriting(&p->btSync); + // Sleep(200); // for debug /* p->MatchFinder->ReleaseStream(); */ } -static void MatchFinderMt_Normalize(CMatchFinderMt *p) + +MY_NO_INLINE +static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { - MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); - p->lzPos = p->historySize + 1; + if (p->failure_LZ_BT) + p->btBufPos = p->failureBuf; + else + { + const UInt32 bi = MtSync_GetNextBlock(&p->btSync); + const UInt32 *bt = p->btBuf + GET_BT_BLOCK_OFFSET(bi); + { + const UInt32 numItems = bt[0]; + p->btBufPosLimit = bt + numItems; + p->btNumAvailBytes = bt[1]; + p->btBufPos = bt + 2; + if (numItems < 2 || numItems > kMtBtBlockSize) + { + p->failureBuf[0] = 0; + p->btBufPos = p->failureBuf; + p->btBufPosLimit = p->failureBuf + 1; + p->failure_LZ_BT = True; + // p->btNumAvailBytes = 0; + /* we don't want to decrease AvailBytes, that was load before. + that can be unxepected for the code that have loaded anopther value before */ + } + } + + if (p->lzPos >= (UInt32)kMtMaxValForNormalize - (UInt32)kMtBtBlockSize) + { + /* we don't check (lzPos) over exact avail bytes in (btBuf). + (fixedHashSize) is small, so normalization is fast */ + const UInt32 subValue = (p->lzPos - p->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + p->lzPos -= subValue; + MatchFinder_Normalize3(subValue, p->hash, p->fixedHashSize); + } + } + return p->btNumAvailBytes; } -static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) -{ - UInt32 blockIndex; - MtSync_GetNextBlock(&p->btSync); - blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); - p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; - p->btBufPosLimit += p->btBuf[p->btBufPos++]; - p->btNumAvailBytes = p->btBuf[p->btBufPos++]; - if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) - MatchFinderMt_Normalize(p); -} + static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } + #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { - GET_NEXT_BLOCK_IF_REQUIRED; - return p->btNumAvailBytes; + if (p->btBufPos != p->btBufPosLimit) + return p->btNumAvailBytes; + return MatchFinderMt_GetNextBlock_Bt(p); } -static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) + +// #define CHECK_FAILURE_LZ(_match_, _pos_) if (_match_ >= _pos_) { p->failure_LZ_LZ = True; return d; } +#define CHECK_FAILURE_LZ(_match_, _pos_) + +static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { - UInt32 h2, curMatch2; + UInt32 h2, c2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; - UInt32 lzPos = p->lzPos; + const UInt32 m = p->lzPos; MT_HASH2_CALC - curMatch2 = hash[h2]; - hash[h2] = lzPos; + c2 = hash[h2]; + hash[h2] = m; - if (curMatch2 >= matchMinPos) - if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + if (c2 >= matchMinPos) + { + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { - *distances++ = 2; - *distances++ = lzPos - curMatch2 - 1; + *d++ = 2; + *d++ = m - c2 - 1; } + } - return distances; + return d; } -static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) { - UInt32 h2, h3, curMatch2, curMatch3; + UInt32 h2, h3, c2, c3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; - UInt32 lzPos = p->lzPos; + const UInt32 m = p->lzPos; MT_HASH3_CALC - curMatch2 = hash[ h2]; - curMatch3 = (hash + kFix3HashSize)[h3]; + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; - hash[ h2] = lzPos; - (hash + kFix3HashSize)[h3] = lzPos; + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; - if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + if (c2 >= matchMinPos) { - distances[1] = lzPos - curMatch2 - 1; - if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) { - distances[0] = 3; - return distances + 2; + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + return d + 2; + } + d[0] = 2; + d += 2; } - distances[0] = 2; - distances += 2; } - if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + if (c3 >= matchMinPos) { - *distances++ = 3; - *distances++ = lzPos - curMatch3 - 1; + CHECK_FAILURE_LZ(c3, m) + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } } - return distances; + return d; } -/* -static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) -{ - UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4; - UInt32 *hash = p->hash; - const Byte *cur = p->pointerToCurPos; - UInt32 lzPos = p->lzPos; - MT_HASH4_CALC - - curMatch2 = hash[ h2]; - curMatch3 = (hash + kFix3HashSize)[h3]; - curMatch4 = (hash + kFix4HashSize)[h4]; - - hash[ h2] = lzPos; - (hash + kFix3HashSize)[h3] = lzPos; - (hash + kFix4HashSize)[h4] = lzPos; - - if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) - { - distances[1] = lzPos - curMatch2 - 1; - if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) - { - distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; - return distances + 2; - } - distances[0] = 2; - distances += 2; - } - - if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) - { - distances[1] = lzPos - curMatch3 - 1; - if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) - { - distances[0] = 4; - return distances + 2; - } - distances[0] = 3; - distances += 2; - } - - if (curMatch4 >= matchMinPos) - if ( - cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && - cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] - ) - { - *distances++ = 4; - *distances++ = lzPos - curMatch4 - 1; - } - - return distances; -} -*/ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; -static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +/* +static +UInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d) { - const UInt32 *btBuf = p->btBuf + p->btBufPos; - UInt32 len = *btBuf++; - p->btBufPos += 1 + len; - p->btNumAvailBytes--; + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + UInt32 matchMinPos; + UInt32 avail = p->btNumAvailBytes - 1; + p->btBufPos = btLim; + { - UInt32 i; - for (i = 0; i < len; i += 2) + p->btNumAvailBytes = avail; + + #define BT_HASH_BYTES_MAX 5 + + matchMinPos = p->lzPos; + + if (len != 0) + matchMinPos -= bt[1]; + else if (avail < (BT_HASH_BYTES_MAX - 1) - 1) { - UInt32 v0 = btBuf[0]; - UInt32 v1 = btBuf[1]; - btBuf += 2; - distances[0] = v0; - distances[1] = v1; - distances += 2; + INCREASE_LZ_POS + return d; + } + else + { + const UInt32 hs = p->historySize; + if (matchMinPos > hs) + matchMinPos -= hs; + else + matchMinPos = 1; } } + + for (;;) + { + + UInt32 h2, h3, c2, c3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 m = p->lzPos; + MT_HASH3_CALC + + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + d += 2; + break; + } + // else + { + d[0] = 2; + d += 2; + } + } + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } + break; + } + + if (len != 0) + { + do + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + while (bt != btLim); + } INCREASE_LZ_POS - return len; + return d; +} +*/ + + +static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +{ + UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + const UInt32 m = p->lzPos; + MT_HASH3_CALC + // MT_HASH4_CALC + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + // c4 = (hash + kFix4HashSize)[h4]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + // (hash + kFix4HashSize)[h4] = m; + + #define _USE_H2 + + #ifdef _USE_H2 + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + // d[0] = (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) ? 4 : 3; + // return d + 2; + + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + return d; + } + d[0] = 2; + d += 2; + } + #endif + + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c3 - 1; + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + } + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + + return d; } -static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) -{ - const UInt32 *btBuf = p->btBuf + p->btBufPos; - UInt32 len = *btBuf++; - p->btBufPos += 1 + len; +static UInt32* MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + p->btBufPos = btLim; + p->btNumAvailBytes--; + INCREASE_LZ_POS + { + while (bt != btLim) + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + } + return d; +} + + + +static UInt32* MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + UInt32 len = *bt++; + const UInt32 avail = p->btNumAvailBytes - 1; + p->btNumAvailBytes = avail; + p->btBufPos = bt + len; if (len == 0) { - /* change for bt5 ! */ - if (p->btNumAvailBytes-- >= 4) - len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + #define BT_HASH_BYTES_MAX 5 + if (avail >= (BT_HASH_BYTES_MAX - 1) - 1) + { + UInt32 m = p->lzPos; + if (m > p->historySize) + m -= p->historySize; + else + m = 1; + d = p->MixMatchesFunc(p, m, d); + } } else { - /* Condition: there are matches in btBuf with length < p->numHashBytes */ - UInt32 *distances2; - p->btNumAvailBytes--; - distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + /* + first match pair from BinTree: (match_len, match_dist), + (match_len >= numHashBytes). + MixMatchesFunc() inserts only hash matches that are nearer than (match_dist) + */ + d = p->MixMatchesFunc(p, p->lzPos - bt[1], d); + // if (d) // check for failure do { - UInt32 v0 = btBuf[0]; - UInt32 v1 = btBuf[1]; - btBuf += 2; - distances2[0] = v0; - distances2[1] = v1; - distances2 += 2; + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; } - while ((len -= 2) != 0); - len = (UInt32)(distances2 - (distances)); + while (len -= 2); } INCREASE_LZ_POS - return len; + return d; } #define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; -#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { @@ -803,12 +1343,16 @@ static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) } /* +// MatchFinderMt4_Skip() is similar to MatchFinderMt3_Skip(). +// The difference is that MatchFinderMt3_Skip() updates hash for last 3 bytes of stream. + static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER_MT(4) - UInt32 h2, h3, h4; - MT_HASH4_CALC - (hash + kFix4HashSize)[h4] = + UInt32 h2, h3; // h4 + MT_HASH3_CALC + // MT_HASH4_CALC + // (hash + kFix4HashSize)[h4] = (hash + kFix3HashSize)[h3] = hash[ h2] = p->lzPos; @@ -816,14 +1360,14 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) } */ -void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; - switch (p->MatchFinder->numHashBytes) + switch (MF(p)->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; @@ -832,22 +1376,25 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: - p->GetHeadsFunc = GetHeads3; + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; - default: - /* case 4: */ - p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + case 4: + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; + + // it's fast inline version of GetMatches() + // vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches_Bt4; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; - /* default: - p->GetHeadsFunc = GetHeads5; + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; - vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + vTable->Skip = + (Mf_Skip_Func)MatchFinderMt3_Skip; + // (Mf_Skip_Func)MatchFinderMt4_Skip; break; - */ } } diff --git a/libraries/lzma/C/LzFindMt.h b/libraries/lzma/C/LzFindMt.h index ef431e3f5..660b7244d 100644 --- a/libraries/lzma/C/LzFindMt.h +++ b/libraries/lzma/C/LzFindMt.h @@ -1,5 +1,5 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2018-07-04 : Igor Pavlov : Public domain */ +2021-07-12 : Igor Pavlov : Public domain */ #ifndef __LZ_FIND_MT_H #define __LZ_FIND_MT_H @@ -9,31 +9,26 @@ EXTERN_C_BEGIN -#define kMtHashBlockSize (1 << 13) -#define kMtHashNumBlocks (1 << 3) -#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) - -#define kMtBtBlockSize (1 << 14) -#define kMtBtNumBlocks (1 << 6) -#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) - typedef struct _CMtSync { + UInt32 numProcessedBlocks; + CThread thread; + UInt64 affinity; + BoolInt wasCreated; BoolInt needStart; + BoolInt csWasInitialized; + BoolInt csWasEntered; + BoolInt exit; BoolInt stopWriting; - CThread thread; CAutoResetEvent canStart; - CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; - BoolInt csWasInitialized; - BoolInt csWasEntered; CCriticalSection cs; - UInt32 numProcessedBlocks; + // UInt32 numBlocks_Sent; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); @@ -49,18 +44,23 @@ typedef struct _CMatchFinderMt /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; - UInt32 btBufPos; - UInt32 btBufPosLimit; + const UInt32 *btBufPos; + const UInt32 *btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; + // UInt32 hash4Mask; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; - + UInt32 failure_LZ_BT; // failure in BT transfered to LZ + // UInt32 failure_LZ_LZ; // failure in LZ tables + UInt32 failureBuf[1]; + // UInt32 crc[256]; + /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; @@ -70,6 +70,8 @@ typedef struct _CMatchFinderMt UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; + UInt32 failure_BT; + CLzRef *son; UInt32 matchMaxLen; @@ -77,7 +79,7 @@ typedef struct _CMatchFinderMt UInt32 pos; const Byte *buffer; UInt32 cyclicBufferPos; - UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 cutValue; /* BT + Hash */ @@ -87,13 +89,19 @@ typedef struct _CMatchFinderMt /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; + // CMatchFinder MatchFinder; } CMatchFinderMt; +// only for Mt part void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); + SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); -void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable); + +/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */ +SRes MatchFinderMt_InitMt(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); EXTERN_C_END diff --git a/libraries/lzma/C/LzFindOpt.c b/libraries/lzma/C/LzFindOpt.c new file mode 100644 index 000000000..8ff006e07 --- /dev/null +++ b/libraries/lzma/C/LzFindOpt.c @@ -0,0 +1,578 @@ +/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms +2021-07-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "LzFind.h" + +// #include "LzFindMt.h" + +// #define LOG_ITERS + +// #define LOG_THREAD + +#ifdef LOG_THREAD +#include +#define PRF(x) x +#else +// #define PRF(x) +#endif + +#ifdef LOG_ITERS +#include +UInt64 g_NumIters_Tree; +UInt64 g_NumIters_Loop; +UInt64 g_NumIters_Bytes; +#define LOG_ITER(x) x +#else +#define LOG_ITER(x) +#endif + +// ---------- BT THREAD ---------- + +#define USE_SON_PREFETCH +#define USE_LONG_MATCH_OPT + +#define kEmptyHashValue 0 + +// #define CYC_TO_POS_OFFSET 0 + +// #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, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes) +{ + do + { + UInt32 delta; + if (hash == size) + break; + delta = *hash++; + + if (delta == 0 || delta > (UInt32)pos) + return NULL; + + lenLimit++; + + if (delta == (UInt32)pos) + { + CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2; + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + UInt32 *_distances = ++d; + + CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1; + CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + + const Byte *len0 = cur, *len1 = cur; + UInt32 cutValue = _cutValue; + const Byte *maxLen = cur + _maxLen; + + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1); + const Byte *len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (len[diff] == len[0]) + { + if (++len != lenLimit && len[diff] == len[0]) + while (++len != lenLimit) + { + LOG_ITER(g_NumIters_Bytes++); + if (len[diff] != len[0]) + break; + } + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + + if (len == lenLimit) + { + const UInt32 pair1 = pair[1]; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + *ptr0 = pair1; + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + + { + for (;;) + { + hash++; + pos++; + cur++; + lenLimit++; + { + CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + #if 0 + *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff]; + #else + const UInt32 p0 = ptr[0 + (diff * 2)]; + const UInt32 p1 = ptr[1 + (diff * 2)]; + ptr[0] = p0; + ptr[1] = p1; + // ptr[0] = ptr[0 + (diff * 2)]; + // ptr[1] = ptr[1 + (diff * 2)]; + #endif + } + // PrintSon(son + 2, pos - 1); + // printf("\npos = %x delta = %x\n", pos, delta); + len++; + *d++ = 2; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + } + } + #endif + + break; + } + } + } + + { + const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); + if (len[diff] < len[0]) + { + delta = pair[1]; + if (delta >= curMatch) + return NULL; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + } + else + { + delta = *pair; + if (delta >= curMatch) + return NULL; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + } + + delta = (UInt32)pos - delta; + + if (--cutValue == 0 || delta >= pos) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } // for (tree iterations) +} + pos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} +*/ + +/* define cbs if you use 2 functions. + GetMatchesSpecN_1() : (pos < _cyclicBufferSize) + GetMatchesSpecN_2() : (pos >= _cyclicBufferSize) + + do not define cbs if you use 1 function: + GetMatchesSpecN_2() +*/ + +// #define cbs _cyclicBufferSize + +/* + we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32 + 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 _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, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes) +{ + do // while (hash != size) + { + UInt32 delta; + + #ifndef cbs + UInt32 cbs; + #endif + + if (hash == size) + break; + + delta = *hash++; + + if (delta == 0) + return NULL; + + lenLimit++; + + #ifndef cbs + cbs = _cyclicBufferSize; + if ((UInt32)pos < cbs) + { + if (delta > (UInt32)pos) + return NULL; + cbs = (UInt32)pos; + } + #endif + + if (delta >= cbs) + { + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + UInt32 *_distances = ++d; + + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + + UInt32 cutValue = _cutValue; + const Byte *len0 = cur, *len1 = cur; + const Byte *maxLen = cur + _maxLen; + + // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + // SPEC code + CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) + ) << 1); + + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + const Byte *len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (len[diff] == len[0]) + { + if (++len != lenLimit && len[diff] == len[0]) + while (++len != lenLimit) + { + LOG_ITER(g_NumIters_Bytes++); + if (len[diff] != len[0]) + break; + } + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)(len - cur); + *d++ = delta - 1; + + if (len == lenLimit) + { + const UInt32 pair1 = pair[1]; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + *ptr0 = pair1; + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + + { + for (;;) + { + *d++ = 2; + *d++ = (UInt32)(lenLimit - cur); + *d++ = delta - 1; + cur++; + lenLimit++; + // SPEC + _cyclicBufferPos++; + { + // SPEC code + CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1); + const CLzRef *src = dest + ((diff + + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1); + // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + #if 0 + *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); + #else + const UInt32 p0 = src[0]; + const UInt32 p1 = src[1]; + dest[0] = p0; + dest[1] = p1; + #endif + } + pos++; + hash++; + if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + break; + } // for() end for long matches + } + #endif + + break; // break from TREE iterations + } + } + } + { + const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff); + if (len[diff] < len[0]) + { + delta = pair[1]; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + if (delta >= curMatch) + return NULL; + } + else + { + delta = *pair; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + if (delta >= curMatch) + return NULL; + } + delta = (UInt32)pos - delta; + + if (--cutValue == 0 || delta >= cbs) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } // for (tree iterations) +} + pos++; + _cyclicBufferPos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} + + + +/* +typedef UInt32 uint32plus; // size_t + +UInt32 * MY_FAST_CALL 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) +{ + do // while (hash != size) + { + UInt32 delta; + + #ifndef cbs + UInt32 cbs; + #endif + + if (hash == size) + break; + + delta = *hash++; + + if (delta == 0) + return NULL; + + #ifndef cbs + cbs = _cyclicBufferSize; + if ((UInt32)pos < cbs) + { + if (delta > (UInt32)pos) + return NULL; + cbs = (UInt32)pos; + } + #endif + + if (delta >= cbs) + { + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + *d++ = 0; + ptr1[0] = kEmptyHashValue; + ptr1[1] = kEmptyHashValue; + } +else +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + UInt32 *_distances = ++d; + uint32plus len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + uint32plus maxLen = _maxLen; + // lenLimit++; // const Byte *lenLimit = cur + _lenLimit; + + for (LOG_ITER(g_NumIters_Tree++);;) + { + LOG_ITER(g_NumIters_Loop++); + { + // const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0) + ) << 1); + const Byte *pb = cur - delta; + uint32plus len = (len0 < len1 ? len0 : len1); + + #ifdef USE_SON_PREFETCH + const UInt32 pair0 = *pair; + #endif + + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = len; + *d++ = (UInt32)len; + *d++ = delta - 1; + if (len == lenLimit) + { + { + const UInt32 pair1 = pair[1]; + *ptr0 = pair1; + *ptr1 = + #ifdef USE_SON_PREFETCH + pair0; + #else + pair[0]; + #endif + } + + _distances[-1] = (UInt32)(d - _distances); + + #ifdef USE_LONG_MATCH_OPT + + if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) + break; + + { + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + for (;;) + { + *d++ = 2; + *d++ = (UInt32)lenLimit; + *d++ = delta - 1; + _cyclicBufferPos++; + { + CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1); + const CLzRef *src = dest + ((diff + + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1); + #if 0 + *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src); + #else + const UInt32 p0 = src[0]; + const UInt32 p1 = src[1]; + dest[0] = p0; + dest[1] = p1; + #endif + } + hash++; + pos++; + cur++; + pb++; + if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit) + break; + } + } + #endif + + break; + } + } + } + { + const UInt32 curMatch = (UInt32)pos - delta; + if (pb[len] < cur[len]) + { + delta = pair[1]; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + } + else + { + delta = *pair; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + } + + { + if (delta >= curMatch) + return NULL; + delta = (UInt32)pos - delta; + if (delta >= cbs + // delta >= _cyclicBufferSize || delta >= pos + || --cutValue == 0) + { + *ptr0 = *ptr1 = kEmptyHashValue; + _distances[-1] = (UInt32)(d - _distances); + break; + } + } + } + } + } // for (tree iterations) +} + pos++; + _cyclicBufferPos++; + cur++; + } + while (d < limit); + *posRes = (UInt32)pos; + return d; +} +*/ diff --git a/libraries/lzma/C/LzHash.h b/libraries/lzma/C/LzHash.h index e7c942303..77b898cfa 100644 --- a/libraries/lzma/C/LzHash.h +++ b/libraries/lzma/C/LzHash.h @@ -1,57 +1,34 @@ /* LzHash.h -- HASH functions for LZ algorithms -2015-04-12 : Igor Pavlov : Public domain */ +2019-10-30 : Igor Pavlov : Public domain */ #ifndef __LZ_HASH_H #define __LZ_HASH_H +/* + (kHash2Size >= (1 << 8)) : Required + (kHash3Size >= (1 << 16)) : Required +*/ + #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) -#define kHash4Size (1 << 20) +// #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) -#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) -#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8); +/* + We use up to 3 crc values for hash: + crc0 + crc1 << Shift_1 + crc2 << Shift_2 + (Shift_1 = 5) and (Shift_2 = 10) is good tradeoff. + Small values for Shift are not good for collision rate. + Big value for Shift_2 increases the minimum size + of hash table, that will be slow for small files. +*/ -#define HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } - -#define HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - temp ^= ((UInt32)cur[2] << 8); \ - h3 = temp & (kHash3Size - 1); \ - hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; } - -#define HASH5_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - temp ^= ((UInt32)cur[2] << 8); \ - h3 = temp & (kHash3Size - 1); \ - temp ^= (p->crc[cur[3]] << 5); \ - h4 = temp & (kHash4Size - 1); \ - hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; } - -/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ -#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; - - -#define MT_HASH2_CALC \ - h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); - -#define MT_HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } - -#define MT_HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - h2 = temp & (kHash2Size - 1); \ - temp ^= ((UInt32)cur[2] << 8); \ - h3 = temp & (kHash3Size - 1); \ - h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } +#define kLzHash_CrcShift_1 5 +#define kLzHash_CrcShift_2 10 #endif diff --git a/libraries/lzma/C/Lzma2Dec.c b/libraries/lzma/C/Lzma2Dec.c index 4e138a4ae..ac970a843 100644 --- a/libraries/lzma/C/Lzma2Dec.c +++ b/libraries/lzma/C/Lzma2Dec.c @@ -1,5 +1,5 @@ /* Lzma2Dec.c -- LZMA2 Decoder -2019-02-02 : Igor Pavlov : Public domain */ +2021-02-09 : Igor Pavlov : Public domain */ /* #define SHOW_DEBUG_INFO */ @@ -93,7 +93,8 @@ void Lzma2Dec_Init(CLzma2Dec *p) LzmaDec_Init(&p->decoder); } -static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +// ELzma2State +static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) { switch (p->state) { diff --git a/libraries/lzma/C/LzmaDec.c b/libraries/lzma/C/LzmaDec.c index ba3e1dd50..d6742e5af 100644 --- a/libraries/lzma/C/LzmaDec.c +++ b/libraries/lzma/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2018-07-04 : Igor Pavlov : Public domain */ +2021-04-01 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -13,10 +13,12 @@ #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 #define RC_INIT_SIZE 5 +#ifndef _LZMA_DEC_OPT + +#define kNumMoveBits 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) @@ -62,9 +64,10 @@ probLit = prob + (offs + bit + symbol); \ GET_BIT2(probLit, symbol, offs ^= bit; , ;) +#endif // _LZMA_DEC_OPT -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } +#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 UPDATE_0_CHECK range = bound; @@ -114,6 +117,9 @@ #define kMatchMinLen 2 #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) +#define kMatchSpecLen_Error_Data (1 << 9) +#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1) + /* External ASM code needs same CLzmaProb array layout. So don't change it. */ /* (probs_1664) is faster and better for code size at some platforms */ @@ -166,10 +172,12 @@ /* p->remainLen : shows status of LZMA decoder: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : need init range coder - = kMatchSpecLenStart + 2 : need init range coder and state + < kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + = kMatchSpecLenStart + 1 : need init range coder + = kMatchSpecLenStart + 2 : need init range coder and state + = kMatchSpecLen_Error_Fail : Internal Code Failure + = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error */ /* ---------- LZMA_DECODE_REAL ---------- */ @@ -188,23 +196,31 @@ In: { LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol - is not END_OF_PAYALOAD_MARKER, then function returns error code. + is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary, + the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later. } Processing: - first LZMA symbol will be decoded in any case - All checks for limits are at the end of main loop, - It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit), + The first LZMA symbol will be decoded in any case. + All main checks for limits are at the end of main loop, + It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit), RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. + But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for + next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX), + that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit. + So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte. Out: RangeCoder is normalized Result: SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished + p->remainLen: + < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + + SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary + p->remainLen : undefined + p->reps[*] : undefined */ @@ -316,11 +332,6 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit else { UPDATE_1(prob); - /* - // that case was checked before with kBadRepCode - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - */ prob = probs + IsRepG0 + state; IF_BIT_0(prob) { @@ -329,6 +340,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit IF_BIT_0(prob) { UPDATE_0(prob); + + // that case was checked before with kBadRepCode + // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; } + // The caller doesn't allow (dicPos == limit) case here + // so we don't need the following check: + // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; } + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; processedPos++; @@ -518,8 +536,10 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) { - p->dicPos = dicPos; - return SZ_ERROR_DATA; + len += kMatchSpecLen_Error_Data + kMatchMinLen; + // len = kMatchSpecLen_Error_Data; + // len += kMatchMinLen; + break; } } @@ -532,8 +552,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit if ((rem = limit - dicPos) == 0) { - p->dicPos = dicPos; - return SZ_ERROR_DATA; + /* + We stop decoding and return SZ_OK, and we can resume decoding later. + Any error conditions can be tested later in caller code. + For more strict mode we can stop decoding with error + // len += kMatchSpecLen_Error_Data; + */ + break; } curLen = ((rem < len) ? (unsigned)rem : len); @@ -572,7 +597,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit p->buf = buf; p->range = range; p->code = code; - p->remainLen = (UInt32)len; + p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too. p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; @@ -580,40 +605,61 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit p->reps[2] = rep2; p->reps[3] = rep3; p->state = (UInt32)state; - + if (len >= kMatchSpecLen_Error_Data) + return SZ_ERROR_DATA; return SZ_OK; } #endif + + static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + unsigned len = (unsigned)p->remainLen; + if (len == 0 /* || len >= kMatchSpecLenStart */) + return; { - Byte *dic = p->dic; SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = (unsigned)p->remainLen; - SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ - SizeT rem = limit - dicPos; - if (rem < len) - len = (unsigned)(rem); + Byte *dic; + SizeT dicBufSize; + SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ + { + SizeT rem = limit - dicPos; + if (rem < len) + { + len = (unsigned)(rem); + if (len == 0) + return; + } + } if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += (UInt32)len; p->remainLen -= (UInt32)len; - while (len != 0) + dic = p->dic; + rep0 = p->reps[0]; + dicBufSize = p->dicBufSize; + do { - len--; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; dicPos++; } + while (--len); p->dicPos = dicPos; } } +/* +At staring of new stream we have one of the following symbols: + - Literal - is allowed + - Non-Rep-Match - is allowed only if it's end marker symbol + - Rep-Match - is not allowed +We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code +*/ + #define kRange0 0xFFFFFFFF #define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) #define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) @@ -621,69 +667,77 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) #error Stop_Compiling_Bad_LZMA_Check #endif + +/* +LzmaDec_DecodeReal2(): + It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize). + +We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(), +and we support the following state of (p->checkDicSize): + if (total_processed < p->prop.dicSize) then + { + (total_processed == p->processedPos) + (p->checkDicSize == 0) + } + else + (p->checkDicSize == p->prop.dicSize) +*/ + static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { - do + if (p->checkDicSize == 0) { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - - if (p->processedPos == 0) - if (p->code >= kBadRepCode) - return SZ_ERROR_DATA; - } - - RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit)); - + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit = p->dicPos + rem; + } + { + int res = LZMA_DECODE_REAL(p, limit, bufLimit); if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; - - LzmaDec_WriteRem(p, limit); + return res; } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - return 0; } + + typedef enum { - DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_INPUT_EOF, /* need more input data */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) + +#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH) + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut) { UInt32 range = p->range; UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; + const Byte *bufLimit = *bufOut; const CLzmaProb *probs = GET_PROBS; unsigned state = (unsigned)p->state; ELzmaDummy res; + for (;;) { const CLzmaProb *prob; UInt32 bound; unsigned ttt; - unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1); + unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1); prob = probs + IsMatch + COMBINED_PS_STATE; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += ((UInt32)LZMA_LIT_SIZE * - ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + - (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) + + ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { @@ -735,8 +789,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; + break; } else { @@ -812,8 +865,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS { unsigned numDirectBits = ((posSlot >> 1) - 1); - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); @@ -844,12 +895,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS } } } + break; } NORMALIZE_CHECK; + + *bufOut = buf; return res; } - +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState) { p->remainLen = kMatchSpecLenStart + 1; @@ -872,16 +926,41 @@ void LzmaDec_Init(CLzmaDec *p) } +/* +LZMA supports optional end_marker. +So the decoder can lookahead for one additional LZMA-Symbol to check end_marker. +That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream. +When the decoder reaches dicLimit, it looks (finishMode) parameter: + if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead + if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position + +When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways: + 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA. + 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller + must check (status) value. The caller can show the error, + if the end of stream is expected, and the (status) is noit + LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK. +*/ + + +#define RETURN__NOT_FINISHED__FOR_FINISH \ + *status = LZMA_STATUS_NOT_FINISHED; \ + return SZ_ERROR_DATA; // for strict mode + // return SZ_OK; // for relaxed mode + + SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; - *status = LZMA_STATUS_NOT_SPECIFIED; if (p->remainLen > kMatchSpecLenStart) { + if (p->remainLen > kMatchSpecLenStart + 2) + return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA; + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize != 0 && p->tempBuf[0] != 0) @@ -896,6 +975,12 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr | ((UInt32)p->tempBuf[2] << 16) | ((UInt32)p->tempBuf[3] << 8) | ((UInt32)p->tempBuf[4]); + + if (p->checkDicSize == 0 + && p->processedPos == 0 + && p->code >= kBadRepCode) + return SZ_ERROR_DATA; + p->range = 0xFFFFFFFF; p->tempBufSize = 0; @@ -913,10 +998,21 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr p->remainLen = 0; } - LzmaDec_WriteRem(p, dicLimit); - - while (p->remainLen != kMatchSpecLenStart) + for (;;) { + if (p->remainLen == kMatchSpecLenStart) + { + if (p->code != 0) + return SZ_ERROR_DATA; + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + + LzmaDec_WriteRem(p, dicLimit); + + { + // (p->remainLen == 0 || p->dicPos == dicLimit) + int checkEndMarkNow = 0; if (p->dicPos >= dicLimit) @@ -933,92 +1029,174 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr } if (p->remainLen != 0) { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; + RETURN__NOT_FINISHED__FOR_FINISH; } checkEndMarkNow = 1; } + // (p->remainLen == 0) + if (p->tempBufSize == 0) { - SizeT processed; const Byte *bufLimit; + int dummyProcessed = -1; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) + const Byte *bufOut = src + inSize; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; + size_t i; + if (inSize >= LZMA_REQUIRED_INPUT_MAX) + break; (*srcLen) += inSize; + p->tempBufSize = (unsigned)inSize; + for (i = 0; i < inSize; i++) + p->tempBuf[i] = src[i]; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + + dummyProcessed = (int)(bufOut - src); + if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; + unsigned i; + (*srcLen) += (unsigned)dummyProcessed; + p->tempBufSize = (unsigned)dummyProcessed; + for (i = 0; i < (unsigned)dummyProcessed; i++) + p->tempBuf[i] = src[i]; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; } + bufLimit = src; + // we will decode only one iteration } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem); - if (dummyRes == DUMMY_ERROR) + int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit); + + SizeT processed = (SizeT)(p->buf - src); + + if (dummyProcessed < 0) { - (*srcLen) += (SizeT)lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; + if (processed > inSize) + break; } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + else if ((unsigned)dummyProcessed != processed) + break; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + + if (res != SZ_OK) { - *status = LZMA_STATUS_NOT_FINISHED; + p->remainLen = kMatchSpecLen_Error_Data; return SZ_ERROR_DATA; } } + continue; + } + + { + // we have some data in (p->tempBuf) + // in strict mode: tempBufSize is not enough for one Symbol decoding. + // in relaxed mode: tempBufSize not larger than required for one Symbol decoding. + + unsigned rem = p->tempBufSize; + unsigned ahead = 0; + int dummyProcessed = -1; + + while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize) + p->tempBuf[rem++] = src[ahead++]; + + // ahead - the size of new data copied from (src) to (p->tempBuf) + // rem - the size of temp buffer including new data from (src) + + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + const Byte *bufOut = p->tempBuf + rem; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) + { + if (rem >= LZMA_REQUIRED_INPUT_MAX) + break; + p->tempBufSize = rem; + (*srcLen) += (SizeT)ahead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + dummyProcessed = (int)(bufOut - p->tempBuf); + + if ((unsigned)dummyProcessed < p->tempBufSize) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) + { + (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize; + p->tempBufSize = (unsigned)dummyProcessed; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; + } + } + p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; { - unsigned kkk = (unsigned)(p->buf - p->tempBuf); - if (rem < kkk) - return SZ_ERROR_FAIL; /* some internal error */ - rem -= kkk; - if (lookAhead < rem) - return SZ_ERROR_FAIL; /* some internal error */ - lookAhead -= rem; + // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf) + int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf); + + SizeT processed = (SizeT)(p->buf - p->tempBuf); + rem = p->tempBufSize; + + if (dummyProcessed < 0) + { + if (processed > LZMA_REQUIRED_INPUT_MAX) + break; + if (processed < rem) + break; + } + else if ((unsigned)dummyProcessed != processed) + break; + + processed -= rem; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + p->tempBufSize = 0; + + if (res != SZ_OK) + { + p->remainLen = kMatchSpecLen_Error_Data; + return SZ_ERROR_DATA; + } } - (*srcLen) += (SizeT)lookAhead; - src += lookAhead; - inSize -= (SizeT)lookAhead; - p->tempBufSize = 0; } + } } - - if (p->code != 0) - return SZ_ERROR_DATA; - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return SZ_OK; + + /* Some unexpected error: internal error of code, memory corruption or hardware failure */ + p->remainLen = kMatchSpecLen_Error_Fail; + return SZ_ERROR_FAIL; } + SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; diff --git a/libraries/lzma/C/LzmaDec.h b/libraries/lzma/C/LzmaDec.h index 1f0927ab1..6f1296250 100644 --- a/libraries/lzma/C/LzmaDec.h +++ b/libraries/lzma/C/LzmaDec.h @@ -1,5 +1,5 @@ /* LzmaDec.h -- LZMA Decoder -2018-04-21 : Igor Pavlov : Public domain */ +2020-03-19 : Igor Pavlov : Public domain */ #ifndef __LZMA_DEC_H #define __LZMA_DEC_H @@ -181,6 +181,7 @@ Returns: LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, @@ -223,6 +224,7 @@ Returns: SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, diff --git a/libraries/lzma/C/LzmaEnc.c b/libraries/lzma/C/LzmaEnc.c index 46a0db000..b04a7b7b7 100644 --- a/libraries/lzma/C/LzmaEnc.c +++ b/libraries/lzma/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2019-01-10: Igor Pavlov : Public domain */ +2021-11-18: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -12,6 +12,7 @@ #include #endif +#include "CpuArch.h" #include "LzmaEnc.h" #include "LzFind.h" @@ -19,12 +20,25 @@ #include "LzFindMt.h" #endif +/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */ + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, 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); + #ifdef SHOW_STAT static unsigned g_STAT_OFFSET = 0; #endif -#define kLzmaMaxHistorySize ((UInt32)3 << 29) -/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */ +/* 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) @@ -36,7 +50,7 @@ static unsigned g_STAT_OFFSET = 0; #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 -#define kBitPrice (1 << kNumBitPriceShiftBits) +// #define kBitPrice (1 << kNumBitPriceShiftBits) #define REP_LEN_COUNT 64 @@ -47,6 +61,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p) p->reduceSize = (UInt64)(Int64)-1; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; + p->affinity = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) @@ -55,16 +70,21 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (level < 0) level = 5; p->level = level; - if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26))); + if (p->dictSize == 0) + p->dictSize = + ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : + ( level <= 6 ? ((UInt32)1 << (level + 19)) : + ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) + ))); + if (p->dictSize > p->reduceSize) { - unsigned i; - UInt32 reduceSize = (UInt32)p->reduceSize; - for (i = 11; i <= 30; i++) - { - if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } - if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } - } + UInt32 v = (UInt32)p->reduceSize; + const UInt32 kReduceMin = ((UInt32)1 << 12); + if (v < kReduceMin) + v = kReduceMin; + if (p->dictSize > v) + p->dictSize = v; } if (p->lc < 0) p->lc = 3; @@ -74,8 +94,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); - if (p->numHashBytes < 0) p->numHashBytes = 4; - if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); + if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = @@ -93,18 +113,85 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) return props.dictSize; } -#if (_MSC_VER >= 1400) -/* BSR code is fast for some new CPUs */ -/* #define LZMA_LOG_BSR */ + +/* +x86/x64: + +BSR: + IF (SRC == 0) ZF = 1, DEST is undefined; + AMD : DEST is unchanged; + IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit + BSR is slow in some processors + +LZCNT: + IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64) + IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits + IF (DEST == 0) ZF = 1; + +LZCNT works only in new processors starting from Haswell. +if LZCNT is not supported by processor, then it's executed as BSR. +LZCNT can be faster than BSR, if supported. +*/ + +// #define LZMA_LOG_BSR + +#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */ + + #if (defined(__clang__) && (__clang_major__ >= 6)) \ + || (defined(__GNUC__) && (__GNUC__ >= 6)) + #define LZMA_LOG_BSR + #elif defined(_MSC_VER) && (_MSC_VER >= 1300) + // #if defined(MY_CPU_ARM_OR_ARM64) + #define LZMA_LOG_BSR + // #endif + #endif #endif +// #include + #ifdef LZMA_LOG_BSR -#define kDicLogSizeMaxCompress 32 +#if defined(__clang__) \ + || defined(__GNUC__) -#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); } +/* + C code: : (30 - __builtin_clz(x)) + gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31) + clang10 for x64 : 31 + (bsr(x) xor -32) +*/ -static unsigned GetPosSlot1(UInt32 pos) + #define MY_clz(x) ((unsigned)__builtin_clz(x)) + // __lzcnt32 + // __builtin_ia32_lzcnt_u32 + +#else // #if defined(_MSC_VER) + + #ifdef MY_CPU_ARM_OR_ARM64 + + #define MY_clz _CountLeadingZeros + + #else // if defined(MY_CPU_X86_OR_AMD64) + + // #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU) + // _BitScanReverse code is not optimal for some MSVC compilers + #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \ + res = (zz + zz) + (pos >> zz); } + + #endif // MY_CPU_X86_OR_AMD64 + +#endif // _MSC_VER + + +#ifndef BSR2_RET + + #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \ + res = (zz + zz) + (pos >> zz); } + +#endif + + +unsigned GetPosSlot1(UInt32 pos); +unsigned GetPosSlot1(UInt32 pos) { unsigned res; BSR2_RET(pos, res); @@ -113,10 +200,10 @@ static unsigned GetPosSlot1(UInt32 pos) #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } -#else -#define kNumLogBits (9 + sizeof(size_t) / 2) -/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */ +#else // ! LZMA_LOG_BSR + +#define kNumLogBits (11 + sizeof(size_t) / 8 * 3) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) @@ -163,7 +250,7 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos) #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } -#endif +#endif // LZMA_LOG_BSR #define LZMA_NUM_REPS 4 @@ -193,7 +280,7 @@ typedef struct #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 -#define kDicLogSizeMin 0 +// #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) @@ -299,7 +386,7 @@ typedef UInt32 CProbPrice; typedef struct { void *matchFinderObj; - IMatchFinder matchFinder; + IMatchFinder2 matchFinder; unsigned optCur; unsigned optEnd; @@ -344,10 +431,14 @@ typedef struct // begin of CMatchFinderMt is used in LZ thread CMatchFinderMt matchFinderMt; // end of CMatchFinderMt is used in BT and HASH threads + // #else + // CMatchFinder matchFinderBase; #endif - CMatchFinder matchFinderBase; + + // we suppose that we have 8-bytes alignment after CMatchFinder + #ifndef _7ZIP_ST Byte pad[128]; #endif @@ -355,8 +446,10 @@ typedef struct // LZ thread CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; - UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + // we want {len , dist} pairs to be 8-bytes aligned in matches array + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2]; + // we want 8-bytes alignment here UInt32 alignPrices[kAlignTableSize]; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; @@ -385,12 +478,19 @@ typedef struct CSaveState saveState; + // BoolInt mf_Failure; #ifndef _7ZIP_ST Byte pad2[128]; #endif } CLzmaEnc; +#define MFB (p->matchFinderBase) +/* +#ifndef _7ZIP_ST +#define MFB (p->matchFinderMt.MatchFinder) +#endif +*/ #define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); @@ -455,41 +555,51 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX - || props.pb > LZMA_PB_MAX - || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress) - || props.dictSize > kLzmaMaxHistorySize) + || props.pb > LZMA_PB_MAX) return SZ_ERROR_PARAM; + + if (props.dictSize > kLzmaMaxHistorySize) + props.dictSize = kLzmaMaxHistorySize; + + #ifndef LZMA_LOG_BSR + { + const UInt64 dict64 = props.dictSize; + if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress)) + return SZ_ERROR_PARAM; + } + #endif + p->dictSize = props.dictSize; { - unsigned fb = props.fb; + unsigned fb = (unsigned)props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } - p->lc = props.lc; - p->lp = props.lp; - p->pb = props.pb; + p->lc = (unsigned)props.lc; + p->lp = (unsigned)props.lp; + p->pb = (unsigned)props.pb; p->fastMode = (props.algo == 0); // p->_maxMode = True; - p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0); + MFB.btMode = (Byte)(props.btMode ? 1 : 0); { unsigned numHashBytes = 4; if (props.btMode) { - if (props.numHashBytes < 2) - numHashBytes = 2; - else if (props.numHashBytes < 4) - numHashBytes = props.numHashBytes; + if (props.numHashBytes < 2) numHashBytes = 2; + else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes; } - p->matchFinderBase.numHashBytes = numHashBytes; + if (props.numHashBytes >= 5) numHashBytes = 5; + + MFB.numHashBytes = numHashBytes; } - p->matchFinderBase.cutValue = props.mc; + MFB.cutValue = props.mc; - p->writeEndMark = props.writeEndMark; + p->writeEndMark = (BoolInt)props.writeEndMark; #ifndef _7ZIP_ST /* @@ -500,6 +610,8 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) } */ p->multiThread = (props.numThreads > 1); + p->matchFinderMt.btSync.affinity = + p->matchFinderMt.hashSync.affinity = props.affinity; #endif return SZ_OK; @@ -509,7 +621,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.expectedDataSize = expectedDataSiize; + MFB.expectedDataSize = expectedDataSiize; } @@ -536,8 +648,8 @@ static void RangeEnc_Construct(CRangeEnc *p) p->bufBase = NULL; } -#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) -#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) +#define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize) +#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) #define RC_BUF_SIZE (1 << 16) @@ -556,12 +668,11 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->bufBase); - p->bufBase = 0; + p->bufBase = NULL; } static void RangeEnc_Init(CRangeEnc *p) { - /* Stream.Init(); */ p->range = 0xFFFFFFFF; p->cache = 0; p->low = 0; @@ -575,12 +686,12 @@ static void RangeEnc_Init(CRangeEnc *p) MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) { - size_t num; - if (p->res != SZ_OK) - return; - num = p->buf - p->bufBase; - if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) - p->res = SZ_ERROR_WRITE; + const size_t num = (size_t)(p->buf - p->bufBase); + if (p->res == SZ_OK) + { + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + } p->processed += num; p->buf = p->bufBase; } @@ -656,7 +767,7 @@ static void RangeEnc_FlushData(CRangeEnc *p) range += newBound & mask; \ mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ mask += ((1 << kNumMoveBits) - 1); \ - ttt += (Int32)(mask - ttt) >> kNumMoveBits; \ + ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \ *(prob) = (CLzmaProb)ttt; \ RC_NORM(p) \ } @@ -749,7 +860,7 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) bitCount++; } } - ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); // printf("\n%3d: %5d", i, ProbPrices[i]); } } @@ -985,7 +1096,11 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) p->additionalOffset++; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); - numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + { + const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + // if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; } + numPairs = (unsigned)(d - p->matches); + } *numPairsRes = numPairs; #ifdef SHOW_STAT @@ -1001,7 +1116,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) if (numPairs == 0) return 0; { - unsigned len = p->matches[(size_t)numPairs - 2]; + const unsigned len = p->matches[(size_t)numPairs - 2]; if (len != p->numFastBytes) return len; { @@ -1011,7 +1126,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) { const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; const Byte *p2 = p1 + len; - ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1]; + const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1]; const Byte *lim = p1 + numAvail; for (; p2 != lim && *p2 == p2[dif]; p2++) {} @@ -1167,6 +1282,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; + if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization + break; } if (repLens[repMaxIndex] >= p->numFastBytes) @@ -1179,10 +1296,12 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } matches = p->matches; + #define MATCHES matches + // #define MATCHES p->matches if (mainLen >= p->numFastBytes) { - p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS; MOVE_POS(p, mainLen - 1) return mainLen; } @@ -1276,13 +1395,13 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) if (len < 2) len = 2; else - while (len > matches[offs]) + while (len > MATCHES[offs]) offs += 2; for (; ; len++) { COptimal *opt; - UInt32 dist = matches[(size_t)offs + 1]; + UInt32 dist = MATCHES[(size_t)offs + 1]; UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); unsigned lenToPosState = GetLenToPosState(len); @@ -1306,7 +1425,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) opt->extra = 0; } - if (len == matches[offs]) + if (len == MATCHES[offs]) { offs += 2; if (offs == numPairs) @@ -1727,8 +1846,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) if (newLen > numAvail) { newLen = numAvail; - for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); - matches[numPairs] = (UInt32)newLen; + for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2); + MATCHES[numPairs] = (UInt32)newLen; numPairs += 2; } @@ -1747,9 +1866,9 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } offs = 0; - while (startLen > matches[offs]) + while (startLen > MATCHES[offs]) offs += 2; - dist = matches[(size_t)offs + 1]; + dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot); @@ -1776,7 +1895,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) } } - if (len == matches[offs]) + if (len == MATCHES[offs]) { // if (p->_maxMode) { // MATCH : LIT : REP_0 @@ -1841,7 +1960,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) offs += 2; if (offs == numPairs) break; - dist = matches[(size_t)offs + 1]; + dist = MATCHES[(size_t)offs + 1]; // if (dist >= kNumFullDistances) GetPosSlot2(dist, posSlot); } @@ -2059,8 +2178,23 @@ static SRes CheckErrors(CLzmaEnc *p) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; - if (p->matchFinderBase.result != SZ_OK) + + #ifndef _7ZIP_ST + if ( + // p->mf_Failure || + (p->mtMode && + ( // p->matchFinderMt.failure_LZ_LZ || + p->matchFinderMt.failure_LZ_BT)) + ) + { + p->result = MY_HRES_ERROR__INTERNAL_ERROR; + // printf("\nCheckErrors p->matchFinderMt.failureLZ\n"); + } + #endif + + if (MFB.result != SZ_OK) p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) p->finished = True; return p->result; @@ -2198,14 +2332,14 @@ MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) -void LzmaEnc_Construct(CLzmaEnc *p) +static void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); - MatchFinder_Construct(&p->matchFinderBase); + MatchFinder_Construct(&MFB); #ifndef _7ZIP_ST + p->matchFinderMt.MatchFinder = &MFB; MatchFinderMt_Construct(&p->matchFinderMt); - p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { @@ -2221,7 +2355,6 @@ void LzmaEnc_Construct(CLzmaEnc *p) LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = NULL; p->saveState.litProbs = NULL; - } CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) @@ -2233,7 +2366,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) return p; } -void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->litProbs); ISzAlloc_Free(alloc, p->saveState.litProbs); @@ -2241,13 +2374,13 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) p->saveState.litProbs = NULL; } -void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) { #ifndef _7ZIP_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif - MatchFinder_Free(&p->matchFinderBase, allocBig); + MatchFinder_Free(&MFB, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } @@ -2259,11 +2392,18 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) } +MY_NO_INLINE static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->needInit) { + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)); + } + #endif p->matchFinder.Init(p->matchFinderObj); p->needInit = 0; } @@ -2521,12 +2661,12 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa // { int y; for (y = 0; y < 100; y++) { FillDistancesPrices(p); // }} - LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); } if (p->repLenEncCounter <= 0) { p->repLenEncCounter = REP_LEN_COUNT; - LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } } @@ -2559,11 +2699,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) { UInt32 beforeSize = kNumOpts; + UInt32 dictSize; + if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; #ifndef _7ZIP_ST - p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); + p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0)); #endif { @@ -2582,36 +2724,56 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, } } - p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); + MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); - if (beforeSize + p->dictSize < keepWindowSize) - beforeSize = keepWindowSize - p->dictSize; + + dictSize = p->dictSize; + if (dictSize == ((UInt32)2 << 30) || + dictSize == ((UInt32)3 << 30)) + { + /* 21.03 : here we reduce the dictionary for 2 reasons: + 1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary. + 2) we want to elimate useless last MatchFinder_Normalize3() for corner cases, + where data size is aligned for 1 GB: 5/6/8 GB. + That reducing must be >= 1 for such corner cases. */ + dictSize -= 1; + } + + if (beforeSize + dictSize < keepWindowSize) + beforeSize = keepWindowSize - dictSize; + + /* in worst case we can look ahead for + max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes. + we send larger value for (keepAfter) to MantchFinder_Create(): + (numFastBytes + LZMA_MATCH_LEN_MAX + 1) + */ #ifndef _7ZIP_ST if (p->mtMode) { - RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, - LZMA_MATCH_LEN_MAX - + 1 /* 18.04 */ + RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */ , allocBig)); p->matchFinderObj = &p->matchFinderMt; - p->matchFinderBase.bigHash = (Byte)( - (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0); + MFB.bigHash = (Byte)( + (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0); MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { - if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + if (!MatchFinder_Create(&MFB, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */ + , allocBig)) return SZ_ERROR_MEM; - p->matchFinderObj = &p->matchFinderBase; - MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + p->matchFinderObj = &MFB; + MatchFinder_CreateVTable(&MFB, &p->matchFinder); } return SZ_OK; } -void LzmaEnc_Init(CLzmaEnc *p) +static void LzmaEnc_Init(CLzmaEnc *p) { unsigned i; p->state = 0; @@ -2675,12 +2837,14 @@ void LzmaEnc_Init(CLzmaEnc *p) p->additionalOffset = 0; - p->pbMask = (1 << p->pb) - 1; + p->pbMask = ((unsigned)1 << p->pb) - 1; p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); + + // p->mf_Failure = False; } -void LzmaEnc_InitPrices(CLzmaEnc *p) +static void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { @@ -2694,8 +2858,8 @@ void LzmaEnc_InitPrices(CLzmaEnc *p) p->repLenEncCounter = REP_LEN_COUNT; - LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); - LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) @@ -2719,7 +2883,7 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInS ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.stream = inStream; + MFB.stream = inStream; p->needInit = 1; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); @@ -2730,16 +2894,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISzAllocPtr alloc, ISzAllocPtr allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->matchFinderBase.stream = inStream; + MFB.stream = inStream; p->needInit = 1; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { - p->matchFinderBase.directInput = 1; - p->matchFinderBase.bufferBase = (Byte *)src; - p->matchFinderBase.directInputRem = srcLen; + MFB.directInput = 1; + MFB.bufferBase = (Byte *)src; + MFB.directInputRem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, @@ -2781,19 +2945,23 @@ static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, s size = p->rem; p->overflow = True; } - memcpy(p->data, data, size); - p->rem -= size; - p->data += size; + if (size != 0) + { + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + } return size; } +/* UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } - +*/ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { @@ -2841,6 +3009,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, } +MY_NO_INLINE static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) { SRes res = SZ_OK; @@ -2870,7 +3039,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) LzmaEnc_Finish(p); /* - if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase)) + if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB)) res = SZ_ERROR_FAIL; } */ @@ -2889,35 +3058,43 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { - CLzmaEnc *p = (CLzmaEnc *)pp; - unsigned i; - UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; - props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); - - if (dictSize >= ((UInt32)1 << 22)) { - UInt32 kDictMask = ((UInt32)1 << 20) - 1; - if (dictSize < (UInt32)0xFFFFFFFF - kDictMask) - dictSize = (dictSize + kDictMask) & ~kDictMask; - } - else for (i = 11; i <= 30; i++) - { - if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } - if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } - } + const CLzmaEnc *p = (const CLzmaEnc *)pp; + const UInt32 dictSize = p->dictSize; + UInt32 v; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + // we write aligned dictionary value to properties for lzma decoder + if (dictSize >= ((UInt32)1 << 21)) + { + const UInt32 kDictMask = ((UInt32)1 << 20) - 1; + v = (dictSize + kDictMask) & ~kDictMask; + if (v < dictSize) + v = dictSize; + } + else + { + unsigned i = 11 * 2; + do + { + v = (UInt32)(2 + (i & 1)) << (i >> 1); + i++; + } + while (v < dictSize); + } - for (i = 0; i < 4; i++) - props[1 + i] = (Byte)(dictSize >> (8 * i)); - return SZ_OK; + SetUi32(props + 1, v); + return SZ_OK; + } } unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) { - return ((CLzmaEnc *)pp)->writeEndMark; + return (unsigned)((CLzmaEnc *)pp)->writeEndMark; } @@ -2974,3 +3151,15 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, LzmaEnc_Destroy(p, alloc, allocBig); return res; } + + +/* +#ifndef _7ZIP_ST +void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + lz_threads[0] = p->matchFinderMt.hashSync.thread; + lz_threads[1] = p->matchFinderMt.btSync.thread; +} +#endif +*/ diff --git a/libraries/lzma/C/LzmaEnc.h b/libraries/lzma/C/LzmaEnc.h index 9194ee576..bc2ed5042 100644 --- a/libraries/lzma/C/LzmaEnc.h +++ b/libraries/lzma/C/LzmaEnc.h @@ -1,5 +1,5 @@ /* LzmaEnc.h -- LZMA Encoder -2017-07-27 : Igor Pavlov : Public domain */ +2019-10-30 : Igor Pavlov : Public domain */ #ifndef __LZMA_ENC_H #define __LZMA_ENC_H @@ -29,6 +29,8 @@ typedef struct _CLzmaEncProps UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. Encoder uses this value to reduce dictionary size */ + + UInt64 affinity; } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); diff --git a/libraries/lzma/C/Ppmd.h b/libraries/lzma/C/Ppmd.h index a5c1e3ef2..b19879208 100644 --- a/libraries/lzma/C/Ppmd.h +++ b/libraries/lzma/C/Ppmd.h @@ -1,5 +1,5 @@ /* Ppmd.h -- PPMD codec common code -2017-04-03 : Igor Pavlov : Public domain +2021-04-13 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #ifndef __PPMD_H @@ -9,7 +9,16 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ EXTERN_C_BEGIN -#ifdef MY_CPU_32BIT +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +/* + PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block. + if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields. + if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields. + if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed, + if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional, + and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit. + PPMD code works slightly faster in (PPMD_32BIT) mode. +*/ #define PPMD_32BIT #endif @@ -28,7 +37,7 @@ EXTERN_C_BEGIN #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) -#pragma pack(push, 1) +MY_CPU_pragma_pack_push_1 /* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ /* SEE-contexts for PPM-contexts with masked symbols */ @@ -40,41 +49,114 @@ typedef struct } CPpmd_See; #define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ - { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); } + { (p)->Summ = (UInt16)((p)->Summ << 1); (p)->Count = (Byte)(3 << (p)->Shift++); } + typedef struct { Byte Symbol; Byte Freq; - UInt16 SuccessorLow; - UInt16 SuccessorHigh; + UInt16 Successor_0; + UInt16 Successor_1; } CPpmd_State; -#pragma pack(pop) +typedef struct CPpmd_State2_ +{ + Byte Symbol; + Byte Freq; +} CPpmd_State2; -typedef - #ifdef PPMD_32BIT - CPpmd_State * - #else - UInt32 - #endif - CPpmd_State_Ref; +typedef struct CPpmd_State4_ +{ + UInt16 Successor_0; + UInt16 Successor_1; +} CPpmd_State4; -typedef - #ifdef PPMD_32BIT - void * - #else - UInt32 - #endif - CPpmd_Void_Ref; +MY_CPU_pragma_pop + +/* + PPMD code can write full CPpmd_State structure data to CPpmd*_Context + at (byte offset = 2) instead of some fields of original CPpmd*_Context structure. + + If we use pointers to different types, but that point to shared + memory space, we can have aliasing problem (strict aliasing). + + XLC compiler in -O2 mode can change the order of memory write instructions + in relation to read instructions, if we have use pointers to different types. + + To solve that aliasing problem we use combined CPpmd*_Context structure + with unions that contain the fields from both structures: + the original CPpmd*_Context and CPpmd_State. + So we can access the fields from both structures via one pointer, + and the compiler doesn't change the order of write instructions + in relation to read instructions. + + If we don't use memory write instructions to shared memory in + some local code, and we use only reading instructions (read only), + then probably it's safe to use pointers to different types for reading. +*/ + + + +#ifdef PPMD_32BIT + + #define Ppmd_Ref_Type(type) type * + #define Ppmd_GetRef(p, ptr) (ptr) + #define Ppmd_GetPtr(p, ptr) (ptr) + #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr) + +#else + + #define Ppmd_Ref_Type(type) UInt32 + #define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) + #define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs)) + +#endif // PPMD_32BIT + + +typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref; +typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref; +typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref; + + +/* +#ifdef MY_CPU_LE_UNALIGN +// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache. +#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0) +#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v) + +#else +*/ + +/* + We can write 16-bit halves to 32-bit (Successor) field in any selected order. + But the native order is more consistent way. + So we use the native order, if LE/BE order can be detected here at compile time. +*/ + +#ifdef MY_CPU_BE + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); } + +#else + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); } + +#endif + +// #endif -typedef - #ifdef PPMD_32BIT - Byte * - #else - UInt32 - #endif - CPpmd_Byte_Ref; #define PPMD_SetAllBitsIn256Bytes(p) \ { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ diff --git a/libraries/lzma/C/Ppmd7.c b/libraries/lzma/C/Ppmd7.c index 470aadccf..cf401cb37 100644 --- a/libraries/lzma/C/Ppmd7.c +++ b/libraries/lzma/C/Ppmd7.c @@ -1,5 +1,5 @@ /* Ppmd7.c -- PPMdH codec -2018-07-04 : Igor Pavlov : Public domain +2021-04-13 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Precomp.h" @@ -8,7 +8,12 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #include "Ppmd7.h" -const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +/* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */ +// #define PPMD7_ORDER_0_SUPPPORT + +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}; #define MAX_FREQ 124 @@ -16,13 +21,10 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) -#define I2U(indx) (p->Indx2Units[indx]) +#define I2U(indx) ((unsigned)p->Indx2Units[indx]) +#define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx]) -#ifdef PPMD_32BIT - #define REF(ptr) (ptr) -#else - #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) -#endif +#define REF(ptr) Ppmd_GetRef(p, ptr) #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) @@ -35,13 +37,7 @@ typedef CPpmd7_Context * CTX_PTR; struct CPpmd7_Node_; -typedef - #ifdef PPMD_32BIT - struct CPpmd7_Node_ * - #else - UInt32 - #endif - CPpmd7_Node_Ref; +typedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref; typedef struct CPpmd7_Node_ { @@ -51,17 +47,13 @@ typedef struct CPpmd7_Node_ CPpmd7_Node_Ref Prev; } CPpmd7_Node; -#ifdef PPMD_32BIT - #define NODE(ptr) (ptr) -#else - #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) -#endif +#define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd7_Node) void Ppmd7_Construct(CPpmd7 *p) { unsigned i, k, m; - p->Base = 0; + p->Base = NULL; for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) { @@ -77,6 +69,7 @@ void Ppmd7_Construct(CPpmd7 *p) for (i = 0; i < 3; i++) p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 256; i++) { p->NS2Indx[i] = (Byte)m; @@ -84,54 +77,63 @@ void Ppmd7_Construct(CPpmd7 *p) k = (++m) - 2; } - memset(p->HB2Flag, 0, 0x40); - memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); + memcpy(p->ExpEscape, PPMD7_kExpEscape, 16); } + void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Base); p->Size = 0; - p->Base = 0; + p->Base = NULL; } + BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) { if (!p->Base || p->Size != size) { - size_t size2; Ppmd7_Free(p, alloc); - size2 = 0 - #ifndef PPMD_32BIT - + UNIT_SIZE - #endif - ; - p->AlignOffset = - #ifdef PPMD_32BIT - (4 - size) & 3; - #else - 4 - (size & 3); - #endif - if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0) + p->AlignOffset = (4 - size) & 3; + if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL) return False; p->Size = size; } return True; } + + +// ---------- 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() +*/ + +#define EMPTY_NODE 0 + + static void InsertNode(CPpmd7 *p, void *node, unsigned indx) { *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx]; + p->FreeList[indx] = REF(node); + } + static void *RemoveNode(CPpmd7 *p, unsigned indx) { CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); p->FreeList[indx] = *node; + // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]); + // p->FreeList[indx] = node->Next; return node; } + static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) { unsigned i, nu = I2U(oldIndx) - I2U(newIndx); @@ -144,123 +146,167 @@ static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) InsertNode(p, ptr, i); } + +/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ + +typedef union _CPpmd7_Node_Union +{ + CPpmd7_Node Node; + CPpmd7_Node_Ref NextRef; +} CPpmd7_Node_Union; + +/* Original PPmdH (Ppmd7) code uses doubly linked list in GlueFreeBlocks() + we use single linked list similar to Ppmd8 code */ + + static void GlueFreeBlocks(CPpmd7 *p) { - #ifdef PPMD_32BIT - CPpmd7_Node headItem; - CPpmd7_Node_Ref head = &headItem; - #else - CPpmd7_Node_Ref head = p->AlignOffset + p->Size; - #endif - - CPpmd7_Node_Ref n = head; - unsigned i; - + /* + we use first UInt16 field of 12-bytes UNITs as record type stamp + CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0 + CPpmd7_Context { UInt16 NumStats; : NumStats != 0 + CPpmd7_Node { UInt16 Stamp : Stamp == 0 for free record + : Stamp == 1 for head record and guard + Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record. + */ + CPpmd7_Node_Ref head, n = 0; + p->GlueCount = 255; - /* create doubly-linked list of free blocks */ - for (i = 0; i < PPMD_NUM_INDEXES; i++) - { - UInt16 nu = I2U(i); - CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; - p->FreeList[i] = 0; - while (next != 0) - { - CPpmd7_Node *node = NODE(next); - node->Next = n; - n = NODE(n)->Prev = next; - next = *(const CPpmd7_Node_Ref *)node; - node->Stamp = 0; - node->NU = (UInt16)nu; - } - } - NODE(head)->Stamp = 1; - NODE(head)->Next = n; - NODE(n)->Prev = head; + + /* we set guard NODE at LoUnit */ if (p->LoUnit != p->HiUnit) - ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; - - /* Glue free blocks */ - while (n != head) + ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1; + { - CPpmd7_Node *node = NODE(n); - UInt32 nu = (UInt32)node->NU; - for (;;) + /* Create list of free blocks. + We still need one additional list walk pass before Glue. */ + unsigned i; + for (i = 0; i < PPMD_NUM_INDEXES; i++) { - CPpmd7_Node *node2 = NODE(n) + nu; - nu += node2->NU; - if (node2->Stamp != 0 || nu >= 0x10000) - break; - NODE(node2->Prev)->Next = node2->Next; - NODE(node2->Next)->Prev = node2->Prev; - node->NU = (UInt16)nu; + const UInt16 nu = I2U_UInt16(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + /* Don't change the order of the following commands: */ + CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next); + const CPpmd7_Node_Ref tmp = next; + next = un->NextRef; + un->Node.Stamp = EMPTY_NODE; + un->Node.NU = nu; + un->Node.Next = n; + n = tmp; + } } - n = node->Next; } - + + head = n; + /* Glue and Fill must walk the list in same direction */ + { + /* Glue free blocks */ + CPpmd7_Node_Ref *prev = &head; + while (n) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = node->NU; + n = node->Next; + if (nu == 0) + { + *prev = n; + continue; + } + prev = &node->Next; + for (;;) + { + CPpmd7_Node *node2 = node + nu; + nu += node2->NU; + if (node2->Stamp != EMPTY_NODE || nu >= 0x10000) + break; + node->NU = (UInt16)nu; + node2->NU = 0; + } + } + } + /* Fill lists of free blocks */ - for (n = NODE(head)->Next; n != head;) + for (n = head; n != 0;) { CPpmd7_Node *node = NODE(n); - unsigned nu; - CPpmd7_Node_Ref next = node->Next; - for (nu = node->NU; nu > 128; nu -= 128, node += 128) + UInt32 nu = node->NU; + unsigned i; + n = node->Next; + if (nu == 0) + continue; + for (; nu > 128; nu -= 128, node += 128) InsertNode(p, node, PPMD_NUM_INDEXES - 1); if (I2U(i = U2I(nu)) != nu) { unsigned k = I2U(--i); - InsertNode(p, node + k, nu - k - 1); + InsertNode(p, node + k, (unsigned)nu - k - 1); } InsertNode(p, node, i); - n = next; } } + +MY_NO_INLINE static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) { unsigned i; - void *retVal; + if (p->GlueCount == 0) { GlueFreeBlocks(p); if (p->FreeList[indx] != 0) return RemoveNode(p, indx); } + i = indx; + do { if (++i == PPMD_NUM_INDEXES) { UInt32 numBytes = U2B(I2U(indx)); + Byte *us = p->UnitsStart; p->GlueCount--; - return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL; } } while (p->FreeList[i] == 0); - retVal = RemoveNode(p, i); - SplitBlock(p, retVal, i, indx); - return retVal; + + { + void *block = RemoveNode(p, i); + SplitBlock(p, block, i, indx); + return block; + } } + static void *AllocUnits(CPpmd7 *p, unsigned indx) { - UInt32 numBytes; if (p->FreeList[indx] != 0) return RemoveNode(p, indx); - numBytes = U2B(I2U(indx)); - if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) { - void *retVal = p->LoUnit; - p->LoUnit += numBytes; - return retVal; + UInt32 numBytes = U2B(I2U(indx)); + Byte *lo = p->LoUnit; + if ((UInt32)(p->HiUnit - lo) >= numBytes) + { + p->LoUnit = lo + numBytes; + return lo; + } } return AllocUnitsRare(p, indx); } -#define MyMem12Cpy(dest, src, num) \ - { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ - do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); } +#define MyMem12Cpy(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); } + + +/* static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) { unsigned i0 = U2I(oldNU); @@ -277,20 +323,25 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU SplitBlock(p, oldPtr, i0, i1); return oldPtr; } +*/ -#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) { - (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); - (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); + Ppmd_SET_SUCCESSOR(p, v); } -static void RestartModel(CPpmd7 *p) + + +MY_NO_INLINE +static +void RestartModel(CPpmd7 *p) { - unsigned i, k, m; + unsigned i, k; memset(p->FreeList, 0, sizeof(p->FreeList)); + p->Text = p->Base + p->AlignOffset; p->HiUnit = p->Text + p->Size; p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; @@ -300,57 +351,110 @@ static void RestartModel(CPpmd7 *p) p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; p->PrevSuccess = 0; - p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ - p->MinContext->Suffix = 0; - p->MinContext->NumStats = 256; - p->MinContext->SummFreq = 256 + 1; - p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ - p->LoUnit += U2B(256 / 2); - p->MinContext->Stats = REF(p->FoundState); - for (i = 0; i < 256; i++) { - CPpmd_State *s = &p->FoundState[i]; - s->Symbol = (Byte)i; - s->Freq = 1; - SetSuccessor(s, 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); */ + + p->LoUnit += U2B(256 / 2); + p->MaxContext = p->MinContext = mc; + p->FoundState = s; + + mc->NumStats = 256; + mc->Union2.SummFreq = 256 + 1; + mc->Union4.Stats = REF(s); + mc->Suffix = 0; + + for (i = 0; i < 256; i++, s++) + { + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + #ifdef PPMD7_ORDER_0_SUPPPORT + if (p->MaxOrder == 0) + { + CPpmd_Void_Ref r = REF(mc); + s = p->FoundState; + for (i = 0; i < 256; i++, s++) + SetSuccessor(s, r); + return; + } + #endif } for (i = 0; i < 128; i++) + + + for (k = 0; k < 8; k++) { + unsigned m; UInt16 *dest = p->BinSumm[i] + k; UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); for (m = 0; m < 64; m += 8) dest[m] = val; } - + + for (i = 0; i < 25; i++) - for (k = 0; k < 16; k++) + { + + CPpmd_See *s = p->See[i]; + + + + unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4)); + for (k = 0; k < 16; k++, s++) { - CPpmd_See *s = &p->See[i][k]; - s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Summ = (UInt16)summ; + s->Shift = (PPMD_PERIOD_BITS - 4); s->Count = 4; } + } + + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Count = 64; /* unused */ } + void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) { p->MaxOrder = maxOrder; + RestartModel(p); - p->DummySee.Shift = PPMD_PERIOD_BITS; - p->DummySee.Summ = 0; /* unused */ - p->DummySee.Count = 64; /* unused */ } -static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) + + +/* + 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 + FoundState->Successor and to identical RAW-Successors in suffix + contexts of MinContex. + + The function returns: + if (OrderFall == 0) then MinContext is already at MAX order, + { return pointer to new or existing context of same MAX order } + else + { return pointer to new real context that will be (Order+1) in comparison with MinContext + + also it can return pointer to real context of same order, +*/ + +MY_NO_INLINE +static CTX_PTR CreateSuccessors(CPpmd7 *p) { - CPpmd_State upState; CTX_PTR c = p->MinContext; CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); - CPpmd_State *ps[PPMD7_MAX_ORDER]; + Byte newSym, newFreq; unsigned numPs = 0; - - if (!skip) + CPpmd_State *ps[PPMD7_MAX_ORDER]; + + if (p->OrderFall != 0) ps[numPs++] = p->FoundState; while (c->Suffix) @@ -358,44 +462,70 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) CPpmd_Void_Ref successor; CPpmd_State *s; c = SUFFIX(c); + + if (c->NumStats != 1) { - for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + Byte sym = p->FoundState->Symbol; + for (s = STATS(c); s->Symbol != sym; s++); + } else + { s = ONE_STATE(c); + + } successor = SUCCESSOR(s); if (successor != upBranch) { + // (c) is real record Context here, c = CTX(successor); if (numPs == 0) + { + // (c) is real record MAX Order Context here, + // So we don't need to create any new contexts. return c; + } break; } ps[numPs++] = s; } - upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); - SetSuccessor(&upState, upBranch + 1); + // All created contexts will have single-symbol with new RAW-Successor + // All new RAW-Successors will point to next position in RAW text + // after FoundState->Successor + + newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + upBranch++; + if (c->NumStats == 1) - upState.Freq = ONE_STATE(c)->Freq; + newFreq = ONE_STATE(c)->Freq; else { UInt32 cf, s0; CPpmd_State *s; - for (s = STATS(c); s->Symbol != upState.Symbol; s++); - cf = s->Freq - 1; - s0 = c->SummFreq - c->NumStats - cf; - upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + for (s = STATS(c); s->Symbol != newSym; s++); + cf = (UInt32)s->Freq - 1; + s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf; + /* + cf - is frequency of symbol that will be Successor in new context records. + s0 - is commulative frequency sum of another symbols from parent context. + max(newFreq)= (s->Freq + 1), when (s0 == 1) + we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[] + so (s->Freq < 128) - is requirement for multi-symbol contexts + */ + newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1)); } + // Create new single-symbol contexts from low order to high order in loop + do { - /* Create Child */ - CTX_PTR c1; /* = AllocContext(p); */ + CTX_PTR c1; + /* = AllocContext(p); */ if (p->HiUnit != p->LoUnit) - c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); else if (p->FreeList[0] != 0) c1 = (CTX_PTR)RemoveNode(p, 0); else @@ -404,8 +534,11 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) if (!c1) return NULL; } + c1->NumStats = 1; - *ONE_STATE(c1) = upState; + ONE_STATE(c1)->Symbol = newSym; + ONE_STATE(c1)->Freq = newFreq; + SetSuccessor(ONE_STATE(c1), upBranch); c1->Suffix = REF(c); SetSuccessor(ps[--numPs], REF(c1)); c = c1; @@ -415,21 +548,26 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) return c; } -static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) -{ - CPpmd_State tmp = *t1; - *t1 = *t2; - *t2 = tmp; -} -static void UpdateModel(CPpmd7 *p) + +#define SwapStates(s) \ + { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } + + +void Ppmd7_UpdateModel(CPpmd7 *p); +MY_NO_INLINE +void Ppmd7_UpdateModel(CPpmd7 *p) { - CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); - CTX_PTR c; + CPpmd_Void_Ref maxSuccessor, minSuccessor; + CTX_PTR c, mc; unsigned s0, ns; - + + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) { + /* Update Freqs in Suffix Context */ + c = SUFFIX(p->MinContext); if (c->NumStats == 1) @@ -441,27 +579,39 @@ static void UpdateModel(CPpmd7 *p) else { CPpmd_State *s = STATS(c); - if (s->Symbol != p->FoundState->Symbol) + Byte sym = p->FoundState->Symbol; + + if (s->Symbol != sym) { - do { s++; } while (s->Symbol != p->FoundState->Symbol); + do + { + // s++; if (s->Symbol == sym) break; + s++; + } + while (s->Symbol != sym); + if (s[0].Freq >= s[-1].Freq) { - SwapStates(&s[0], &s[-1]); + SwapStates(s); s--; } } + if (s->Freq < MAX_FREQ - 9) { - s->Freq += 2; - c->SummFreq += 2; + s->Freq = (Byte)(s->Freq + 2); + c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); } } } + if (p->OrderFall == 0) { - p->MinContext = p->MaxContext = CreateSuccessors(p, True); - if (p->MinContext == 0) + /* MAX ORDER context */ + /* (FoundState->Successor) is RAW-Successor. */ + p->MaxContext = p->MinContext = CreateSuccessors(p); + if (!p->MinContext) { RestartModel(p); return; @@ -469,45 +619,93 @@ static void UpdateModel(CPpmd7 *p) SetSuccessor(p->FoundState, REF(p->MinContext)); return; } + + + /* NON-MAX ORDER context */ - *p->Text++ = p->FoundState->Symbol; - successor = REF(p->Text); - if (p->Text >= p->UnitsStart) { - RestartModel(p); - return; + Byte *text = p->Text; + *text++ = p->FoundState->Symbol; + p->Text = text; + if (text >= p->UnitsStart) + { + RestartModel(p); + return; + } + maxSuccessor = REF(text); } - if (fSuccessor) + minSuccessor = SUCCESSOR(p->FoundState); + + if (minSuccessor) { - if (fSuccessor <= successor) + // there is Successor for FoundState in MinContext. + // So the next context will be one order higher than MinContext. + + if (minSuccessor <= maxSuccessor) { - CTX_PTR cs = CreateSuccessors(p, False); - if (cs == NULL) + // minSuccessor is RAW-Successor. So we will create real contexts records: + CTX_PTR cs = CreateSuccessors(p); + if (!cs) { RestartModel(p); return; } - fSuccessor = REF(cs); + minSuccessor = REF(cs); } + + // minSuccessor now is real Context pointer that points to existing (Order+1) context + if (--p->OrderFall == 0) { - successor = fSuccessor; + /* + if we move to MaxOrder context, then minSuccessor will be common Succesor for both: + MinContext that is (MaxOrder - 1) + MaxContext that is (MaxOrder) + so we don't need new RAW-Successor, and we can use real minSuccessor + as succssors for both MinContext and MaxContext. + */ + maxSuccessor = minSuccessor; + + /* + if (MaxContext != MinContext) + { + there was order fall from MaxOrder and we don't need current symbol + to transfer some RAW-Succesors to real contexts. + So we roll back pointer in raw data for one position. + } + */ p->Text -= (p->MaxContext != p->MinContext); } } else { - SetSuccessor(p->FoundState, successor); - fSuccessor = REF(p->MinContext); + /* + FoundState has NULL-Successor here. + And only root 0-order context can contain NULL-Successors. + We change Successor in FoundState to RAW-Successor, + And next context will be same 0-order root Context. + */ + SetSuccessor(p->FoundState, maxSuccessor); + minSuccessor = REF(p->MinContext); } - - s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); - - for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) + + mc = p->MinContext; + c = p->MaxContext; + + p->MaxContext = p->MinContext = CTX(minSuccessor); + + if (c == mc) + return; + + // s0 : is pure Escape Freq + s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1); + + do { unsigned ns1; - UInt32 cf, sf; + UInt32 sum; + if ((ns1 = c->NumStats) != 1) { if ((ns1 & 1) == 0) @@ -527,80 +725,127 @@ static void UpdateModel(CPpmd7 *p) oldPtr = STATS(c); MyMem12Cpy(ptr, oldPtr, oldNU); InsertNode(p, oldPtr, i); - c->Stats = STATS_REF(ptr); + c->Union4.Stats = STATS_REF(ptr); } } - c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); + sum = c->Union2.SummFreq; + /* max increase of Escape_Freq is 3 here. + total increase of Union2.SummFreq for all symbols is less than 256 here */ + sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)); + /* original PPMdH uses 16-bit variable for (sum) here. + But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ + // sum = (UInt16)sum; } else { + // instead of One-symbol context we create 2-symbol context CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); if (!s) { RestartModel(p); return; } - *s = *ONE_STATE(c); - c->Stats = REF(s); - if (s->Freq < MAX_FREQ / 4 - 1) - s->Freq <<= 1; - else - s->Freq = MAX_FREQ - 4; - c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); - } - cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); - sf = (UInt32)s0 + c->SummFreq; - if (cf < 6 * sf) - { - cf = 1 + (cf > sf) + (cf >= 4 * sf); - c->SummFreq += 3; - } - else - { - cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); - c->SummFreq = (UInt16)(c->SummFreq + cf); + { + unsigned freq = c->Union2.State2.Freq; + // s = *ONE_STATE(c); + s->Symbol = c->Union2.State2.Symbol; + s->Successor_0 = c->Union4.State4.Successor_0; + s->Successor_1 = c->Union4.State4.Successor_1; + // SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of + // (Successor_0 and Successor_1) in LE/BE. + c->Union4.Stats = REF(s); + if (freq < MAX_FREQ / 4 - 1) + freq <<= 1; + else + freq = MAX_FREQ - 4; + // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context + s->Freq = (Byte)freq; + // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here + sum = freq + p->InitEsc + (ns > 3); + } } + { CPpmd_State *s = STATS(c) + ns1; - SetSuccessor(s, successor); + UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq; + UInt32 sf = (UInt32)s0 + sum; s->Symbol = p->FoundState->Symbol; - s->Freq = (Byte)cf; c->NumStats = (UInt16)(ns1 + 1); + SetSuccessor(s, maxSuccessor); + + if (cf < 6 * sf) + { + cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf); + sum += 3; + /* It can add (0, 1, 2) to Escape_Freq */ + } + else + { + cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + sum += cf; + } + + c->Union2.SummFreq = (UInt16)sum; + s->Freq = (Byte)cf; } + c = SUFFIX(c); } - p->MaxContext = p->MinContext = CTX(fSuccessor); + while (c != mc); } + + +MY_NO_INLINE static void Rescale(CPpmd7 *p) { unsigned i, adder, sumFreq, escFreq; CPpmd_State *stats = STATS(p->MinContext); CPpmd_State *s = p->FoundState; + + /* Sort the list by Freq */ + if (s != stats) { CPpmd_State tmp = *s; - for (; s != stats; s--) + do s[0] = s[-1]; + while (--s != stats); *s = tmp; } - escFreq = p->MinContext->SummFreq - s->Freq; - s->Freq += 4; - adder = (p->OrderFall != 0); - s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + escFreq = p->MinContext->Union2.SummFreq - sumFreq; + + /* + if (p->OrderFall == 0), adder = 0 : it's allowed to remove symbol from MAX Order context + if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context + */ + + adder = (p->OrderFall != 0); + + #ifdef PPMD7_ORDER_0_SUPPPORT + adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context + #endif + + sumFreq = (sumFreq + 4 + adder) >> 1; + i = (unsigned)p->MinContext->NumStats - 1; + s->Freq = (Byte)sumFreq; - i = p->MinContext->NumStats - 1; do { - escFreq -= (++s)->Freq; - s->Freq = (Byte)((s->Freq + adder) >> 1); - sumFreq += s->Freq; - if (s[0].Freq > s[-1].Freq) + unsigned freq = (++s)->Freq; + escFreq -= freq; + freq = (freq + adder) >> 1; + sumFreq += freq; + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) { + CPpmd_State tmp = *s; CPpmd_State *s1 = s; - CPpmd_State tmp = *s1; do + { s1[0] = s1[-1]; - while (--s1 != stats && tmp.Freq > s1[-1].Freq); + } + while (--s1 != stats && freq > s1[-1].Freq); *s1 = tmp; } } @@ -608,47 +853,89 @@ static void Rescale(CPpmd7 *p) if (s->Freq == 0) { - unsigned numStats = p->MinContext->NumStats; - unsigned n0, n1; - do { i++; } while ((--s)->Freq == 0); + /* Remove all items with Freq == 0 */ + CPpmd7_Context *mc; + unsigned numStats, numStatsNew, n0, n1; + + i = 0; do { i++; } while ((--s)->Freq == 0); + + /* We increase (escFreq) for the number of removed symbols. + So we will have (0.5) increase for Escape_Freq in avarage per + removed symbol after Escape_Freq halving */ escFreq += i; - p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); - if (p->MinContext->NumStats == 1) + mc = p->MinContext; + numStats = mc->NumStats; + numStatsNew = numStats - i; + mc->NumStats = (UInt16)(numStatsNew); + n0 = (numStats + 1) >> 1; + + if (numStatsNew == 1) { - CPpmd_State tmp = *stats; + /* Create Single-Symbol context */ + unsigned freq = stats->Freq; + do { - tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); escFreq >>= 1; + freq = (freq + 1) >> 1; } while (escFreq > 1); - InsertNode(p, stats, U2I(((numStats + 1) >> 1))); - *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + + s = ONE_STATE(mc); + *s = *stats; + s->Freq = (Byte)freq; // (freq <= 260 / 4) + p->FoundState = s; + InsertNode(p, stats, U2I(n0)); return; } - n0 = (numStats + 1) >> 1; - n1 = (p->MinContext->NumStats + 1) >> 1; + + n1 = (numStatsNew + 1) >> 1; if (n0 != n1) - p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + { + // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + unsigned i0 = U2I(n0); + unsigned i1 = U2I(n1); + if (i0 != i1) + { + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + p->MinContext->Union4.Stats = STATS_REF(ptr); + MyMem12Cpy(ptr, (const void *)stats, n1); + InsertNode(p, stats, i0); + } + else + SplitBlock(p, stats, i0, i1); + } + } + } + { + CPpmd7_Context *mc = p->MinContext; + mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + // Escape_Freq halving here + p->FoundState = STATS(mc); } - p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); - p->FoundState = STATS(p->MinContext); } + CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) { CPpmd_See *see; - unsigned nonMasked = p->MinContext->NumStats - numMasked; - if (p->MinContext->NumStats != 256) + const CPpmd7_Context *mc = p->MinContext; + unsigned numStats = mc->NumStats; + if (numStats != 256) { - see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + - (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + - 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + - 4 * (unsigned)(numMasked > nonMasked) + + unsigned nonMasked = numStats - numMasked; + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats) + + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats) + + 4 * (unsigned)(numMasked > nonMasked) + p->HiBitsFlag; { - unsigned r = (see->Summ >> see->Shift); - see->Summ = (UInt16)(see->Summ - r); + // 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); } } @@ -660,53 +947,158 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) return see; } + static void NextContext(CPpmd7 *p) { CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); - if (p->OrderFall == 0 && (Byte *)c > p->Text) - p->MinContext = p->MaxContext = c; + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; else - UpdateModel(p); + Ppmd7_UpdateModel(p); } + void Ppmd7_Update1(CPpmd7 *p) { CPpmd_State *s = p->FoundState; - s->Freq += 4; - p->MinContext->SummFreq += 4; - if (s[0].Freq > s[-1].Freq) + unsigned freq = s->Freq; + freq += 4; + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) { - SwapStates(&s[0], &s[-1]); + SwapStates(s); p->FoundState = --s; - if (s->Freq > MAX_FREQ) + if (freq > MAX_FREQ) Rescale(p); } NextContext(p); } + void Ppmd7_Update1_0(CPpmd7 *p) { - p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); - p->RunLength += p->PrevSuccess; - p->MinContext->SummFreq += 4; - if ((p->FoundState->Freq += 4) > MAX_FREQ) + CPpmd_State *s = p->FoundState; + CPpmd7_Context *mc = p->MinContext; + unsigned freq = s->Freq; + unsigned summFreq = mc->Union2.SummFreq; + p->PrevSuccess = (2 * freq > summFreq); + p->RunLength += (int)p->PrevSuccess; + mc->Union2.SummFreq = (UInt16)(summFreq + 4); + freq += 4; + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) Rescale(p); NextContext(p); } + +/* void Ppmd7_UpdateBin(CPpmd7 *p) { - p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); + unsigned freq = p->FoundState->Freq; + p->FoundState->Freq = (Byte)(freq + (freq < 128)); p->PrevSuccess = 1; p->RunLength++; NextContext(p); } +*/ void Ppmd7_Update2(CPpmd7 *p) { - p->MinContext->SummFreq += 4; - if ((p->FoundState->Freq += 4) > MAX_FREQ) - Rescale(p); + CPpmd_State *s = p->FoundState; + unsigned freq = s->Freq; + freq += 4; p->RunLength = p->InitRL; - UpdateModel(p); + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) + Rescale(p); + Ppmd7_UpdateModel(p); } + + + +/* +PPMd Memory Map: +{ + [ 0 ] contains subset of original raw text, that is required to create context + records, Some symbols are not written, when max order context was reached + [ Text ] free area + [ UnitsStart ] CPpmd_State vectors and CPpmd7_Context records + [ LoUnit ] free area for CPpmd_State and CPpmd7_Context items +[ HiUnit ] CPpmd7_Context records + [ Size ] end of array +} + +These addresses don't cross at any time. +And the following condtions is true for addresses: + (0 <= Text < UnitsStart <= LoUnit <= HiUnit <= Size) + +Raw text is BYTE--aligned. +the data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs. + +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 allocates UNITs with the following order: + +Allocation of 1 UNIT for Context record + - from free space (HiUnit) down to (LoUnit) + - from FreeList[0] + - AllocUnitsRare() + +AllocUnits() for CPpmd_State vectors: + - from FreeList[i] + - from free space (LoUnit) up to (HiUnit) + - AllocUnitsRare() + +AllocUnitsRare() + - if (GlueCount == 0) + { Glue lists, GlueCount = 255, allocate from FreeList[i]] } + - loop for all higher sized FreeList[...] lists + - from (UnitsStart - Text), GlueCount-- + - ERROR + + +Each Record with Context contains the CPpmd_State vector, where each +CPpmd_State contains the link to Successor. +There are 3 types of Successor: + 1) NULL-Successor - NULL pointer. NULL-Successor links can be stored + only in 0-order Root Context Record. + We use 0 value as NULL-Successor + 2) RAW-Successor - the link to position in raw text, + that "RAW-Successor" is being created after first + occurrence of new symbol for some existing context record. + (RAW-Successor > 0). + 3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1), + that record is being created when we go via RAW-Successor again. + +For any successors at any time: the following condtions are true for Successor links: +(NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor) + + +---------- Symbol Frequency, SummFreq and Range in Range_Coder ---------- + +CPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq + +The PPMd code tries to fulfill the condition: + (SummFreq <= (256 * 128 = RC::kBot)) + +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 +max-order context. + +When the PPMd code still break (Total <= RC::Range) condition in range coder, +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. +*/ diff --git a/libraries/lzma/C/Ppmd7.h b/libraries/lzma/C/Ppmd7.h index 610539a04..d31809aeb 100644 --- a/libraries/lzma/C/Ppmd7.h +++ b/libraries/lzma/C/Ppmd7.h @@ -1,10 +1,8 @@ -/* Ppmd7.h -- PPMdH compression codec -2018-07-04 : Igor Pavlov : Public domain -This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ - -/* This code supports virtual RangeDecoder and includes the implementation -of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H. -If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */ +/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + #ifndef __PPMD7_H #define __PPMD7_H @@ -21,23 +19,56 @@ EXTERN_C_BEGIN struct CPpmd7_Context_; -typedef - #ifdef PPMD_32BIT - struct CPpmd7_Context_ * - #else - UInt32 - #endif - CPpmd7_Context_Ref; +typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref; + +// MY_CPU_pragma_pack_push_1 typedef struct CPpmd7_Context_ { UInt16 NumStats; - UInt16 SummFreq; - CPpmd_State_Ref Stats; + + + union + { + UInt16 SummFreq; + CPpmd_State2 State2; + } Union2; + + union + { + CPpmd_State_Ref Stats; + CPpmd_State4 State4; + } Union4; + CPpmd7_Context_Ref Suffix; } CPpmd7_Context; -#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) +// MY_CPU_pragma_pop + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2) + + + + +typedef struct +{ + UInt32 Range; + UInt32 Code; + UInt32 Low; + IByteIn *Stream; +} CPpmd7_RangeDec; + + +typedef struct +{ + UInt32 Range; + Byte Cache; + // Byte _dummy_[3]; + UInt64 Low; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + typedef struct { @@ -48,17 +79,30 @@ typedef struct UInt32 Size; UInt32 GlueCount; - Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; UInt32 AlignOffset; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; - Byte Indx2Units[PPMD_NUM_INDEXES]; + + + + union + { + CPpmd7_RangeDec dec; + CPpmd7z_RangeEnc enc; + } rc; + + Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment Byte Units2Indx[128]; CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; - Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + + Byte NS2BSIndx[256], NS2Indx[256]; + Byte ExpEscape[16]; CPpmd_See DummySee, See[25][16]; UInt16 BinSumm[128][64]; + // int LastSymbol; } CPpmd7; + void Ppmd7_Construct(CPpmd7 *p); BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); @@ -68,74 +112,69 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); /* ---------- Internal Functions ---------- */ -extern const Byte PPMD7_kExpEscape[16]; - -#ifdef PPMD_32BIT - #define Ppmd7_GetPtr(p, ptr) (ptr) - #define Ppmd7_GetContext(p, ptr) (ptr) - #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) -#else - #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) - #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) - #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) -#endif +#define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr) +#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context) +#define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State) void Ppmd7_Update1(CPpmd7 *p); void Ppmd7_Update1_0(CPpmd7 *p); void Ppmd7_Update2(CPpmd7 *p); -void Ppmd7_UpdateBin(CPpmd7 *p); + +#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3)) +#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4)) +// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3)) +// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4)) #define Ppmd7_GetBinSumm(p) \ - &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ - p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ - (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ - 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \ - ((p->RunLength >> 26) & 0x20)] + &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \ + [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \ + + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \ + + PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \ + + (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ] CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); +/* +We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure: + 1) Ppmd7a_*: original PPMdH + 2) Ppmd7z_*: modified PPMdH with 7z Range Coder +Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH) +*/ + /* ---------- Decode ---------- */ -typedef struct IPpmd7_RangeDec IPpmd7_RangeDec; +#define PPMD7_SYM_END (-1) +#define PPMD7_SYM_ERROR (-2) -struct IPpmd7_RangeDec -{ - UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total); - void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size); - UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0); -}; +/* +You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init() -typedef struct -{ - IPpmd7_RangeDec vt; - UInt32 Range; - UInt32 Code; - IByteIn *Stream; -} CPpmd7z_RangeDec; +Ppmd7*_DecodeSymbol() +out: + >= 0 : decoded byte + -1 : PPMD7_SYM_END : End of payload marker + -2 : PPMD7_SYM_ERROR : Data error +*/ -void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); -BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); +/* Ppmd7a_* : original PPMdH */ +BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p); +#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd7a_DecodeSymbol(CPpmd7 *p); + +/* Ppmd7z_* : modified PPMdH with 7z Range Coder */ +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p); #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) - -int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc); +int Ppmd7z_DecodeSymbol(CPpmd7 *p); +// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim); /* ---------- Encode ---------- */ -typedef struct -{ - UInt64 Low; - UInt32 Range; - Byte Cache; - UInt64 CacheSize; - IByteOut *Stream; -} CPpmd7z_RangeEnc; - -void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p); -void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p); - -void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol); +void Ppmd7z_Init_RangeEnc(CPpmd7 *p); +void Ppmd7z_Flush_RangeEnc(CPpmd7 *p); +// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol); +void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim); EXTERN_C_END diff --git a/libraries/lzma/C/Ppmd7Dec.c b/libraries/lzma/C/Ppmd7Dec.c index 311e9f9dd..55d74ff9d 100644 --- a/libraries/lzma/C/Ppmd7Dec.c +++ b/libraries/lzma/C/Ppmd7Dec.c @@ -1,6 +1,8 @@ -/* Ppmd7Dec.c -- PPMdH Decoder -2018-07-04 : Igor Pavlov : Public domain -This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ +/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + #include "Precomp.h" @@ -8,184 +10,288 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ #define kTopValue (1 << 24) -BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) + +#define READ_BYTE(p) IByteIn_Read((p)->Stream) + +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p) { unsigned i; p->Code = 0; p->Range = 0xFFFFFFFF; - if (IByteIn_Read(p->Stream) != 0) + if (READ_BYTE(p) != 0) return False; for (i = 0; i < 4; i++) - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); + p->Code = (p->Code << 8) | READ_BYTE(p); return (p->Code < 0xFFFFFFFF); } -#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt); - -static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) +#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \ + { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8; + +#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 R (&p->rc.dec) + +MY_FORCE_INLINE +// MY_NO_INLINE +static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size) { - GET_Ppmd7z_RangeDec - return p->Code / (p->Range /= total); + + + R->Code -= start * R->Range; + R->Range *= size; + RC_NORM_LOCAL(R) } -static void Range_Normalize(CPpmd7z_RangeDec *p) -{ - if (p->Range < kTopValue) - { - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); - p->Range <<= 8; - if (p->Range < kTopValue) - { - p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); - p->Range <<= 8; - } - } -} - -static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) -{ - GET_Ppmd7z_RangeDec - p->Code -= start * p->Range; - p->Range *= size; - Range_Normalize(p); -} - -static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) -{ - GET_Ppmd7z_RangeDec - UInt32 newBound = (p->Range >> 14) * size0; - UInt32 symbol; - if (p->Code < newBound) - { - symbol = 0; - p->Range = newBound; - } - else - { - symbol = 1; - p->Code -= newBound; - p->Range -= newBound; - } - Range_Normalize(p); - return symbol; -} - -void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) -{ - p->vt.GetThreshold = Range_GetThreshold; - p->vt.Decode = Range_Decode; - p->vt.DecodeBit = Range_DecodeBit; -} +#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 MASK(sym) ((signed char *)charMask)[sym] +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +typedef CPpmd7_Context * CTX_PTR; +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) +void Ppmd7_UpdateModel(CPpmd7 *p); -int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc) +#define MASK(sym) ((unsigned char *)charMask)[sym] +// MY_FORCE_INLINE +// static +int Ppmd7z_DecodeSymbol(CPpmd7 *p) { size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) { CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); unsigned i; UInt32 count, hiCnt; - if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + UInt32 summFreq = p->MinContext->Union2.SummFreq; + + + + + count = RC_GetThreshold(summFreq); + hiCnt = count; + + if ((Int32)(count -= s->Freq) < 0) { - Byte symbol; - rc->Decode(rc, 0, s->Freq); + Byte sym; + RC_DecodeFinal(0, s->Freq); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update1_0(p); - return symbol; + return sym; } + p->PrevSuccess = 0; - i = p->MinContext->NumStats - 1; + i = (unsigned)p->MinContext->NumStats - 1; + do { - if ((hiCnt += (++s)->Freq) > count) + if ((Int32)(count -= (++s)->Freq) < 0) { - Byte symbol; - rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Byte sym; + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update1(p); - return symbol; + return sym; } } while (--i); - if (count >= p->MinContext->SummFreq) - return -2; - p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; - rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); + + if (hiCnt >= summFreq) + return PPMD7_SYM_ERROR; + + hiCnt -= count; + RC_Decode(hiCnt, summFreq - hiCnt); + + 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); + // 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 { + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); UInt16 *prob = Ppmd7_GetBinSumm(p); - if (rc->DecodeBit(rc, *prob) == 0) + UInt32 pr = *prob; + UInt32 size0 = (R->Range >> 14) * pr; + pr = PPMD_UPDATE_PROB_1(pr); + + if (R->Code < size0) { - Byte symbol; - *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); - symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; - Ppmd7_UpdateBin(p); - return symbol; + Byte sym; + *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); + + // RangeDec_DecodeBit0(size0); + R->Range = size0; + RC_NORM_1(R) + /* we can use single byte normalization here because of + (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */ + + // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + // Ppmd7_UpdateBin(p); + { + unsigned freq = s->Freq; + CTX_PTR c = CTX(SUCCESSOR(s)); + sym = s->Symbol; + 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 sym; } - *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); - p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + + *prob = (UInt16)pr; + p->InitEsc = p->ExpEscape[pr >> 10]; + + // RangeDec_DecodeBit1(size0); + + R->Code -= size0; + R->Range -= size0; + RC_NORM_LOCAL(R) + PPMD_SetAllBitsIn256Bytes(charMask); MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; p->PrevSuccess = 0; } + for (;;) { - CPpmd_State *ps[256], *s; + CPpmd_State *s, *s2; UInt32 freqSum, count, hiCnt; + CPpmd_See *see; - unsigned i, num, numMasked = p->MinContext->NumStats; + CPpmd7_Context *mc; + unsigned numMasked; + RC_NORM_REMOTE(R) + mc = p->MinContext; + numMasked = mc->NumStats; + do { p->OrderFall++; - if (!p->MinContext->Suffix) - return -1; - p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + if (!mc->Suffix) + return PPMD7_SYM_END; + mc = Ppmd7_GetContext(p, mc->Suffix); } - while (p->MinContext->NumStats == numMasked); - hiCnt = 0; - s = Ppmd7_GetStats(p, p->MinContext); - i = 0; - num = p->MinContext->NumStats - numMasked; - do - { - int k = (int)(MASK(s->Symbol)); - hiCnt += (s->Freq & k); - ps[i] = s++; - i -= k; - } - while (i != num); + while (mc->NumStats == numMasked); + s = Ppmd7_GetStats(p, mc); + + { + unsigned num = mc->NumStats; + unsigned num2 = num / 2; + + num &= 1; + hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); + s += num; + p->MinContext = mc; + + do + { + unsigned sym0 = s[0].Symbol; + unsigned sym1 = s[1].Symbol; + s += 2; + hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); + hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); + } + while (--num2); + } + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); freqSum += hiCnt; - count = rc->GetThreshold(rc, freqSum); + + + + + count = RC_GetThreshold(freqSum); if (count < hiCnt) { - Byte symbol; - CPpmd_State **pps = ps; - for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); - s = *pps; - rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Byte sym; + + s = Ppmd7_GetStats(p, p->MinContext); + hiCnt = count; + // count -= s->Freq & (unsigned)(MASK(s->Symbol)); + // if ((Int32)count >= 0) + { + for (;;) + { + 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); + + // new (see->Summ) value can overflow over 16-bits in some rare cases Ppmd_See_Update(see); p->FoundState = s; - symbol = s->Symbol; + sym = s->Symbol; Ppmd7_Update2(p); - return symbol; + return sym; } + if (count >= freqSum) - return -2; - rc->Decode(rc, hiCnt, freqSum - hiCnt); + return PPMD7_SYM_ERROR; + + 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 see->Summ = (UInt16)(see->Summ + freqSum); - do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + + s = Ppmd7_GetStats(p, p->MinContext); + s2 = s + p->MinContext->NumStats; + do + { + MASK(s->Symbol) = 0; + s++; + } + while (s != s2); } } + +/* +Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim) +{ + int sym = 0; + if (buf != lim) + do + { + sym = Ppmd7z_DecodeSymbol(p); + if (sym < 0) + break; + *buf = (Byte)sym; + } + while (++buf < lim); + p->LastSymbol = sym; + return buf; +} +*/ diff --git a/libraries/lzma/C/Threads.c b/libraries/lzma/C/Threads.c index 930ad271b..58eb90ffa 100644 --- a/libraries/lzma/C/Threads.c +++ b/libraries/lzma/C/Threads.c @@ -1,9 +1,11 @@ /* Threads.c -- multithreading library -2017-06-26 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #include "Precomp.h" -#ifndef UNDER_CE +#ifdef _WIN32 + +#ifndef USE_THREADS_CreateThread #include #endif @@ -29,28 +31,103 @@ WRes HandlePtr_Close(HANDLE *p) return 0; } -WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } +WRes Handle_WaitObject(HANDLE h) +{ + DWORD dw = WaitForSingleObject(h, INFINITE); + /* + (dw) result: + WAIT_OBJECT_0 // 0 + WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space + WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space + WAIT_FAILED // 0xFFFFFFFF + */ + if (dw == WAIT_FAILED) + { + dw = GetLastError(); + if (dw == 0) + return WAIT_FAILED; + } + return (WRes)dw; +} + +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +WRes Thread_Wait_Close(CThread *p) +{ + WRes res = Thread_Wait(p); + WRes res2 = Thread_Close(p); + return (res != 0 ? res : res2); +} WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ - - #ifdef UNDER_CE - + + #ifdef USE_THREADS_CreateThread + DWORD threadId; - *p = CreateThread(0, 0, func, param, 0, &threadId); - + *p = CreateThread(NULL, 0, func, param, 0, &threadId); + #else - + unsigned threadId; - *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); - + *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); + #endif /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(*p); } + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + #ifdef USE_THREADS_CreateThread + + UNUSED_VAR(affinity) + return Thread_Create(p, func, param); + + #else + + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + HANDLE h; + WRes wres; + unsigned threadId; + h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); + *p = h; + wres = HandleToWRes(h); + if (h) + { + { + // DWORD_PTR prevMask = + SetThreadAffinityMask(h, (DWORD_PTR)affinity); + /* + if (prevMask == 0) + { + // affinity change is non-critical error, so we can ignore it + // wres = GetError(); + } + */ + } + { + DWORD prevSuspendCount = ResumeThread(h); + /* ResumeThread() returns: + 0 : was_not_suspended + 1 : was_resumed + -1 : error + */ + if (prevSuspendCount == (DWORD)-1) + wres = GetError(); + } + } + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return wres; + + #endif +} + + static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); @@ -68,10 +145,22 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEven WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { + // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore() *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); return HandleToWRes(*p); } +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + // if (Semaphore_IsCreated(p)) + { + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + } + return Semaphore_Create(p, initCount, maxCount); +} + static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) @@ -80,7 +169,9 @@ WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes CriticalSection_Init(CCriticalSection *p) { - /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + /* InitializeCriticalSection() can raise exception: + Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception + Windows Vista+ : no exceptions */ #ifdef _MSC_VER __try #endif @@ -89,7 +180,361 @@ WRes CriticalSection_Init(CCriticalSection *p) /* InitializeCriticalSectionAndSpinCount(p, 0); */ } #ifdef _MSC_VER - __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } #endif return 0; } + + + + +#else // _WIN32 + +// ---------- POSIX ---------- + +#ifndef __APPLE__ +#ifndef _7ZIP_AFFINITY_DISABLE +// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET +#define _GNU_SOURCE +#endif +#endif + +#include "Threads.h" + +#include +#include +#include +#ifdef _7ZIP_AFFINITY_SUPPORTED +// #include +#endif + + +// #include +// #define PRF(p) p +#define PRF(p) + +#define Print(s) PRF(printf("\n%s\n", s)) + +// #include + +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"); + + pthread_attr_t attr; + int ret; + // int ret2; + + p->_created = 0; + + RINOK(pthread_attr_init(&attr)); + + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + if (!ret) + { + if (cpuSet) + { + #ifdef _7ZIP_AFFINITY_SUPPORTED + + /* + printf("\n affinity :"); + unsigned i; + for (i = 0; i < sizeof(*cpuSet) && i < 8; i++) + { + Byte b = *((const Byte *)cpuSet + i); + char temp[32]; + #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + temp[0] = GET_HEX_CHAR((b & 0xF)); + temp[1] = GET_HEX_CHAR((b >> 4)); + // temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian + // temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian + temp[2] = 0; + printf("%s", temp); + } + printf("\n"); + */ + + // ret2 = + pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + #endif + } + + ret = pthread_create(&p->_tid, &attr, func, param); + + if (!ret) + { + p->_created = 1; + /* + if (cpuSet) + { + // ret2 = + pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + } + */ + } + } + // ret2 = + pthread_attr_destroy(&attr); + // if (ret2 != 0) ret = ret2; + return ret; +} + + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + return Thread_Create_With_CpuSet(p, func, param, NULL); +} + + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + Print("Thread_Create_WithAffinity"); + CCpuSet cs; + unsigned i; + CpuSet_Zero(&cs); + for (i = 0; i < sizeof(affinity) * 8; i++) + { + if (affinity == 0) + break; + if (affinity & 1) + { + CpuSet_Set(&cs, i); + } + affinity >>= 1; + } + return Thread_Create_With_CpuSet(p, func, param, &cs); +} + + +WRes Thread_Close(CThread *p) +{ + // Print("Thread_Close"); + int ret; + if (!p->_created) + return 0; + + ret = pthread_detach(p->_tid); + p->_tid = 0; + p->_created = 0; + return ret; +} + + +WRes Thread_Wait_Close(CThread *p) +{ + // Print("Thread_Wait_Close"); + void *thread_return; + int ret; + if (!p->_created) + return EINVAL; + + ret = pthread_join(p->_tid, &thread_return); + // probably we can't use that (_tid) after pthread_join(), so we close thread here + p->_created = 0; + p->_tid = 0; + return ret; +} + + + +static WRes Event_Create(CEvent *p, int manualReset, int signaled) +{ + 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; + return 0; +} + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) + { return Event_Create(p, True, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) + { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) + { return Event_Create(p, False, signaled); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) + { return AutoResetEvent_Create(p, 0); } + + +WRes Event_Set(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + p->_state = True; + int res1 = pthread_cond_broadcast(&p->_cond); + int res2 = pthread_mutex_unlock(&p->_mutex); + return (res2 ? res2 : res1); +} + +WRes Event_Reset(CEvent *p) +{ + 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)); + while (p->_state == False) + { + // ETIMEDOUT + // ret = + pthread_cond_wait(&p->_cond, &p->_mutex); + // if (ret != 0) break; + } + if (p->_manual_reset == False) + { + p->_state = False; + } + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Event_Close(CEvent *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + +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)); + p->_count = initCount; + p->_maxCount = maxCount; + p->_created = 1; + return 0; +} + + +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + if (Semaphore_IsCreated(p)) + { + /* + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + */ + if (initCount > maxCount || maxCount < 1) + return EINVAL; + // return EINVAL; // for debug + p->_count = initCount; + p->_maxCount = maxCount; + return 0; + } + return Semaphore_Create(p, initCount, maxCount); +} + + +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) +{ + UInt32 newCount; + int ret; + + if (releaseCount < 1) + return EINVAL; + + RINOK(pthread_mutex_lock(&p->_mutex)); + + newCount = p->_count + releaseCount; + if (newCount > p->_maxCount) + ret = ERROR_TOO_MANY_POSTS; // EINVAL; + else + { + p->_count = newCount; + ret = pthread_cond_broadcast(&p->_cond); + } + RINOK(pthread_mutex_unlock(&p->_mutex)); + return ret; +} + +WRes Semaphore_Wait(CSemaphore *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + while (p->_count < 1) + { + pthread_cond_wait(&p->_cond, &p->_mutex); + } + p->_count--; + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Semaphore_Close(CSemaphore *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + + +WRes CriticalSection_Init(CCriticalSection *p) +{ + // Print("CriticalSection_Init"); + if (!p) + return EINTR; + return pthread_mutex_init(&p->_mutex, NULL); +} + +void CriticalSection_Enter(CCriticalSection *p) +{ + // Print("CriticalSection_Enter"); + if (p) + { + // int ret = + pthread_mutex_lock(&p->_mutex); + } +} + +void CriticalSection_Leave(CCriticalSection *p) +{ + // Print("CriticalSection_Leave"); + if (p) + { + // int ret = + pthread_mutex_unlock(&p->_mutex); + } +} + +void CriticalSection_Delete(CCriticalSection *p) +{ + // Print("CriticalSection_Delete"); + if (p) + { + // int ret = + pthread_mutex_destroy(&p->_mutex); + } +} + +LONG InterlockedIncrement(LONG volatile *addend) +{ + // Print("InterlockedIncrement"); + #ifdef USE_HACK_UNSAFE_ATOMIC + LONG val = *addend + 1; + *addend = val; + return val; + #else + return __sync_add_and_fetch(addend, 1); + #endif +} + +#endif // _WIN32 diff --git a/libraries/lzma/C/Threads.h b/libraries/lzma/C/Threads.h index e53ace435..89ecb92be 100644 --- a/libraries/lzma/C/Threads.h +++ b/libraries/lzma/C/Threads.h @@ -1,38 +1,139 @@ /* Threads.h -- multithreading library -2017-06-18 : Igor Pavlov : Public domain */ +2021-12-21 : Igor Pavlov : Public domain */ #ifndef __7Z_THREADS_H #define __7Z_THREADS_H #ifdef _WIN32 -#include +#include +#else + +#if defined(__linux__) +#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) +#ifndef _7ZIP_AFFINITY_DISABLE +#define _7ZIP_AFFINITY_SUPPORTED +// #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED") +// #define _GNU_SOURCE +#endif +#endif +#endif + +#include + #endif #include "7zTypes.h" EXTERN_C_BEGIN +#ifdef _WIN32 + WRes HandlePtr_Close(HANDLE *h); 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)) +// #define Thread_Wait(p) Handle_WaitObject(*(p)) + +#ifdef UNDER_CE + // if (USE_THREADS_CreateThread is defined), we use _beginthreadex() + // if (USE_THREADS_CreateThread is not definned), we use CreateThread() + #define USE_THREADS_CreateThread +#endif typedef -#ifdef UNDER_CE - DWORD + #ifdef USE_THREADS_CreateThread + DWORD + #else + unsigned + #endif + THREAD_FUNC_RET_TYPE; + +typedef DWORD_PTR CAffinityMask; +typedef DWORD_PTR CCpuSet; + +#define CpuSet_Zero(p) { *(p) = 0; } +#define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); } + +#else // _WIN32 + +typedef struct _CThread +{ + pthread_t _tid; + int _created; +} CThread; + +#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; + +typedef UInt64 CAffinityMask; + +#ifdef _7ZIP_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) + #else - unsigned + +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) + #endif - THREAD_FUNC_RET_TYPE; + + +#endif // _WIN32 + #define THREAD_FUNC_CALL_TYPE MY_STD_CALL -#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE + +#if defined(_WIN32) && defined(__GNUC__) +/* GCC compiler for x86 32-bit uses the rule: + the stack is 16-byte aligned before CALL instruction for function calling. + But only root function main() contains instructions that + set 16-byte alignment for stack pointer. And another functions + just keep alignment, if it was set in some parent function. + + The problem: + if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(), + the root function of thread doesn't set 16-byte alignment. + And stack frames in all child functions also will be unaligned in that case. + + Here we set (force_align_arg_pointer) attribute for root function of new thread. + Do we need (force_align_arg_pointer) also for another systems? */ + + #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer)) + // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions +#else + #define THREAD_FUNC_ATTRIB_ALIGN_ARG +#endif + +#define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE + typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); 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); +WRes Thread_Wait_Close(CThread *p); + +#ifdef _WIN32 +#define Thread_Create_With_CpuSet(p, func, param, cs) \ + Thread_Create_With_Affinity(p, func, param, *cs) +#else +WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); +#endif + + +#ifdef _WIN32 typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; @@ -54,6 +155,7 @@ typedef HANDLE CSemaphore; #define Semaphore_Close(p) HandlePtr_Close(p) #define Semaphore_Wait(p) Handle_WaitObject(*(p)) WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); @@ -63,6 +165,68 @@ WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) + +#else // _WIN32 + +typedef struct _CEvent +{ + int _created; + int _manual_reset; + int _state; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CEvent; + +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; + +#define Event_Construct(p) (p)->_created = 0 +#define Event_IsCreated(p) ((p)->_created) + +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); +WRes Event_Close(CEvent *p); + + +typedef struct _CSemaphore +{ + int _created; + UInt32 _count; + UInt32 _maxCount; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CSemaphore; + +#define Semaphore_Construct(p) (p)->_created = 0 +#define Semaphore_IsCreated(p) ((p)->_created) + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) +WRes Semaphore_Wait(CSemaphore *p); +WRes Semaphore_Close(CSemaphore *p); + + +typedef struct _CCriticalSection +{ + pthread_mutex_t _mutex; +} CCriticalSection; + +WRes CriticalSection_Init(CCriticalSection *p); +void CriticalSection_Delete(CCriticalSection *cs); +void CriticalSection_Enter(CCriticalSection *cs); +void CriticalSection_Leave(CCriticalSection *cs); + +LONG InterlockedIncrement(LONG volatile *addend); + +#endif // _WIN32 + EXTERN_C_END #endif diff --git a/libraries/lzma/CMakeLists.txt b/libraries/lzma/CMakeLists.txt index 570265049..2ef5b078f 100644 --- a/libraries/lzma/CMakeLists.txt +++ b/libraries/lzma/CMakeLists.txt @@ -4,7 +4,9 @@ make_release_only() set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_PPMD_SUPPPORT" ) -set( LZMA_FILES +find_package(Threads) + +add_library( lzma STATIC C/7zArcIn.c C/7zBuf.c C/7zCrc.c @@ -18,17 +20,13 @@ set( LZMA_FILES C/CpuArch.c C/Delta.c C/LzFind.c + C/LzFindMt.c + C/LzFindOpt.c C/Lzma2Dec.c C/LzmaDec.c C/LzmaEnc.c C/Ppmd7.c - C/Ppmd7Dec.c ) - -if( WIN32 ) - set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c ) -else() - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST" ) -endif() - -add_library( lzma STATIC ${LZMA_FILES} ) -target_link_libraries( lzma ) + C/Ppmd7Dec.c + C/Threads.c +) +target_link_libraries( lzma Threads::Threads ) diff --git a/libraries/lzma/DOC/lzma-history.txt b/libraries/lzma/DOC/lzma-history.txt index 48ee74813..0963c7bf7 100644 --- a/libraries/lzma/DOC/lzma-history.txt +++ b/libraries/lzma/DOC/lzma-history.txt @@ -1,6 +1,80 @@ HISTORY of the LZMA SDK ----------------------- +21.07 2021-12-26 +------------------------- +- New switches: -spm and -im!{file_path} to exclude directories from processing + for specified paths that don't contain path separator character at the end of path. +- The sorting order of files in archives was slightly changed to be more consistent + for cases where the name of some directory is the same as the prefix part of the name + of another directory or file. + + +21.06 2021-11-24 +------------------------- +- Bug in LZMA encoder in file LzmaEnc.c was fixed: + LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, + if size value for output buffer is smaller than size required for all compressed data. + LzmaEnc_Encode() could work incorrectly, + if callback ISeqOutStream::Write() doesn't write all compressed data. + NCompress::NLzma::CEncoder::Code() could work incorrectly, + if callback ISequentialOutStream::Write() returns error code. +- Bug in versions 21.00-21.05 was fixed: + 7-Zip didn't set attributes of directories during archive extracting. + + +21.04 beta 2021-11-02 +------------------------- +- 7-Zip now reduces the number of working CPU threads for compression, + if RAM size is not enough for compression with big LZMA2 dictionary. +- 7-Zip now can create and check "file.sha256" text files that contain the list + of file names and SHA-256 checksums in format compatible with sha256sum program. + + +21.03 beta 2021-07-20 +------------------------- +- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB). +- Minor speed optimizations in LZMA/LZMA2 compressing. + + +21.02 alpha 2021-05-06 +------------------------- +- The command line version of 7-Zip for macOS was released. +- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux + was increased by 20%-60%. + + +21.01 alpha 2021-03-09 +------------------------- +- The command line version of 7-Zip for Linux was released. +- The improvements for speed of ARM64 version using hardware CPU instructions + for AES, CRC-32, SHA-1 and SHA-256. +- Some bugs were fixed. + + +20.02 alpha 2020-08-08 +------------------------- +- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. + It allows to increase the compression speed for big 7z archives, if there is a big number + of CPU cores and threads. +- The speed of PPMd compressing/decompressing was increased for 7z archives. +- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system + to modify "Last Access Time" property of source files for archiving and hashing operations. +- Some bugs were fixed. + + +20.00 alpha 2020-02-06 +------------------------- +- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, + that can work faster than bt4 and hc4 match finders for the data with big redundancy. +- The compression ratio was improved for Fast and Fastest compression levels with the + following default settings: + - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. + - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. +- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra + compression levels. + + 19.00 2019-02-21 ------------------------- - Encryption strength for 7z archives was increased: diff --git a/libraries/lzma/DOC/lzma-sdk.txt b/libraries/lzma/DOC/lzma-sdk.txt index b0e14a2e2..9621c8d5d 100644 --- a/libraries/lzma/DOC/lzma-sdk.txt +++ b/libraries/lzma/DOC/lzma-sdk.txt @@ -1,4 +1,4 @@ -LZMA SDK 19.00 +LZMA SDK 21.07 -------------- LZMA SDK provides the documentation, samples, header files, @@ -62,14 +62,61 @@ LZMA SDK Contents UNIX/Linux version ------------------ -To compile C++ version of file->file LZMA encoding, go to directory -CPP/7zip/Bundles/LzmaCon -and call make to recompile it: - make -f makefile.gcc clean all +There are several otpions to compile 7-Zip with different compilers: gcc and clang. +Also 7-Zip code contains two versions for some critical parts of code: in C and in Assembeler. +So if you compile the version with Assembeler code, you will get faster 7-Zip binary. + +7-Zip's assembler code uses the following syntax for different platforms: + +1) x86 and x86-64 (AMD64): MASM syntax. + There are 2 programs that supports MASM syntax in Linux. +' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some + cpu instructions used in 7-Zip. + So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version + of 7-Zip x86 and x86-64: + https://github.com/nidud/asmc + +2) arm64: GNU assembler for ARM64 with preprocessor. + That systax of that arm64 assembler code in 7-Zip is supported by GCC and CLANG for ARM64. + +There are different binaries that can be compiled from 7-Zip source. +There are 2 main files in folder for compiling: + makefile - that can be used for compiling Windows version of 7-Zip with nmake command + makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip with make command + +At first you must change the current folder to folder that contains `makefile.gcc`: + + cd CPP/7zip/Bundles/Alone7z + +Then you can compile `makefile.gcc` with the command: + + make -j -f makefile.gcc + +Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile +7-Zip binaries with optimized code and optimzing options. + +To compile with GCC without assembler: + cd CPP/7zip/Bundles/Alone7z + make -j -f ../../cmpl_gcc.mak + +To compile with CLANG without assembler: + make -j -f ../../cmpl_clang.mak + +To compile 7-Zip for x86-64 with asmc assembler: + make -j -f ../../cmpl_gcc_x64.mak + +To compile 7-Zip for arm64 with assembler: + make -j -f ../../cmpl_gcc_arm64.mak + +To compile 7-Zip for arm64 for macOS: + make -j -f ../../cmpl_mac_arm64.mak + +Also you can change some compiler options in the mak files: + cmpl_gcc.mak + var_gcc.mak + warn_gcc.mak + -In some UNIX/Linux versions you must compile LZMA with static libraries. -To compile with static libraries, you can use -LIB = -lm -static Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux): diff --git a/libraries/zlib/ChangeLog b/libraries/zlib/ChangeLog index 30199a65a..457526bc6 100644 --- a/libraries/zlib/ChangeLog +++ b/libraries/zlib/ChangeLog @@ -1,6 +1,81 @@ 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 @@ -96,7 +171,7 @@ Changes in 1.2.7.1 (24 Mar 2013) - 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 -- Suport i686 and amd64 assembler builds in CMakeLists.txt +- 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 @@ -296,14 +371,14 @@ Changes in 1.2.5.1 (10 Sep 2011) - 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 indeterminancy +- 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 assmebler code [Londer] +- 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] @@ -511,7 +586,7 @@ Changes in 1.2.3.5 (8 Jan 2010) - 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 . +- 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 @@ -685,7 +760,7 @@ Changes in 1.2.2.4 (11 July 2005) - 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. + 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] @@ -721,7 +796,7 @@ Changes in 1.2.2.2 (30 December 2004) - 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. + 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 @@ -792,7 +867,7 @@ Changes in 1.2.1.1 (9 January 2004) - 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. +- 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 @@ -970,7 +1045,7 @@ Changes in 1.2.0.1 (17 March 2003) - 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 -- Enchance comments in zlib.h on what happens if gzprintf() tries to +- 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 @@ -1036,14 +1111,14 @@ Changes in 1.2.0 (9 March 2003) - 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. +- 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. + 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). + 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 @@ -1117,7 +1192,7 @@ Changes in 1.1.1 (27 Feb 98) - 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. + matches in deflate_slow - added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) Changes in 1.1.0 (24 Feb 98) @@ -1148,7 +1223,7 @@ Changes in 1.0.9 (17 Feb 1998) - 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) + 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) @@ -1162,7 +1237,7 @@ Changes in 1.0.8 (27 Jan 1998) - 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". + 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 @@ -1201,12 +1276,12 @@ 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. + 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. +- 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) @@ -1218,7 +1293,7 @@ Changes in 1.0.6 (19 Jan 1998) - added Makefile.nt (thanks to Stephen Williams) - added the unsupported "contrib" directory: contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). + 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 @@ -1226,7 +1301,7 @@ Changes in 1.0.6 (19 Jan 1998) 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. + 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) @@ -1235,8 +1310,8 @@ Changes in 1.0.6 (19 Jan 1998) - 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. +- 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 @@ -1249,7 +1324,7 @@ Changes in 1.0.6 (19 Jan 1998) - 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). +- 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) @@ -1259,7 +1334,7 @@ Changes in 1.0.6 (19 Jan 1998) - 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. +- 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 @@ -1280,7 +1355,7 @@ Changes in 1.0.5 (3 Jan 98) 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. + 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) @@ -1310,7 +1385,7 @@ 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. +- 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), @@ -1331,7 +1406,7 @@ 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. + 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 @@ -1373,30 +1448,30 @@ Changes in 0.99 (27 Jan 96) - 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. +- 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). +- 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. +- 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?). + (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). + 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). + (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). + typedefs and because voidnp was not near in large model) Changes in 0.94 (13 Aug 95) - support MSDOS medium model @@ -1405,12 +1480,12 @@ Changes in 0.94 (13 Aug 95) - 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. +- 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. +- 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 @@ -1429,7 +1504,7 @@ Changes in 0.92 (3 May 95) - no memcpy on Pyramid - suppressed inftest.c - optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. +- optimized inflate on stored blocks - untabify all sources to simplify patches Changes in 0.91 (2 May 95) @@ -1447,7 +1522,7 @@ Changes in 0.9 (1 May 95) - 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. +- 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++ @@ -1456,7 +1531,7 @@ Changes in 0.9 (1 May 95) 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. + 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 @@ -1466,50 +1541,50 @@ Changes in 0.8 (29 April 95) Changes in 0.71 (14 April 95) - Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. + TurboC large model Changes in 0.7 (14 April 95) -- Added full inflate support. +- 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. + 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. +- 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. +- 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). +- 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. + not yet Z_FULL_FLUSH - support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. +- 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. +- 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. +- avoid "zip" everywhere, use zlib instead of ziplib - suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. + 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 the method parameter for deflateInit2 - added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting +- simplified considerably deflateInit and inflateInit by not supporting user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. + and inflateInit2 Changes in 0.3: - prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. +- use Z_FINISH instead of deflateEnd to finish compression - added Z_HUFFMAN_ONLY - added gzerror() diff --git a/libraries/zlib/README b/libraries/zlib/README index 51106de47..ba34d1894 100644 --- a/libraries/zlib/README +++ b/libraries/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.11 is a general purpose data compression library. All the code is +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 @@ -31,7 +31,7 @@ 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.11 are documented in the file ChangeLog. +The changes made in version 1.2.13 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -84,7 +84,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2017 Jean-loup Gailly and Mark Adler + (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 @@ -108,7 +108,10 @@ Copyright notice: 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. +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 diff --git a/libraries/zlib/compress.c b/libraries/zlib/compress.c index e2db404ab..2ad5326c1 100644 --- a/libraries/zlib/compress.c +++ b/libraries/zlib/compress.c @@ -19,7 +19,7 @@ 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) +int ZEXPORT compress2(dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -65,7 +65,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) /* =========================================================================== */ -int ZEXPORT compress (dest, destLen, source, sourceLen) +int ZEXPORT compress(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -78,7 +78,7 @@ int ZEXPORT compress (dest, destLen, source, sourceLen) If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound (sourceLen) +uLong ZEXPORT compressBound(sourceLen) uLong sourceLen; { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + diff --git a/libraries/zlib/crc32.c b/libraries/zlib/crc32.c index 9580440c0..f8357b083 100644 --- a/libraries/zlib/crc32.c +++ b/libraries/zlib/crc32.c @@ -1,12 +1,10 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + * 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$ */ @@ -14,11 +12,12 @@ /* 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 + 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(). - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + 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 @@ -28,175 +27,722 @@ # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ -#include "zutil.h" /* for STDC and FAR definitions */ +#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ -/* Definitions for doing the crc four data bytes at a time. */ -#if !defined(NOBYFOUR) && defined(Z_U4) -# define BYFOUR -#endif -#ifdef BYFOUR - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, z_size_t)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, z_size_t)); -# define TBLS 8 + /* + 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 TBLS 1 -#endif /* BYFOUR */ +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); +/* + 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 volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; +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 *)); + 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 + 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 + 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+1), then the CRC is (q*x^32) mod p, + 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 + 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. + 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. + */ - The first 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. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ local void make_crc_table() { - z_crc_t c; - int n, k; - z_crc_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + unsigned i, j, n; + z_crc_t p; - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (z_crc_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (z_crc_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; + /* 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 - /* write out CRC tables to crc32.h */ { + /* + 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; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const z_crc_t FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); + + /* 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, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\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 -local void write_table(out, table) + +/* + 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 < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\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 of CRC-32s of all single-byte values, made by make_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() + * 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 - if (crc_table_empty) - make_crc_table(); + once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ return (const z_crc_t FAR *)crc_table; } -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 +/* ========================================================================= + * 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) @@ -204,35 +750,324 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) const unsigned char FAR *buf; z_size_t len; { - if (buf == Z_NULL) return 0UL; + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - z_crc_t endian; + /* 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))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); + 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 /* BYFOUR */ - crc = crc ^ 0xffffffffUL; + +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ while (len >= 8) { - DO8; 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]; } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; + 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; @@ -242,186 +1077,16 @@ unsigned long ZEXPORT crc32(crc, buf, len) return crc32_z(crc, buf, len); } -#ifdef BYFOUR - -/* - This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit - integer pointer type. This violates the strict aliasing rule, where a - compiler can assume, for optimization purposes, that two pointers to - fundamentally different types won't ever point to the same memory. This can - manifest as a problem only if one of the pointers is written to. This code - only reads from those pointers. So long as this code remains isolated in - this compilation unit, there won't be a problem. For this reason, this code - should not be copied and pasted into a compilation unit in which other code - writes to the buffer that is passed to these routines. - */ - /* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = (z_crc_t)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = ZSWAP32((z_crc_t)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(ZSWAP32(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_(crc1, crc2, len2) +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) uLong crc1; uLong crc2; z_off64_t len2; { - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); } /* ========================================================================= */ @@ -430,13 +1095,31 @@ uLong ZEXPORT crc32_combine(crc1, crc2, len2) uLong crc2; z_off_t len2; { - return crc32_combine_(crc1, crc2, len2); + return crc32_combine64(crc1, crc2, (z_off64_t)len2); } -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_gen64(len2) z_off64_t len2; { - return crc32_combine_(crc1, crc2, 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 index 9e0c77810..137df68d6 100644 --- a/libraries/zlib/crc32.h +++ b/libraries/zlib/crc32.h @@ -2,440 +2,9445 @@ * Generated automatically by crc32.c */ -local const z_crc_t FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL +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 index 1ec761448..4a689db35 100644 --- a/libraries/zlib/deflate.c +++ b/libraries/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; + " 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 @@ -87,13 +87,7 @@ 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)); -#ifdef ASMV -# pragma message("Assembler code may have bugs -- use at your own risk") - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif #ifdef ZLIB_DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, @@ -160,7 +154,7 @@ local const config configuration_table[10] = { * 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)<hash_shift) ^ (c)) & s->hash_mask) +#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== @@ -190,8 +184,11 @@ local const config configuration_table[10] = { * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + 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 @@ -252,11 +249,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, int wrap = 1; static const char my_version[] = ZLIB_VERSION; - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; @@ -287,6 +279,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP @@ -316,7 +310,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, 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->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)); @@ -326,9 +320,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + /* 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) { @@ -337,8 +369,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, deflateEnd (strm); return Z_MEM_ERROR; } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + 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; @@ -350,7 +386,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck (strm) +local int deflateStateCheck(strm) z_streamp strm; { deflate_state *s; @@ -373,7 +409,7 @@ local int deflateStateCheck (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; @@ -442,7 +478,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) z_streamp strm; Bytef *dictionary; uInt *dictLength; @@ -464,7 +500,7 @@ int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) +int ZEXPORT deflateResetKeep(strm) z_streamp strm; { deflate_state *s; @@ -488,13 +524,13 @@ int ZEXPORT deflateResetKeep (strm) #ifdef GZIP s->wrap == 2 ? GZIP_STATE : #endif - s->wrap ? INIT_STATE : BUSY_STATE; + INIT_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + s->last_flush = -2; _tr_init(s); @@ -502,7 +538,7 @@ int ZEXPORT deflateResetKeep (strm) } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateReset(strm) z_streamp strm; { int ret; @@ -514,7 +550,7 @@ int ZEXPORT deflateReset (strm) } /* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) +int ZEXPORT deflateSetHeader(strm, head) z_streamp strm; gz_headerp head; { @@ -525,7 +561,7 @@ int ZEXPORT deflateSetHeader (strm, head) } /* ========================================================================= */ -int ZEXPORT deflatePending (strm, pending, bits) +int ZEXPORT deflatePending(strm, pending, bits) unsigned *pending; int *bits; z_streamp strm; @@ -539,7 +575,7 @@ int ZEXPORT deflatePending (strm, pending, bits) } /* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) +int ZEXPORT deflatePrime(strm, bits, value) z_streamp strm; int bits; int value; @@ -549,7 +585,8 @@ int ZEXPORT deflatePrime (strm, bits, value) if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + 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; @@ -587,12 +624,12 @@ int ZEXPORT deflateParams(strm, level, strategy) func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - s->high_water) { + s->last_flush != -2) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) return err; - if (strm->avail_out == 0) + if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) return Z_BUF_ERROR; } if (s->level != level) { @@ -633,36 +670,50 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) } /* ========================================================================= - * 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. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. + * 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, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. + * 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. * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. + * 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 complen, wraplen; + uLong fixedlen, storelen, wraplen; - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + /* 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; - /* if can't get parameters, return conservative bound plus zlib wrapper */ + /* 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 complen + 6; + return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; @@ -699,11 +750,12 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen = 6; } - /* if not default parameters, return conservative bound */ + /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; + return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen; - /* default settings: return tight bound for that case */ + /* 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; } @@ -713,7 +765,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB (s, b) +local void putShortMSB(s, b) deflate_state *s; uInt b; { @@ -760,7 +812,7 @@ local void flush_pending(strm) } while (0) /* ========================================================================= */ -int ZEXPORT deflate (strm, flush) +int ZEXPORT deflate(strm, flush) z_streamp strm; int flush; { @@ -811,9 +863,11 @@ int ZEXPORT deflate (strm, flush) } /* 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 header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) @@ -1073,7 +1127,7 @@ int ZEXPORT deflate (strm, flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd (strm) +int ZEXPORT deflateEnd(strm) z_streamp strm; { int status; @@ -1099,7 +1153,7 @@ int ZEXPORT deflateEnd (strm) * 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) +int ZEXPORT deflateCopy(dest, source) z_streamp dest; z_streamp source; { @@ -1108,7 +1162,6 @@ int ZEXPORT deflateCopy (dest, source) #else deflate_state *ds; deflate_state *ss; - ushf *overlay; if (deflateStateCheck(source) || dest == Z_NULL) { @@ -1128,8 +1181,7 @@ int ZEXPORT deflateCopy (dest, source) 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)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; + 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) { @@ -1143,8 +1195,7 @@ int ZEXPORT deflateCopy (dest, source) 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->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + 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; @@ -1191,7 +1242,7 @@ local unsigned read_buf(strm, buf, size) /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ -local void lm_init (s) +local void lm_init(s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; @@ -1212,11 +1263,6 @@ local void lm_init (s) s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif } #ifndef FASTEST @@ -1229,10 +1275,6 @@ local void lm_init (s) * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ @@ -1257,10 +1299,10 @@ local uInt longest_match(s, cur_match) */ 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); + 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_end1 = scan[best_len - 1]; register Byte scan_end = scan[best_len]; #endif @@ -1278,7 +1320,8 @@ local uInt longest_match(s, cur_match) */ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); @@ -1296,43 +1339,44 @@ local uInt longest_match(s, cur_match) /* 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 || + 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 + * 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 + * 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) && + } 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"); + /* 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); + 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; + 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 + /* 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 @@ -1342,7 +1386,7 @@ local uInt longest_match(s, cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1351,7 +1395,8 @@ local uInt longest_match(s, cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; @@ -1363,9 +1408,9 @@ local uInt longest_match(s, cur_match) best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); + scan_end = *(ushf*)(scan + best_len - 1); #else - scan_end1 = scan[best_len-1]; + scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } @@ -1375,7 +1420,6 @@ local uInt longest_match(s, cur_match) if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } -#endif /* ASMV */ #else /* FASTEST */ @@ -1396,7 +1440,8 @@ local uInt longest_match(s, cur_match) */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); Assert(cur_match < s->strstart, "no future"); @@ -1406,7 +1451,7 @@ local uInt longest_match(s, cur_match) */ 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 + /* 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 @@ -1416,7 +1461,7 @@ local uInt longest_match(s, cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1425,7 +1470,7 @@ local uInt longest_match(s, cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); @@ -1461,7 +1506,7 @@ local void check_match(s, start, match, length) z_error("invalid match"); } if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); + fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } @@ -1507,12 +1552,14 @@ local void fill_window(s) /* 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)) { + if (s->strstart >= wsize + MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); + 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; } @@ -1638,7 +1685,7 @@ local void fill_window(s) * * 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 opportunites to have a single copy from next_in to next_out. + * maximizes the opportunities to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; @@ -1742,6 +1789,7 @@ local block_state deflate_stored(s, flush) 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) { @@ -1750,12 +1798,14 @@ local block_state deflate_stored(s, flush) 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; - s->insert += MIN(used, s->w_size - s->insert); } if (s->high_water < s->strstart) s->high_water = s->strstart; @@ -1770,7 +1820,7 @@ local block_state deflate_stored(s, flush) return block_done; /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart - 1; + 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; @@ -1779,12 +1829,15 @@ local block_state deflate_stored(s, flush) 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; @@ -1842,7 +1895,7 @@ local block_state deflate_fast(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1890,7 +1943,7 @@ local block_state deflate_fast(s, flush) 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]); + UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif @@ -1901,7 +1954,7 @@ local block_state deflate_fast(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -1912,7 +1965,7 @@ local block_state deflate_fast(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -1945,7 +1998,7 @@ local block_state deflate_slow(s, flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1987,17 +2040,17 @@ local block_state deflate_slow(s, flush) 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); + check_match(s, s->strstart - 1, s->prev_match, s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, + _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 + * 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->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { @@ -2015,8 +2068,8 @@ local block_state deflate_slow(s, flush) * 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); + 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); } @@ -2034,8 +2087,8 @@ local block_state deflate_slow(s, flush) } 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); + 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; @@ -2043,7 +2096,7 @@ local block_state deflate_slow(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -2092,7 +2145,8 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (uInt)(s->window_size - 1), + "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -2107,7 +2161,7 @@ local block_state deflate_rle(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -2118,7 +2172,7 @@ local block_state deflate_rle(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } @@ -2147,7 +2201,7 @@ local block_state deflate_huff(s, flush) /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); @@ -2157,7 +2211,7 @@ local block_state deflate_huff(s, flush) FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } diff --git a/libraries/zlib/deflate.h b/libraries/zlib/deflate.h index 23ecdd312..1a06cd5f2 100644 --- a/libraries/zlib/deflate.h +++ b/libraries/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2016 Jean-loup Gailly + * Copyright (C) 1995-2018 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -217,7 +217,7 @@ typedef struct internal_state { /* Depth of each subtree used as tie breaker for trees of equal frequency */ - uchf *l_buf; /* buffer for literals or lengths */ + uchf *sym_buf; /* buffer for distances and literals/lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for @@ -239,13 +239,8 @@ typedef struct internal_state { * - I can't count above 4 */ - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ + 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 */ @@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ + 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->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ + 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->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) diff --git a/libraries/zlib/gzguts.h b/libraries/zlib/gzguts.h index 990a4d251..57faf3716 100644 --- a/libraries/zlib/gzguts.h +++ b/libraries/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -39,7 +39,7 @@ # include #endif -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) # define WIDECHAR #endif @@ -190,6 +190,7 @@ typedef struct { /* 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 */ diff --git a/libraries/zlib/infback.c b/libraries/zlib/infback.c index 59679ecbf..babeaf180 100644 --- a/libraries/zlib/infback.c +++ b/libraries/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -66,6 +66,7 @@ int stream_size; state->window = window; state->wnext = 0; state->whave = 0; + state->sane = 1; return Z_OK; } @@ -477,6 +478,7 @@ void FAR *out_desc; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; + /* fallthrough */ case LEN: /* use inflate_fast() if we have enough input and output */ @@ -604,25 +606,27 @@ void FAR *out_desc; break; case DONE: - /* inflate stream terminated properly -- write leftover output */ + /* inflate stream terminated properly */ ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; - default: /* can't happen, but makes compilers happy */ + default: + /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } - /* Return unused input */ + /* 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; diff --git a/libraries/zlib/inffast.c b/libraries/zlib/inffast.c index 0dbd1dbc0..1fec7f363 100644 --- a/libraries/zlib/inffast.c +++ b/libraries/zlib/inffast.c @@ -70,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ 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 here; /* retrieved table entry */ + 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 */ @@ -107,20 +107,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold += (unsigned long)(*in++) << bits; bits += 8; } - here = lcode[hold & lmask]; + here = lcode + (hold & lmask); dolen: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - *out++ = (unsigned char)(here.val); + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ - len = (unsigned)(here.val); + len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { @@ -138,14 +138,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold += (unsigned long)(*in++) << bits; bits += 8; } - here = dcode[hold & dmask]; + here = dcode + (hold & dmask); dodist: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); + dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(*in++) << bits; @@ -264,7 +264,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; + here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { @@ -274,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; + here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ diff --git a/libraries/zlib/inflate.c b/libraries/zlib/inflate.c index ac333e8c2..8acbef44e 100644 --- a/libraries/zlib/inflate.c +++ b/libraries/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -130,6 +130,7 @@ z_streamp strm; state->mode = HEAD; state->last = 0; state->havedict = 0; + state->flags = -1; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; @@ -167,6 +168,8 @@ int windowBits; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { + if (windowBits < -15) + return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } @@ -447,10 +450,10 @@ unsigned copy; /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP -# define UPDATE(check, buf, len) \ +# define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else -# define UPDATE(check, buf, len) adler32(check, buf, len) +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ @@ -670,7 +673,6 @@ int flush; state->mode = FLAGS; break; } - state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ @@ -697,6 +699,7 @@ int flush; 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; @@ -722,6 +725,7 @@ int flush; CRC2(state->check, hold); INITBITS(); state->mode = TIME; + /* fallthrough */ case TIME: NEEDBITS(32); if (state->head != Z_NULL) @@ -730,6 +734,7 @@ int flush; CRC4(state->check, hold); INITBITS(); state->mode = OS; + /* fallthrough */ case OS: NEEDBITS(16); if (state->head != Z_NULL) { @@ -740,6 +745,7 @@ int flush; CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; + /* fallthrough */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); @@ -753,14 +759,16 @@ int flush; 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 != 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); @@ -775,6 +783,7 @@ int flush; } state->length = 0; state->mode = NAME; + /* fallthrough */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; @@ -796,6 +805,7 @@ int flush; state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; + /* fallthrough */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; @@ -816,6 +826,7 @@ int flush; else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; + /* fallthrough */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); @@ -839,6 +850,7 @@ int flush; strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; + /* fallthrough */ case DICT: if (state->havedict == 0) { RESTORE(); @@ -846,8 +858,10 @@ int flush; } 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(); @@ -898,8 +912,10 @@ int flush; 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) { @@ -935,6 +951,7 @@ int flush; Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; + /* fallthrough */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); @@ -956,6 +973,7 @@ int flush; Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; + /* fallthrough */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { @@ -1039,8 +1057,10 @@ int flush; 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(); @@ -1090,6 +1110,7 @@ int flush; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; + /* fallthrough */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); @@ -1100,6 +1121,7 @@ int flush; 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)]; @@ -1127,6 +1149,7 @@ int flush; state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; + /* fallthrough */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); @@ -1143,6 +1166,7 @@ int flush; #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; + /* fallthrough */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; @@ -1202,7 +1226,7 @@ int flush; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, put - out, out); + UPDATE_CHECK(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP @@ -1218,10 +1242,11 @@ int flush; } #ifdef GUNZIP state->mode = LENGTH; + /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; @@ -1231,6 +1256,7 @@ int flush; } #endif state->mode = DONE; + /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; @@ -1240,6 +1266,7 @@ int flush; case MEM: return Z_MEM_ERROR; case SYNC: + /* fallthrough */ default: return Z_STREAM_ERROR; } @@ -1265,7 +1292,7 @@ int flush; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); + 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); @@ -1401,6 +1428,7 @@ 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; @@ -1433,9 +1461,15 @@ z_streamp strm; /* 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; } @@ -1531,7 +1565,7 @@ int check; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - if (check) + if (check && state->wrap) state->wrap |= 4; else state->wrap &= ~4; diff --git a/libraries/zlib/inflate.h b/libraries/zlib/inflate.h index a46cce6b6..f127b6b1f 100644 --- a/libraries/zlib/inflate.h +++ b/libraries/zlib/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -86,7 +86,8 @@ struct inflate_state { 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) */ + 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 */ diff --git a/libraries/zlib/inftrees.c b/libraries/zlib/inftrees.c index 2ea08fc13..57d2793be 100644 --- a/libraries/zlib/inftrees.c +++ b/libraries/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; + " 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 @@ -62,7 +62,7 @@ unsigned short FAR *work; 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, 77, 202}; + 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, diff --git a/libraries/zlib/inftrees.h b/libraries/zlib/inftrees.h index baa53a0b1..f53665311 100644 --- a/libraries/zlib/inftrees.h +++ b/libraries/zlib/inftrees.h @@ -38,7 +38,7 @@ typedef struct { /* 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 distribtution. The arguments to that + 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. diff --git a/libraries/zlib/trees.c b/libraries/zlib/trees.c index 50cf4b457..5f305c472 100644 --- a/libraries/zlib/trees.c +++ b/libraries/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2017 Jean-loup Gailly + * 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 */ @@ -149,7 +149,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, 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 value, int length)); +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)); @@ -193,7 +193,7 @@ local void send_bits(s, value, 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)) + * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { @@ -256,7 +256,7 @@ local void tr_static_init() length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; - for (n = 0; n < (1<>= 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++) { + 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"); + 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; @@ -312,7 +312,7 @@ local void tr_static_init() } /* =========================================================================== - * Genererate the file trees.h describing the static trees. + * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG @@ -321,7 +321,7 @@ local void tr_static_init() # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) % (width) == (width) - 1 ? ",\n" : ", ")) void gen_trees_header() { @@ -416,7 +416,7 @@ local void init_block(s) s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; + s->sym_next = s->matches = 0; } #define SMALLEST 1 @@ -458,7 +458,7 @@ local void pqdownheap(s, tree, 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)) { + smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ @@ -507,7 +507,7 @@ local void gen_bitlen(s, desc) */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + 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++; @@ -518,7 +518,7 @@ local void gen_bitlen(s, desc) s->bl_count[bits]++; xbits = 0; - if (n >= base) xbits = extra[n-base]; + 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); @@ -530,10 +530,10 @@ local void gen_bitlen(s, desc) /* Find the first bit length which could increase: */ do { - bits = max_length-1; + 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[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] @@ -569,7 +569,7 @@ local void gen_bitlen(s, desc) * 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) +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 */ @@ -583,13 +583,13 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; + 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<heap_len = 0, s->heap_max = HEAP_SIZE; @@ -652,7 +652,7 @@ local void build_tree(s, desc) } desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + /* 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); @@ -700,7 +700,7 @@ local void build_tree(s, desc) * 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) +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 */ @@ -714,10 +714,10 @@ local void scan_tree (s, tree, max_code) int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ + tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -745,7 +745,7 @@ local void scan_tree (s, tree, max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree (s, tree, max_code) +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 */ @@ -758,11 +758,11 @@ local void send_tree (s, tree, max_code) int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ - /* tree[max_code+1].Len = -1; */ /* guard already set */ + /* 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; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -773,13 +773,13 @@ local void send_tree (s, tree, max_code) 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); + 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); + 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); + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { @@ -807,8 +807,8 @@ local int build_bl_tree(s) /* 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. + /* 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 @@ -819,7 +819,7 @@ local int build_bl_tree(s) 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; + 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)); @@ -841,19 +841,19 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) 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 */ + 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 */ + 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 */ + send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } @@ -866,17 +866,18 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) 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 */ + 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); - zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, 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; + s->bits_sent += stored_len << 3; #endif } @@ -942,14 +943,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) 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; + 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->last_lit)); + s->sym_next / 3)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; +#ifndef FORCE_STATIC + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) +#endif + opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); @@ -959,7 +963,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { + 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. @@ -970,21 +974,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) */ _tr_stored_block(s, buf, stored_len, last); -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); + } 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); + 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 @@ -1003,21 +1003,22 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) s->compressed_len += 7; /* align on byte boundary */ #endif } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); + 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) +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 (if dist==0) */ + unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ { - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; + 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++; @@ -1029,33 +1030,10 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) (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_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ + return (s->sym_next == s->sym_end); } /* =========================================================================== @@ -1068,20 +1046,21 @@ local void compress_block(s, ltree, dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ + unsigned sx = 0; /* running index in sym_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; + 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 the length code */ + send_code(s, code + LITERALS + 1, ltree); /* send length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; @@ -1099,11 +1078,10 @@ local void compress_block(s, ltree, dtree) } } /* literal or match pair ? */ - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); + /* Check that the overlay between pending_buf and sym_buf is ok: */ + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - } while (lx < s->last_lit); + } while (sx < s->sym_next); send_code(s, END_BLOCK, ltree); } @@ -1112,9 +1090,9 @@ local void compress_block(s, ltree, dtree) * 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 - * "black list" (0..6, 14..25, 28..31). + * "block list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * "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: @@ -1124,19 +1102,19 @@ local void compress_block(s, ltree, dtree) local int detect_data_type(s) deflate_state *s; { - /* black_mask is the bit mask of black-listed bytes + /* block_mask is the bit mask of block-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ - unsigned long black_mask = 0xf3ffc07fUL; + unsigned long block_mask = 0xf3ffc07fUL; int n; - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + /* 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 ("white-listed") bytes. */ + /* 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; @@ -1144,7 +1122,7 @@ local int detect_data_type(s) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; - /* There are no "black-listed" or "white-listed" bytes: + /* There are no "block-listed" or "allow-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; @@ -1198,6 +1176,6 @@ local void bi_windup(s) s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; + s->bits_sent = (s->bits_sent + 7) & ~7; #endif } diff --git a/libraries/zlib/uncompr.c b/libraries/zlib/uncompr.c index f03a1a865..f9532f46c 100644 --- a/libraries/zlib/uncompr.c +++ b/libraries/zlib/uncompr.c @@ -24,7 +24,7 @@ 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) +int ZEXPORT uncompress2(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -83,7 +83,7 @@ int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) err; } -int ZEXPORT uncompress (dest, destLen, source, sourceLen) +int ZEXPORT uncompress(dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; diff --git a/libraries/zlib/win32/zlib.def b/libraries/zlib/win32/zlib.def index a2188b000..666bc6fbb 100644 --- a/libraries/zlib/win32/zlib.def +++ b/libraries/zlib/win32/zlib.def @@ -69,6 +69,7 @@ EXPORTS gzoffset64 adler32_combine64 crc32_combine64 + crc32_combine_gen64 ; checksum functions adler32 adler32_z @@ -76,6 +77,8 @@ EXPORTS crc32_z adler32_combine crc32_combine + crc32_combine_gen + crc32_combine_op ; various hacks, don't look :) deflateInit_ deflateInit2_ diff --git a/libraries/zlib/win32/zlib1.rc b/libraries/zlib/win32/zlib1.rc index 234e641c3..ceb4ee5c6 100644 --- a/libraries/zlib/win32/zlib1.rc +++ b/libraries/zlib/win32/zlib1.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileDescription", "zlib data compression library\0" VALUE "FileVersion", ZLIB_VERSION "\0" VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\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" diff --git a/libraries/zlib/zconf.h b/libraries/zlib/zconf.h index 5e1d68a00..bf977d3e7 100644 --- a/libraries/zlib/zconf.h +++ b/libraries/zlib/zconf.h @@ -38,6 +38,9 @@ # 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 @@ -349,6 +352,9 @@ # 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. */ @@ -467,11 +473,18 @@ typedef uLong FAR uLongf; # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#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) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ diff --git a/libraries/zlib/zlib.3 b/libraries/zlib/zlib.3 index bda4eb073..6f6e91404 100644 --- a/libraries/zlib/zlib.3 +++ b/libraries/zlib/zlib.3 @@ -1,4 +1,4 @@ -.TH ZLIB 3 "15 Jan 2017" +.TH ZLIB 3 "13 Oct 2022" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS @@ -105,9 +105,9 @@ 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.11 +Version 1.2.13 .LP -Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +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 diff --git a/libraries/zlib/zlib.3.pdf b/libraries/zlib/zlib.3.pdf index 6fa519c5b..8132d840c 100644 Binary files a/libraries/zlib/zlib.3.pdf and b/libraries/zlib/zlib.3.pdf differ diff --git a/libraries/zlib/zlib.h b/libraries/zlib/zlib.h index f09cdaf1e..953cb5012 100644 --- a/libraries/zlib/zlib.h +++ b/libraries/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.11, January 15th, 2017 + version 1.2.13, October 13th, 2022 - Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + 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 @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.11" -#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VERSION "1.2.13" +#define ZLIB_VERNUM 0x12d0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_REVISION 13 #define ZLIB_VER_SUBREVISION 0 /* @@ -276,7 +276,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); == 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 ouput + 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 @@ -543,8 +543,7 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int strategy)); This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. + 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. @@ -661,7 +660,7 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, 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. - Similary, if dictLength is Z_NULL, then it is not set. + 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 @@ -712,11 +711,12 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, 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 any input has been consumed in a previous - deflate() call, 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(). + 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 @@ -865,9 +865,11 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 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 streams. - inflate() will return Z_STREAM_END at the end of the gzip stream. The state - would need to be reset to continue decoding a subsequent gzip stream. + 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 @@ -913,7 +915,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, 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. - Similary, if dictLength is Z_NULL, then it is not set. + 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. @@ -1302,14 +1304,14 @@ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - Opens a gzip (.gz) file for reading or 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. + 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 @@ -1339,9 +1341,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* - gzdopen associates 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. + 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 @@ -1362,13 +1364,13 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* - Set the internal buffer size used by this library's functions. 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). + 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(). @@ -1378,9 +1380,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. Previously provided - data is flushed before the parameter change. + 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, @@ -1389,7 +1391,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* - Reads the given number of uncompressed bytes from the compressed file. If + 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. @@ -1420,11 +1422,11 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, gzFile file)); /* - Read up to nitems items of size size from file to 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. + 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 @@ -1435,26 +1437,24 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, 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 nevetheless read into buf + 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, reseting and retrying on end-of-file, when size is not 1. + file, resetting and retrying on end-of-file, when size is not 1. */ -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. + 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)); /* - gzfwrite() writes nitems items of size size from buf to file, duplicating + 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. @@ -1467,22 +1467,22 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of + 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() + 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)); /* - Writes the given null-terminated string to the compressed file, excluding + 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. @@ -1490,11 +1490,12 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* - Reads bytes from the compressed file until len-1 characters are read, or 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 == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. + 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 @@ -1503,13 +1504,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* - Writes c, converted to an unsigned char, into the compressed file. gzputc + 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)); /* - Reads one byte from the compressed file. gzgetc returns this byte or -1 + 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 @@ -1518,8 +1519,8 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. + 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 @@ -1530,9 +1531,9 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* - Flushes all pending output into the compressed 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. + 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 @@ -1547,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the + 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. @@ -1565,18 +1566,18 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* - Rewinds the given file. This function is supported only for reading. + Rewind file. This function is supported only for reading. - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - Returns the starting position for the next gzread or gzwrite on the given - compressed 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(). + 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) */ @@ -1584,22 +1585,22 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); /* ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - Returns the current offset in the file being read or written. 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. + 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)); /* - Returns true (1) if the end-of-file indicator 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. + 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 @@ -1608,7 +1609,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* - Returns true (1) if file is being copied directly while reading, or false + 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 @@ -1629,8 +1630,8 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you + 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. @@ -1654,10 +1655,10 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* - Returns the error message for the last error which occurred on the given - compressed 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. + 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 @@ -1670,7 +1671,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* - Clears the error and end-of-file flags for file. This is analogous to the + 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. */ @@ -1688,8 +1689,9 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); 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. If buf is Z_NULL, this function returns the - required initial value for the checksum. + 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. @@ -1722,12 +1724,13 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, negative, the result has no meaning or utility. */ -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +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. 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. + 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: @@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ -ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, +ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, z_size_t len)); /* Same as crc32(), but with a size_t length. @@ -1755,6 +1758,20 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); 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 :) */ @@ -1842,6 +1859,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ 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) @@ -1852,6 +1870,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # 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 @@ -1859,6 +1878,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # 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 *)); @@ -1867,6 +1887,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ 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 *)); @@ -1875,12 +1896,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ 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 */ @@ -1890,10 +1913,10 @@ 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 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(__CYGWIN__)) && !defined(Z_SOLO) +#if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif diff --git a/libraries/zlib/zutil.c b/libraries/zlib/zutil.c index a76c6b0c7..9543ae825 100644 --- a/libraries/zlib/zutil.c +++ b/libraries/zlib/zutil.c @@ -61,9 +61,11 @@ uLong ZEXPORT zlibCompileFlags() #ifdef ZLIB_DEBUG flags += 1 << 8; #endif + /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif + */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif @@ -119,7 +121,7 @@ uLong ZEXPORT zlibCompileFlags() # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error (m) +void ZLIB_INTERNAL z_error(m) char *m; { fprintf(stderr, "%s\n", m); @@ -136,8 +138,8 @@ const char * ZEXPORT zError(err) return ERR_MSG(err); } -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have +#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. */ @@ -214,7 +216,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; @@ -240,7 +242,7 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; @@ -277,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +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 ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); @@ -302,7 +304,7 @@ extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) +voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) voidpf opaque; unsigned items; unsigned size; @@ -312,7 +314,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree (opaque, ptr) +void ZLIB_INTERNAL zcfree(opaque, ptr) voidpf opaque; voidpf ptr; { diff --git a/libraries/zlib/zutil.h b/libraries/zlib/zutil.h index b079ea6a8..0bc7f4ecd 100644 --- a/libraries/zlib/zutil.h +++ b/libraries/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -29,10 +29,6 @@ # include #endif -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#endif - #ifndef local # define local static #endif @@ -46,6 +42,17 @@ 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++) */ @@ -170,10 +177,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif # else # define fdopen(fd,type) _fdopen(fd,type) # endif @@ -190,6 +193,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ (!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 */ diff --git a/options.checklist b/options.checklist new file mode 100644 index 000000000..c2cfa95e2 --- /dev/null +++ b/options.checklist @@ -0,0 +1,34 @@ +N/A weapon_recoil Firing a weapon pushes the player back +---N/A (todo, lastenemy?) monsters_remember 1 Friendly monsters return to old target when losing current one +!LEVEL2_NOINFIGHTING monster_infighting 1 Monsters infight +LEVEL3_AVOIDMELEE monster_backing Ranged monsters will back away from close melee targets +COMPATF2_AVOID_HAZARDS monster_avoid_hazards 1 Monsters avoid hazards such as crushing ceilings +N/A monkeys Monsters can climb steep stairs +COMPATF_MBFMONSTERMOVE monster_friction 1 Monsters are affected by friction modifiers + help_friends Friendly monsters prefer targets of friends + player_helpers Number of dogs to spawn + friend_distance 128 Friendly monsters try to keep at least this distance apart +!LEVEL3_NOJUMPDOWN dog_jumping 1 Dogs can jump down from high ledges +N/A comp_telefrag Spawners only telefrag on Map 30 +COMPATF_DROPOFF comp_dropoff 01 Discourage / prevent enemies from walking off ledges (?) +COMPATF_CORPSEGIBS,BCOMPATF_VILEGHOSTS comp_vile Archviles can create ghosts +COMPATF_LIMITPAIN comp_pain Pain elementals don't spawn lost souls if there are over 20 +--- N/A (todo) comp_skull Lost souls can spawn past impassable lines +N/A comp_blazing Blazing doors have double sounds +COMPATF_NODOORLIGHT comp_doorlight Door lighting changes are abrupt +COMPATF_LIGHT,COMPATF_SHORTTEX (partial) comp_model Assorted physics quirks and bugs +N/A comp_god God mode is removed in sector 11 & ignored at 1000+ damage +N/A comp_falloff Don't pull monsters off ledges they are hanging off of +COMPATF2_FLOORMOVE comp_floors Assorted floor bugs +N/A comp_skymap Don't apply invulnerability palette to skies +---todo comp_pursuit 1 Monsters can infight immediately when alerted +N/A comp_doorstuck Monsters get stuck in door tracks +COMPATF2_STAYONLIFT comp_staylift Monsters don't prefer staying on lifts their target is on +N/A comp_zombie Dead players can activate things +COMPATF_STAIRINDEX comp_stairs Assorted stair bugs +N/A comp_infcheat ? +N/A comp_zerotags Allow tag zero actions +N/A comp_respawn Monsters not spawned at level start respawn at the origin +N/A comp_soul Buggy lost soul bouncing +COMPATF_CROSSDROPOFF comp_ledgeblock 10 Monsters are blocked by ledges (except when scrolling) +---todo comp_friendlyspawn 1 Spawned things inherit the friend attribute from the source \ No newline at end of file diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index cb3a6736f..8218feeb1 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -156,31 +156,40 @@ Note: All fields default to false unless mentioned otherwise. sidedef { - scalex_top = ; // X scale for upper texture, Default = 1.0. - scaley_top = ; // y scale for upper texture, Default = 1.0. - scalex_mid = ; // X scale for mid texture, Default = 1.0. - scaley_mid = ; // y scale for mid texture, Default = 1.0. - scalex_bottom = ; // X scale for lower texture, Default = 1.0. - scaley_bottom = ; // y scale for lower texture, Default = 1.0. - offsetx_top = ; // X offset for upper texture, Default = 0.0. - offsety_top = ; // y offset for upper texture, Default = 0.0. - offsetx_mid = ; // X offset for mid texture, Default = 0.0. - offsety_mid = ; // y offset for mid texture, Default = 0.0. - offsetx_bottom = ; // X offset for lower texture, Default = 0.0. - offsety_bottom = ; // y offset for lower texture, Default = 0.0. - // When global texture offsets are used they will - // be added on top of these values. - light = ; // This side's light level. Default is 0. - lightabsolute = ; // true = 'light' is an absolute value. Default is - // relative to the owning sector's light level. - lightfog = ; // true = This side's relative lighting is used even in - // foggy sectors. Default is to disable relative - // lighting in foggy sectors. - nofakecontrast = ; // Disables use of fake contrast on this sidedef. - smoothlighting = ; // Use smooth fake contrast. - clipmidtex = ; // Side's mid textures are clipped to floor and ceiling. - wrapmidtex = ; // Side's mid textures are wrapped. - nodecals = ; // Disables decals on the sidedef. + scalex_top = ; // X scale for upper texture, Default = 1.0. + scaley_top = ; // Y scale for upper texture, Default = 1.0. + scalex_mid = ; // X scale for mid texture, Default = 1.0. + scaley_mid = ; // Y scale for mid texture, Default = 1.0. + scalex_bottom = ; // X scale for lower texture, Default = 1.0. + scaley_bottom = ; // Y scale for lower texture, Default = 1.0. + offsetx_top = ; // X offset for upper texture, Default = 0.0. + offsety_top = ; // Y offset for upper texture, Default = 0.0. + offsetx_mid = ; // X offset for mid texture, Default = 0.0. + offsety_mid = ; // Y offset for mid texture, Default = 0.0. + offsetx_bottom = ; // X offset for lower texture, Default = 0.0. + offsety_bottom = ; // Y offset for lower texture, Default = 0.0. + // When global texture offsets are used they will + // be added on top of these values. + light = ; // This side's light level. Default is 0. + lightabsolute = ; // true = 'light' is an absolute value. Default is + // relative to the owning sector's light level. + light_top = ; // This side's top tier light level. Default is 0. + lightabsolute_top = ; // true = 'light_top' is an absolute value. Default is + // relative to the sidedef's resulting light level. + light_mid = ; // This side's mid tier light level. Default is 0. + lightabsolute_mid = ; // true = 'light_mid' is an absolute value. Default is + // relative to the sidedef's resulting light level. + light_bottom = ; // This side's bottom tier light level. Default is 0. + lightabsolute_bottom = ; // true = 'light_bottom' is an absolute value. Default is + // relative to the sidedef's resulting light level. + lightfog = ; // true = This side's relative lighting is used even in + // foggy sectors. Default is to disable relative + // lighting in foggy sectors. + nofakecontrast = ; // Disables use of fake contrast on this sidedef. + smoothlighting = ; // Use smooth fake contrast. + clipmidtex = ; // Side's mid textures are clipped to floor and ceiling. + wrapmidtex = ; // Side's mid textures are wrapped. + nodecals = ; // Disables decals on the sidedef. nogradient_top = ; // disables color gradient on upper tier. (Hardware rendering only.) flipgradient_top = ; // flips gradient colors on upper tier. (Hardware rendering only.) @@ -202,9 +211,6 @@ Note: All fields default to false unless mentioned otherwise. useowncolors_bottom = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. uppercolor_bottom = ; // Material color of the top of the lower tier. lowercolor_bottom = ; // Material color of the bottom of the lower tier. (Hardware rendering only.) - colorscalefactor_top = // scales the material color by the given factor. Default is 1. - colorscalefactor_mid = // scales the material color by the given factor. Default is 1. - colorscalefactor_bottom = // scales the material color by the given factor. Default is 1. useowncoloradd_top = ; // Controls where the advanced colorization properties are taken from. useowncoloradd_mid = ; // 0: From the containing sector, 1: from the given part of the linedef itself @@ -510,6 +516,9 @@ Coloriation options added 1.32 28.06.2021 Blocklandmonsters MBF21 flag +1.33 06.11.2021 +Added separate light levels for sidedef tiers (top/mid/bottom) + =============================================================================== EOF =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b5213d46..15aea2823 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,30 +14,7 @@ include( CheckIncludeFiles ) include( CheckLibraryExists ) include( FindPkgConfig ) -if( MSVC ) - find_package( ZMusic ) -else() - find_package( ZMusic REQUIRED ) -endif() - -message("Building for target architecture: ${ZDOOM_TARGET_ARCH}") - -if( MSVC AND NOT ZMUSIC_FOUND ) - # Use prebuilt library - set( ZMUSIC_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/windows/zmusic" ) - set( ZMUSIC_INCLUDE_DIR ${ZMUSIC_ROOT_PATH}/include ) - set( ZMUSIC_LIBRARIES zmusic ) - if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" ) - link_directories( ${ZMUSIC_ROOT_PATH}/64bit ) - elseif( ${ZDOOM_TARGET_ARCH} MATCHES "arm" ) - link_directories( ${ZMUSIC_ROOT_PATH}/arm64 ) - else() - link_directories( ${ZMUSIC_ROOT_PATH}/32bit ) - endif() - set( ZMUSIC_FOUND TRUE ) -endif() - -if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) option( NO_STRIP "Do not strip Release or MinSizeRel builds" ) # At least some versions of Xcode fail if you strip with the linker # instead of the separate strip utility. @@ -50,60 +27,38 @@ if( APPLE ) option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON ) endif() -if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" ) - set( X64 64 ) +option( ZDOOM_ENABLE_SWR "Enable software renderer" ON ) +if( NOT ZDOOM_ENABLE_SWR ) + add_definitions( -DNO_SWRENDERER ) endif() -if( X64 OR ${ZDOOM_TARGET_ARCH} MATCHES "i386" ) +target_architecture(TARGET_ARCHITECTURE) +message(STATUS "Architecture is ${TARGET_ARCHITECTURE}") + +if ( ${TARGET_ARCHITECTURE} MATCHES "arm64" ) + set (ARM64 aarch64) +endif() + +# Right now only 64 bit is supported. +if( ${TARGET_ARCHITECTURE} MATCHES "x86_64" ) + set( X64 64 ) add_definitions( -DARCH_IA32 ) endif() -if( NOT ZDOOM_LIBS ) - set( ZDOOM_LIBS "" ) +if( NOT PROJECT_LIBRARIES ) + set( PROJECT_LIBRARIES "" ) endif() +add_definitions( -DTHIS_IS_GZDOOM ) + if( WIN32 ) - if( X64 ) - set( WIN_TYPE Win64 ) - set( XBITS x64 ) - else() - set( WIN_TYPE Win32 ) - set( XBITS x86 ) - endif() add_definitions( -D_WIN32 ) - - if( MSVC ) # For VS 2017 and later. - # for modern Windows SDKs the DirectX headers should be available by default. - set( DX_dinput8_LIBRARY dinput8 ) - else() - - find_library( DX_dinput8_LIBRARY dinput8 - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) - find_library( DX_dxguid_LIBRARY dxguid - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) - - # Modern versions of the Windows SDK include dinput8.lib. Unfortunately, - # CMake cannot find these libraries via find_library. - if( NOT DX_dinput8_LIBRARY ) - # If we got this far, assume dinput8.lib is in the system library path. - set( DX_dinput8_LIBRARY dinput8 ) - endif() - - # Modern versions of the Windows SDK do NOT include dxguid.lib. Its contents - # were moved to dinput8.lib. - if( NOT DX_dxguid_LIBRARY ) - message( STATUS "Could not find dxguid.lib. Build may fail on old Windows SDKs.") - endif() - endif() - - set( ZDOOM_LIBS + set( PROJECT_LIBRARIES wsock32 winmm - "${DX_dinput8_LIBRARY}" + dinput8 ole32 user32 gdi32 @@ -112,17 +67,13 @@ if( WIN32 ) ws2_32 setupapi oleaut32 - dbghelp ) + dbghelp + legacy_stdio_definitions ) - if( NOT ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} DelayImp ) - endif() - - if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) + if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( DX_dxguid_LIBRARY ) - list( APPEND ZDOOM_LIBS "${DX_dxguid_LIBRARY}" ) + list( APPEND PROJECT_LIBRARIES "${DX_dxguid_LIBRARY}" ) endif() - list( APPEND ZDOOM_LIBS d3d9 ) endif() else() if( APPLE ) @@ -143,7 +94,7 @@ else() pkg_check_modules( GTK3 gtk+-3.0 ) if( GTK3_FOUND ) if( NOT DYN_GTK ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK3_LIBRARIES} ) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${GTK3_LIBRARIES} ) endif() include_directories( ${GTK3_INCLUDE_DIRS} ) link_directories( ${GTK3_LIBRARY_DIRS} ) @@ -151,7 +102,7 @@ else() pkg_check_modules( GTK2 gtk+-2.0 ) if( GTK2_FOUND ) if( NOT DYN_GTK ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} ) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${GTK2_LIBRARIES} ) endif() include_directories( ${GTK2_INCLUDE_DIRS} ) link_directories( ${GTK2_LIBRARY_DIRS} ) @@ -162,10 +113,12 @@ else() endif() endif() - option( NO_SDL_JOYSTICK "Disable SDL joystick support (Not applicable to Windows)" OFF ) - if ( NO_SDL_JOYSTICK ) - add_definitions( -DNO_SDL_JOYSTICK=1 ) - endif ( NO_SDL_JOYSTICK ) + if ( NOT WIN32 ) + option( NO_SDL_JOYSTICK "Disable SDL joystick support (Not applicable to Windows)" OFF ) + if ( NO_SDL_JOYSTICK ) + add_definitions( -DNO_SDL_JOYSTICK=1 ) + endif() + endif() if( NO_GTK ) add_definitions( -DNO_GTK ) @@ -179,14 +132,9 @@ else() if( NOT APPLE OR NOT OSX_COCOA_BACKEND ) find_package( SDL2 REQUIRED ) include_directories( "${SDL2_INCLUDE_DIR}" ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SDL2_LIBRARY}" ) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "${SDL2_LIBRARY}" ) endif() - find_path( FPU_CONTROL_DIR fpu_control.h ) - if( FPU_CONTROL_DIR ) - include_directories( ${FPU_CONTROL_DIR} ) - add_definitions( -DHAVE_FPU_CONTROL ) - endif() endif() if( NOT NO_OPENAL ) @@ -197,7 +145,7 @@ if( NOT NO_OPENAL ) include_directories( ${OPENAL_INCLUDE_DIR} ) mark_as_advanced(CLEAR OPENAL_LIBRARY) if( OPENAL_LIBRARY ) - set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} ) + set( PROJECT_LIBRARIES ${OPENAL_LIBRARY} ${PROJECT_LIBRARIES} ) else() set( NO_OPENAL ON ) endif() @@ -215,33 +163,8 @@ endif() # Decide on SSE setup -# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. -if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) - CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) - CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) - if( CAN_DO_MFPMATH ) - set( SSE1_ENABLE "-msse -mfpmath=sse" ) - set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) - elseif( CAN_DO_ARCHSSE2 ) - set( SSE1_ENABLE -arch:SSE ) - set( SSE2_ENABLE -arch:SSE2 ) - endif() -endif() - if( X64 ) set( HAVE_MMX 1 ) -else( X64 ) - set( SAFE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) - - if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmmx") - endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) - - CHECK_CXX_SOURCE_COMPILES("#include - int main(void) { __m64 v = _m_from_int(0); }" - HAVE_MMX) - - set( CMAKE_CXX_FLAGS ${SAFE_CMAKE_CXX_FLAGS} ) endif( X64 ) CHECK_CXX_SOURCE_COMPILES("#include @@ -261,7 +184,7 @@ endif (MSVC) # Set up flags for GCC -if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( PROFILE ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" ) set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" ) @@ -269,7 +192,6 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" ) endif() - #set( REL_CXX_FLAGS "-fno-rtti" ) if( NOT PROFILE AND NOT APPLE ) # On OS X frame pointers are required for exception handling, at least with Clang set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" ) @@ -361,16 +283,6 @@ endif() # Check for functions that may or may not exist. -CHECK_FUNCTION_EXISTS( filelength FILELENGTH_EXISTS ) -if( FILELENGTH_EXISTS ) - add_definitions( -DHAVE_FILELENGTH=1 ) -endif() - -CHECK_FUNCTION_EXISTS( strupr STRUPR_EXISTS ) -if( NOT STRUPR_EXISTS ) - add_definitions( -DNEED_STRUPR=1 ) -endif() - require_stricmp() require_strnicmp() @@ -387,7 +299,7 @@ if( UNIX ) add_definitions( -DNO_CLOCK_GETTIME ) endif() else() - set( ZDOOM_LIBS ${ZDOOM_LIBS} rt ) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} rt ) endif() endif() @@ -400,18 +312,75 @@ add_custom_target( revision_check ALL WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) -# Libraries ZDoom needs +# required libraries -set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${CMAKE_DL_LIBS}" ) +set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${CMAKE_DL_LIBS}" "${DRPC_LIBRARIES}") if (HAVE_VULKAN) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "glslang" "SPIRV" "OGLCompiler") + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "zvulkan") endif() -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" ) + +# ZMUSIC + +if( MSVC ) + find_package( ZMusic ) +else() + find_package( ZMusic REQUIRED ) +endif() + +message("Building for target architecture: ${TARGET_ARCHITECTURE}") + +if( MSVC AND NOT ZMUSIC_FOUND ) + # Use prebuilt library + set( ZMUSIC_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/windows/zmusic" ) + set( ZMUSIC_INCLUDE_DIR ${ZMUSIC_ROOT_PATH}/include ) + set( ZMUSIC_LIBRARIES zmusic ) + if( X64 ) + link_directories( ${ZMUSIC_ROOT_PATH}/64bit ) + elseif( ARM64 ) + link_directories( ${ZMUSIC_ROOT_PATH}/arm64 ) + else() + link_directories( ${ZMUSIC_ROOT_PATH}/32bit ) + endif() + set( ZMUSIC_FOUND TRUE ) +endif() + + +# VPX + +if( MSVC AND NOT VPX_FOUND ) + # Use prebuilt library + set( VPX_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/Windows/vpx" ) + set( VPX_INCLUDE_DIR ${VPX_ROOT_PATH}/include ) + set( VPX_LIBRARIES libvpx ) + if ( NOT ARM64 ) + set (VPX_LIBRARIES ${VPX_LIBRARIES} libcompat-to-msvc ) + endif() + if( ARM64 ) + link_directories( ${VPX_ROOT_PATH}/lib/arm64 ) + elseif( X64 ) + link_directories( ${VPX_ROOT_PATH}/lib/64 ) + else() + link_directories( ${VPX_ROOT_PATH}/lib/32 ) + # Workaround for "error LNK2026: module unsafe for SAFESEH image." + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO" ) + endif() + set( VPX_FOUND TRUE ) +endif() + +if( VPX_FOUND ) + add_definitions( "-DUSE_LIBVPX=1" ) + include_directories( "${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}") if( ${HAVE_VM_JIT} ) add_definitions( -DHAVE_VM_JIT ) include_directories( "${ASMJIT_INCLUDE_DIR}" ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ASMJIT_LIBRARIES}") + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} "${ASMJIT_LIBRARIES}") endif() # Start defining source files for ZDoom @@ -425,15 +394,15 @@ set( PLAT_WIN32_SOURCES common/platform/win32/i_rawps2.cpp common/platform/win32/i_xinput.cpp common/platform/win32/i_main.cpp + common/platform/win32/i_mainwindow.cpp common/platform/win32/i_system.cpp common/platform/win32/i_specialpaths.cpp common/platform/win32/st_start.cpp - common/platform/win32/st_start_util.cpp common/platform/win32/gl_sysfb.cpp common/platform/win32/base_sysfb.cpp common/platform/win32/win32basevideo.cpp common/platform/win32/win32glvideo.cpp - common/platform/win32/win32polyvideo.cpp) + ) if (HAVE_VULKAN) set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/win32vulkanvideo.cpp ) @@ -441,10 +410,10 @@ endif() # todo: implement an actual crash catcher for ARM # for now this is purely experimental -if (NOT ${ZDOOM_TARGET_ARCH} MATCHES "arm" ) +if (NOT ${TARGET_ARCHITECTURE} MATCHES "arm" ) set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/i_crash.cpp ) endif() -if (MSVC AND ${ZDOOM_TARGET_ARCH} MATCHES "arm") +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() @@ -501,9 +470,15 @@ elseif( APPLE ) set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) set_source_files_properties( common/platform/posix/osx/iwadpicker_cocoa.mm PROPERTIES COMPILE_FLAGS -fobjc-exceptions ) else() + option (SYSTEMINSTALL "Set global progdir based on CMake Install Dir" OFF) + set( SYSTEM_SOURCES_DIR common/platform/posix common/platform/posix/sdl ) set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_UNIX_SOURCES} ) set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} ) + + if ( SYSTEMINSTALL ) + add_definitions( -DPROGDIR="${CMAKE_INSTALL_PREFIX}/${INSTALL_PK3_PATH}" ) + endif() endif() if( HAVE_MMX ) @@ -515,14 +490,14 @@ if( HAVE_MMX ) common/textures/hires/hqnx_asm/hq4x_asm.cpp common/textures/hires/hqnx_asm/hqnx_asm_Image.cpp) - if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) + if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set_source_files_properties( common/textures/hires/hqnx_asm/hq2x_asm.cpp common/textures/hires/hqnx_asm/hq3x_asm.cpp common/textures/hires/hqnx_asm/hq4x_asm.cpp common/textures/hires/hqresize.cpp PROPERTIES COMPILE_FLAGS "-mmmx" ) - endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) + endif( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif( HAVE_MMX ) if( HAVE_PARALLEL_FOR ) @@ -587,6 +562,7 @@ file( GLOB HEADER_FILES common/audio/music/*.h* common/2d/*.h common/console/*.h + common/cutscenes/*.h common/utility/*.h common/engine/*.h common/menu/*.h @@ -599,20 +575,18 @@ file( GLOB HEADER_FILES common/platform/win32/*.h common/models/*.h common/textures/*.h + common/startscreen/*.h common/textures/hires/hqnx/*.h common/textures/hires/hqnx_asm/*.h common/textures/hires/xbr/*.h common/thirdparty/*.h common/thirdparty/rapidjson/*.h common/thirdparty/math/*h + common/thirdparty/libsmackerdec/include/*.h common/rendering/*.h common/rendering/gl_load/*.h common/rendering/gles/*.h common/rendering/hwrenderer/data/*.h - common/rendering/polyrenderer/*.h - common/rendering/polyrenderer/math/*.h - common/rendering/polyrenderer/drawers/*.h - common/rendering/polyrenderer/backend/*.h common/rendering/vulkan/*.h common/rendering/vulkan/system/*.h common/rendering/vulkan/renderer/*.h @@ -624,6 +598,7 @@ file( GLOB HEADER_FILES common/scripting/interface/*.h common/scripting/backend/*.h common/scripting/frontend/*.h + utility/*.h scripting/*.h scripting/backend/*.h @@ -682,7 +657,6 @@ set ( SWRENDER_SOURCES rendering/swrenderer/things/r_sprite.cpp rendering/swrenderer/things/r_wallsprite.cpp rendering/swrenderer/things/r_decal.cpp - rendering/swrenderer/things/r_model.cpp rendering/swrenderer/plane/r_visibleplane.cpp rendering/swrenderer/plane/r_visibleplanelist.cpp rendering/swrenderer/plane/r_skyplane.cpp @@ -691,21 +665,11 @@ set ( SWRENDER_SOURCES rendering/swrenderer/plane/r_slopeplane.cpp ) -set( POLYRENDER_SOURCES - common/rendering/polyrenderer/drawers/poly_triangle.cpp - common/rendering/polyrenderer/drawers/poly_thread.cpp - common/rendering/polyrenderer/drawers/screen_triangle.cpp - common/rendering/polyrenderer/drawers/screen_scanline_setup.cpp - common/rendering/polyrenderer/drawers/screen_shader.cpp - common/rendering/polyrenderer/drawers/screen_blend.cpp -) - # These files will be flagged as "headers" so that they appear in project files # without being compiled. set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} ${SWRENDER_SOURCES} - ${POLYRENDER_SOURCES} sc_man_scanner.h common/engine/sc_man_scanner.re g_statusbar/sbarinfo_commands.cpp @@ -716,7 +680,6 @@ set( NOT_COMPILED_SOURCE_FILES zcc-parse.c zcc-parse.h common/platform/win32/zutil.natvis - common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.natvis ) set( VM_JIT_SOURCES @@ -738,7 +701,6 @@ set( VM_JIT_SOURCES set( FASTMATH_SOURCES rendering/swrenderer/r_all.cpp rendering/swrenderer/r_swscene.cpp - common/rendering/polyrenderer/poly_all.cpp common/textures/hires/hqnx/init.cpp common/textures/hires/hqnx/hq2x.cpp common/textures/hires/hqnx/hq3x.cpp @@ -768,22 +730,26 @@ set( FASTMATH_SOURCES #Vulkan stuff must go into a separate list because it needs to be disabled for some platforms set (VULKAN_SOURCES - common/rendering/vulkan/system/vk_device.cpp - common/rendering/vulkan/system/vk_swapchain.cpp - common/rendering/vulkan/system/vk_builders.cpp - common/rendering/vulkan/system/vk_framebuffer.cpp - common/rendering/vulkan/system/vk_buffers.cpp + common/rendering/vulkan/system/vk_renderdevice.cpp + common/rendering/vulkan/system/vk_commandbuffer.cpp + common/rendering/vulkan/system/vk_hwbuffer.cpp + common/rendering/vulkan/system/vk_buffer.cpp common/rendering/vulkan/renderer/vk_renderstate.cpp common/rendering/vulkan/renderer/vk_renderpass.cpp common/rendering/vulkan/renderer/vk_streambuffer.cpp common/rendering/vulkan/renderer/vk_postprocess.cpp - common/rendering/vulkan/renderer/vk_renderbuffers.cpp + common/rendering/vulkan/renderer/vk_pprenderstate.cpp + common/rendering/vulkan/renderer/vk_descriptorset.cpp + common/rendering/vulkan/renderer/vk_raytrace.cpp common/rendering/vulkan/shaders/vk_shader.cpp + common/rendering/vulkan/shaders/vk_ppshader.cpp common/rendering/vulkan/textures/vk_samplers.cpp common/rendering/vulkan/textures/vk_hwtexture.cpp + common/rendering/vulkan/textures/vk_pptexture.cpp common/rendering/vulkan/textures/vk_imagetransition.cpp - common/rendering/vulkan/thirdparty/volk/volk.c - common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp + common/rendering/vulkan/textures/vk_renderbuffers.cpp + common/rendering/vulkan/textures/vk_texture.cpp + common/rendering/vulkan/textures/vk_framebuffer.cpp ) if (HAVE_GLES2) @@ -810,15 +776,10 @@ if (HAVE_VULKAN) set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES}) endif() -set (POLYBACKEND_SOURCES - common/rendering/polyrenderer/backend/poly_framebuffer.cpp - common/rendering/polyrenderer/backend/poly_buffers.cpp - common/rendering/polyrenderer/backend/poly_hwtexture.cpp - common/rendering/polyrenderer/backend/poly_renderstate.cpp -) -set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${POLYBACKEND_SOURCES}) +set (FASTMATH_SOURCES ${FASTMATH_SOURCES}) set (PCH_SOURCES + common/thirdparty/richpresence.cpp am_map.cpp playsim/bots/b_bot.cpp playsim/bots/b_func.cpp @@ -844,7 +805,6 @@ set (PCH_SOURCES g_hub.cpp g_level.cpp gameconfigfile.cpp - gitinfo.cpp hu_scores.cpp m_cheat.cpp m_misc.cpp @@ -907,6 +867,7 @@ set (PCH_SOURCES 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 @@ -931,13 +892,12 @@ set (PCH_SOURCES g_statusbar/sbarinfo.cpp g_statusbar/sbar_mugshot.cpp g_statusbar/shared_sbar.cpp - rendering/2d/f_wipe.cpp rendering/2d/v_blend.cpp rendering/hwrenderer/hw_entrypoint.cpp rendering/hwrenderer/hw_vertexbuilder.cpp rendering/hwrenderer/doom_aabbtree.cpp + rendering/hwrenderer/doom_levelmesh.cpp rendering/hwrenderer/hw_models.cpp - rendering/hwrenderer/hw_postprocessshader.cpp rendering/hwrenderer/hw_precache.cpp rendering/hwrenderer/scene/hw_lighting.cpp rendering/hwrenderer/scene/hw_drawlistadd.cpp @@ -1015,8 +975,15 @@ set (PCH_SOURCES common/2d/v_2ddrawer.cpp common/2d/v_drawtext.cpp common/2d/v_draw.cpp + common/2d/wipe.cpp common/thirdparty/gain_analysis.cpp common/thirdparty/sfmt/SFMT.cpp + common/startscreen/startscreen.cpp + common/startscreen/startscreen_heretic.cpp + common/startscreen/startscreen_hexen.cpp + common/startscreen/startscreen_strife.cpp + common/startscreen/startscreen_generic.cpp + common/startscreen/endoom.cpp common/fonts/singlelumpfont.cpp common/fonts/singlepicfont.cpp common/fonts/specialfont.cpp @@ -1052,17 +1019,20 @@ set (PCH_SOURCES common/textures/formats/pcxtexture.cpp common/textures/formats/pngtexture.cpp common/textures/formats/rawpagetexture.cpp + common/textures/formats/startuptexture.cpp common/textures/formats/emptytexture.cpp common/textures/formats/shadertexture.cpp common/textures/formats/tgatexture.cpp common/textures/formats/stbtexture.cpp common/textures/formats/anmtexture.cpp + common/textures/formats/startscreentexture.cpp common/textures/hires/hqresize.cpp common/models/models_md3.cpp common/models/models_md2.cpp common/models/models_voxel.cpp common/models/models_ue1.cpp common/models/models_obj.cpp + common/models/models_iqm.cpp common/models/model.cpp common/models/voxels.cpp common/console/c_commandline.cpp @@ -1077,8 +1047,12 @@ set (PCH_SOURCES common/console/c_notifybufferbase.cpp common/console/c_tabcomplete.cpp common/console/c_expr.cpp + common/cutscenes/playmve.cpp + common/cutscenes/movieplayer.cpp + common/cutscenes/screenjob.cpp common/utility/engineerrors.cpp common/utility/i_module.cpp + common/utility/gitinfo.cpp common/utility/m_alloc.cpp common/utility/utf8.cpp common/utility/palette.cpp @@ -1096,6 +1070,11 @@ set (PCH_SOURCES common/thirdparty/base64.cpp common/thirdparty/md5.cpp common/thirdparty/superfasthash.cpp + common/thirdparty/libsmackerdec/src/BitReader.cpp + common/thirdparty/libsmackerdec/src/FileStream.cpp + 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 @@ -1149,11 +1128,14 @@ set (PCH_SOURCES common/rendering/hwrenderer/data/hw_cvars.cpp common/rendering/hwrenderer/data/hw_vrmodes.cpp common/rendering/hwrenderer/data/hw_lightbuffer.cpp + common/rendering/hwrenderer/data/hw_bonebuffer.cpp common/rendering/hwrenderer/data/hw_aabbtree.cpp common/rendering/hwrenderer/data/hw_shadowmap.cpp common/rendering/hwrenderer/data/hw_shaderpatcher.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp common/rendering/hwrenderer/postprocessing/hw_postprocess_cvars.cpp + common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp common/rendering/gl_load/gl_interface.cpp common/rendering/gl/gl_renderer.cpp common/rendering/gl/gl_stereo3d.cpp @@ -1168,6 +1150,7 @@ set (PCH_SOURCES common/rendering/gl/gl_samplers.cpp common/rendering/gl/gl_shader.cpp common/rendering/gl/gl_shaderprogram.cpp + common/scripting/core/maps.cpp common/scripting/core/dictionary.cpp common/scripting/core/dynarrays.cpp common/scripting/core/symbols.cpp @@ -1244,22 +1227,24 @@ set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") # [BL] Solaris requires these to be explicitly linked. - set( ZDOOM_LIBS ${ZDOOM_LIBS} nsl socket) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} nsl socket) endif() if( UNIX ) find_package( Backtrace ) if(Backtrace_FOUND) - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${Backtrace_LIBRARIES} ) + set( PROJECT_LIBRARIES ${PROJECT_LIBRARIES} ${Backtrace_LIBRARIES} ) endif() endif() -target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa lzma ${ZMUSIC_LIBRARIES} ) +target_link_libraries( zdoom ${PROJECT_LIBRARIES} gdtoa lzma ${ZMUSIC_LIBRARIES} ) include_directories( . common/audio/sound common/audio/music common/2d + common/cutscenes + common/thirdparty/libsmackerdec/include common/thirdparty common/textures common/textures/formats @@ -1274,6 +1259,7 @@ include_directories( . common/statusbar common/fonts common/objects + common/startscreen common/rendering common/rendering/hwrenderer/data common/rendering/gl_load @@ -1281,9 +1267,6 @@ include_directories( . common/rendering/gles common/rendering/gles/glad/include common/rendering/gles/Mali_OpenGL_ES_Emulator/include - common/rendering/vulkan/thirdparty - common/rendering/polyrenderer/backend - common/rendering/polyrenderer/drawers common/scripting/vm common/scripting/jit common/scripting/core @@ -1312,8 +1295,7 @@ include_directories( . scripting/zscript rendering ../libraries/gdtoa - ../libraries/glslang/glslang/Public - ../libraries/glslang/spirv + ../libraries/ZVulkan/include ${CMAKE_BINARY_DIR}/libraries/gdtoa ${SYSTEM_SOURCES_DIR} ) @@ -1359,7 +1341,14 @@ if( NOT WIN32 AND NOT APPLE ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) add_custom_command( TARGET zdoom POST_BUILD COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make - COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/link-make ) + IF ("${INSTALL_RPATH}" STREQUAL "") + set_target_properties(zdoom PROPERTIES + #allow libzmusic.so.1 library in same folder as executable at runtime + INSTALL_RPATH "\$ORIGIN" + BUILD_WITH_INSTALL_RPATH ON + ) + endif() endif() add_custom_command(TARGET zdoom POST_BUILD @@ -1380,20 +1369,13 @@ install(DIRECTORY "${PROJECT_BINARY_DIR}/soundfonts" "${PROJECT_BINARY_DIR}/fm_b DESTINATION ${INSTALL_SOUNDFONT_PATH} COMPONENT "Soundfont resources") -if( CMAKE_COMPILER_IS_GNUCXX ) - # GCC misoptimizes this file - set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) -endif() -if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) +if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) # Need to enable intrinsics for these files. - if( SSE_MATTERS ) - set_property( SOURCE - common/rendering/polyrenderer/poly_all.cpp - rendering/swrenderer/r_all.cpp - utility/palette.cpp - utility/x86.cpp - APPEND_STRING PROPERTY COMPILE_FLAGS " -msse2 -mmmx" ) - endif() + set_property( SOURCE + common/utility/palette.cpp + common/utility/x86.cpp + rendering/swrenderer/r_all.cpp + APPEND_STRING PROPERTY COMPILE_FLAGS " ${SSE2_ENABLE}" ) endif() if( APPLE ) @@ -1463,6 +1445,7 @@ source_group("Common\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/ source_group("Common\\Utility" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/utility/.+") source_group("Common\\Engine" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/engine/.+") source_group("Common\\2D" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/2d/.+") +source_group("Common\\Cutscenes" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/cutscenes/.+") source_group("Common\\Objects" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/objects/.+") source_group("Common\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+") source_group("Common\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") @@ -1490,12 +1473,6 @@ source_group("Common\\Rendering\\Vulkan Renderer\\System" REGULAR_EXPRESSION "^$ source_group("Common\\Rendering\\Vulkan Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/renderer/.+") 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\\Third Party" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/thirdparty/.+") -source_group("Common\\Rendering\\Vulkan Renderer\\Third Party\\Volk" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/thirdparty/volk/.+") -source_group("Common\\Rendering\\Vulkan Renderer\\Third Party\\Vk_Mem_Alloc" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/thirdparty/vk_mem_alloc.+") -source_group("Common\\Rendering\\Poly Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/polyrenderer/.+") -source_group("Common\\Rendering\\Poly Renderer\\Drawers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/polyrenderer/drawers/.+") -source_group("Common\\Rendering\\Poly Renderer\\Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/polyrenderer/backend/.+") 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/.+") @@ -1509,6 +1486,9 @@ source_group("Common\\Third Party\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRE source_group("Common\\Third Party\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/thirdparty/sfmt/.+") 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("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) diff --git a/src/am_map.cpp b/src/am_map.cpp index 148648ae8..dd3d93423 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -29,7 +29,7 @@ #include #include "doomdef.h" -#include "templates.h" + #include "g_level.h" #include "st_stuff.h" #include "p_local.h" @@ -133,6 +133,7 @@ struct islope_t CVAR(Bool, am_textured, false, CVAR_ARCHIVE) CVAR(Float, am_linealpha, 1.0f, CVAR_ARCHIVE) CVAR(Int, am_linethickness, 1, CVAR_ARCHIVE) +CVAR(Int, am_lineantialiasing, 0, CVAR_ARCHIVE) CVAR(Bool, am_thingrenderstyles, true, CVAR_ARCHIVE) CVAR(Int, am_showsubsector, -1, 0); @@ -196,7 +197,7 @@ CUSTOM_CVAR(Int, am_emptyspacemargin, 0, CVAR_ARCHIVE) CVAR(Bool, am_followplayer, true, CVAR_ARCHIVE) CVAR(Bool, am_portaloverlay, true, CVAR_ARCHIVE) CVAR(Bool, am_showgrid, false, CVAR_ARCHIVE) -CVAR(Float, am_zoomdir, 0, CVAR_ARCHIVE) +CVAR(Float, am_zoomdir, 0.f, CVAR_ARCHIVE) static const char *const DEFAULT_FONT_NAME = "AMMNUMx"; CVAR(String, am_markfont, DEFAULT_FONT_NAME, CVAR_ARCHIVE) @@ -421,11 +422,11 @@ struct AMColorset bool forcebackground; bool defined; // only for mod specific colorsets: must be true to be usable - void initFromCVars(FColorCVar **values) + void initFromCVars(FColorCVarRef **values) { for(int i=0;iget())); } uint32_t ba = *(values[0]); @@ -513,7 +514,7 @@ static const int AUTOMAP_LINE_COLORS[AMLS_COUNT] = // //============================================================================= -static FColorCVar *cv_standard[] = { +static FColorCVarRef *cv_standard[] = { &am_backcolor, &am_yourcolor, &am_wallcolor, @@ -540,7 +541,7 @@ static FColorCVar *cv_standard[] = { &am_portalcolor }; -static FColorCVar *cv_overlay[] = { +static FColorCVarRef *cv_overlay[] = { &am_backcolor, // this will not be used in overlay mode &am_ovyourcolor, &am_ovwallcolor, @@ -571,11 +572,11 @@ CCMD(am_restorecolors) { for (unsigned i = 0; i < countof(cv_standard); i++) { - cv_standard[i]->ResetToDefault(); + cv_standard[i]->get()->ResetToDefault(); } for (unsigned i = 0; i < countof(cv_overlay); i++) { - cv_overlay[i]->ResetToDefault(); + cv_overlay[i]->get()->ResetToDefault(); } } @@ -1284,7 +1285,7 @@ void DAutomap::changeWindowLoc () oincy = incy = m_paninc.y * twod->GetHeight() / 200; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - rotate(&incx, &incy, players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - 90.); + rotate(&incx, &incy, players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - DAngle::fromDeg(90.)); } m_x += incx; @@ -1525,7 +1526,7 @@ void DAutomap::doFollowPlayer () sy = (f_oldloc.y - ampos.Y); if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - rotate(&sx, &sy, cam->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - 90); + rotate(&sx, &sy, cam->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - DAngle::fromDeg(90)); } ScrollParchment(sx, sy); @@ -1741,11 +1742,63 @@ void DAutomap::drawMline (mline_t *ml, const AMColor &color) const int y1 = f_y + fl.a.y; const int x2 = f_x + fl.b.x; const int y2 = f_y + fl.b.y; - if (am_linethickness >= 2) { - twod->AddThickLine(x1, y1, x2, y2, am_linethickness, color.RGB, uint8_t(am_linealpha * 255)); + + if (am_lineantialiasing) { + // Draw 5 lines (am_linethickness 2) or 9 lines (am_linethickness >= 3) + // slightly offset from each other, but with lower opacity + // as a bruteforce way to achieve antialiased line drawing. + const int aa_alpha_divide = am_linethickness >= 3 ? 3 : 2; + + // Subtract to line thickness to compensate for the antialiasing making lines thicker. + const int aa_linethickness = max(1, am_linethickness - 2); + + if (aa_linethickness >= 2) { + // Top row. + twod->AddThickLine(DVector2(x1 - 1, y1 - 1), DVector2(x2 - 1, y2 - 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1 + 1, y1 - 1), DVector2(x2 + 1, y2 - 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1, y1 - 1), DVector2(x2, y2 - 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + + // Middle row. + twod->AddThickLine(DVector2(x1 - 1, y1), DVector2(x2 - 1, y2), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1 + 1, y1), DVector2(x2 + 1, y2), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1, y1), DVector2(x2, y2), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + + // Bottom row. + twod->AddThickLine(DVector2(x1 - 1, y1 + 1), DVector2(x2 - 1, y2 + 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1 + 1, y1 + 1), DVector2(x2 + 1, y2 + 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddThickLine(DVector2(x1, y1 - 1), DVector2(x2, y2 - 1), aa_linethickness, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + } else { + // Use more efficient thin line drawing routine. + // Top row. + if (am_linethickness >= 3) { + // If original line thickness is 2, do not add diagonal lines to allow thin lines to be represented. + // This part is not needed for thick antialiased drawing, as original line thickness is always greater than 3. + twod->AddLine(DVector2(x1 - 1, y1 - 1), DVector2(x2 - 1, y2 - 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddLine(DVector2(x1 + 1, y1 - 1), DVector2(x2 + 1, y2 - 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + } + twod->AddLine(DVector2(x1, y1 - 1), DVector2(x2, y2 - 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + + // Middle row. + twod->AddLine(DVector2(x1 - 1, y1), DVector2(x2 - 1, y2), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddLine(DVector2(x1 + 1, y1), DVector2(x2 + 1, y2), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddLine(DVector2(x1, y1), DVector2(x2, y2), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + + // Bottom row. + if (am_linethickness >= 3) { + // If original line thickness is 2, do not add diagonal lines to allow thin lines to be represented. + // This part is not needed for thick antialiased drawing, as original line thickness is always greater than 3. + twod->AddLine(DVector2(x1 - 1, y1 + 1), DVector2(x2 - 1, y2 + 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + twod->AddLine(DVector2(x1 + 1, y1 + 1), DVector2(x2 + 1, y2 + 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + } + twod->AddLine(DVector2(x1, y1 - 1), DVector2(x2, y2 - 1), nullptr, color.RGB, uint8_t(am_linealpha * 255 / aa_alpha_divide)); + } } else { - // Use more efficient thin line drawing routine. - twod->AddLine(x1, y1, x2, y2, -1, -1, INT_MAX, INT_MAX, color.RGB, uint8_t(am_linealpha * 255)); + if (am_linethickness >= 2) { + twod->AddThickLine(DVector2(x1, y1), DVector2(x2, y2), am_linethickness, color.RGB, uint8_t(am_linealpha * 255)); + } else { + // Use more efficient thin line drawing routine. + twod->AddLine(DVector2(x1, y1), DVector2(x2, y2), nullptr, color.RGB, uint8_t(am_linealpha * 255)); + } } } } @@ -2075,14 +2128,14 @@ void DAutomap::drawSubsectors() } // Apply the floor's rotation to the texture origin. - if (rotation != 0) + if (rotation != nullAngle) { rotate(&originpt.x, &originpt.y, rotation); } // Apply the automap's rotation to the texture origin. if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - rotation = rotation + 90. - players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw; + rotation = rotation + DAngle::fromDeg(90.) - players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw; rotatePoint(&originpt.x, &originpt.y); } originx = f_x + ((originpt.x - m_x) * scale); @@ -2646,7 +2699,7 @@ void DAutomap::drawWalls (bool allmap) void DAutomap::rotate(double *xp, double *yp, DAngle a) { - static DAngle angle_saved = 0.; + static DAngle angle_saved = nullAngle; static double sinrot = 0; static double cosrot = 1; @@ -2678,7 +2731,7 @@ void DAutomap::rotatePoint (double *x, double *y) double pivoty = m_y + m_h/2; *x -= pivotx; *y -= pivoty; - rotate (x, y, -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + 90.); + rotate (x, y, -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + DAngle::fromDeg(90.)); *x += pivotx; *y += pivoty; } @@ -2704,7 +2757,7 @@ void DAutomap::drawLineCharacter(const mline_t *lineguy, size_t lineguylines, do l.a.y *= scale; } - if (angle != 0) + if (angle != nullAngle) rotate(&l.a.x, &l.a.y, angle); l.a.x += x; @@ -2719,7 +2772,7 @@ void DAutomap::drawLineCharacter(const mline_t *lineguy, size_t lineguylines, do l.b.y *= scale; } - if (angle != 0) + if (angle != nullAngle) rotate(&l.b.x, &l.b.y, angle); l.b.x += x; @@ -2758,7 +2811,7 @@ void DAutomap::drawPlayers () pt.y = pos.Y; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - angle = 90.; + angle = DAngle::fromDeg(90.); rotatePoint (&pt.x, &pt.y); } else @@ -2826,7 +2879,7 @@ void DAutomap::drawPlayers () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { rotatePoint (&pt.x, &pt.y); - angle -= players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - 90.; + angle -= players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - DAngle::fromDeg(90.); } drawLineCharacter(&MapArrow[0], MapArrow.Size(), 0, angle, color, pt.x, pt.y); @@ -2860,7 +2913,7 @@ void DAutomap::drawKeys () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { rotatePoint (&p.x, &p.y); - angle += -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + 90.; + angle += -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + DAngle::fromDeg(90.); } if (key->flags & MF_SPECIAL) @@ -2872,7 +2925,7 @@ void DAutomap::drawKeys () if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); else color = AMColors[AMColors.ThingColor_CountItem]; - drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0., color, p.x, p.y); + drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, nullAngle, color, p.x, p.y); } } } @@ -2914,13 +2967,13 @@ void DAutomap::drawThings () const size_t spriteIndex = sprite.spriteframes + (show > 1 ? t->frame : 0); frame = &SpriteFrames[spriteIndex]; - DAngle angle = 270. + 22.5 - t->InterpolatedAngles(r_viewpoint.TicFrac).Yaw; - if (frame->Texture[0] != frame->Texture[1]) angle += 180. / 16; + DAngle angle = DAngle::fromDeg(270. + 22.5) - t->InterpolatedAngles(r_viewpoint.TicFrac).Yaw; + if (frame->Texture[0] != frame->Texture[1]) angle += DAngle::fromDeg(180. / 16); if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { - angle += players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - 90.; + angle += players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw - DAngle::fromDeg(90.); } - rotation = int((angle.Normalized360() * (16. / 360.)).Degrees); + rotation = int((angle.Normalized360() * (16. / 360.)).Degrees()); const FTextureID textureID = frame->Texture[show > 2 ? rotation : 0]; texture = TexMan.GetGameTexture(textureID, true); @@ -2944,7 +2997,7 @@ void DAutomap::drawThings () if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { rotatePoint (&p.x, &p.y); - angle += -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + 90.; + angle += -players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw + DAngle::fromDeg(90.); } color = AMColors[AMColors.ThingColor]; @@ -2974,7 +3027,7 @@ void DAutomap::drawThings () if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); else color = AMColors[AMColors.ThingColor_CountItem]; - drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0., color, p.x, p.y); + drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, nullAngle, color, p.x, p.y); color.RGB = 0; } else @@ -3025,6 +3078,11 @@ void DAutomap::DrawMarker (FGameTexture *tex, double x, double y, int yadjust, { return; } + if (xscale < 0) + { + flip = !flip; + xscale = -xscale; + } if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { rotatePoint (&x, &y); diff --git a/src/common/2d/v_2ddrawer.cpp b/src/common/2d/v_2ddrawer.cpp index 612eef005..4de396962 100644 --- a/src/common/2d/v_2ddrawer.cpp +++ b/src/common/2d/v_2ddrawer.cpp @@ -33,7 +33,7 @@ */ #include -#include "templates.h" + #include "v_2ddrawer.h" #include "vectors.h" #include "vm.h" @@ -41,14 +41,17 @@ #include "v_draw.h" #include "v_video.h" #include "fcolormap.h" +#include "texturemanager.h" -static F2DDrawer drawer; +static F2DDrawer drawer = F2DDrawer(); F2DDrawer* twod = &drawer; EXTERN_CVAR(Float, transsouls) CVAR(Float, classic_scaling_factor, 1.0, CVAR_ARCHIVE) CVAR(Float, classic_scaling_pixelaspect, 1.2f, CVAR_ARCHIVE) +IMPLEMENT_CLASS(FCanvas, false, false) + IMPLEMENT_CLASS(DShape2DTransform, false, false) static void Shape2DTransform_Clear(DShape2DTransform* self) @@ -104,17 +107,44 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Translate, Shape2DTransform_Tra return 0; } +static void Shape2DTransform_From2D( + DShape2DTransform* self, + double m00, double m01, double m10, double m11, double vx, double vy +) +{ + self->transform.Cells[0][0] = m00; + self->transform.Cells[0][1] = m01; + self->transform.Cells[1][0] = m10; + self->transform.Cells[1][1] = m11; + + self->transform.Cells[0][2] = vx; + self->transform.Cells[1][2] = vy; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, From2D, Shape2DTransform_From2D) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + PARAM_FLOAT(m00); + PARAM_FLOAT(m01); + PARAM_FLOAT(m10); + PARAM_FLOAT(m11); + PARAM_FLOAT(vx); + PARAM_FLOAT(vy); + Shape2DTransform_From2D(self, m00, m01, m10, m11, vx, vy); + return 0; +} + IMPLEMENT_CLASS(DShape2D, false, false) static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform) { - self->transform = transform->transform; + self->transform = PARAM_NULLCHECK(transform, transform)->transform; } DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, SetTransform, Shape2D_SetTransform) { PARAM_SELF_PROLOGUE(DShape2D); - PARAM_OBJECT(transform, DShape2DTransform); + PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); Shape2D_SetTransform(self, transform); return 0; } @@ -455,15 +485,26 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) // Note that this only works for unflipped and unrotated full textures. if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { - double wi = std::min(parms.windowright, parms.texwidth); + double wi = min(parms.windowright, parms.texwidth); x += parms.windowleft * xscale; w -= (parms.texwidth - wi + parms.windowleft) * xscale; u1 = float(u1 + parms.windowleft / parms.texwidth); u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth); } + auto t = this->transform; + auto tCorners = { + (t * DVector3(x, y, 1.0)).XY(), + (t * DVector3(x, y + h, 1.0)).XY(), + (t * DVector3(x + w, y, 1.0)).XY(), + (t * DVector3(x + w, y + h, 1.0)).XY() + }; + double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; + double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; + double miny = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y; + double maxy = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y; - if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip) + if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip) { dg.mScissor[0] = parms.lclip + int(offset.X); dg.mScissor[1] = parms.uclip + int(offset.Y); @@ -479,10 +520,10 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) dg.mVertCount = 4; dg.mVertIndex = (int)mVertices.Reserve(4); TwoDVertex* ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x, y, 0, u1, v1, vertexcolor); ptr++; - Set(ptr, x, y + h, 0, u1, v2, vertexcolor); ptr++; - Set(ptr, x + w, y, 0, u2, v1, vertexcolor); ptr++; - Set(ptr, x + w, y + h, 0, u2, v2, vertexcolor); ptr++; + ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++; } else { @@ -515,12 +556,16 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) dg.mVertCount = 4; dg.mVertIndex = (int)mVertices.Reserve(4); TwoDVertex* ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x1, y1, 0, u1, v1, vertexcolor); ptr++; - Set(ptr, x2, y2, 0, u1, v2, vertexcolor); ptr++; - Set(ptr, x3, y3, 0, u2, v1, vertexcolor); ptr++; - Set(ptr, x4, y4, 0, u2, v2, vertexcolor); ptr++; + ptr->Set(x1, y1, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x2, y2, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x3, y3, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x4, y4, 0, u2, v2, vertexcolor); ptr++; } + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -579,7 +624,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) shape->lastParms = new DrawParms(parms); } - if (!img->isHardwareCanvas() && parms.TranslationId != -1) + if (!(img != nullptr && img->isHardwareCanvas()) && parms.TranslationId != -1) dg.mTranslationId = parms.TranslationId; auto osave = offset; @@ -599,11 +644,12 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) if ( shape->mVertices[i].Y > shape->maxy ) shape->maxy = shape->mVertices[i].Y; } } + auto t = this->transform * shape->transform; auto tCorners = { - (shape->transform * DVector3(shape->minx, shape->miny, 1.0)).XY(), - (shape->transform * DVector3(shape->minx, shape->maxy, 1.0)).XY(), - (shape->transform * DVector3(shape->maxx, shape->miny, 1.0)).XY(), - (shape->transform * DVector3(shape->maxx, shape->maxy, 1.0)).XY() + (t * DVector3(shape->minx, shape->miny, 1.0)).XY(), + (t * DVector3(shape->minx, shape->maxy, 1.0)).XY(), + (t * DVector3(shape->maxx, shape->miny, 1.0)).XY(), + (t * DVector3(shape->maxx, shape->maxy, 1.0)).XY() }; double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; @@ -621,7 +667,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) memset(dg.mScissor, 0, sizeof(dg.mScissor)); dg.useTransform = true; - dg.transform = shape->transform; + dg.transform = t; dg.transform.Cells[0][2] += offset.X; dg.transform.Cells[1][2] += offset.Y; dg.shape2DBufInfo = shape->bufferInfo; @@ -693,7 +739,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, poly.mColor1.g = uint8_t(colormap.FadeColor.g * fadelevel); poly.mColor1.b = uint8_t(colormap.FadeColor.b * fadelevel); - bool dorotate = rotation != 0; + bool dorotate = rotation != nullAngle; float cosrot = (float)cos(rotation.Radians()); float sinrot = (float)sin(rotation.Radians()); @@ -715,7 +761,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, u = t * cosrot - v * sinrot; v = v * cosrot + t * sinrot; } - Set(&mVertices[poly.mVertIndex+i], points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0); + mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0); } poly.mIndexIndex = mIndices.Size(); @@ -736,6 +782,10 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, mIndices[addr + i] = poly.mVertIndex + indices[i]; } } + poly.useTransform = true; + poly.transform = this->transform; + poly.transform.Cells[0][2] += offset.X; + poly.transform.Cells[1][2] += offset.Y; AddCommand(&poly); } @@ -746,20 +796,19 @@ 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, int clipx1, int clipy1, int clipx2, int clipy2) +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) { RenderCommand dg; - int method = 0; if (!img || !img->isValid()) return; dg.mType = DrawTypeTriangles; - if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth() - 1 || clipy2 < GetHeight() - 1) + if (clip != nullptr) { - dg.mScissor[0] = clipx1 + int(offset.X); - dg.mScissor[1] = clipy1 + int(offset.Y); - dg.mScissor[2] = clipx2 + 1 + int(offset.X); - dg.mScissor[3] = clipy2 + 1 + int(offset.Y); + dg.mScissor[0] = clip->Left() + int(offset.X); + dg.mScissor[1] = clip->Top() + int(offset.Y); + dg.mScissor[2] = clip->Right() + int(offset.X); + dg.mScissor[3] = clip->Bottom() + int(offset.Y); dg.mFlags |= DTF_Scissor; } @@ -774,7 +823,7 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u for (size_t i=0;iSet(vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color); ptr++; } dg.mIndexIndex = mIndices.Size(); @@ -799,6 +848,10 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u dg.mIndexCount = (int)vtcount; } + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; AddCommand(&dg); } @@ -835,13 +888,13 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu dg.mFlags = DTF_Wrap; float fs = 1.f / float(flatscale); - bool flipc = false; float sw = GetClassicFlatScalarWidth(); float sh = GetClassicFlatScalarHeight(); switch (local_origin) { + default: case 0: fU1 = float(left) / (float)src->GetDisplayWidth() * fs; fV1 = float(top) / (float)src->GetDisplayHeight() * fs; @@ -917,18 +970,22 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu dg.mVertIndex = (int)mVertices.Reserve(4); auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, left, top, 0, fU1, fV1, color); ptr++; + ptr->Set(left, top, 0, fU1, fV1, color); ptr++; if (local_origin < 4) { - Set(ptr, left, bottom, 0, fU1, fV2, color); ptr++; - Set(ptr, right, top, 0, fU2, fV1, color); ptr++; + ptr->Set(left, bottom, 0, fU1, fV2, color); ptr++; + ptr->Set(right, top, 0, fU2, fV1, color); ptr++; } else { - Set(ptr, left, bottom, 0, fU2, fV1, color); ptr++; - Set(ptr, right, top, 0, fU1, fV2, color); ptr++; + ptr->Set(left, bottom, 0, fU2, fV1, color); ptr++; + ptr->Set(right, top, 0, fU1, fV2, color); ptr++; } - Set(ptr, right, bottom, 0, fU2, fV2, color); ptr++; + ptr->Set(right, bottom, 0, fU2, fV2, color); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -951,10 +1008,14 @@ void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, F dg.mVertIndex = (int)mVertices.Reserve(4); dg.mRenderStyle = style? *style : LegacyRenderStyles[STYLE_Translucent]; auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x1, y1, 0, 0, 0, color); ptr++; - Set(ptr, x1, y1 + h, 0, 0, 0, color); ptr++; - Set(ptr, x1 + w, y1, 0, 0, 0, color); ptr++; - Set(ptr, x1 + w, y1 + h, 0, 0, 0, color); ptr++; + ptr->Set(x1, y1, 0, 0, 0, color); ptr++; + ptr->Set(x1, y1 + h, 0, 0, 0, color); ptr++; + ptr->Set(x1 + w, y1, 0, 0, 0, color); ptr++; + ptr->Set(x1 + w, y1 + h, 0, 0, 0, color); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -979,28 +1040,32 @@ void F2DDrawer::ClearScreen(PalEntry color) // //========================================================================== -void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1, int clipy1, int clipx2, int clipy2, uint32_t color, uint8_t alpha) +void F2DDrawer::AddLine(const DVector2& v1, const DVector2& v2, const IntRect* clip, uint32_t color, uint8_t alpha) { PalEntry p = (PalEntry)color; p.a = alpha; RenderCommand dg; - if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth()- 1 || clipy2 < GetHeight() - 1) + if (clip != nullptr) { - dg.mScissor[0] = clipx1 + int(offset.X); - dg.mScissor[1] = clipy1 + int(offset.Y); - dg.mScissor[2] = clipx2 + 1 + int(offset.X); - dg.mScissor[3] = clipy2 + 1 + int(offset.Y); + dg.mScissor[0] = clip->Left() + int(offset.X); + dg.mScissor[1] = clip->Top() + int(offset.Y); + dg.mScissor[2] = clip->Right() + int(offset.X); + dg.mScissor[3] = clip->Bottom() + int(offset.Y); dg.mFlags |= DTF_Scissor; } - + dg.mType = DrawTypeLines; dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; dg.mVertCount = 2; dg.mVertIndex = (int)mVertices.Reserve(2); - Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p); - Set(&mVertices[dg.mVertIndex+1], x2, y2, 0, 0, 0, p); + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; + mVertices[dg.mVertIndex].Set(v1.X, v1.Y, 0, 0, 0, p); + mVertices[dg.mVertIndex+1].Set(v2.X, v2.Y, 0, 0, 0, p); AddCommand(&dg); } @@ -1010,23 +1075,20 @@ void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1, // //========================================================================== -void F2DDrawer::AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha) +void F2DDrawer::AddThickLine(const DVector2& v1, const DVector2& v2, double thickness, uint32_t color, uint8_t alpha) { PalEntry p = (PalEntry)color; p.a = alpha; - DVector2 point0(x1, y1); - DVector2 point1(x2, y2); - - DVector2 delta = point1 - point0; - DVector2 perp(-delta.Y, delta.X); + DVector2 delta = v2 - v1; + DVector2 perp = delta.Rotated90CCW(); perp.MakeUnit(); perp *= thickness / 2; - DVector2 corner0 = point0 + perp; - DVector2 corner1 = point0 - perp; - DVector2 corner2 = point1 + perp; - DVector2 corner3 = point1 - perp; + DVector2 corner0 = v1 + perp; + DVector2 corner1 = v1 - perp; + DVector2 corner2 = v2 + perp; + DVector2 corner3 = v2 - perp; RenderCommand dg; @@ -1035,10 +1097,14 @@ void F2DDrawer::AddThickLine(int x1, int y1, int x2, int y2, double thickness, u dg.mVertIndex = (int)mVertices.Reserve(4); dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, corner0.X, corner0.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner1.X, corner1.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner2.X, corner2.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner3.X, corner3.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner0.X, corner0.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner1.X, corner1.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner2.X, corner2.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner3.X, corner3.Y, 0, 0, 0, p); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -1062,7 +1128,60 @@ void F2DDrawer::AddPixel(int x1, int y1, uint32_t color) dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; dg.mVertCount = 1; dg.mVertIndex = (int)mVertices.Reserve(1); - Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p); + mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p); + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + +void F2DDrawer::AddEnableStencil(bool on) +{ + RenderCommand dg; + + dg.isSpecial = SpecialDrawCommand::EnableStencil; + dg.stencilOn = on; + + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + +void F2DDrawer::AddSetStencil(int offs, int op, int flags) +{ + RenderCommand dg; + + dg.isSpecial = SpecialDrawCommand::SetStencil; + dg.stencilOffs = offs; + dg.stencilOp = op; + dg.stencilFlags = flags; + + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + +void F2DDrawer::AddClearStencil() +{ + RenderCommand dg; + + dg.isSpecial = SpecialDrawCommand::ClearStencil; + AddCommand(&dg); } @@ -1107,3 +1226,48 @@ F2DVertexBuffer::F2DVertexBuffer() }; mVertexBuffer->SetFormat(1, 3, sizeof(F2DDrawer::TwoDVertex), format); } + +//========================================================================== +// +// +// +//========================================================================== + +TArray AllCanvases; + +class InitTextureCanvasGC +{ +public: + InitTextureCanvasGC() + { + GC::AddMarkerFunc([]() { + for (auto canvas : AllCanvases) + GC::Mark(canvas); + }); + } +}; + +FCanvas* GetTextureCanvas(const FString& texturename) +{ + FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + if (textureid.isValid()) + { + // Only proceed if the texture is a canvas texture. + auto tex = TexMan.GetGameTexture(textureid); + if (tex && tex->GetTexture()->isCanvas()) + { + FCanvasTexture* canvasTex = static_cast(tex->GetTexture()); + if (!canvasTex->Canvas) + { + static InitTextureCanvasGC initCanvasGC; // Does the common code have a natural init function this could be moved to? + + canvasTex->Canvas = Create(); + canvasTex->Canvas->Tex = canvasTex; + canvasTex->Canvas->Drawer.SetSize(tex->GetTexelWidth(), tex->GetTexelHeight()); + AllCanvases.Push(canvasTex->Canvas); + } + return canvasTex->Canvas; + } + } + return nullptr; +} diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index f662de7ac..7203ca3c1 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -11,6 +11,7 @@ struct DrawParms; struct FColormap; +struct IntRect; class DShape2DTransform : public DObject { @@ -52,9 +53,20 @@ struct F2DPolygons class DShape2D; struct DShape2DBufferInfo; +enum class SpecialDrawCommand { + NotSpecial, + + EnableStencil, + SetStencil, + ClearStencil, +}; + class F2DDrawer { public: + F2DDrawer() { + this->transform.Identity(); + } enum EDrawType : uint8_t { @@ -101,9 +113,17 @@ public: } }; - + struct RenderCommand { + SpecialDrawCommand isSpecial; + + bool stencilOn; + + int stencilOffs; + int stencilOp; + int stencilFlags; + EDrawType mType; int mVertIndex; int mVertCount; @@ -132,12 +152,16 @@ public: RenderCommand() { - memset(this, 0, sizeof(*this)); + memset((void*)this, 0, sizeof(*this)); } // If these fields match, two draw commands can be batched. bool isCompatible(const RenderCommand &other) const { + if ( + isSpecial != SpecialDrawCommand::NotSpecial || + other.isSpecial != SpecialDrawCommand::NotSpecial + ) return false; if (shape2DBufInfo != nullptr || other.shape2DBufInfo != nullptr) return false; return mTexture == other.mTexture && mType == other.mType && @@ -169,13 +193,14 @@ public: TArray mData; int Width, Height; bool isIn2D; - bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades) + 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; + DMatrix3x3 transform; public: int fullscreenautoaspect = 3; int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1; - + int AddCommand(RenderCommand *data); void AddIndices(int firstvert, int count, ...); private: @@ -191,7 +216,7 @@ public: 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, int clipx1, int clipy1, int clipx2, int clipy2); + 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, 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); @@ -200,12 +225,16 @@ public: void ClearScreen(PalEntry color = 0xff000000); void AddDim(PalEntry color, float damount, int x1, int y1, int w, int h); void AddClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); - - - void AddLine(double x1, double y1, double x2, double y2, int cx, int cy, int cx2, int cy2, uint32_t color, uint8_t alpha = 255); - void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255); + + + void AddLine(const DVector2& v1, const DVector2& v2, const IntRect* clip, uint32_t color, uint8_t alpha = 255); + void AddThickLine(const DVector2& v1, const DVector2& v2, double thickness, uint32_t color, uint8_t alpha = 255); void AddPixel(int x1, int y1, uint32_t color); + void AddEnableStencil(bool on); + void AddSetStencil(int offs, int op, int flags); + void AddClearStencil(); + void Clear(); void Lock() { locked = true; } void SetScreenFade(float factor) { screenFade = factor; } @@ -229,11 +258,14 @@ public: return v; } - void Set(TwoDVertex* v, double xx, double yy, double zz, double uu, double vv, PalEntry col) + void SetTransform(const DShape2DTransform& transform) { - v->Set(xx + offset.X, yy + offset.Y, zz, uu, vv, col); + this->transform = transform.transform; + } + void ClearTransform() + { + this->transform.Identity(); } - int DrawCount() const { @@ -243,6 +275,15 @@ public: bool mIsFirstPass = true; }; +// DCanvas is already taken so using FCanvas instead. +class FCanvas : public DObject +{ + DECLARE_CLASS(FCanvas, DObject) +public: + F2DDrawer Drawer; + FCanvasTexture* Tex = nullptr; +}; + struct DShape2DBufferInfo : RefCountedBase { TArray buffers; diff --git a/src/common/2d/v_draw.cpp b/src/common/2d/v_draw.cpp index 9c53e754b..7c1beb0c8 100644 --- a/src/common/2d/v_draw.cpp +++ b/src/common/2d/v_draw.cpp @@ -36,7 +36,7 @@ #include #include "v_draw.h" #include "vm.h" -#include "templates.h" + #include "texturemanager.h" #include "r_videoscale.h" #include "c_cvars.h" @@ -144,15 +144,15 @@ int GetUIScale(F2DDrawer *drawer, int altval) // Default should try to scale to 640x400 int vscale = drawer->GetHeight() / 400; int hscale = drawer->GetWidth() / 640; - scaleval = clamp(vscale, 1, hscale); + scaleval = max(1, min(vscale, hscale)); } else scaleval = uiscale; // block scales that result in something larger than the current screen. int vmax = drawer->GetHeight() / 200; int hmax = drawer->GetWidth() / 320; - int max = MAX(vmax, hmax); - return MAX(1,MIN(scaleval, max)); + int max = std::max(vmax, hmax); + return std::max(1,min(scaleval, max)); } // The new console font is twice as high, so the scaling calculation must factor that in. @@ -163,17 +163,17 @@ int GetConScale(F2DDrawer* drawer, int altval) else if (uiscale == 0) { // Default should try to scale to 640x400 - int vscale = drawer->GetHeight() / 800; + int vscale = drawer->GetHeight() / 720; int hscale = drawer->GetWidth() / 1280; - scaleval = clamp(vscale, 1, hscale); + scaleval = max(1, min(vscale, hscale)); } else scaleval = (uiscale+1) / 2; // block scales that result in something larger than the current screen. int vmax = drawer->GetHeight() / 400; int hmax = drawer->GetWidth() / 640; - int max = MAX(vmax, hmax); - return MAX(1, MIN(scaleval, max)); + int max = std::max(vmax, hmax); + return std::max(1, min(scaleval, max)); } @@ -194,14 +194,12 @@ int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; // //========================================================================== -void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, ...) +void DoDrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, Va_List& tags) { - Va_List tags; - va_start(tags.list, tags_first); DrawParms parms; if (!img || !img->isValid()) return; - bool res = ParseDrawTextureTags(drawer, img, x, y, tags_first, tags, &parms, false); + bool res = ParseDrawTextureTags(drawer, img, x, y, tags_first, tags, &parms, DrawTexture_Normal); va_end(tags.list); if (!res) { @@ -210,6 +208,23 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t drawer->AddTexture(img, parms); } + +void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, ...) +{ + Va_List tags; + va_start(tags.list, tags_first); + DoDrawTexture(drawer, img, x, y, tags_first, tags); +} + +void DrawTexture(F2DDrawer *drawer, FTextureID texid, bool animate, double x, double y, int tags_first, ...) +{ + Va_List tags; + va_start(tags.list, tags_first); + auto img = TexMan.GetGameTexture(texid, animate); + DoDrawTexture(drawer, img, x, y, tags_first, tags); +} + + //========================================================================== // // ZScript texture drawing function @@ -218,12 +233,12 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t int ListGetInt(VMVa_List &tags); -static void DrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y, VMVa_List &args) +void DoDrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y, VMVa_List &args) { DrawParms parms; uint32_t tag = ListGetInt(args); if (!img || !img->isValid()) return; - bool res = ParseDrawTextureTags(drawer, img, x, y, tag, args, &parms, false); + bool res = ParseDrawTextureTags(drawer, img, x, y, tag, args, &parms, DrawTexture_Normal); if (!res) return; drawer->AddTexture(img, parms); } @@ -242,7 +257,24 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture) auto tex = TexMan.GameByIndex(texid, animate); VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; - DrawTexture(twod, tex, x, y, args); + DoDrawTexture(twod, tex, x, y, args); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, DrawTexture) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(texid); + PARAM_BOOL(animate); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + auto tex = TexMan.GameByIndex(texid, animate); + VMVa_List args = { param + 5, 0, numparam - 6, va_reginfo + 5 }; + DoDrawTexture(&self->Drawer, tex, x, y, args); + self->Tex->NeedUpdate(); return 0; } @@ -258,7 +290,7 @@ void DrawShape(F2DDrawer *drawer, FGameTexture *img, DShape2D *shape, int tags_f va_start(tags.list, tags_first); DrawParms parms; - bool res = ParseDrawTextureTags(drawer, img, 0, 0, tags_first, tags, &parms, false); + bool res = ParseDrawTextureTags(drawer, img, 0, 0, tags_first, tags, &parms, DrawTexture_Normal); va_end(tags.list); if (!res) return; drawer->AddShape(img, shape, parms); @@ -269,11 +301,22 @@ void DrawShape(F2DDrawer *drawer, FGameTexture *img, DShape2D *shape, VMVa_List DrawParms parms; uint32_t tag = ListGetInt(args); - bool res = ParseDrawTextureTags(drawer, img, 0, 0, tag, args, &parms, false); + bool res = ParseDrawTextureTags(drawer, img, 0, 0, tag, args, &parms, DrawTexture_Normal); if (!res) return; drawer->AddShape(img, shape, parms); } +void DrawShapeFill(F2DDrawer *drawer, PalEntry color, double amount, DShape2D *shape, VMVa_List &args) +{ + DrawParms parms; + uint32_t tag = ListGetInt(args); + + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, DrawTexture_Fill, color, amount); + if (!res) return; + + drawer->AddShape(nullptr, shape, parms); +} + DEFINE_ACTION_FUNCTION(_Screen, DrawShape) { PARAM_PROLOGUE; @@ -292,6 +335,56 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawShape) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, DrawShape) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(texid); + PARAM_BOOL(animate); + PARAM_POINTER(shape, DShape2D); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + auto tex = TexMan.GameByIndex(texid, animate); + VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; + + DrawShape(&self->Drawer, tex, shape, args); + self->Tex->NeedUpdate(); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawShapeFill) +{ + PARAM_PROLOGUE; + PARAM_COLOR(color); + PARAM_FLOAT(amount); + PARAM_POINTER(shape, DShape2D); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + VMVa_List args = { param + 3, 0, numparam - 4, va_reginfo + 3 }; + + DrawShapeFill(twod, color, amount, shape, args); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, DrawShapeFill) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_COLOR(color); + PARAM_FLOAT(amount); + PARAM_POINTER(shape, DShape2D); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; + + DrawShapeFill(&self->Drawer, color, amount, shape, args); + self->Tex->NeedUpdate(); + return 0; +} + //========================================================================== // // Clipping rect @@ -300,10 +393,14 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawShape) void F2DDrawer::SetClipRect(int x, int y, int w, int h) { - clipleft = clamp(x, 0, GetWidth()); - clipwidth = clamp(w, -1, GetWidth() - x); - cliptop = clamp(y, 0, GetHeight()); - clipheight = clamp(h, -1, GetHeight() - y); + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x >= GetWidth()) { x = GetWidth(); w = 0; } + if (y >= GetHeight()) { x = GetHeight(); h = 0; } + clipleft = x; + clipwidth = w; + cliptop = y; + clipheight = h; } DEFINE_ACTION_FUNCTION(_Screen, SetClipRect) @@ -317,6 +414,18 @@ DEFINE_ACTION_FUNCTION(_Screen, SetClipRect) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, SetClipRect) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(x); + PARAM_INT(y); + PARAM_INT(w); + PARAM_INT(h); + self->Drawer.SetClipRect(x, y, w, h); + self->Tex->NeedUpdate(); + return 0; +} + DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) { PARAM_PROLOGUE; @@ -324,6 +433,14 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, ClearClipRect) +{ + PARAM_SELF_PROLOGUE(FCanvas); + self->Drawer.ClearClipRect(); + self->Tex->NeedUpdate(); + return 0; +} + DEFINE_ACTION_FUNCTION(_Screen, ClearScreen) { PARAM_PROLOGUE; @@ -331,6 +448,14 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearScreen) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, ClearScreen) +{ + PARAM_SELF_PROLOGUE(FCanvas); + self->Drawer.ClearScreen(); + self->Tex->NeedUpdate(); + return 0; +} + DEFINE_ACTION_FUNCTION(_Screen, SetScreenFade) { PARAM_PROLOGUE; @@ -339,6 +464,15 @@ DEFINE_ACTION_FUNCTION(_Screen, SetScreenFade) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, SetScreenFade) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(x); + self->Drawer.SetScreenFade(float(x)); + self->Tex->NeedUpdate(); + return 0; +} + void F2DDrawer::GetClipRect(int *x, int *y, int *w, int *h) { @@ -357,7 +491,19 @@ DEFINE_ACTION_FUNCTION(_Screen, GetClipRect) if (numret > 1) ret[1].SetInt(y); if (numret > 2) ret[2].SetInt(w); if (numret > 3) ret[3].SetInt(h); - return MIN(numret, 4); + return min(numret, 4); +} + +DEFINE_ACTION_FUNCTION(FCanvas, GetClipRect) +{ + PARAM_SELF_PROLOGUE(FCanvas); + int x, y, w, h; + self->Drawer.GetClipRect(&x, &y, &w, &h); + if (numret > 0) ret[0].SetInt(x); + if (numret > 1) ret[1].SetInt(y); + if (numret > 2) ret[2].SetInt(w); + if (numret > 3) ret[3].SetInt(h); + return min(numret, 4); } @@ -384,7 +530,7 @@ void CalcFullscreenScale(DrawParms *parms, double srcwidth, double srcheight, in if (autoaspect == FSMode_ScaleToFit43 || autoaspect == FSMode_ScaleToFit43Top || autoaspect == FSMode_ScaleToFit43Bottom) { // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxed if the screen is taller than the image - if (screenratio >= aspect || aspect < 1.4) autoaspect = FSMode_ScaleToFit; + if (screenratio >= aspect || aspect < 1.4) autoaspect = FSMode_ScaleToFit; else if (screenratio > 1.32) autoaspect = FSMode_ScaleToFill; // on anything 4:3 and wider crop the sides of the image. else { @@ -460,9 +606,27 @@ DEFINE_ACTION_FUNCTION(_Screen, GetFullscreenRect) if (numret >= 2) ret[1].SetFloat(rect.top); if (numret >= 3) ret[2].SetFloat(rect.width); if (numret >= 4) ret[3].SetFloat(rect.height); - return MIN(numret, 4); + return min(numret, 4); } +DEFINE_ACTION_FUNCTION(FCanvas, GetFullscreenRect) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(virtw); + PARAM_FLOAT(virth); + PARAM_INT(fsmode); + + DrawParms parms; + DoubleRect rect; + parms.viewport.width = self->Drawer.GetWidth(); + parms.viewport.height = self->Drawer.GetHeight(); + CalcFullscreenScale(&parms, virtw, virth, fsmode, rect); + if (numret >= 1) ret[0].SetFloat(rect.left); + if (numret >= 2) ret[1].SetFloat(rect.top); + if (numret >= 3) ret[2].SetFloat(rect.width); + if (numret >= 4) ret[3].SetFloat(rect.height); + return min(numret, 4); +} //========================================================================== @@ -667,14 +831,13 @@ 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, bool fortext) +bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, int type, PalEntry fill, double fillalpha) { INTBOOL boolval; int intval; - bool translationset = false; - bool fillcolorset = false; + bool fillcolorset = type == DrawTexture_Fill; - if (!fortext) + if (type == DrawTexture_Normal) { if (img == NULL || !img->isValid()) { @@ -690,7 +853,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double return false; } - parms->fortext = fortext; + parms->fortext = type == DrawTexture_Text; parms->windowleft = 0; parms->windowright = INT_MAX; parms->dclip = drawer->GetHeight(); @@ -701,8 +864,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->top = INT_MAX; parms->destwidth = INT_MAX; parms->destheight = INT_MAX; - parms->Alpha = 1.f; - parms->fillcolor = -1; + parms->Alpha = type == DrawTexture_Fill ? (float)fillalpha : 1.f; + parms->fillcolor = type == DrawTexture_Fill ? fill : PalEntry(~0u); parms->TranslationId = -1; parms->colorOverlay = 0; parms->alphaChannel = false; @@ -751,29 +914,29 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_DestWidth: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->cleanmode = DTA_Base; parms->destwidth = ListGetInt(tags); break; case DTA_DestWidthF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->cleanmode = DTA_Base; parms->destwidth = ListGetDouble(tags); break; case DTA_DestHeight: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->cleanmode = DTA_Base; parms->destheight = ListGetInt(tags); break; case DTA_DestHeightF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->cleanmode = DTA_Base; parms->destheight = ListGetDouble(tags); break; @@ -858,7 +1021,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->cleanmode = DTA_Base; parms->virtHeight = ListGetDouble(tags); break; - + case DTA_FullscreenScale: intval = ListGetInt(tags); if (intval >= FSMode_None && intval < FSMode_Max) @@ -881,7 +1044,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double boolval = ListGetInt(tags); if (boolval) { - assert(fortext == false); + assert(type != DrawTexture_Text); if (img == NULL) return false; parms->cleanmode = DTA_Fullscreen; parms->fsscalemode = (uint8_t)twod->fullscreenautoaspect; @@ -895,7 +1058,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double intval = ListGetInt(tags); if (intval >= 0 && intval <= 3) { - assert(fortext == false); + assert(type != DrawTexture_Text); if (img == NULL) return false; parms->cleanmode = DTA_Fullscreen; parms->fsscalemode = (uint8_t)intval; @@ -905,7 +1068,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_Alpha: - parms->Alpha = (float)(MIN(1., ListGetDouble(tags))); + parms->Alpha = (float)(min(1., ListGetDouble(tags))); break; case DTA_AlphaChannel: @@ -970,32 +1133,32 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_TopOffset: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->top = ListGetInt(tags); break; case DTA_TopOffsetF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->top = ListGetDouble(tags); break; case DTA_LeftOffset: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->left = ListGetInt(tags); break; case DTA_LeftOffsetF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->left = ListGetDouble(tags); break; case DTA_TopLeft: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; if (ListGetInt(tags)) { parms->left = 0; @@ -1004,8 +1167,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_CenterOffset: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; if (ListGetInt(tags)) { parms->left = img->GetDisplayWidth() * 0.5; @@ -1014,18 +1177,24 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_CenterOffsetRel: - assert(fortext == false); - if (fortext) return false; - if (ListGetInt(tags)) + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; + intval = ListGetInt(tags); + if (intval == 1) { - parms->left = img->GetDisplayLeftOffset() + img->GetDisplayWidth() * 0.5; - parms->top = img->GetDisplayTopOffset() + img->GetDisplayHeight() * 0.5; + parms->left = img->GetDisplayLeftOffset() + (img->GetDisplayWidth() * 0.5); + parms->top = img->GetDisplayTopOffset() + (img->GetDisplayHeight() * 0.5); + } + else if (intval == 2) + { + parms->left = img->GetDisplayLeftOffset() + floor(img->GetDisplayWidth() * 0.5); + parms->top = img->GetDisplayTopOffset() + floor(img->GetDisplayHeight() * 0.5); } break; case DTA_CenterBottomOffset: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; if (ListGetInt(tags)) { parms->left = img->GetDisplayWidth() * 0.5; @@ -1034,26 +1203,26 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_WindowLeft: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->windowleft = ListGetInt(tags); break; case DTA_WindowLeftF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->windowleft = ListGetDouble(tags); break; case DTA_WindowRight: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->windowright = ListGetInt(tags); break; case DTA_WindowRightF: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->windowright = ListGetDouble(tags); break; @@ -1090,7 +1259,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_ShadowAlpha: - //parms->shadowAlpha = (float)MIN(1., ListGetDouble(tags)); + //parms->shadowAlpha = (float)min(1., ListGetDouble(tags)); break; case DTA_ShadowColor: @@ -1191,8 +1360,8 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double break; case DTA_Rotate: - assert(fortext == false); - if (fortext) return false; + assert(type != DrawTexture_Text); + if (type == DrawTexture_Text) return false; parms->rotateangle = ListGetDouble(tags); break; @@ -1265,8 +1434,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, bool fortext); -template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext); +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); //========================================================================== // @@ -1275,7 +1444,7 @@ template bool ParseDrawTextureTags(F2DDrawer* drawer, FGameTexture *i //========================================================================== static void VirtualToRealCoords(F2DDrawer *drawer, double Width, double Height, double &x, double &y, double &w, double &h, - double vwidth, double vheight, bool vbottom, bool handleaspect) + double vwidth, double vheight, bool vbottom, bool handleaspect) { float myratio = float(handleaspect ? ActiveRatio (Width, Height) : (4.0 / 3.0)); @@ -1286,10 +1455,10 @@ static void VirtualToRealCoords(F2DDrawer *drawer, double Width, double Height, { case 1: default: - myratio = MIN(64.0f / 27.0f, myratio); + myratio = min(64.0f / 27.0f, myratio); break; case 0: - myratio = MIN(16.0f / 9.0f, myratio); + myratio = min(16.0f / 9.0f, myratio); case -1: break; } @@ -1348,7 +1517,24 @@ DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords) VirtualToRealCoords(twod, x, y, w, h, vw, vh, vbottom, handleaspect); if (numret >= 1) ret[0].SetVector2(DVector2(x, y)); if (numret >= 2) ret[1].SetVector2(DVector2(w, h)); - return MIN(numret, 2); + return min(numret, 2); +} + +DEFINE_ACTION_FUNCTION(FCanvas, VirtualToRealCoords) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(w); + PARAM_FLOAT(h); + PARAM_FLOAT(vw); + PARAM_FLOAT(vh); + PARAM_BOOL(vbottom); + PARAM_BOOL(handleaspect); + VirtualToRealCoords(&self->Drawer, x, y, w, h, vw, vh, vbottom, handleaspect); + if (numret >= 1) ret[0].SetVector2(DVector2(x, y)); + if (numret >= 2) ret[1].SetVector2(DVector2(w, h)); + return min(numret, 2); } void VirtualToRealCoordsInt(F2DDrawer *drawer, int &x, int &y, int &w, int &h, @@ -1373,38 +1559,52 @@ void VirtualToRealCoordsInt(F2DDrawer *drawer, int &x, int &y, int &w, int &h, // //========================================================================== -static void DrawLine(int x0, int y0, int x1, int y1, uint32_t realcolor, int alpha) +static void DrawLine(double x1, double y1, double x2, double y2, uint32_t realcolor, int alpha) { if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - twod->AddLine((float)x0, (float)y0, (float)x1, (float)y1, -1, -1, INT_MAX, INT_MAX, realcolor | MAKEARGB(255, 0, 0, 0), alpha); + twod->AddLine(DVector2(x1, y1), DVector2(x2, y2), nullptr, realcolor | MAKEARGB(255, 0, 0, 0), alpha); } DEFINE_ACTION_FUNCTION_NATIVE(_Screen, DrawLine, DrawLine) { PARAM_PROLOGUE; - PARAM_INT(x0); - PARAM_INT(y0); - PARAM_INT(x1); - PARAM_INT(y1); + PARAM_FLOAT(x0); + PARAM_FLOAT(y0); + PARAM_FLOAT(x1); + PARAM_FLOAT(y1); PARAM_INT(color); PARAM_INT(alpha); DrawLine(x0, y0, x1, y1, color, alpha); return 0; } -static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, uint32_t realcolor, int alpha) +DEFINE_ACTION_FUNCTION(FCanvas, DrawLine) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(x0); + PARAM_FLOAT(y0); + PARAM_FLOAT(x1); + PARAM_FLOAT(y1); + PARAM_INT(color); + PARAM_INT(alpha); + self->Drawer.AddLine(DVector2(x0, y0), DVector2(x1, y1), nullptr, color | MAKEARGB(255, 0, 0, 0), alpha); + self->Tex->NeedUpdate(); + return 0; +} + +static void DrawThickLine(double x1, double y1, double x2, double y2, double thickness, uint32_t realcolor, int alpha) { if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - twod->AddThickLine(x0, y0, x1, y1, thickness, realcolor, alpha); + twod->AddThickLine(DVector2(x1, y1), DVector2(x2, y2), thickness, realcolor, alpha); } DEFINE_ACTION_FUNCTION_NATIVE(_Screen, DrawThickLine, DrawThickLine) { PARAM_PROLOGUE; - PARAM_INT(x0); - PARAM_INT(y0); - PARAM_INT(x1); - PARAM_INT(y1); + PARAM_FLOAT(x0); + PARAM_FLOAT(y0); + PARAM_FLOAT(x1); + PARAM_FLOAT(y1); PARAM_FLOAT(thickness); PARAM_INT(color); PARAM_INT(alpha); @@ -1412,6 +1612,21 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Screen, DrawThickLine, DrawThickLine) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, DrawThickLine) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(x0); + PARAM_FLOAT(y0); + PARAM_FLOAT(x1); + PARAM_FLOAT(y1); + PARAM_FLOAT(thickness); + PARAM_INT(color); + PARAM_INT(alpha); + self->Drawer.AddThickLine(DVector2(x0, y0), DVector2(x1, y1), thickness, color, alpha); + self->Tex->NeedUpdate(); + return 0; +} + //========================================================================== // // ClearRect @@ -1471,6 +1686,20 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, Clear) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(x2); + PARAM_INT(y2); + PARAM_INT(color); + PARAM_INT(palcol); + ClearRect(&self->Drawer, x1, y1, x2, y2, palcol, color); + self->Tex->NeedUpdate(); + return 0; +} + //========================================================================== // // DoDim @@ -1529,8 +1758,24 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim) PARAM_INT(y1); PARAM_INT(w); PARAM_INT(h); + PARAM_INT(style); if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - Dim(twod, color, float(amount), x1, y1, w, h); + Dim(twod, color, float(amount), x1, y1, w, h, &LegacyRenderStyles[style]); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, Dim) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(color); + PARAM_FLOAT(amount); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(w); + PARAM_INT(h); + PARAM_INT(style); + Dim(&self->Drawer, color, float(amount), x1, y1, w, h, &LegacyRenderStyles[style]); + self->Tex->NeedUpdate(); return 0; } @@ -1590,10 +1835,24 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawLineFrame) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, DrawLineFrame) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_COLOR(color); + PARAM_INT(left); + PARAM_INT(top); + PARAM_INT(width); + PARAM_INT(height); + PARAM_INT(thickness); + DrawFrame(&self->Drawer, color, left, top, width, height, thickness); + self->Tex->NeedUpdate(); + return 0; +} + void V_CalcCleanFacs(int designwidth, int designheight, int realwidth, int realheight, int* cleanx, int* cleany, int* _cx1, int* _cx2) { if (designheight < 240 && realheight >= 480) designheight = 240; - *cleanx = *cleany = std::min(realwidth / designwidth, realheight / designheight); + *cleanx = *cleany = min(realwidth / designwidth, realheight / designheight); } @@ -1603,4 +1862,119 @@ DEFINE_ACTION_FUNCTION(_Screen, SetOffset) PARAM_FLOAT(x); PARAM_FLOAT(y); ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y))); -} \ No newline at end of file +} + +DEFINE_ACTION_FUNCTION(FCanvas, SetOffset) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + ACTION_RETURN_VEC2(self->Drawer.SetOffset(DVector2(x, y))); +} + +DEFINE_ACTION_FUNCTION(_Screen, EnableStencil) +{ + PARAM_PROLOGUE; + PARAM_BOOL(on); + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->AddEnableStencil(on); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, EnableStencil) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_BOOL(on); + + self->Drawer.AddEnableStencil(on); + self->Tex->NeedUpdate(); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, SetStencil) +{ + PARAM_PROLOGUE; + PARAM_INT(offs); + PARAM_INT(op); + PARAM_INT(flags); + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->AddSetStencil(offs, op, flags); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, SetStencil) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_INT(offs); + PARAM_INT(op); + PARAM_INT(flags); + + self->Drawer.AddSetStencil(offs, op, flags); + self->Tex->NeedUpdate(); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, ClearStencil) +{ + PARAM_PROLOGUE; + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->AddClearStencil(); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, ClearStencil) +{ + PARAM_SELF_PROLOGUE(FCanvas); + + self->Drawer.AddClearStencil(); + self->Tex->NeedUpdate(); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, SetTransform) +{ + PARAM_PROLOGUE; + PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->SetTransform(*transform); + + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, SetTransform) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); + + self->Drawer.SetTransform(*transform); + self->Tex->NeedUpdate(); + + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, ClearTransform) +{ + PARAM_PROLOGUE; + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->ClearTransform(); + return 0; +} + +DEFINE_ACTION_FUNCTION(FCanvas, ClearTransform) +{ + PARAM_SELF_PROLOGUE(FCanvas); + + self->Drawer.ClearTransform(); + self->Tex->NeedUpdate(); + return 0; +} diff --git a/src/common/2d/v_draw.h b/src/common/2d/v_draw.h index a0407179e..686e5dc46 100644 --- a/src/common/2d/v_draw.h +++ b/src/common/2d/v_draw.h @@ -36,7 +36,7 @@ enum FSMode_Max, - + // These all use ScaleToFit43, their purpose is to cut down on verbosity because they imply the virtual screen size. FSMode_Predefined = 1000, FSMode_Fit320x200 = 1000, @@ -103,7 +103,7 @@ enum DTA_CellX, // horizontal size of character cell DTA_CellY, // vertical size of character cell - // New additions. + // New additions. DTA_Color, DTA_FlipY, // bool: flip image vertically DTA_SrcX, // specify a source rectangle (this supersedes the poorly implemented DTA_WindowLeft/Right @@ -258,8 +258,15 @@ inline int active_con_scale(F2DDrawer *drawer) #undef DrawText // See WinUser.h for the definition of DrawText as a macro #endif +enum +{ + DrawTexture_Normal, + DrawTexture_Text, + DrawTexture_Fill, +}; + template -bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, bool fortext); +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); template void DrawTextCommon(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const T* string, DrawParms& parms); @@ -272,6 +279,7 @@ void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double void DrawChar(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...); void DrawTexture(F2DDrawer* drawer, FGameTexture* img, double x, double y, int tags_first, ...); +void DrawTexture(F2DDrawer *drawer, FTextureID texid, bool animate, double x, double y, int tags_first, ...); void DoDim(F2DDrawer* drawer, PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr); void Dim(F2DDrawer* drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr); @@ -325,3 +333,6 @@ public: CleanHeight = savedheight; } }; + +void Draw2D(F2DDrawer* drawer, FRenderState& state); +void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int height); diff --git a/src/common/2d/v_drawtext.cpp b/src/common/2d/v_drawtext.cpp index 2bddac961..2bdb64dca 100644 --- a/src/common/2d/v_drawtext.cpp +++ b/src/common/2d/v_drawtext.cpp @@ -179,7 +179,7 @@ void DrawChar(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double DrawParms parms; Va_List tags; va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(drawer, pic, x, y, tag_first, tags, &parms, false); + bool res = ParseDrawTextureTags(drawer, pic, x, y, tag_first, tags, &parms, DrawTexture_Normal); va_end(tags.list); if (!res) { @@ -208,7 +208,7 @@ void DrawChar(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double { DrawParms parms; uint32_t tag = ListGetInt(args); - bool res = ParseDrawTextureTags(drawer, pic, x, y, tag, args, &parms, false); + bool res = ParseDrawTextureTags(drawer, pic, x, y, tag, args, &parms, DrawTexture_Normal); if (!res) return; bool palettetrans = (normalcolor == CR_NATIVEPAL && parms.TranslationId != 0); PalEntry color = 0xffffffff; @@ -235,6 +235,23 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar) return 0; } +DEFINE_ACTION_FUNCTION(FCanvas, DrawChar) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_POINTER(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_INT(chr); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + VMVa_List args = { param + 6, 0, numparam - 7, va_reginfo + 6 }; + DrawChar(&self->Drawer, font, cr, x, y, chr, args); + self->Tex->NeedUpdate(); + return 0; +} + //========================================================================== // // DrawText @@ -244,7 +261,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar) //========================================================================== // This is only needed as a dummy. The code using wide strings does not need color control. -EColorRange V_ParseFontColor(const char32_t *&color_value, int normalcolor, int boldcolor) { return CR_UNTRANSLATED; } +EColorRange V_ParseFontColor(const char32_t *&color_value, int normalcolor, int boldcolor) { return CR_UNTRANSLATED; } template void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, const chartype *string, DrawParms &parms) @@ -357,7 +374,7 @@ void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double return; va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, true); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, DrawTexture_Text); va_end(tags.list); if (!res) { @@ -376,7 +393,7 @@ void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double return; va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, true); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, DrawTexture_Text); va_end(tags.list); if (!res) { @@ -394,7 +411,7 @@ void DrawText(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double return; uint32_t tag = ListGetInt(args); - bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, true); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, DrawTexture_Text); if (!res) { return; @@ -420,3 +437,21 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText) return 0; } + +DEFINE_ACTION_FUNCTION(FCanvas, DrawText) +{ + PARAM_SELF_PROLOGUE(FCanvas); + PARAM_POINTER_NOT_NULL(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_STRING(chr); + + 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); + self->Tex->NeedUpdate(); + return 0; +} diff --git a/src/rendering/2d/f_wipe.cpp b/src/common/2d/wipe.cpp similarity index 70% rename from src/rendering/2d/f_wipe.cpp rename to src/common/2d/wipe.cpp index 320bb869d..cc57ca29f 100644 --- a/src/rendering/2d/f_wipe.cpp +++ b/src/common/2d/wipe.cpp @@ -1,35 +1,47 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// Copyright 1999-2016 Randy Heit -// -// 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 3 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. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- -// -// DESCRIPTION: -// Mission begin melt/wipe screen special effect. -// -//----------------------------------------------------------------------------- +/* +** wipe.cpp +** Screen wipe implementation +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2005-2022 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 "v_video.h" #include "m_random.h" -#include "f_wipe.h" -#include "templates.h" +#include "wipe.h" + #include "bitmap.h" #include "hw_material.h" #include "v_draw.h" +#include "s_soundinternal.h" +#include "i_time.h" class FBurnTexture : public FTexture { @@ -74,11 +86,11 @@ int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density) { unsigned int offs = (a+b) & (width - 1); unsigned int v = M_Random(); - v = MIN(from[offs] + 4 + (v & 15) + (v >> 3) + (M_Random() & 31), 255u); + v = min(from[offs] + 4 + (v & 15) + (v >> 3) + (M_Random() & 31), 255u); from[offs] = from[width*2 + ((offs + width*3/2) & (width - 1))] = v; } - density = MIN(density + 10, width * 7); + density = min(density + 10, width * 7); from = burnarray; for (b = 0; b <= height; b += 2) @@ -144,6 +156,23 @@ int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density) // TYPES ------------------------------------------------------------------- +class Wiper +{ +protected: + FGameTexture* startScreen = nullptr, * endScreen = nullptr; +public: + virtual ~Wiper(); + virtual bool Run(int ticks) = 0; + virtual void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) + { + startScreen = startscreen; + endScreen = endscreen; + } + + static Wiper* Create(int type); +}; + + class Wiper_Crossfade : public Wiper { public: @@ -160,7 +189,7 @@ public: bool Run(int ticks) override; private: - static const int WIDTH = 320, HEIGHT = 200; + enum { WIDTH = 320, HEIGHT = 200 }; int y[WIDTH]; }; @@ -250,15 +279,10 @@ bool Wiper_Crossfade::Run(int ticks) Wiper_Melt::Wiper_Melt() { - int i, r; - - // setup initial column positions - // (y<0 => not ready to scroll yet) y[0] = -(M_Random() & 15); - for (i = 1; i < WIDTH; ++i) + for (int i = 1; i < WIDTH; ++i) { - r = (M_Random()%3) - 1; - y[i] = clamp(y[i-1] + r, -15, 0); + y[i] = clamp(y[i-1] + (M_Random() % 3) - 1, -15, 0); } } @@ -272,7 +296,7 @@ Wiper_Melt::Wiper_Melt() bool Wiper_Melt::Run(int ticks) { - bool done; + bool done = false; DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); // Copy the old screen in vertical strips on top of the new one. @@ -281,15 +305,14 @@ bool Wiper_Melt::Run(int ticks) done = true; for (int i = 0; i < WIDTH; i++) { - if (y[i] < 0) + if (y[i] < HEIGHT) { - y[i]++; - done = false; - } - else if (y[i] < HEIGHT) - { - int dy = (y[i] < 16) ? y[i] + 1 : 8; - y[i] = MIN(y[i] + dy, HEIGHT); + if (y[i] < 0) + y[i]++; + else if (y[i] < 16) + y[i] += y[i] + 1; + else + y[i] = min(y[i] + 8, HEIGHT); done = false; } if (ticks == 0) @@ -306,12 +329,11 @@ bool Wiper_Melt::Run(int ticks) } rect; // Only draw for the final tick. - // No need for optimization. Wipes won't ever be drawn with anything else. int w = startScreen->GetTexelWidth(); int h = startScreen->GetTexelHeight(); dpt.x = i * w / WIDTH; - dpt.y = MAX(0, y[i] * h / HEIGHT); + dpt.y = max(0, y[i] * h / HEIGHT); rect.left = dpt.x; rect.top = 0; rect.right = (i + 1) * w / WIDTH; @@ -361,14 +383,13 @@ Wiper_Burn::~Wiper_Burn() bool Wiper_Burn::Run(int ticks) { - bool done; - + bool done = false; + BurnTime += ticks; ticks *= 2; // Make the fire burn - done = false; while (!done && ticks--) { Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density); @@ -396,3 +417,44 @@ bool Wiper_Burn::Run(int ticks) // after an arbitrary maximum time. return done || (BurnTime > 40); } + + +void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function overlaydrawer) +{ + // wipe update + uint64_t wipestart, nowtime, diff; + bool done; + + GSnd->SetSfxPaused(true, 1); + I_FreezeTime(true); + twod->End(); + assert(startimg != nullptr && endimg != nullptr); + auto starttex = MakeGameTexture(startimg, nullptr, ETextureType::SWCanvas); + auto endtex = MakeGameTexture(endimg, nullptr, ETextureType::SWCanvas); + auto wiper = Wiper::Create(wipe_type); + wiper->SetTextures(starttex, endtex); + + wipestart = I_msTime(); + + do + { + do + { + I_WaitVBL(2); + nowtime = I_msTime(); + diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. + } while (diff < 1); + wipestart = nowtime; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + done = wiper->Run(1); + if (overlaydrawer) overlaydrawer(); + twod->End(); + screen->Update(); + twod->OnFrameDone(); + + } while (!done); + delete wiper; + I_FreezeTime(false); + GSnd->SetSfxPaused(false, 1); + +} diff --git a/src/common/2d/wipe.h b/src/common/2d/wipe.h new file mode 100644 index 000000000..08a7eeb3b --- /dev/null +++ b/src/common/2d/wipe.h @@ -0,0 +1,21 @@ +#ifndef __F_WIPE_H__ +#define __F_WIPE_H__ + +#include "stdint.h" +#include + +class FTexture; + +enum +{ + wipe_None, // don't bother + wipe_Melt, // weird screen melt + wipe_Burn, // fade in shape of fire + wipe_Fade, // crossfade from old to new + wipe_NUMWIPES +}; + +void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stopsound, std::function overlaydrawer); + + +#endif diff --git a/src/common/audio/music/i_music.cpp b/src/common/audio/music/i_music.cpp index b73c630ca..0bc858292 100644 --- a/src/common/audio/music/i_music.cpp +++ b/src/common/audio/music/i_music.cpp @@ -43,7 +43,7 @@ #include "m_argv.h" #include "filesystem.h" #include "c_dispatch.h" -#include "templates.h" + #include "stats.h" #include "cmdlib.h" #include "c_cvars.h" @@ -200,7 +200,8 @@ static void SetupWgOpn() static void SetupDMXGUS() { - int lump = fileSystem.CheckNumForFullName("DMXGUS"); + int lump = fileSystem.CheckNumForName("DMXGUSC", ns_global); + if (lump < 0) lump = fileSystem.CheckNumForName("DMXGUS", ns_global); if (lump < 0) { return; @@ -221,12 +222,12 @@ void I_InitMusic(void) { I_InitSoundFonts(); - snd_musicvolume.Callback (); + snd_musicvolume->Callback (); nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); - snd_mididevice.Callback(); - + snd_mididevice->Callback(); + ZMusicCallbacks callbacks{}; callbacks.MessageFunc = zmusic_printfunc; @@ -256,7 +257,7 @@ void I_SetRelativeVolume(float vol) { relative_volume = (float)vol; ChangeMusicSetting(zmusic_relative_volume, nullptr, (float)vol); - snd_musicvolume.Callback(); + snd_musicvolume->Callback(); } //========================================================================== // diff --git a/src/common/audio/music/i_music.h b/src/common/audio/music/i_music.h index 85be1dea2..a6609eadb 100644 --- a/src/common/audio/music/i_music.h +++ b/src/common/audio/music/i_music.h @@ -58,12 +58,12 @@ EXTERN_CVAR(Float, snd_musicvolume) inline float AmplitudeTodB(float amplitude) { - return 20.0f * log10(amplitude); + return 20.0f * log10f(amplitude); } inline float dBToAmplitude(float dB) { - return pow(10.0f, dB / 20.0f); + return powf(10.0f, dB / 20.0f); } #endif //__I_MUSIC_H__ diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp index a8b4e9fdf..f05f0cb76 100644 --- a/src/common/audio/music/i_soundfont.cpp +++ b/src/common/audio/music/i_soundfont.cpp @@ -38,12 +38,13 @@ #include "i_soundinternal.h" #include "cmdlib.h" #include "i_system.h" -#include "gameconfigfile.h" #include "filereadermusicinterface.h" #include #include "resourcefile.h" #include "version.h" #include "findfile.h" +#include "i_interface.h" +#include "configfile.h" //========================================================================== // @@ -140,7 +141,7 @@ FileReader FSoundFontReader::Open(const char *name, std::string& filename) ZMusicCustomReader* FSoundFontReader::open_interface(const char* name) { std::string filename; - + FileReader fr = Open(name, filename); if (!fr.isOpen()) return nullptr; auto fri = GetMusicReader(fr); @@ -194,6 +195,7 @@ FileReader FSF2Reader::OpenFile(const char *name) FZipPatReader::FZipPatReader(const char *filename) { + mAllowAbsolutePaths = true; resf = FResourceFile::OpenResourceFile(filename, true); } @@ -218,6 +220,7 @@ FileReader FZipPatReader::OpenFile(const char *name) return lump->NewReader(); } } + fr.OpenFile(name); return fr; } @@ -336,7 +339,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) // We already got a soundfont with this name. Do not add again. if (!sfi.mName.CompareNoCase(fb)) return; } - + FileReader fr; if (fr.OpenFile(fn)) { @@ -390,6 +393,7 @@ void FSoundFontManager::CollectSoundfonts() findstate_t c_file; void *file; + FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories")) { const char *key; @@ -478,13 +482,6 @@ 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); - } - // The sound font collection did not yield any good results. // Next check if the file is a .sf file if (allowed & SF_SF2) { @@ -500,6 +497,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed } } } + // Next check if the file is a resource file (it should contains gus patches and a timidity.cfg file) if (allowed & SF_GUS) { FileReader fr; @@ -523,6 +521,13 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed return new FPatchSetReader(name); } } + // Lastly check in the sound font collection for a specific item or pick the first valid item available. + auto sfi = FindSoundFont(name, allowed); + if (sfi != nullptr) + { + if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename); + else return new FZipPatReader(sfi->mFilename); + } return nullptr; } diff --git a/src/common/audio/music/i_soundfont.h b/src/common/audio/music/i_soundfont.h index 9f07b8cc4..ef0295071 100644 --- a/src/common/audio/music/i_soundfont.h +++ b/src/common/audio/music/i_soundfont.h @@ -29,13 +29,13 @@ protected: // When reading from an archive it will always be case insensitive, just like the lump manager. bool mCaseSensitivePaths = false; TArray mPaths; - - + + int pathcmp(const char *p1, const char *p2); - - + + public: - + virtual ~FSoundFontReader() {} virtual FileReader OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets virtual FString MainConfigFileName() @@ -147,15 +147,15 @@ public: class FSoundFontManager { TArray soundfonts; - + void ProcessOneFile(const FString & fn); - + public: void CollectSoundfonts(); const FSoundFontInfo *FindSoundFont(const char *name, int allowedtypes) const; FSoundFontReader *OpenSoundFont(const char *name, int allowedtypes); const auto &GetList() const { return soundfonts; } // This is for the menu - + }; diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 1b36041da..3da91a6e9 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -51,8 +51,8 @@ #include #include "md5.h" #include "gain_analysis.h" -#include "gameconfigfile.h" #include "i_specialpaths.h" +#include "configfile.h" // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -117,10 +117,11 @@ int MusicEnabled() // int return is for scripting static std::unique_ptr musicStream; static TArray customStreams; -SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata) +SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, MusicCustomStreamType sampletype, StreamCallback cb, void *userdata) { int flags = 0; if (numchannels < 2) flags |= SoundStream::Mono; + if (sampletype == MusicSamplesFloat) flags |= SoundStream::Float; auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata); if (stream) { @@ -180,7 +181,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) fbuf[i] = convert[i] * mus_playing.replayGainFactor * (1.f/32768.f); } } - + if (!written) { memset((char*)buff, 0, len); @@ -240,15 +241,15 @@ static bool S_StartMusicPlaying(ZMusic_MusicStream song, bool loop, float rel_vo } ZMusic_Stop(song); // make sure the volume modifiers update properly in case replay gain settings have changed. - fluid_gain.Callback(); - mod_dumb_mastervolume.Callback(); + fluid_gain->Callback(); + mod_dumb_mastervolume->Callback(); if (!ZMusic_Start(song, subsong, loop)) { return false; } // Notify the sound system of the changed relative volume - snd_musicvolume.Callback(); + snd_musicvolume->Callback(); return true; } @@ -298,7 +299,7 @@ void S_UpdateMusic () if (mus_playing.handle != nullptr) { ZMusic_Update(mus_playing.handle); - + // [RH] Update music and/or playlist. IsPlaying() must be called // to attempt to reconnect to broken net streams and to advance the // playlist when the current song finishes. @@ -516,8 +517,8 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const { mus_playing.replayGain = 0.f; mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset); - fluid_gain.Callback(); - mod_dumb_mastervolume.Callback(); + fluid_gain->Callback(); + mod_dumb_mastervolume->Callback(); if (!mus_usereplaygain) return; FileReader reader = mus_cb.OpenMusic(musicname); @@ -603,13 +604,13 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const { float* sbuf = (float*)readbuffer.Data(); int numsamples = fmt.mBufferSize / 8; - auto index = lbuffer.Reserve(numsamples); + auto addr = lbuffer.Reserve(numsamples); rbuffer.Reserve(numsamples); for (int i = 0; i < numsamples; i++) { - lbuffer[index + i] = sbuf[i * 2] * 32768.f; - rbuffer[index + i] = sbuf[i * 2 + 1] * 32768.f; + lbuffer[addr + i] = sbuf[i * 2] * 32768.f; + rbuffer[addr + i] = sbuf[i * 2 + 1] * 32768.f; } } float accTime = lbuffer.Size() / (float)fmt.mSampleRate; @@ -684,8 +685,6 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) return true; } - int lumpnum = -1; - int length = 0; ZMusic_MusicStream handle = nullptr; MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname); diff --git a/src/common/audio/music/music_config.cpp b/src/common/audio/music/music_config.cpp index 86eef267e..efdb05637 100644 --- a/src/common/audio/music/music_config.cpp +++ b/src/common/audio/music/music_config.cpp @@ -75,12 +75,12 @@ CUSTOM_CVAR(Int, adl_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIR FORWARD_CVAR(adl_emulator_id); } -CUSTOM_CVAR(Bool, adl_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, adl_run_at_pcm_rate, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(adl_run_at_pcm_rate); } -CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, adl_fullpan, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(adl_fullpan); } @@ -90,7 +90,7 @@ CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_VIRTUAL) FORWARD_CVAR(adl_bank); } -CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, adl_use_custom_bank, false, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(adl_use_custom_bank); } @@ -201,7 +201,7 @@ CUSTOM_CVAR(Float, fluid_chorus_speed, 0.3f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | } // depth is in ms and actual maximum depends on the sample rate -CUSTOM_CVAR(Float, fluid_chorus_depth, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Float, fluid_chorus_depth, 8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_CVAR(fluid_chorus_depth); } @@ -251,17 +251,17 @@ CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIR FORWARD_CVAR(opn_emulator_id); } -CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(opn_run_at_pcm_rate); } -CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, opn_fullpan, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(opn_fullpan); } -CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_VIRTUAL) +CUSTOM_CVAR(Bool, opn_use_custom_bank, false, CVAR_ARCHIVE | CVAR_VIRTUAL) { FORWARD_BOOL_CVAR(opn_use_custom_bank); } @@ -278,7 +278,7 @@ CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) //========================================================================== -CUSTOM_CVAR(String, midi_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, midi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(gus_config); } @@ -344,7 +344,7 @@ CUSTOM_CVAR(Bool, timidity_channel_pressure, false, CVAR_ARCHIVE | CVAR_GLOBALCO FORWARD_BOOL_CVAR(timidity_channel_pressure); } -CUSTOM_CVAR(Int, timidity_lpf_def, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Int, timidity_lpf_def, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_CVAR(timidity_lpf_def); } @@ -384,12 +384,12 @@ CUSTOM_CVAR(Int, timidity_key_adjust, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR FORWARD_CVAR(timidity_key_adjust); } -CUSTOM_CVAR(Float, timidity_tempo_adjust, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Float, timidity_tempo_adjust, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_CVAR(timidity_tempo_adjust); } -CUSTOM_CVAR(Float, timidity_min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(Float, timidity_min_sustain_time, 5000.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_CVAR(timidity_min_sustain_time); } diff --git a/src/common/audio/music/s_music.h b/src/common/audio/music/s_music.h index fc1b86ca0..1970a57da 100644 --- a/src/common/audio/music/s_music.h +++ b/src/common/audio/music/s_music.h @@ -11,9 +11,13 @@ class FileReader; class SoundStream; +enum MusicCustomStreamType : bool { + MusicSamples16bit, + MusicSamplesFloat +}; int MusicEnabled(); typedef bool(*StreamCallback)(SoundStream* stream, void* buff, int len, void* userdata); -SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata); +SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, MusicCustomStreamType sampletype, StreamCallback cb, void *userdata); void S_StopCustomStream(SoundStream* stream); void S_PauseAllCustomStreams(bool on); diff --git a/src/common/audio/sound/alext.h b/src/common/audio/sound/alext.h new file mode 100644 index 000000000..edfae4735 --- /dev/null +++ b/src/common/audio/sound/alext.h @@ -0,0 +1,643 @@ +/** + * 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/efx.h b/src/common/audio/sound/efx.h index 0ccef95d6..addd25834 100644 --- a/src/common/audio/sound/efx.h +++ b/src/common/audio/sound/efx.h @@ -1,6 +1,7 @@ #ifndef AL_EFX_H #define AL_EFX_H +#include #ifdef __cplusplus extern "C" { @@ -201,12 +202,12 @@ extern "C" { /* Effect object function types. */ typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); @@ -214,12 +215,12 @@ typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); /* Filter object function types. */ typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); @@ -227,87 +228,87 @@ typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); /* Auxiliary Effect Slot object function types. */ typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); #ifdef AL_ALEXT_PROTOTYPES -AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); -AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects); +AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); +AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); -AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); +AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); +AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); +AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); +AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); +AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); +AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); +AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); -AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters); +AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); +AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); -AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); +AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); +AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); +AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); +AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); +AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); +AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); +AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); -AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); +AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); +AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); -AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); -AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); +AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); +AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); +AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); +AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); #endif /* Filter ranges and defaults. */ /* Lowpass filter */ -#define LOWPASS_MIN_GAIN (0.0f) -#define LOWPASS_MAX_GAIN (1.0f) -#define LOWPASS_DEFAULT_GAIN (1.0f) +#define AL_LOWPASS_MIN_GAIN (0.0f) +#define AL_LOWPASS_MAX_GAIN (1.0f) +#define AL_LOWPASS_DEFAULT_GAIN (1.0f) -#define LOWPASS_MIN_GAINHF (0.0f) -#define LOWPASS_MAX_GAINHF (1.0f) -#define LOWPASS_DEFAULT_GAINHF (1.0f) +#define AL_LOWPASS_MIN_GAINHF (0.0f) +#define AL_LOWPASS_MAX_GAINHF (1.0f) +#define AL_LOWPASS_DEFAULT_GAINHF (1.0f) /* Highpass filter */ -#define HIGHPASS_MIN_GAIN (0.0f) -#define HIGHPASS_MAX_GAIN (1.0f) -#define HIGHPASS_DEFAULT_GAIN (1.0f) +#define AL_HIGHPASS_MIN_GAIN (0.0f) +#define AL_HIGHPASS_MAX_GAIN (1.0f) +#define AL_HIGHPASS_DEFAULT_GAIN (1.0f) -#define HIGHPASS_MIN_GAINLF (0.0f) -#define HIGHPASS_MAX_GAINLF (1.0f) -#define HIGHPASS_DEFAULT_GAINLF (1.0f) +#define AL_HIGHPASS_MIN_GAINLF (0.0f) +#define AL_HIGHPASS_MAX_GAINLF (1.0f) +#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f) /* Bandpass filter */ -#define BANDPASS_MIN_GAIN (0.0f) -#define BANDPASS_MAX_GAIN (1.0f) -#define BANDPASS_DEFAULT_GAIN (1.0f) +#define AL_BANDPASS_MIN_GAIN (0.0f) +#define AL_BANDPASS_MAX_GAIN (1.0f) +#define AL_BANDPASS_DEFAULT_GAIN (1.0f) -#define BANDPASS_MIN_GAINHF (0.0f) -#define BANDPASS_MAX_GAINHF (1.0f) -#define BANDPASS_DEFAULT_GAINHF (1.0f) +#define AL_BANDPASS_MIN_GAINHF (0.0f) +#define AL_BANDPASS_MAX_GAINHF (1.0f) +#define AL_BANDPASS_DEFAULT_GAINHF (1.0f) -#define BANDPASS_MIN_GAINLF (0.0f) -#define BANDPASS_MAX_GAINLF (1.0f) -#define BANDPASS_DEFAULT_GAINLF (1.0f) +#define AL_BANDPASS_MIN_GAINLF (0.0f) +#define AL_BANDPASS_MAX_GAINLF (1.0f) +#define AL_BANDPASS_DEFAULT_GAINLF (1.0f) /* Effect parameter ranges and defaults. */ diff --git a/src/common/audio/sound/i_sound.cpp b/src/common/audio/sound/i_sound.cpp index 5f828d985..90fda4be2 100644 --- a/src/common/audio/sound/i_sound.cpp +++ b/src/common/audio/sound/i_sound.cpp @@ -70,9 +70,6 @@ CVAR(Int, snd_hrtf, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -// killough 2/21/98: optionally use varying pitched sounds -CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE) - SoundRenderer *GSnd; bool nosound; bool nosfx; @@ -99,8 +96,8 @@ CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVA self = 1.f; ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self); - snd_sfxvolume.Callback(); - snd_musicvolume.Callback(); + snd_sfxvolume->Callback(); + snd_musicvolume->Callback(); } //========================================================================== @@ -178,11 +175,11 @@ public: } // Starts a sound. - FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) + FISoundChannel *StartSound (SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) { return NULL; } - FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) + FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, float pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) { return NULL; } @@ -283,7 +280,7 @@ void I_InitSound () GSnd = new NullSoundRenderer; Printf (TEXTCOLOR_RED"Sound init failed. Using nosound.\n"); } - snd_sfxvolume.Callback (); + snd_sfxvolume->Callback (); } @@ -302,6 +299,7 @@ const char *GetSampleTypeName(SampleType type) { case SampleType_UInt8: return "Unsigned 8-bit"; case SampleType_Int16: return "Signed 16-bit"; + default: break; } return "(invalid sample type)"; } diff --git a/src/common/audio/sound/i_sound.h b/src/common/audio/sound/i_sound.h index 060838edf..b2f281f29 100644 --- a/src/common/audio/sound/i_sound.h +++ b/src/common/audio/sound/i_sound.h @@ -35,6 +35,7 @@ #ifndef __I_SOUND__ #define __I_SOUND__ +#include #include #include "i_soundinternal.h" #include "zstring.h" @@ -62,7 +63,7 @@ enum ECodecType class SoundStream { public: - virtual ~SoundStream () {} + virtual ~SoundStream() = default; enum { // For CreateStream @@ -75,11 +76,18 @@ public: Loop = 16 }; + struct Position { + uint64_t samplesplayed; + std::chrono::nanoseconds latency; + }; + virtual bool Play(bool looping, float volume) = 0; virtual void Stop() = 0; virtual void SetVolume(float volume) = 0; virtual bool SetPaused(bool paused) = 0; virtual bool IsEnded() = 0; + // Be aware this can be called during the callback invocation after Play is called. + virtual Position GetPlayPosition() = 0; virtual FString GetStats(); }; @@ -107,10 +115,10 @@ public: // Streaming sounds. virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; - + // Starts a sound. - virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; - virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; + virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; + virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, float pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; // Stops a sound channel. virtual void StopChannel (FISoundChannel *chan) = 0; diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index 252688572..81ec4cae7 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -36,7 +36,7 @@ #include #include "c_cvars.h" -#include "templates.h" + #include "oalsound.h" #include "c_dispatch.h" #include "v_text.h" @@ -110,7 +110,6 @@ ReverbContainer *ForcedEnvironment; EXTERN_CVAR (Int, snd_channels) EXTERN_CVAR (Int, snd_samplerate) EXTERN_CVAR (Bool, snd_waterreverb) -EXTERN_CVAR (Bool, snd_pitched) EXTERN_CVAR (Int, snd_hrtf) @@ -183,6 +182,8 @@ class OpenALSoundStream : public SoundStream std::atomic Playing; //bool Looping; ALfloat Volume; + uint64_t Offset = 0; + std::mutex Mutex; bool SetupSource() { @@ -263,6 +264,7 @@ public: return true; /* Clear the buffer queue, then fill and queue each buffer */ + Offset = 0; alSourcei(Source, AL_BUFFER, 0); for(int i = 0;i < BufferCount;i++) { @@ -297,6 +299,7 @@ public: alSourcei(Source, AL_BUFFER, 0); getALError(); + Offset = 0; Playing.store(false); } @@ -324,12 +327,49 @@ public: virtual bool IsEnded() { return !Playing.load(); - } + } + + Position GetPlayPosition() override + { + using namespace std::chrono; + + std::lock_guard _{Mutex}; + ALint64SOFT offset[2]{}; + ALint state{}, queued{}; + alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued); + if(Renderer->AL.SOFT_source_latency) + { + // AL_SAMPLE_OFFSET_LATENCY_SOFT fills offset[0] with the source sample + // offset in 32.32 fixed-point (which we chop off the sub-sample position + // since it's not crucial), and offset[1] with the playback latency in + // nanoseconds (how many nanoseconds until the sample point in offset[0] + // reaches the DAC). + Renderer->alGetSourcei64vSOFT(Source, AL_SAMPLE_OFFSET_LATENCY_SOFT, offset); + offset[0] >>= 32; + } + else + { + // Without AL_SOFT_source_latency, we can only get the sample offset, no + // latency info. + ALint ioffset{}; + alGetSourcei(Source, AL_SAMPLE_OFFSET, &ioffset); + offset[0] = ioffset; + offset[1] = 0; + } + alGetSourcei(Source, AL_SOURCE_STATE, &state); + // If the source is stopped, there was an underrun, so the play position is + // the end of the queue. + if(state == AL_STOPPED) + return Position{Offset + queued*(Data.Size()/FrameSize), nanoseconds{offset[1]}}; + // The offset is otherwise valid as long as the source has been started. + if(state != AL_INITIAL) + return Position{Offset + offset[0], nanoseconds{offset[1]}}; + return Position{0, nanoseconds{0}}; + } virtual FString GetStats() { FString stats; - size_t pos = 0, len = 0; ALfloat volume; ALint offset; ALint processed; @@ -387,8 +427,12 @@ public: // Unqueue the oldest buffer, fill it with more data, and queue it // on the end - alSourceUnqueueBuffers(Source, 1, &bufid); - processed--; + { + std::lock_guard _{Mutex}; + alSourceUnqueueBuffers(Source, 1, &bufid); + Offset += Data.Size() / FrameSize; + processed--; + } if(Callback(this, &Data[0], Data.Size(), UserData)) { @@ -482,8 +526,6 @@ public: #define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */ -#define PITCH(pitch) (snd_pitched ? (pitch)/128.f : 1.f) - static size_t GetChannelCount(ChannelConfig chans) { switch(chans) @@ -579,7 +621,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() // Make sure one source is capable of stereo output with the rest doing // mono, without running out of voices attribs.Push(ALC_MONO_SOURCES); - attribs.Push(std::max(snd_channels, 2) - 1); + attribs.Push(max(snd_channels, 2) - 1); attribs.Push(ALC_STEREO_SOURCES); attribs.Push(1); if(ALC.SOFT_HRTF) @@ -625,6 +667,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS"); AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates"); AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points"); + AL.SOFT_source_latency = !!alIsExtensionPresent("AL_SOFT_source_latency"); AL.SOFT_source_resampler = !!alIsExtensionPresent("AL_SOFT_source_resampler"); AL.SOFT_source_spatialize = !!alIsExtensionPresent("AL_SOFT_source_spatialize"); @@ -652,6 +695,8 @@ OpenALSoundRenderer::OpenALSoundRenderer() alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT; } + if(AL.SOFT_source_latency) + LOAD_FUNC(alGetSourcei64vSOFT); if(AL.SOFT_source_resampler) LOAD_FUNC(alGetStringiSOFT); @@ -681,7 +726,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() // At least Apple's OpenAL implementation returns zeroes, // although it can generate reasonable number of sources. - const int numChannels = std::max(snd_channels, 2); + const int numChannels = max(snd_channels, 2); int numSources = numMono + numStereo; if (0 == numSources) @@ -689,7 +734,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() numSources = numChannels; } - Sources.Resize(std::min(numChannels, numSources)); + Sources.Resize(min(numChannels, numSources)); for(unsigned i = 0;i < Sources.Size();i++) { alGenSources(1, &Sources[i]); @@ -1176,7 +1221,7 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int return stream; } -FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) +FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) { if(FreeSfx.Size() == 0) { @@ -1222,9 +1267,9 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); } if(WasInWater && !(chanflags&SNDF_NOREVERB)) - alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); + alSourcef(source, AL_PITCH, pitch * PITCH_MULT); else - alSourcef(source, AL_PITCH, PITCH(pitch)); + alSourcef(source, AL_PITCH, pitch); if(!reuse_chan || reuse_chan->StartTime == 0) { @@ -1278,7 +1323,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int } FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, - FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, + FRolloffInfo *rolloff, float distscale, float pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) { float dist_sqr = (float)(pos - listener->position).LengthSquared(); @@ -1346,7 +1391,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener float gain = GetRolloff(rolloff, dist * distscale); // Don't let the ref distance go to 0, or else distance attenuation is // lost with the inverse distance model. - alSourcef(source, AL_REFERENCE_DISTANCE, std::max(gain*dist, 0.0004f)); + alSourcef(source, AL_REFERENCE_DISTANCE, max(gain*dist, 0.0004f)); alSourcef(source, AL_MAX_DISTANCE, std::numeric_limits::max()); alSourcef(source, AL_ROLLOFF_FACTOR, 1.f); } @@ -1390,9 +1435,9 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSourcef(source, AL_ROOM_ROLLOFF_FACTOR, 0.f); } if(WasInWater && !(chanflags&SNDF_NOREVERB)) - alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); + alSourcef(source, AL_PITCH, pitch * PITCH_MULT); else - alSourcef(source, AL_PITCH, PITCH(pitch)); + alSourcef(source, AL_PITCH, pitch); if(!reuse_chan || reuse_chan->StartTime == 0) { @@ -1466,9 +1511,9 @@ void OpenALSoundRenderer::ChannelPitch(FISoundChannel *chan, float pitch) ALuint source = GET_PTRID(chan->SysChannel); if (WasInWater && !(chan->ChanFlags & CHANF_UI)) - alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)*PITCH_MULT); + alSourcef(source, AL_PITCH, max(pitch, 0.0001f)*PITCH_MULT); else - alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)); + alSourcef(source, AL_PITCH, max(pitch, 0.0001f)); } void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) @@ -1622,7 +1667,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh { float dist = sqrtf(dist_sqr); float gain = GetRolloff(&chan->Rolloff, dist * chan->DistanceScale); - alSourcef(source, AL_REFERENCE_DISTANCE, std::max(gain*dist, 0.0004f)); + alSourcef(source, AL_REFERENCE_DISTANCE, max(gain*dist, 0.0004f)); } alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); @@ -1676,7 +1721,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) const_cast(env)->Modified = false; } - + // NOTE: Moving into and out of water will undo pitch variations on sounds. if(listener->underwater || env->SoftwareWater) { @@ -1714,7 +1759,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) { ALuint source = GET_PTRID(schan->SysChannel); if (source && !(schan->ChanFlags & CHANF_UI)) - alSourcef(source, AL_PITCH, schan->Pitch / 128.0f * PITCH_MULT); + alSourcef(source, AL_PITCH, schan->Pitch * PITCH_MULT); schan = schan->NextChan; } getALError(); @@ -1722,7 +1767,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } else if(WasInWater) { - + WasInWater = false; if(EnvSlot != 0) @@ -1752,7 +1797,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) { ALuint source = GET_PTRID(schan->SysChannel); if (source && !(schan->ChanFlags & CHANF_UI)) - alSourcef(source, AL_PITCH, schan->Pitch / 128.0f); + alSourcef(source, AL_PITCH, schan->Pitch); schan = schan->NextChan; } getALError(); diff --git a/src/common/audio/sound/oalsound.h b/src/common/audio/sound/oalsound.h index 13fa3e588..90cb8c8bd 100644 --- a/src/common/audio/sound/oalsound.h +++ b/src/common/audio/sound/oalsound.h @@ -21,100 +21,7 @@ #include "alc.h" #endif -#include "efx.h" - -#ifndef ALC_ENUMERATE_ALL_EXT -#define ALC_ENUMERATE_ALL_EXT 1 -#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 -#define ALC_ALL_DEVICES_SPECIFIER 0x1013 -#endif - -#ifndef ALC_EXT_disconnect -#define ALC_EXT_disconnect 1 -#define ALC_CONNECTED 0x313 -#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 -#define ALC_OUTPUT_LIMITER_SOFT 0x199A - -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_EXT_source_distance_model -#define AL_EXT_source_distance_model 1 -#define AL_SOURCE_DISTANCE_MODEL 0x200 -#endif - -#ifndef AL_SOFT_loop_points -#define AL_SOFT_loop_points 1 -#define AL_LOOP_POINTS_SOFT 0x2015 -#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_MCFORMATS -#define AL_EXT_MCFORMATS 1 -#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_SOURCE_RADIUS -#define AL_EXT_SOURCE_RADIUS 1 -#define AL_SOURCE_RADIUS 0x1031 -#endif - -#ifndef AL_SOFT_source_resampler -#define AL_SOFT_source_resampler 1 -#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 +#include "alext.h" class OpenALSoundStream; @@ -138,8 +45,8 @@ public: virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata); // Starts a sound. - virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime); - virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime); + FISoundChannel *StartSound(SoundHandle sfx, float vol, float pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) override; + FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, float pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) override; // Changes a channel's volume. virtual void ChannelVolume(FISoundChannel *chan, float volume); @@ -190,6 +97,7 @@ private: bool EXT_SOURCE_RADIUS; bool SOFT_deferred_updates; bool SOFT_loop_points; + bool SOFT_source_latency; bool SOFT_source_resampler; bool SOFT_source_spatialize; } AL; @@ -239,6 +147,8 @@ private: LPALGETSTRINGISOFT alGetStringiSOFT; + LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT; + void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device); void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device); diff --git a/src/common/audio/sound/s_environment.cpp b/src/common/audio/sound/s_environment.cpp index d2e52e21a..7a2dbd9a5 100644 --- a/src/common/audio/sound/s_environment.cpp +++ b/src/common/audio/sound/s_environment.cpp @@ -34,7 +34,7 @@ #include "s_soundinternal.h" #include "sc_man.h" -#include "templates.h" + #include "cmdlib.h" @@ -530,7 +530,7 @@ void S_ReadReverbDef (FScanner &sc) { const ReverbContainer *def; ReverbContainer *newenv; - REVERB_PROPERTIES props; + REVERB_PROPERTIES props = {}; char *name; int id1, id2, i, j; bool inited[NUM_REVERB_FIELDS]; diff --git a/src/common/audio/sound/s_reverbedit.cpp b/src/common/audio/sound/s_reverbedit.cpp index 25993a400..a8ce5ac0d 100644 --- a/src/common/audio/sound/s_reverbedit.cpp +++ b/src/common/audio/sound/s_reverbedit.cpp @@ -36,7 +36,7 @@ #include "s_soundinternal.h" #include "sc_man.h" #include "cmdlib.h" -#include "templates.h" + #include "filesystem.h" #include "i_system.h" #include "printf.h" @@ -309,7 +309,6 @@ DEFINE_ACTION_FUNCTION(DReverbEdit, GetValue) } } ACTION_RETURN_FLOAT(v); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, SetValue) @@ -337,14 +336,12 @@ DEFINE_ACTION_FUNCTION(DReverbEdit, SetValue) } ACTION_RETURN_FLOAT(v); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, GrayCheck) { PARAM_PROLOGUE; ACTION_RETURN_BOOL(CurrentEnv->Builtin); - return 1; } DEFINE_ACTION_FUNCTION(DReverbEdit, GetSelectedEnvironment) @@ -472,12 +469,12 @@ static void SelectEnvironment(const char *envname) int newid = FirstFreeID(env->ID, env->Builtin); UCVarValue cv; cv.Int = HIBYTE(newid); - reverbedit_id1.ForceSet(cv, CVAR_Int); + reverbedit_id1->ForceSet(cv, CVAR_Int); cv.Int = LOBYTE(newid); - reverbedit_id2.ForceSet(cv, CVAR_Int); + reverbedit_id2->ForceSet(cv, CVAR_Int); FString selectname = SuggestNewName(env); cv.String = selectname.GetChars(); - reverbedit_name.ForceSet(cv, CVAR_String); + reverbedit_name->ForceSet(cv, CVAR_String); return; } } diff --git a/src/common/audio/sound/s_sound.cpp b/src/common/audio/sound/s_sound.cpp index f6acbb885..11c598f04 100644 --- a/src/common/audio/sound/s_sound.cpp +++ b/src/common/audio/sound/s_sound.cpp @@ -36,7 +36,7 @@ #include #include -#include "templates.h" + #include "s_soundinternal.h" #include "m_swap.h" #include "superfasthash.h" @@ -44,8 +44,13 @@ #include "m_random.h" #include "printf.h" #include "c_cvars.h" +#include "gamestate.h" CVARD(Bool, snd_enabled, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enables/disables sound effects") +CVAR(Bool, i_soundinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, i_pauseinbackground, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +// killough 2/21/98: optionally use varying pitched sounds +CVAR(Bool, snd_pitched, false, CVAR_ARCHIVE) int SoundEnabled() { @@ -86,7 +91,7 @@ void SoundEngine::Clear() { StopAllChannels(); UnloadAllSounds(); - GetSounds().Clear(); + S_sfx.Clear(); ClearRandoms(); } @@ -116,11 +121,11 @@ void SoundEngine::Shutdown () // //========================================================================== -void SoundEngine::MarkUsed(int id) +void SoundEngine::MarkUsed(FSoundID sid) { - if ((unsigned)id < S_sfx.Size()) + if (isValidSoundId(sid)) { - S_sfx[id].bUsed = true; + S_sfx[sid.index()].bUsed = true; } } @@ -164,10 +169,9 @@ void SoundEngine::CacheSound (sfxinfo_t *sfx) { if (GSnd && !sfx->bTentative) { - sfxinfo_t *orig = sfx; - while (!sfx->bRandomHeader && sfx->link != sfxinfo_t::NO_LINK) + while (!sfx->bRandomHeader && isValidSoundId(sfx->link)) { - sfx = &S_sfx[sfx->link]; + sfx = &S_sfx[sfx->link.index()]; } if (sfx->bRandomHeader) { @@ -313,7 +317,7 @@ FString SoundEngine::ListSoundChannels() CalcPosVel(chan, &chanorigin, nullptr); - output.AppendFormat("%s at (%1.5f, %1.5f, %1.5f)\n", (const char*)S_sfx[chan->SoundID].name.GetChars(), chanorigin.X, chanorigin.Y, chanorigin.Z); + output.AppendFormat("%s at (%1.5f, %1.5f, %1.5f)\n", (const char*)S_sfx[chan->SoundID.index()].name.GetChars(), chanorigin.X, chanorigin.Y, chanorigin.Z); count++; } } @@ -352,7 +356,7 @@ bool SoundEngine::ValidatePosVel(const FSoundChan* const chan, const FVector3& p FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &attenuation) { - const sfxinfo_t &sfx = S_sfx[soundid]; + const sfxinfo_t &sfx = S_sfx[soundid.index()]; if (sfx.bRandomHeader) { @@ -366,6 +370,31 @@ FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &a } } +//========================================================================== +// +// +// +//========================================================================== + +static float CalcPitch(int pitchmask, float defpitch, float defpitchmax) +{ + if (defpitch > 0.0) // $PitchSet overrides $PitchShift + { + if (defpitchmax > 0.0 && defpitch != defpitchmax) + { + defpitch = pr_soundpitch.GenRand_Real1() * (defpitchmax - defpitch) + defpitch; + } + return defpitch; + } + + // Vary the sfx pitches. Overridden by $PitchSet and A_StartSound. + if (pitchmask != 0 && snd_pitched) + { + return (DEFAULT_PITCH - (pr_soundpitch() & pitchmask) + (pr_soundpitch() & pitchmask)) / (float)DEFAULT_PITCH; + } + return 1.f; +} + //========================================================================== // // S_StartSound @@ -383,13 +412,12 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, sfxinfo_t *sfx; EChanFlags chanflags = flags; int basepriority; - int org_id; - int pitch; + FSoundID org_id; FSoundChan *chan; FVector3 pos, vel; FRolloffInfo *rolloff; - if (sound_id <= 0 || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds) + if (!isValidSoundId(sound_id) || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds) return NULL; // prevent crashes. @@ -403,11 +431,11 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, { return nullptr; } - - sfx = &S_sfx[sound_id]; + + sfx = &S_sfx[sound_id.index()]; // Scale volume according to SNDINFO data. - volume = std::min(volume * sfx->Volume, 1.f); + volume = min(volume * sfx->Volume, 1.f); if (volume <= 0) return NULL; @@ -417,15 +445,14 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, float limit_range = sfx->LimitRange; float defpitch = sfx->DefPitch; float defpitchmax = sfx->DefPitchMax; - auto pitchmask = sfx->PitchMask; rolloff = &sfx->Rolloff; // Resolve player sounds, random sounds, and aliases while (sfx->link != sfxinfo_t::NO_LINK) { sound_id = ResolveSound(source, type, sound_id, attenuation); - if (sound_id < 0) return nullptr; - auto newsfx = &S_sfx[sound_id]; + if (!isValidSoundId(sound_id)) return nullptr; + auto newsfx = &S_sfx[sound_id.index()]; if (newsfx != sfx) { if (near_limit < 0) @@ -540,16 +567,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, return NULL; } - // Vary the sfx pitches. Overridden by $PitchSet and A_StartSound. - if (pitchmask != 0) - { - pitch = DEFAULT_PITCH - (rand() & pitchmask) + (rand() & pitchmask); - } - else - { - pitch = DEFAULT_PITCH; - } - + float pitch = spitch > 0 ? spitch : CalcPitch(sfx->PitchMask, defpitch, defpitchmax); if (chanflags & CHANF_EVICTED) { chan = NULL; @@ -593,7 +611,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, if (chan != NULL) { chan->SoundID = sound_id; - chan->OrgID = FSoundID(org_id); + chan->OrgID = org_id; chan->EntChannel = channel; chan->Volume = float(volume); chan->ChanFlags |= chanflags; @@ -612,27 +630,6 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, { chan->Source = source; } - - if (spitch > 0.0) // A_StartSound has top priority over all others. - SetPitch(chan, spitch); - else if (defpitch > 0.0) // $PitchSet overrides $PitchShift - { - if (defpitchmax > 0.0) - { - if (defpitchmax < defpitch) - std::swap(defpitch, defpitchmax); - - if (defpitch != defpitchmax) - { - FRandom &rng = pr_soundpitch; - int random = (rng)(0x7FFF); - float frandom = random / float(0x7FFF); - - defpitch = frandom * (defpitchmax - defpitch) + defpitch; - } - } - SetPitch(chan, defpitch); - } } return chan; @@ -651,7 +648,7 @@ void SoundEngine::RestartChannel(FSoundChan *chan) assert(chan->ChanFlags & CHANF_EVICTED); FSoundChan *ochan; - sfxinfo_t *sfx = &S_sfx[chan->SoundID]; + sfxinfo_t *sfx = &S_sfx[chan->SoundID.index()]; // If this is a singular sound, don't play it if it's already playing. if (sfx->bSingular && CheckSingular(chan->SoundID)) @@ -686,7 +683,7 @@ void SoundEngine::RestartChannel(FSoundChan *chan) // If this sound doesn't like playing near itself, don't play it if // that's what would happen. - if (chan->NearLimit > 0 && CheckSoundLimit(&S_sfx[chan->SoundID], pos, chan->NearLimit, chan->LimitRange, 0, NULL, 0, chan->DistanceScale)) + if (chan->NearLimit > 0 && CheckSoundLimit(&S_sfx[chan->SoundID.index()], pos, chan->NearLimit, chan->LimitRange, 0, NULL, 0, chan->DistanceScale)) { return; } @@ -727,7 +724,7 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) { return sfx; } - + // See if there is another sound already initialized with this lump. If so, // then set this one up as a link, and don't load the sound again. for (i = 0; i < S_sfx.Size(); i++) @@ -736,7 +733,7 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) (!sfx->bLoadRAW || (sfx->RawRate == S_sfx[i].RawRate))) // Raw sounds with different sample rates may not share buffers, even if they use the same source data. { DPrintf (DMSG_NOTIFY, "Linked %s to %s (%d)\n", sfx->name.GetChars(), S_sfx[i].name.GetChars(), i); - sfx->link = i; + sfx->link = FSoundID::fromInt(i); // This is necessary to avoid using the rolloff settings of the linked sound if its // settings are different. if (sfx->Rolloff.MinDistance == 0) sfx->Rolloff = S_Rolloff; @@ -797,7 +794,7 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) // //========================================================================== -bool SoundEngine::CheckSingular(int sound_id) +bool SoundEngine::CheckSingular(FSoundID sound_id) { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { @@ -831,11 +828,11 @@ bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_ { FSoundChan *chan; int count; - + for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan) { if (chan->ChanFlags & CHANF_FORGETTABLE) continue; - if (!(chan->ChanFlags & CHANF_EVICTED) && &S_sfx[chan->SoundID] == sfx) + if (!(chan->ChanFlags & CHANF_EVICTED) && &S_sfx[chan->SoundID.index()] == sfx) { FVector3 chanorigin; @@ -847,7 +844,7 @@ bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_ CalcPosVel(chan, &chanorigin, NULL); // scale the limit distance with the attenuation. An attenuation of 0 means the limit distance is infinite and all sounds within the level are inside the limit. - float attn = std::min(chan->DistanceScale, attenuation); + float attn = min(chan->DistanceScale, attenuation); if (attn <= 0 || (chanorigin - pos).LengthSquared() <= limit_range / attn) { count++; @@ -865,7 +862,7 @@ bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_ // //========================================================================== -void SoundEngine::StopSoundID(int sound_id) +void SoundEngine::StopSoundID(FSoundID sound_id) { FSoundChan* chan = Channels; while (chan != NULL) @@ -887,13 +884,13 @@ void SoundEngine::StopSoundID(int sound_id) // //========================================================================== -void SoundEngine::StopSound (int channel, int sound_id) +void SoundEngine::StopSound (int channel, FSoundID sound_id) { FSoundChan *chan = Channels; while (chan != NULL) { FSoundChan *next = chan->NextChan; - if ((chan->SourceType == SOURCE_None && (sound_id == -1 || sound_id == chan->OrgID)) && (channel == CHAN_AUTO || channel == chan->EntChannel)) + if ((chan->SourceType == SOURCE_None && (sound_id == INVALID_SOUND || sound_id == chan->OrgID)) && (channel == CHAN_AUTO || channel == chan->EntChannel)) { StopChannel(chan); } @@ -909,7 +906,7 @@ void SoundEngine::StopSound (int channel, int sound_id) // //========================================================================== -void SoundEngine::StopSound(int sourcetype, const void* actor, int channel, int sound_id) +void SoundEngine::StopSound(int sourcetype, const void* actor, int channel, FSoundID sound_id) { FSoundChan* chan = Channels; while (chan != NULL) @@ -917,7 +914,7 @@ void SoundEngine::StopSound(int sourcetype, const void* actor, int channel, int FSoundChan* next = chan->NextChan; if (chan->SourceType == sourcetype && chan->Source == actor && - (sound_id == -1? (chan->EntChannel == channel || channel < 0) : (chan->OrgID == sound_id))) + (sound_id == INVALID_SOUND? (chan->EntChannel == channel || channel < 0) : (chan->OrgID == sound_id))) { StopChannel(chan); } @@ -1057,13 +1054,13 @@ void SoundEngine::SetVolume(FSoundChan* chan, float volume) // //========================================================================== -void SoundEngine::ChangeSoundPitch(int sourcetype, const void *source, int channel, double pitch, int sound_id) +void SoundEngine::ChangeSoundPitch(int sourcetype, const void *source, int channel, double pitch, FSoundID sound_id) { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { if (chan->SourceType == sourcetype && chan->Source == source && - (sound_id == -1? (chan->EntChannel == channel) : (chan->OrgID == sound_id))) + (sound_id == INVALID_SOUND? (chan->EntChannel == channel) : (chan->OrgID == sound_id))) { SetPitch(chan, (float)pitch); } @@ -1074,8 +1071,8 @@ void SoundEngine::ChangeSoundPitch(int sourcetype, const void *source, int chann void SoundEngine::SetPitch(FSoundChan *chan, float pitch) { assert(chan != nullptr); - GSnd->ChannelPitch(chan, std::max(0.0001f, pitch)); - chan->Pitch = std::max(1, int(float(DEFAULT_PITCH) * pitch)); + GSnd->ChannelPitch(chan, max(0.0001f, pitch)); + chan->Pitch = pitch; } //========================================================================== @@ -1085,13 +1082,14 @@ void SoundEngine::SetPitch(FSoundChan *chan, float pitch) // Is a sound being played by a specific emitter? //========================================================================== -int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int sound_id) +int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, FSoundID sound_id, int chann) { int count = 0; - if (sound_id > 0) + if (sound_id.isvalid()) { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { + if (chann != -1 && chann != chan->EntChannel) continue; if (chan->OrgID == sound_id && (sourcetype == SOURCE_Any || (chan->SourceType == sourcetype && chan->Source == source))) @@ -1104,6 +1102,7 @@ int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int so { for (FSoundChan* chan = Channels; chan != NULL; chan = chan->NextChan) { + if (chann != -1 && chann != chan->EntChannel) continue; if ((sourcetype == SOURCE_Any || (chan->SourceType == sourcetype && chan->Source == source))) { count++; @@ -1149,13 +1148,13 @@ bool SoundEngine::IsChannelUsed(int sourcetype, const void *actor, int channel, // //========================================================================== -bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, int channel, int sound_id) +bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, int channel, FSoundID sound_id) { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { if (chan->SourceType == sourcetype && (sourcetype == SOURCE_None || sourcetype == SOURCE_Unattached || chan->Source == actor)) { - if ((channel == 0 || chan->EntChannel == channel) && (sound_id <= 0 || chan->OrgID == sound_id)) + if ((channel == 0 || chan->EntChannel == channel) && (sound_id == INVALID_SOUND || chan->OrgID == sound_id)) { return true; } @@ -1351,7 +1350,7 @@ void SoundEngine::ChannelEnded(FISoundChannel *ichan) else { unsigned int pos = GSnd->GetPosition(schan); - unsigned int len = GSnd->GetSampleLength(S_sfx[schan->SoundID].data); + unsigned int len = GSnd->GetSampleLength(S_sfx[schan->SoundID.index()].data); if (pos == 0) { evicted = !!(schan->ChanFlags & CHANF_JUSTSTARTED); @@ -1459,29 +1458,19 @@ void SoundEngine::Reset() // Given a logical name, find the sound's index in S_sfx. //========================================================================== -int SoundEngine::FindSound(const char* logicalname) +FSoundID SoundEngine::FindSound(const char* logicalname) { - int i; - - if (logicalname != NULL) - { - i = S_sfx[MakeKey(logicalname) % S_sfx.Size()].index; - - while ((i != 0) && stricmp(S_sfx[i].name, logicalname)) - i = S_sfx[i].next; - - return i; - } - else - { - return 0; - } + if (!logicalname) return NO_SOUND; + FName name(logicalname, true); + if (name == NAME_None) return NO_SOUND; + auto p = SoundMap.CheckKey(name); + return p ? *p : NO_SOUND; } -int SoundEngine::FindSoundByResID(int resid) +FSoundID SoundEngine::FindSoundByResID(int resid) { auto p = ResIdMap.CheckKey(resid); - return p ? *p : 0; + return p ? *p : NO_SOUND; } //========================================================================== @@ -1492,18 +1481,41 @@ int SoundEngine::FindSoundByResID(int resid) // using the hash table. //========================================================================== -int SoundEngine::FindSoundNoHash(const char* logicalname) +FSoundID SoundEngine::FindSoundNoHash(const char* logicalname) +{ + if (!logicalname) return NO_SOUND; + FName name(logicalname, true); + if (name == NAME_None) return NO_SOUND; + + for (unsigned i = 1; i < S_sfx.Size(); i++) + { + if (S_sfx[i].name == name) + { + return FSoundID::fromInt(i); + } + } + return NO_SOUND; +} + +//========================================================================== +// +// S_FindSoundByResIDNoHash +// +// same with resource IDs. +//========================================================================== + +FSoundID SoundEngine::FindSoundByResIDNoHash(int resid) { unsigned int i; for (i = 1; i < S_sfx.Size(); i++) { - if (stricmp(S_sfx[i].name, logicalname) == 0) + if (S_sfx[i].ResourceId == resid) { - return i; + return FSoundID::fromInt(i); } } - return 0; + return NO_SOUND; } //========================================================================== @@ -1513,7 +1525,7 @@ int SoundEngine::FindSoundNoHash(const char* logicalname) // Given a sound lump, find the sound's index in S_sfx. //========================================================================== -int SoundEngine::FindSoundByLump(int lump) +FSoundID SoundEngine::FindSoundByLump(int lump) { if (lump != -1) { @@ -1521,9 +1533,9 @@ int SoundEngine::FindSoundByLump(int lump) for (i = 1; i < S_sfx.Size(); i++) if (S_sfx[i].lumpnum == lump) - return i; + return FSoundID::fromInt(i); } - return 0; + return NO_SOUND; } //========================================================================== @@ -1533,21 +1545,19 @@ int SoundEngine::FindSoundByLump(int lump) // Adds a new sound mapping to S_sfx. //========================================================================== -int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid, int nearlimit) +FSoundID SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid, int nearlimit) { S_sfx.Reserve(1); sfxinfo_t &newsfx = S_sfx.Last(); newsfx.name = logicalname; newsfx.lumpnum = lump; - newsfx.next = 0; newsfx.PitchMask = CurrentPitchMask; newsfx.NearLimit = nearlimit; newsfx.ResourceId = resid; newsfx.bTentative = false; - - if (resid >= 0) ResIdMap[resid] = S_sfx.Size() - 1; - return (int)S_sfx.Size()-1; + auto id = FSoundID::fromInt(S_sfx.Size() - 1); + return id; } @@ -1560,13 +1570,13 @@ int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitc // an associated lump is created. //========================================================================== -int SoundEngine::FindSoundTentative(const char* name) +FSoundID SoundEngine::FindSoundTentative(const char* name, int nearlimit) { - int id = FindSoundNoHash(name); - if (id == 0) + auto id = FindSoundNoHash(name); + if (id == NO_SOUND) { - id = AddSoundLump(name, -1, 0); - S_sfx[id].bTentative = true; + id = AddSoundLump(name, -1, 0, -1, nearlimit); + S_sfx[id.index()].bTentative = true; } return id; } @@ -1584,12 +1594,12 @@ void SoundEngine::CacheRandomSound(sfxinfo_t* sfx) { if (sfx->bRandomHeader) { - const FRandomSoundList* list = &S_rnd[sfx->link]; + const FRandomSoundList* list = &S_rnd[sfx->link.index()]; for (unsigned i = 0; i < list->Choices.Size(); ++i) { - sfx = &S_sfx[list->Choices[i]]; + sfx = &S_sfx[list->Choices[i].index()]; sfx->bUsed = true; - CacheSound(&S_sfx[list->Choices[i]]); + CacheSound(&S_sfx[list->Choices[i].index()]); } } } @@ -1605,12 +1615,12 @@ void SoundEngine::CacheRandomSound(sfxinfo_t* sfx) unsigned int SoundEngine::GetMSLength(FSoundID sound) { - if ((unsigned int)sound >= S_sfx.Size()) + if (!isValidSoundId(sound)) { return 0; } - sfxinfo_t* sfx = &S_sfx[sound]; + sfxinfo_t* sfx = &S_sfx[sound.index()]; // Resolve player sounds, random sounds, and aliases if (sfx->link != sfxinfo_t::NO_LINK) @@ -1622,7 +1632,7 @@ unsigned int SoundEngine::GetMSLength(FSoundID sound) // I think the longest one makes more sense. int length = 0; - const FRandomSoundList* list = &S_rnd[sfx->link]; + const FRandomSoundList* list = &S_rnd[sfx->link.index()]; for (auto& me : list->Choices) { @@ -1634,7 +1644,7 @@ unsigned int SoundEngine::GetMSLength(FSoundID sound) } else { - sfx = &S_sfx[sfx->link]; + sfx = &S_sfx[sfx->link.index()]; } } @@ -1651,11 +1661,11 @@ unsigned int SoundEngine::GetMSLength(FSoundID sound) // is not the head of a random list, then the sound passed is returned. //========================================================================== -int SoundEngine::PickReplacement(int refid) +FSoundID SoundEngine::PickReplacement(FSoundID refid) { - while (S_sfx[refid].bRandomHeader) + while (S_sfx[refid.index()].bRandomHeader) { - const FRandomSoundList* list = &S_rnd[S_sfx[refid].link]; + const FRandomSoundList* list = &S_rnd[S_sfx[refid.index()].link.index()]; refid = list->Choices[rand() % int(list->Choices.Size())]; } return refid; @@ -1670,36 +1680,32 @@ int SoundEngine::PickReplacement(int refid) void SoundEngine::HashSounds() { - unsigned int i; - unsigned int j; - unsigned int size; - S_sfx.ShrinkToFit(); - size = S_sfx.Size(); + SoundMap.Clear(); + ResIdMap.Clear(); - // Mark all buckets as empty - for (i = 0; i < size; i++) - S_sfx[i].index = 0; - - // Now set up the chains - for (i = 1; i < size; i++) + for (unsigned i = 1; i < S_sfx.Size(); i++) { - j = MakeKey(S_sfx[i].name) % size; - S_sfx[i].next = S_sfx[j].index; - S_sfx[j].index = i; + SoundMap.Insert(S_sfx[i].name, FSoundID::fromInt(i)); + if (S_sfx[i].ResourceId != -1) + { + ResIdMap.Insert(S_sfx[i].ResourceId, FSoundID::fromInt(i)); + } } S_rnd.ShrinkToFit(); + + } -void SoundEngine::AddRandomSound(int Owner, TArray list) +void SoundEngine::AddRandomSound(FSoundID Owner, TArray list) { auto index = S_rnd.Reserve(1); auto& random = S_rnd.Last(); random.Choices = std::move(list); random.Owner = Owner; - S_sfx[Owner].link = index; - S_sfx[Owner].bRandomHeader = true; - S_sfx[Owner].NearLimit = -1; + S_sfx[Owner.index()].link = FSoundID::fromInt(index); + S_sfx[Owner.index()].bRandomHeader = true; + S_sfx[Owner.index()].NearLimit = -1; } void S_SoundReset() @@ -1709,3 +1715,149 @@ void S_SoundReset() S_RestartMusic(); } +//========================================================================== +// +// CCMD cachesound +// +//========================================================================== + +#include "s_music.h" +#include "vm.h" +#include "c_dispatch.h" +#include "stats.h" +#include "i_net.h" +#include "i_interface.h" + + +CCMD(cachesound) +{ + if (argv.argc() < 2) + { + Printf("Usage: cachesound ...\n"); + return; + } + for (int i = 1; i < argv.argc(); ++i) + { + FSoundID sfxnum = S_FindSound(argv[i]); + if (sfxnum != NO_SOUND) + { + soundEngine->CacheSound(sfxnum); + } + } +} + + +CCMD(listsoundchannels) +{ + Printf("%s", soundEngine->ListSoundChannels().GetChars()); +} + +// intentionally moved here to keep the s_music include out of the rest of the file. + +//========================================================================== +// +// S_PauseSound +// +// Stop music and sound effects, during game PAUSE. +//========================================================================== + +void S_PauseSound(bool notmusic, bool notsfx) +{ + if (!notmusic) + { + S_PauseMusic(); + } + if (!notsfx) + { + soundEngine->SetPaused(true); + GSnd->SetSfxPaused(true, 0); + } +} + +DEFINE_ACTION_FUNCTION(DObject, S_PauseSound) +{ + PARAM_PROLOGUE; + PARAM_BOOL(notmusic); + PARAM_BOOL(notsfx); + S_PauseSound(notmusic, notsfx); + return 0; +} + +//========================================================================== +// +// S_ResumeSound +// +// Resume music and sound effects, after game PAUSE. +//========================================================================== + +void S_ResumeSound(bool notsfx) +{ + S_ResumeMusic(); + if (!notsfx) + { + soundEngine->SetPaused(false); + GSnd->SetSfxPaused(false, 0); + } +} + +DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound) +{ + PARAM_PROLOGUE; + PARAM_BOOL(notsfx); + S_ResumeSound(notsfx); + return 0; +} + +//========================================================================== +// +// S_SetSoundPaused +// +// Called with state non-zero when the app is active, zero when it isn't. +// +//========================================================================== + +void S_SetSoundPaused(int state) +{ + if (!netgame && (i_pauseinbackground)) + { + pauseext = !state; + } + + if ((state || i_soundinbackground) && !pauseext) + { + S_ResumeSound(true); + if (GSnd != nullptr) + { + GSnd->SetInactive(SoundRenderer::INACTIVE_Active); + } + } + else + { + S_PauseSound(false, true); + if (GSnd != nullptr) + { + GSnd->SetInactive(gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL ? + SoundRenderer::INACTIVE_Complete : + SoundRenderer::INACTIVE_Mute); + } + } +} + + + +CCMD(snd_status) +{ + GSnd->PrintStatus(); +} + +CCMD(snd_listdrivers) +{ + GSnd->PrintDriversList(); +} + +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 d35cb524a..b29081fda 100644 --- a/src/common/audio/sound/s_soundinternal.h +++ b/src/common/audio/sound/s_soundinternal.h @@ -1,12 +1,7 @@ #pragma once #include "i_sound.h" - -struct FRandomSoundList -{ - TArray Choices; - uint32_t Owner = 0; -}; +#include "name.h" enum { @@ -15,47 +10,6 @@ enum -// -// SoundFX struct. -// -struct sfxinfo_t -{ - // Next field is for use by the system sound interface. - // A non-null data means the sound has been loaded. - SoundHandle data{}; - - FString name; // [RH] Sound name defined in SNDINFO - int lumpnum = sfx_empty; // lump number of sfx - - unsigned int next = -1, index = 0; // [RH] For hashing - float Volume = 1.f; - - int ResourceId = -1; // Resource ID as implemented by Blood. Not used by Doom but added for completeness. - float LimitRange = 256*256; // Range for sound limiting (squared for faster computations) - float DefPitch = 0.f; // A defined pitch instead of a random one the sound plays at, similar to A_StartSound. - float DefPitchMax = 0.f; // Randomized range with stronger control over pitch itself. - - int16_t NearLimit = 4; // 0 means unlimited. - uint8_t PitchMask = 0; - bool bRandomHeader = false; - bool bLoadRAW = false; - bool b16bit = false; - bool bUsed = false; - bool bSingular = false; - bool bTentative = true; - - TArray UserData; - - int RawRate = 0; // Sample rate to use when bLoadRAW is true - int LoopStart = -1; // -1 means no specific loop defined - - unsigned int link = NO_LINK;; - enum { NO_LINK = 0xffffffff }; - - FRolloffInfo Rolloff{}; - float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound. -}; - // Rolloff types enum { @@ -65,69 +19,96 @@ enum ROLLOFF_Custom // Lookup volume from SNDCURVE }; -inline int S_FindSoundByResID(int ndx); -inline int S_FindSound(const char* name); // An index into the S_sfx[] array. class FSoundID { public: FSoundID() = default; - - static FSoundID byResId(int ndx) + +private: + constexpr FSoundID(int id) : ID(id) { - return FSoundID(S_FindSoundByResID(ndx)); } - FSoundID(int id) +public: + static constexpr FSoundID fromInt(int i) { - ID = id; - } - FSoundID(const char *name) - { - ID = S_FindSound(name); - } - FSoundID(const FString &name) - { - ID = S_FindSound(name.GetChars()); + return FSoundID(i); } FSoundID(const FSoundID &other) = default; FSoundID &operator=(const FSoundID &other) = default; - FSoundID &operator=(const char *name) - { - ID = S_FindSound(name); - return *this; - } - FSoundID &operator=(const FString &name) - { - ID = S_FindSound(name.GetChars()); - return *this; - } bool operator !=(FSoundID other) const { return ID != other.ID; } - bool operator !=(int other) const + bool operator ==(FSoundID other) const { - return ID != other; + return ID == other.ID; } - operator int() const + bool operator ==(int other) const = delete; + bool operator !=(int other) const = delete; + constexpr int index() const { return ID; } + constexpr bool isvalid() const + { + return ID > 0; + } private: + int ID; -protected: - enum EDummy { NoInit }; - FSoundID(EDummy) {} -}; - - class FSoundIDNoInit : public FSoundID -{ -public: - FSoundIDNoInit() : FSoundID(NoInit) {} - using FSoundID::operator=; }; +constexpr FSoundID NO_SOUND = FSoundID::fromInt(0); +constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1); + + struct FRandomSoundList + { + TArray Choices; + FSoundID Owner = NO_SOUND; + }; + + + // +// SoundFX struct. +// + struct sfxinfo_t + { + // Next field is for use by the system sound interface. + // A non-null data means the sound has been loaded. + SoundHandle data{}; + + FName name; // [RH] Sound name defined in SNDINFO + int lumpnum = sfx_empty; // lump number of sfx + + float Volume = 1.f; + + int ResourceId = -1; // Resource ID as implemented by Blood. Not used by Doom but added for completeness. + float LimitRange = 256 * 256; // Range for sound limiting (squared for faster computations) + float DefPitch = 0.f; // A defined pitch instead of a random one the sound plays at, similar to A_StartSound. + float DefPitchMax = 0.f; // Randomized range with stronger control over pitch itself. + + int16_t NearLimit = 4; // 0 means unlimited. + uint8_t PitchMask = 0; + bool bRandomHeader = false; + bool bLoadRAW = false; + bool b16bit = false; + bool bUsed = false; + bool bSingular = false; + bool bTentative = true; + + TArray UserData; + + int RawRate = 0; // Sample rate to use when bLoadRAW is true + int LoopStart = -1; // -1 means no specific loop defined + + FSoundID link = NO_LINK; + constexpr static FSoundID NO_LINK = FSoundID::fromInt(-1); + + FRolloffInfo Rolloff{}; + float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound. + }; struct FSoundChan : public FISoundChannel @@ -139,7 +120,7 @@ struct FSoundChan : public FISoundChannel float Volume; int EntChannel; // Actor's sound channel. int UserData; // Not used by the engine, the caller can use this to store some additional info. - int16_t Pitch; // Pitch variation. + float Pitch; // Pitch variation. int16_t NearLimit; int8_t Priority; uint8_t SourceType; @@ -196,7 +177,7 @@ void S_SetEnvironment (const ReverbContainer *settings); ReverbContainer *S_FindEnvironment (const char *name); ReverbContainer *S_FindEnvironment (int id); void S_AddEnvironment (ReverbContainer *settings); - + class SoundEngine { protected: @@ -211,7 +192,8 @@ protected: TArray S_sfx; FRolloffInfo S_Rolloff{}; TArray S_SoundCurve; - TMap ResIdMap; + TMap SoundMap; + TMap ResIdMap; TArray S_rnd; bool blockNewSounds = false; @@ -231,8 +213,9 @@ private: bool ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel); // Checks if a copy of this sound is already playing. - bool CheckSingular(int sound_id); + bool CheckSingular(FSoundID sound_id); virtual TArray ReadSound(int lumpnum) = 0; + protected: virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel, float attenuation); virtual FSoundID ResolveSound(const void *ent, int srctype, FSoundID soundid, float &attenuation); @@ -249,15 +232,27 @@ public: blockNewSounds = on; } - virtual int SoundSourceIndex(FSoundChan* chan) { return 0; } - virtual void SetSource(FSoundChan* chan, int index) {} - virtual void StopChannel(FSoundChan* chan); sfxinfo_t* LoadSound(sfxinfo_t* sfx); - const sfxinfo_t* GetSfx(unsigned snd) + sfxinfo_t* GetWritableSfx(FSoundID snd) { - if (snd >= S_sfx.Size()) return nullptr; - return &S_sfx[snd]; + if ((unsigned)snd.index() >= S_sfx.Size()) return nullptr; + return &S_sfx[snd.index()]; + } + + const sfxinfo_t* GetSfx(FSoundID snd) + { + return GetWritableSfx(snd); + } + + unsigned GetNumSounds() const + { + return S_sfx.Size(); + } + + sfxinfo_t* AllocateSound() + { + return &S_sfx[S_sfx.Reserve(1)]; } // Initializes sound stuff, including volume @@ -279,7 +274,7 @@ public: // Loads a sound, including any random sounds it might reference. virtual void CacheSound(sfxinfo_t* sfx); - void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); } + void CacheSound(FSoundID sfx) { CacheSound(&S_sfx[sfx.index()]); } void UnloadSound(sfxinfo_t* sfx); void UnloadSound(int sfx) { @@ -292,23 +287,24 @@ public: const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f, float startTime = 0.0f); // Stops an origin-less sound from playing from this channel. - void StopSoundID(int sound_id); - void StopSound(int channel, int sound_id = -1); - void StopSound(int sourcetype, const void* actor, int channel, int sound_id = -1); + void StopSoundID(FSoundID sound_id); + void StopSound(int channel, FSoundID sound_id = INVALID_SOUND); + void StopSound(int sourcetype, const void* actor, int channel, FSoundID sound_id = INVALID_SOUND); void StopActorSounds(int sourcetype, const void* actor, int chanmin, int chanmax); void RelinkSound(int sourcetype, const void* from, const void* to, const FVector3* optpos); void ChangeSoundVolume(int sourcetype, const void* source, int channel, double dvolume); - void ChangeSoundPitch(int sourcetype, const void* source, int channel, double pitch, int sound_id = -1); - bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id = -1); + void ChangeSoundPitch(int sourcetype, const void* source, int channel, double pitch, FSoundID sound_id = INVALID_SOUND); + bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, FSoundID sound_id = INVALID_SOUND); // Stop and resume music, during game PAUSE. - int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id); + int GetSoundPlayingInfo(int sourcetype, const void* source, FSoundID sound_id, int chan = -1); void UnloadAllSounds(); void Reset(); - void MarkUsed(int num); + void MarkUsed(FSoundID num); void CacheMarkedSounds(); TArray AllActiveChannels(); + virtual void SetSoundPaused(int state) {} void MarkAllUnused() { @@ -341,31 +337,28 @@ public: } const char *GetSoundName(FSoundID id) { - return id == 0 ? "" : S_sfx[id].name.GetChars(); + return !id.isvalid() ? "" : S_sfx[id.index()].name.GetChars(); } - TArray &GetSounds() //This should only be used for constructing the sound list or for diagnostics code prinring information about the sound list. - { - return S_sfx; - } - FRolloffInfo& GlobalRolloff() // like GetSounds this is meant for sound list generators, not for gaining cheap access to the sound engine's innards. + FRolloffInfo& GlobalRolloff() // this is meant for sound list generators, not for gaining cheap access to the sound engine's innards. { return S_Rolloff; } FRandomSoundList *ResolveRandomSound(sfxinfo_t* sfx) { - return &S_rnd[sfx->link]; + return &S_rnd[sfx->link.index()]; } void ClearRandoms() { S_rnd.Clear(); } - int *GetUserData(int snd) + int *GetUserData(FSoundID snd) { - return S_sfx[snd].UserData.Data(); + return S_sfx[snd.index()].UserData.Data(); } - bool isValidSoundId(int id) + bool isValidSoundId(FSoundID sid) { - return id > 0 && id < (int)S_sfx.Size() && !S_sfx[id].bTentative && S_sfx[id].lumpnum != sfx_empty; + int id = sid.index(); + return id > 0 && id < (int)S_sfx.Size() && !S_sfx[id].bTentative && (S_sfx[id].lumpnum != sfx_empty || S_sfx[id].bRandomHeader || S_sfx[id].link != sfxinfo_t::NO_LINK); } template bool EnumerateChannels(func callback) @@ -395,17 +388,18 @@ public: virtual void SoundDone(FISoundChannel* ichan); // gets called when the sound has been completely taken down. // Lookup utilities. - int FindSound(const char* logicalname); - int FindSoundByResID(int rid); - int FindSoundNoHash(const char* logicalname); - int FindSoundByLump(int lump); - virtual int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2); - int FindSoundTentative(const char* name); + FSoundID FindSound(const char* logicalname); + FSoundID FindSoundByResID(int rid); + FSoundID FindSoundNoHash(const char* logicalname); + FSoundID FindSoundByResIDNoHash(int rid); + FSoundID FindSoundByLump(int lump); + virtual FSoundID AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2); + FSoundID FindSoundTentative(const char* name, int nearlimit = 2); void CacheRandomSound(sfxinfo_t* sfx); unsigned int GetMSLength(FSoundID sound); - int PickReplacement(int refid); + FSoundID PickReplacement(FSoundID refid); void HashSounds(); - void AddRandomSound(int Owner, TArray list); + void AddRandomSound(FSoundID Owner, TArray list); }; @@ -420,12 +414,12 @@ struct FReverbField }; -inline int S_FindSoundByResID(int ndx) +inline FSoundID S_FindSoundByResID(int ndx) { return soundEngine->FindSoundByResID(ndx); } -inline int S_FindSound(const char* name) +inline FSoundID S_FindSound(const char* name) { return soundEngine->FindSound(name); } diff --git a/src/common/console/c_bind.cpp b/src/common/console/c_bind.cpp index b390dc122..90ceaedce 100644 --- a/src/common/console/c_bind.cpp +++ b/src/common/console/c_bind.cpp @@ -41,7 +41,7 @@ #include "c_dispatch.h" #include "configfile.h" #include "filesystem.h" -#include "templates.h" + #include "i_time.h" #include "printf.h" #include "sc_man.h" @@ -49,8 +49,6 @@ #include "d_eventbase.h" -extern int chatmodeon; - const char *KeyNames[NUM_KEYS] = { // We use the DirectInput codes and assume a qwerty keyboard layout. @@ -69,7 +67,7 @@ const char *KeyNames[NUM_KEYS] = "KP2", "KP3", "KP0", "KP.", nullptr, nullptr, "OEM102", "F11", //50 "F12", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //58 nullptr, nullptr, nullptr, nullptr, "F13", "F14", "F15", "F16", //60 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //68 + "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", //68 "Kana", nullptr, nullptr, "Abnt_C1", nullptr, nullptr, nullptr, nullptr, //70 nullptr, "Convert", nullptr, "NoConvert",nullptr, "Yen", "Abnt_C2", nullptr, //78 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //80 @@ -393,7 +391,7 @@ void FKeyBindings::PerformBind(FCommandLine &argv, const char *msg) else { Printf ("%s:\n", msg); - + for (i = 0; i < NUM_KEYS; i++) { if (!Binds[i].IsEmpty()) @@ -686,6 +684,17 @@ void ReadBindings(int lump, bool override) FKeyBindings* dest = &Bindings; int key; + if (sc.Compare("unbind")) + { + sc.MustGetString(); + if (override) + { + // This is only for games to clear unsuitable base defaults, not for mods. + dest->UnbindKey(sc.String); + } + continue; + } + // bind destination is optional and is the same as the console command if (sc.Compare("bind")) { @@ -722,7 +731,18 @@ void ReadBindings(int lump, bool override) void C_SetDefaultKeys(const char* baseconfig) { auto lump = fileSystem.CheckNumForFullName("engine/commonbinds.txt"); - if (lump >= 0) ReadBindings(lump, true); + if (lump >= 0) + { + // Bail out if a mod tries to override this. Main game resources are allowed to do this, though. + auto fileno2 = fileSystem.GetFileContainer(lump); + if (fileno2 > fileSystem.GetMaxIwadNum()) + { + I_FatalError("File %s is overriding core lump %s.", + fileSystem.GetResourceFileFullName(fileno2), "engine/commonbinds.txt"); + } + + ReadBindings(lump, true); + } int lastlump = 0; while ((lump = fileSystem.FindLumpFullName(baseconfig, &lastlump)) != -1) diff --git a/src/common/console/c_buttons.cpp b/src/common/console/c_buttons.cpp index 0ea14dd46..3464553e3 100644 --- a/src/common/console/c_buttons.cpp +++ b/src/common/console/c_buttons.cpp @@ -34,7 +34,7 @@ */ #include "c_buttons.h" -#include "templates.h" + #include "c_dispatch.h" #include "printf.h" #include "cmdlib.h" @@ -101,13 +101,13 @@ int ButtonMap::ListActionCommands (const char *pattern) int ButtonMap::FindButtonIndex (const char *key, int funclen) const { if (!key) return -1; - + FName name = funclen == -1? FName(key, true) : FName(key, funclen, true); if (name == NAME_None) return -1; - + auto res = NameToNum.CheckKey(name); if (!res) return -1; - + return *res; } diff --git a/src/common/console/c_buttons.h b/src/common/console/c_buttons.h index 3567a8548..3bfbbd0fb 100644 --- a/src/common/console/c_buttons.h +++ b/src/common/console/c_buttons.h @@ -72,6 +72,12 @@ public: return Buttons[x].bWentUp; } + void ButtonSet(int x) const + { + Buttons[x].bDown = Buttons[x].bWentDown = true; + Buttons[x].bWentUp = false; + } + void ClearButton(int x) { Buttons[x].Reset(); diff --git a/src/common/console/c_commandbuffer.cpp b/src/common/console/c_commandbuffer.cpp index bf459350f..0c570da14 100644 --- a/src/common/console/c_commandbuffer.cpp +++ b/src/common/console/c_commandbuffer.cpp @@ -144,7 +144,7 @@ void FCommandBuffer::MakeStartPosGood() { // The cursor is in front of the visible part of the line n = CursorPosCells; } - StartPosCells = std::max(0, n); + StartPosCells = max(0, n); bool overflow; StartPos = CharsForCells(StartPosCells, &overflow); if (overflow) @@ -299,7 +299,7 @@ void FCommandBuffer::AddString(FString clip) } auto strp = (const uint8_t*)clip.GetChars(); while (auto chr = GetCharFromString(strp)) build += chr; - + if (Text.length() == 0) { Text = build; diff --git a/src/common/console/c_commandbuffer.h b/src/common/console/c_commandbuffer.h index be257fb24..179651c45 100644 --- a/src/common/console/c_commandbuffer.h +++ b/src/common/console/c_commandbuffer.h @@ -29,7 +29,7 @@ public: void Draw(int x, int y, int scale, bool cursor); unsigned CalcCellSize(unsigned length); unsigned CharsForCells(unsigned cellin, bool *overflow); - void MakeStartPosGood();; + void MakeStartPosGood(); void CursorStart(); void CursorEnd(); diff --git a/src/common/console/c_commandline.cpp b/src/common/console/c_commandline.cpp index 4516af4ed..4f500ffe6 100644 --- a/src/common/console/c_commandline.cpp +++ b/src/common/console/c_commandline.cpp @@ -57,17 +57,19 @@ // \c becomes just TEXTCOLOR_ESCAPE // $ is replaced by the contents of -static long ParseCommandLine(const char* args, int* argc, char** argv, bool no_escapes) +static size_t ParseCommandLine(const char* args, int* argc, char** argv, bool no_escapes) { int count; + char* buffstart; char* buffplace; count = 0; - buffplace = NULL; + buffstart = NULL; if (argv != NULL) { - buffplace = argv[0]; + buffstart = argv[0]; } + buffplace = buffstart; for (;;) { @@ -154,7 +156,7 @@ static long ParseCommandLine(const char* args, int* argc, char** argv, bool no_e { *argc = count; } - return (long)(buffplace - (char*)0); + return (buffplace - buffstart); } FCommandLine::FCommandLine (const char *commandline, bool no_escapes) diff --git a/src/common/console/c_commandline.h b/src/common/console/c_commandline.h index 88b19cc93..dc5466df1 100644 --- a/src/common/console/c_commandline.h +++ b/src/common/console/c_commandline.h @@ -50,9 +50,9 @@ public: private: const char *cmd; + bool noescapes; int _argc; char **_argv; - long argsize; - bool noescapes; + size_t argsize; }; diff --git a/src/common/console/c_console.cpp b/src/common/console/c_console.cpp index 5cafbb080..f6366d7cd 100644 --- a/src/common/console/c_console.cpp +++ b/src/common/console/c_console.cpp @@ -34,7 +34,7 @@ #include -#include "templates.h" + #include "version.h" #include "c_bind.h" #include "c_console.h" @@ -45,7 +45,7 @@ #include "filesystem.h" #include "d_gui.h" #include "cmdlib.h" -#include "d_event.h" +#include "d_eventbase.h" #include "c_consolebuffer.h" #include "utf8.h" #include "v_2ddrawer.h" @@ -95,8 +95,6 @@ static FTextureID conflat; static uint32_t conshade; static bool conline; -extern int chatmodeon; -extern FBaseCVar *CVars; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; int ConWidth; @@ -104,7 +102,9 @@ bool vidactive = false; bool cursoron = false; int ConBottom, ConScroll, RowAdjust; uint64_t CursorTicker; -constate_e ConsoleState = c_up; +uint8_t ConsoleState = c_up; + +DEFINE_GLOBAL(ConsoleState) static int TopLine, InsertLine; @@ -177,7 +177,7 @@ static void setmsgcolor (int index, int color); FILE *Logfile = NULL; -FIntCVar msglevel ("msg", 0, CVAR_ARCHIVE); +CVARD_NAMED(Int, msglevel, msg, 0, CVAR_ARCHIVE, "Filters HUD message by importance"); CUSTOM_CVAR (Int, msg0color, CR_UNTRANSLATED, CVAR_ARCHIVE) { @@ -311,36 +311,20 @@ void C_DeinitConsole () } HistTail = HistHead = HistPos = NULL; - // Free cvars allocated at runtime - FBaseCVar *var, *next, **nextp; - for (var = CVars, nextp = &CVars; var != NULL; var = next) - { - next = var->m_Next; - if (var->GetFlags() & CVAR_UNSETTABLE) - { - delete var; - *nextp = next; - } - else - { - nextp = &var->m_Next; - } - } - // Free alias commands. (i.e. The "commands" that can be allocated // at runtime.) for (size_t i = 0; i < countof(Commands); ++i) { - FConsoleCommand *cmd = Commands[i]; + FConsoleCommand *command = Commands[i]; - while (cmd != NULL) + while (command != NULL) { - FConsoleCommand *next = cmd->m_Next; - if (cmd->IsAlias()) + FConsoleCommand *nextcmd = command->m_Next; + if (command->IsAlias()) { - delete cmd; + delete command; } - cmd = next; + command = nextcmd; } } @@ -605,7 +589,7 @@ void C_DrawConsole () if (conback.isValid() && gamestate != GS_FULLCONSOLE) { - DrawTexture (twod, TexMan.GetGameTexture(conback), 0, visheight - screen->GetHeight(), + DrawTexture (twod, conback, false, 0, visheight - screen->GetHeight(), DTA_DestWidth, twod->GetWidth(), DTA_DestHeight, twod->GetHeight(), DTA_ColorOverlay, conshade, @@ -856,7 +840,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) { // Scroll console buffer down if (ev->subtype == EV_GUI_WheelDown) { - RowAdjust = std::max (0, RowAdjust - 3); + RowAdjust = max (0, RowAdjust - 3); } else { @@ -1027,7 +1011,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) TabbedList = false; break; } - + case '`': // Check to see if we have ` bound to the console before accepting // it as a way to close the console. diff --git a/src/common/console/c_console.h b/src/common/console/c_console.h index 2d79992bf..bae857f7d 100644 --- a/src/common/console/c_console.h +++ b/src/common/console/c_console.h @@ -41,11 +41,10 @@ struct event_t; -typedef enum cstate_t +enum cstate_t : uint8_t { c_up=0, c_down=1, c_falling=2, c_rising=3 -} -constate_e; +}; enum { @@ -53,7 +52,7 @@ enum }; extern int PrintColors[PRINTLEVELS + 2]; -extern constate_e ConsoleState; +extern uint8_t ConsoleState; // Initialize the console void C_InitConsole (int width, int height, bool ingame); @@ -86,5 +85,6 @@ extern double NotifyFontScale; void C_SetNotifyFontScale(double scale); extern const char *console_bar; +extern int chatmodeon; #endif diff --git a/src/common/console/c_consolebuffer.cpp b/src/common/console/c_consolebuffer.cpp index a75a0588c..ea6be80e2 100644 --- a/src/common/console/c_consolebuffer.cpp +++ b/src/common/console/c_consolebuffer.cpp @@ -72,7 +72,7 @@ FConsoleBuffer::FConsoleBuffer() void FConsoleBuffer::AddText(int printlevel, const char *text) { FString build = TEXTCOLOR_TAN; - + if (mAddType == REPLACELINE) { // Just wondering: Do we actually need this case? If so, it may need some work. @@ -85,15 +85,15 @@ void FConsoleBuffer::AddText(int printlevel, const char *text) printlevel = -1; mLastLineNeedsUpdate = true; } - + if (printlevel >= 0 && printlevel != PRINT_HIGH) { if (printlevel == 200) build = TEXTCOLOR_GREEN; else if (printlevel < PRINTLEVELS) build.Format("%c%c", TEXTCOLOR_ESCAPE, PrintColors[printlevel]+'A'); } - + size_t textsize = strlen(text); - + if (text[textsize-1] == '\r') { textsize--; diff --git a/src/common/console/c_consolebuffer.h b/src/common/console/c_consolebuffer.h index 98a42b42e..58bc0edea 100644 --- a/src/common/console/c_consolebuffer.h +++ b/src/common/console/c_consolebuffer.h @@ -56,12 +56,12 @@ class FConsoleBuffer EAddType mAddType; int mTextLines; bool mBufferWasCleared; - + FFont *mLastFont; int mLastDisplayWidth; bool mLastLineNeedsUpdate; - + public: FConsoleBuffer(); void AddText(int printlevel, const char *string); diff --git a/src/common/console/c_cvars.cpp b/src/common/console/c_cvars.cpp index 7e5bd94ba..d89bb3da3 100644 --- a/src/common/console/c_cvars.cpp +++ b/src/common/console/c_cvars.cpp @@ -43,6 +43,7 @@ #include "engineerrors.h" #include "printf.h" #include "palutil.h" +#include "i_interface.h" struct FLatchedValue @@ -55,11 +56,6 @@ struct FLatchedValue static TArray LatchedValues; -bool FBaseCVar::m_DoNoSet = false; -bool FBaseCVar::m_UseCallback = false; - -FBaseCVar *CVars = NULL; - int cvar_defflags; @@ -72,6 +68,86 @@ void C_InstallHandlers(ConsoleCallbacks* cb) callbacks = cb; } +void C_InitCVars(int which) +{ + AutoSegs::CVarDecl.ForEach([](FCVarDecl* cvInfo) + { + FBaseCVar* newcvar; + switch(cvInfo->type) + { + default: + return; + + case CVAR_Int: + { + using callbacktype = void (*)(FIntCVar &); + newcvar = new FIntCVar(cvInfo->name, cvInfo->defaultval.Int, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Bool: + { + using callbacktype = void (*)(FBoolCVar &); + newcvar = new FBoolCVar(cvInfo->name, cvInfo->defaultval.Bool, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Float: + { + using callbacktype = void (*)(FFloatCVar &); + newcvar = new FFloatCVar(cvInfo->name, cvInfo->defaultval.Float, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_String: + { + using callbacktype = void (*)(FStringCVar &); + newcvar = new FStringCVar(cvInfo->name, cvInfo->defaultval.String, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Color: + { + using callbacktype = void (*)(FColorCVar &); + newcvar = new FColorCVar(cvInfo->name, cvInfo->defaultval.Int, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + + } + *(void**)cvInfo->refAddr = newcvar; + }); + AutoSegs::CVarDecl.ForEach([](FCVarDecl* cvInfo) + { + FBaseCVar* newcvar; + switch (cvInfo->type) + { + default: + return; + + case CVAR_Flag: + { + newcvar = new FFlagCVar(cvInfo->name, *cvInfo->defaultval.Pointer->get(), cvInfo->flags, cvInfo->description); + break; + } + case CVAR_Mask: + { + newcvar = new FMaskCVar(cvInfo->name, *cvInfo->defaultval.Pointer->get(), cvInfo->flags, cvInfo->description); + break; + } + + } + *(void**)cvInfo->refAddr = newcvar; + }); +} + +void C_UninitCVars() +{ + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair* pair; + while (it.NextPair(pair)) + { + auto var = pair->Value; + pair->Value = nullptr; + delete var; + } +} + FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr) { if (var_name != nullptr && (flags & CVAR_SERVERINFO)) @@ -100,8 +176,7 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa var = FindCVar(var_name, NULL); C_AddTabCommand (var_name); VarName = var_name; - m_Next = CVars; - CVars = this; + cvarMap.Insert(var_name, this); } if (var) @@ -111,11 +186,7 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa value = var->GetFavoriteRep (&type); ForceSet (value, type); - - if (var->Flags & CVAR_AUTO) - delete var; - else - var->~FBaseCVar(); + delete var; Flags = flags; } @@ -135,16 +206,34 @@ FBaseCVar::~FBaseCVar () if (var == this) { - if (prev) - prev->m_Next = m_Next; - else - CVars = m_Next; - } - if (var->Flags & CVAR_AUTO) + cvarMap.Remove(var->VarName); C_RemoveTabCommand(VarName); + } } } +void FBaseCVar::SetCallback(void (*callback)(FBaseCVar&)) +{ + m_Callback = callback; + m_UseCallback = true; +} + +void FBaseCVar::ClearCallback() +{ + m_Callback = nullptr; + m_UseCallback = false; +} + +void FBaseCVar::SetExtraDataPointer(void *pointer) +{ + m_ExtraDataPointer = pointer; +} + +void* FBaseCVar::GetExtraDataPointer() +{ + return m_ExtraDataPointer; +} + const char *FBaseCVar::GetHumanString(int precision) const { return GetGenericRep(CVAR_String).String; @@ -333,6 +422,7 @@ UCVarValue FBaseCVar::FromBool (bool value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -363,6 +453,7 @@ UCVarValue FBaseCVar::FromInt (int value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -395,6 +486,7 @@ UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -456,6 +548,7 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) break; default: + ret.Int = 0; break; } @@ -498,15 +591,15 @@ void FBaseCVar::EnableNoSet () void FBaseCVar::EnableCallbacks () { m_UseCallback = true; - FBaseCVar *cvar = CVars; - - while (cvar) + CVarMap::Iterator it(cvarMap); + CVarMap::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if (!(cvar->Flags & CVAR_NOINITCALL)) { cvar->Callback (); } - cvar = cvar->m_Next; } } @@ -859,15 +952,16 @@ int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) void FBaseCVar::ResetColors () { - FBaseCVar *var = CVars; - - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; + if (var->GetRealType () == CVAR_Color) { var->DoSet (var->GetGenericRep (CVAR_Int), CVAR_Int); } - var = var->m_Next; } } @@ -924,7 +1018,7 @@ BitVal (bitval) ECVarType FFlagCVar::GetRealType () const { - return CVAR_DummyBool; + return CVAR_Flag; } UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const @@ -1020,7 +1114,7 @@ BitVal (bitval) ECVarType FMaskCVar::GetRealType () const { - return CVAR_DummyInt; + return CVAR_Mask; } UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const @@ -1107,8 +1201,11 @@ static int sortcvars (const void *a, const void *b) void FilterCompactCVars (TArray &cvars, uint32_t filter) { // Accumulate all cvars that match the filter flags. - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_IGNORE)) cvars.Push(cvar); } @@ -1130,7 +1227,7 @@ void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact) FString C_GetMassCVarString (uint32_t filter, bool compact) { - FBaseCVar *cvar; + FBaseCVar* cvar; FString dump; if (compact) @@ -1146,8 +1243,11 @@ FString C_GetMassCVarString (uint32_t filter, bool compact) } else { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + cvar = pair->Value; if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE|CVAR_IGNORE))) { UCVarValue val = cvar->GetGenericRep(CVAR_String); @@ -1239,8 +1339,11 @@ void C_BackupCVars (void) FCVarBackup backup; - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) && !(cvar->Flags & CVAR_LATCH)) { backup.Name = cvar->GetName(); @@ -1266,47 +1369,24 @@ void C_ForgetCVars (void) FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) { - FBaseCVar *var; - FBaseCVar *dummy; + if (var_name == nullptr) + return nullptr; - if (var_name == NULL) - return NULL; - - if (prev == NULL) - prev = &dummy; - - var = CVars; - *prev = NULL; - while (var) - { - if (stricmp (var->GetName (), var_name) == 0) - break; - *prev = var; - var = var->m_Next; - } - return var; + FName vname(var_name, true); + if (vname == NAME_None) return nullptr; + auto find = cvarMap.CheckKey(vname); + return find? *find : nullptr; } FBaseCVar *FindCVarSub (const char *var_name, int namelen) { - FBaseCVar *var; - if (var_name == NULL) return NULL; - var = CVars; - while (var) - { - const char *probename = var->GetName (); - - if (strnicmp (probename, var_name, namelen) == 0 && - probename[namelen] == 0) - { - break; - } - var = var->m_Next; - } - return var; + FName vname(var_name, namelen, true); + if (vname == NAME_None) return nullptr; + auto find = cvarMap.CheckKey(vname); + return find ? *find : nullptr; } FBaseCVar *GetCVar(int playernum, const char *cvarname) @@ -1371,26 +1451,24 @@ void UnlatchCVars (void) void DestroyCVarsFlagged (uint32_t flags) { - FBaseCVar *cvar = CVars; - FBaseCVar *next = cvar; - - while(cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { - next = cvar->m_Next; + auto cvar = pair->Value; if(cvar->Flags & flags) delete cvar; - - cvar = next; } } void C_SetCVarsToDefaults (void) { - FBaseCVar *cvar = CVars; - - while (cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; // Only default save-able cvars if (cvar->Flags & CVAR_ARCHIVE) { @@ -1399,7 +1477,6 @@ void C_SetCVarsToDefaults (void) val = cvar->GetFavoriteRepDefault (&type); cvar->SetGenericRep (val, type); } - cvar = cvar->m_Next; } } @@ -1412,26 +1489,27 @@ static int cvarcmp(const void* a, const void* b) void C_ArchiveCVars (FConfigFile *f, uint32_t filter) { - FBaseCVar *cvar = CVars; TArray cvarlist; - while (cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_MOD|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE|CVAR_CONFIG_ONLY)) == filter) { cvarlist.Push(cvar); } - cvar = cvar->m_Next; } qsort(cvarlist.Data(), cvarlist.Size(), sizeof(FBaseCVar*), cvarcmp); - for (auto cvar : cvarlist) + for (auto cv : cvarlist) { - const char* const value = (cvar->Flags & CVAR_ISDEFAULT) - ? cvar->GetGenericRep(CVAR_String).String - : cvar->SafeValue.GetChars(); - f->SetValueForKey(cvar->GetName(), value); + const char* const value = (cv->Flags & CVAR_ISDEFAULT) + ? cv->GetGenericRep(CVAR_String).String + : cv->SafeValue.GetChars(); + f->SetValueForKey(cv->GetName(), value); } } @@ -1439,7 +1517,7 @@ EXTERN_CVAR(Bool, sv_cheats); void FBaseCVar::CmdSet (const char *newval) { - if ((GetFlags() & CVAR_CHEAT) && CheckCheatmode ()) + if ((GetFlags() & CVAR_CHEAT) && sysCallbacks.CheckCheatmode && sysCallbacks.CheckCheatmode(true, false)) return; MarkUnsafe(); @@ -1567,11 +1645,13 @@ CCMD (toggle) void FBaseCVar::ListVars (const char *filter, bool plain) { - FBaseCVar *var = CVars; int count = 0; - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; if (CheckWildcards (filter, var->GetName())) { uint32_t flags = var->GetFlags(); @@ -1600,7 +1680,6 @@ void FBaseCVar::ListVars (const char *filter, bool plain) var->GetHumanString()); } } - var = var->m_Next; } Printf ("%d cvars\n", count); } @@ -1642,16 +1721,15 @@ CCMD (archivecvar) void C_ListCVarsWithoutDescription() { - FBaseCVar* var = CVars; - int count = 0; - - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; if (var->GetDescription().IsEmpty()) { Printf("%s\n", var->GetName()); } - var = var->m_Next; } } diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index abbe31a4b..d60771d2d 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -35,6 +35,8 @@ #define __C_CVARS_H__ #include "zstring.h" #include "tarray.h" +#include "autosegs.h" +#include "name.h" class FSerializer; // this needs to go away. /* @@ -72,20 +74,6 @@ enum CVAR_CONFIG_ONLY = 1 << 18, // do not save var to savegame and do not send it across network. }; -union UCVarValue -{ - bool Bool; - int Int; - float Float; - const char* String; - - UCVarValue() = default; - UCVarValue(bool v) { Bool = v; } - UCVarValue(int v) { Int = v; } - UCVarValue(float v) { Float = v; } - UCVarValue(const char * v) { String = v; } -}; - enum ECVarType { CVAR_Bool, @@ -93,17 +81,46 @@ enum ECVarType CVAR_Float, CVAR_String, CVAR_Color, // stored as CVAR_Int - CVAR_DummyBool, // just redirects to another cvar - CVAR_DummyInt, // just redirects to another cvar - CVAR_Dummy // Unknown + CVAR_Flag, // just redirects to another cvar + CVAR_Mask, // just redirects to another cvar + CVAR_Dummy, // Unknown }; + +class FIntCVarRef; +union UCVarValue +{ + bool Bool; + int Int; + float Float; + const char* String; + FIntCVarRef* Pointer; + + UCVarValue() = default; + constexpr UCVarValue(bool v) : Bool(v) { } + constexpr UCVarValue(int v) : Int(v) { } + constexpr UCVarValue(float v) : Float(v) { } + constexpr UCVarValue(double v) : Float(float(v)) { } + constexpr UCVarValue(const char * v) : String(v) { } + constexpr UCVarValue(FIntCVarRef& v); +}; + +template constexpr UCVarValue CVarValue(bool v) { static_assert(t == CVAR_Bool); return v; } +template constexpr UCVarValue CVarValue(int v) { static_assert(t == CVAR_Int || t == CVAR_Color); return v; } +template constexpr UCVarValue CVarValue(float v) { static_assert(t == CVAR_Float); return v; } +template constexpr UCVarValue CVarValue(double v) { static_assert(t == CVAR_Float); return v; } +template constexpr UCVarValue CVarValue(const char* v) { static_assert(t == CVAR_String); return v; } +template constexpr UCVarValue CVarValue(FIntCVarRef& v) { static_assert(t == CVAR_Flag || t == CVAR_Mask); return v; } + class FConfigFile; class FxCVar; class FBaseCVar; +using CVarMap = TMap; +inline CVarMap cvarMap; + // These are calls into the game code. Having these hard coded in the CVAR implementation has always been the biggest blocker // for reusing the CVAR module outside of ZDoom. So now they get called through this struct for easier reusability. struct ConsoleCallbacks @@ -134,7 +151,6 @@ public: inline const char *GetName () const { return VarName.GetChars(); } inline uint32_t GetFlags () const { return Flags; } - inline FBaseCVar *GetNext() const { return m_Next; } void CmdSet (const char *newval); void ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend=false); @@ -175,7 +191,7 @@ public: static void ResetColors (); // recalc color cvars' indices after screen change static void ListVars (const char *filter, bool plain); - + const FString &GetDescription() const { return Description; }; const FString& GetToggleMessage(int which) { return ToggleMessages[which]; } void SetToggleMessages(const char* on, const char* off) @@ -184,6 +200,12 @@ public: ToggleMessages[1] = on; } + void SetCallback(void (*callback)(FBaseCVar&)); + void ClearCallback(); + + void SetExtraDataPointer(void *pointer); + + void* GetExtraDataPointer(); protected: virtual void DoSet (UCVarValue value, ECVarType type) = 0; @@ -208,10 +230,11 @@ private: FBaseCVar (const FBaseCVar &var) = delete; FBaseCVar (const char *name, uint32_t flags); void (*m_Callback)(FBaseCVar &); - FBaseCVar *m_Next; - static bool m_UseCallback; - static bool m_DoNoSet; + static inline bool m_UseCallback = false; + static inline bool m_DoNoSet = false; + + void *m_ExtraDataPointer; // These need to go away! friend FString C_GetMassCVarString (uint32_t filter, bool compact); @@ -271,6 +294,8 @@ void C_SetCVarsToDefaults (void); void FilterCompactCVars (TArray &cvars, uint32_t filter); void C_DeinitConsole(); +void C_InitCVars(int which); +void C_UninitCVars(); class FBoolCVar : public FBaseCVar { @@ -398,7 +423,7 @@ public: protected: virtual void DoSet (UCVarValue value, ECVarType type); - + static UCVarValue FromInt2 (int value, ECVarType type); static int ToInt2 (UCVarValue value, ECVarType type); }; @@ -457,6 +482,88 @@ protected: int BitNum; }; +class FBoolCVarRef +{ + FBoolCVar* ref; +public: + + inline bool operator= (bool val) { *ref = val; return val; } + inline operator bool () const { return **ref; } + inline bool operator *() const { return **ref; } + inline FBoolCVar* operator->() { return ref; } + inline FBoolCVar* get() { return ref; } +}; + +class FIntCVarRef +{ + FIntCVar* ref; +public: + + int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FIntCVar* operator->() { return ref; } + inline FIntCVar* get() { return ref; } +}; + +class FFloatCVarRef +{ + FFloatCVar* ref; +public: + + float operator= (float val) { *ref = val; return val; } + inline operator float () const { return **ref; } + inline float operator *() const { return **ref; } + inline FFloatCVar* operator->() { return ref; } + inline FFloatCVar* get() { return ref; } +}; + +class FStringCVarRef +{ + FStringCVar* ref; +public: + + const char* operator= (const char* val) { *ref = val; return val; } + inline operator const char* () const { return **ref; } + inline const char* operator *() const { return **ref; } + inline FStringCVar* operator->() { return ref; } + inline FStringCVar* get() { return ref; } +}; + +class FColorCVarRef +{ + FColorCVar* ref; +public: + + //uint32_t operator= (uint32_t val) { *ref = val; return val; } + inline operator uint32_t () const { return **ref; } + inline uint32_t operator *() const { return **ref; } + inline FColorCVar* operator->() { return ref; } + inline FColorCVar* get() { return ref; } +}; + +class FFlagCVarRef +{ + FFlagCVar* ref; +public: + inline bool operator= (bool val) { *ref = val; return val; } + inline bool operator= (const FFlagCVar& val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FFlagCVar& operator->() { return *ref; } +}; + +class FMaskCVarRef +{ + FMaskCVar* ref; +public: + //int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FMaskCVar& operator->() { return *ref; } +}; + + extern int cvar_defflags; FBaseCVar *cvar_set (const char *var_name, const char *value); @@ -465,6 +572,18 @@ FBaseCVar *cvar_forceset (const char *var_name, const char *value); inline FBaseCVar *cvar_set (const char *var_name, const uint8_t *value) { return cvar_set (var_name, (const char *)value); } inline FBaseCVar *cvar_forceset (const char *var_name, const uint8_t *value) { return cvar_forceset (var_name, (const char *)value); } +constexpr UCVarValue::UCVarValue(FIntCVarRef& v) : Pointer(&v) { } + +struct FCVarDecl +{ + void * refAddr; + ECVarType type; + unsigned int flags; + const char * name; + UCVarValue defaultval; + const char *description; + void* callbackp; // actually a function pointer with unspecified arguments. C++ does not like that much... +}; // Restore demo cvars. Called after demo playback to restore all cvars @@ -474,35 +593,59 @@ void C_RestoreCVars (void); void C_ForgetCVars (void); +#if defined(_MSC_VER) +#pragma section(SECTION_VREG,read) + +#define MSVC_VSEG __declspec(allocate(SECTION_VREG)) +#define GCC_VSEG +#else +#define MSVC_VSEG +#define GCC_VSEG __attribute__((section(SECTION_VREG))) __attribute__((used)) +#endif + #define CUSTOM_CVAR(type,name,def,flags) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#name, def, flags, cvarfunc_##name); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, CVarValue(def), nullptr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) + #define CUSTOM_CVAR_NAMED(type,name,cname,def,flags) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#cname, def, flags, cvarfunc_##name); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #cname, CVarValue(def), nullptr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) #define CVAR(type,name,def,flags) \ - F##type##CVar name (#name, def, flags); + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, CVarValue(def), nullptr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; -#define EXTERN_CVAR(type,name) extern F##type##CVar name; +#define EXTERN_CVAR(type,name) extern F##type##CVarRef name; #define CUSTOM_CVARD(type,name,def,flags,descr) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#name, def, flags, cvarfunc_##name, descr); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, CVarValue(def), descr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) #define CVARD(type,name,def,flags, descr) \ - F##type##CVar name (#name, def, flags, nullptr, descr); + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, CVarValue(def), descr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; #define CVARD_NAMED(type,name,varname,def,flags, descr) \ -F##type##CVar varname (#name, def, flags, nullptr, descr); - -#define CVAR_UNAMED(type,varname) \ -F##type##CVar varname (nullptr, 0, 0, nullptr, nullptr); - -extern FBaseCVar *CVars; + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #varname, CVarValue(def), descr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; #endif //__C_CVARS_H__ diff --git a/src/common/console/c_dispatch.cpp b/src/common/console/c_dispatch.cpp index ce9f2cef7..7de13e2ea 100644 --- a/src/common/console/c_dispatch.cpp +++ b/src/common/console/c_dispatch.cpp @@ -39,7 +39,7 @@ #include #include -#include "templates.h" + #include "cmdlib.h" #include "c_console.h" #include "c_dispatch.h" @@ -253,7 +253,7 @@ void C_DoCommand (const char *cmd, int keynum) return; } } - + // Parse it as a normal command // Checking for matching commands follows this search order: // 1. Check the Commands[] hash table @@ -282,8 +282,8 @@ void C_DoCommand (const char *cmd, int keynum) } else { - auto cmd = new FStoredCommand(com, beg); - delayedCommandQueue.AddCommand(cmd); + auto command = new FStoredCommand(com, beg); + delayedCommandQueue.AddCommand(command); } } } @@ -373,8 +373,8 @@ void AddCommandString (const char *text, int keynum) // Note that deferred commands lose track of which key // (if any) they were pressed from. *brkpt = ';'; - auto cmd = new FWaitingCommand(brkpt, tics, UnsafeExecutionContext); - delayedCommandQueue.AddCommand(cmd); + auto command = new FWaitingCommand(brkpt, tics, UnsafeExecutionContext); + delayedCommandQueue.AddCommand(command); } return; } @@ -851,8 +851,8 @@ CCMD (key) for (i = 1; i < argv.argc(); ++i) { - unsigned int key = MakeKey (argv[i]); - Printf (" 0x%08x\n", key); + unsigned int hash = MakeKey (argv[i]); + Printf (" 0x%08x\n", hash); } } } @@ -1014,7 +1014,6 @@ void FExecList::AddPullins(TArray &wads, FConfigFile *config) const FExecList *C_ParseExecFile(const char *file, FExecList *exec) { char cmd[4096]; - int retval = 0; FileReader fr; @@ -1092,7 +1091,7 @@ void C_SearchForPullins(FExecList *exec, const char *file, FCommandLine &argv) lastSlash1 = strrchr(file, '/'); lastSlash2 = strrchr(file, '\\'); - lastSlash = MAX(lastSlash1, lastSlash2); + lastSlash = max(lastSlash1, lastSlash2); #endif for (int i = 1; i < argv.argc(); ++i) diff --git a/src/common/console/c_dispatch.h b/src/common/console/c_dispatch.h index 57d681c49..532ed9b92 100644 --- a/src/common/console/c_dispatch.h +++ b/src/common/console/c_dispatch.h @@ -59,8 +59,6 @@ extern bool ParsingKeyConf, UnsafeExecutionContext; extern FString StoredWarp; // [RH] +warp at the command line -extern bool CheckCheatmode (bool printmsg = true, bool sponly = false); - FExecList *C_ParseCmdLineParams(FExecList *exec); // Add commands to the console as if they were typed in. Can handle wait diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index 0af6f3b56..13593cb32 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -52,6 +52,8 @@ #include "version.h" #include "findfile.h" #include "md5.h" +#include "i_specialpaths.h" +#include "i_system.h" extern FILE* Logfile; @@ -177,12 +179,12 @@ UNSAFE_CCMD (crashout) UNSAFE_CCMD (dir) { FString dir, path; - char curdir[256]; const char *match; findstate_t c_file; void *file; - if (!getcwd (curdir, countof(curdir))) + FString curdir = I_GetCWD(); + if (curdir.IsEmpty()) { Printf ("Current path too long\n"); return; @@ -191,7 +193,7 @@ UNSAFE_CCMD (dir) if (argv.argc() > 1) { path = NicePath(argv[1]); - if (chdir(path)) + if (!I_ChDir(path)) { match = path; dir = ExtractFilePath(path); @@ -207,7 +209,7 @@ UNSAFE_CCMD (dir) { match = "*"; } - if (chdir (dir)) + if (!I_ChDir(dir)) { Printf ("%s not found\n", dir.GetChars()); return; @@ -244,7 +246,7 @@ UNSAFE_CCMD (dir) I_FindClose (file); } - chdir (curdir); + I_ChDir(curdir); } //========================================================================== @@ -336,3 +338,4 @@ CCMD(printlocalized) } } + diff --git a/src/common/console/c_expr.cpp b/src/common/console/c_expr.cpp index d203c8cd5..4a48439b7 100644 --- a/src/common/console/c_expr.cpp +++ b/src/common/console/c_expr.cpp @@ -248,7 +248,7 @@ done: bool IsFloat (const char *str) { const char *pt; - + if (*str == '+' || *str == '-') str++; @@ -367,7 +367,7 @@ static FStringProd *DoubleToString (FProduction *prod) static FDoubleProd *StringToDouble (FProduction *prod) { FDoubleProd *newprod; - + newprod = NewDoubleProd (atof (static_cast(prod)->Value)); M_Free (prod); return newprod; diff --git a/src/common/console/c_notifybufferbase.cpp b/src/common/console/c_notifybufferbase.cpp index e31a8f07c..11be81dd3 100644 --- a/src/common/console/c_notifybufferbase.cpp +++ b/src/common/console/c_notifybufferbase.cpp @@ -126,7 +126,7 @@ void FNotifyBufferBase::Tick() { Text[i].Ticker++; } - + for (i = 0; i < Text.Size(); ++i) { if (Text[i].TimeOut != 0 && Text[i].TimeOut > Text[i].Ticker) diff --git a/src/common/console/c_tabcomplete.cpp b/src/common/console/c_tabcomplete.cpp index ca8339062..eccd64b03 100644 --- a/src/common/console/c_tabcomplete.cpp +++ b/src/common/console/c_tabcomplete.cpp @@ -273,7 +273,7 @@ bool C_TabCompleteList () } } nummatches++; - maxwidth = std::max (maxwidth, strlen (TabCommands[i].TabName.GetChars())); + maxwidth = max (maxwidth, strlen (TabCommands[i].TabName.GetChars())); } } if (nummatches > 1) diff --git a/src/common/cutscenes/movieplayer.cpp b/src/common/cutscenes/movieplayer.cpp new file mode 100644 index 000000000..94a7e4c60 --- /dev/null +++ b/src/common/cutscenes/movieplayer.cpp @@ -0,0 +1,976 @@ +/* +** movieplayer.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2020 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 "types.h" +#include "screenjob.h" +#include "i_time.h" +#include "v_2ddrawer.h" +#include "animlib.h" +#include "v_draw.h" +#include "s_soundinternal.h" +#include "animtexture.h" +#include "gamestate.h" +#include "SmackerDecoder.h" +#include "playmve.h" +#include +#include +#include "filesystem.h" +#include "vm.h" +#include "printf.h" +#include +#include +#include +#include "filereadermusicinterface.h" + +class MoviePlayer +{ +protected: + enum EMovieFlags + { + NOSOUNDCUTOFF = 1, + FIXEDVIEWPORT = 2, // Forces fixed 640x480 screen size like for Blood's intros. + NOMUSICCUTOFF = 4, + }; + + int flags; +public: + virtual void Start() {} + virtual bool Frame(uint64_t clock) = 0; + virtual void Stop() {} + virtual ~MoviePlayer() = default; + virtual FTextureID GetTexture() = 0; +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +// A simple filter is used to smooth out jittery timers +static const double AudioAvgFilterCoeff{std::pow(0.01, 1.0/10.0)}; +// A threshold is in place to avoid constantly skipping due to imprecise timers. +static constexpr double AudioSyncThreshold{0.03}; + +class MovieAudioTrack +{ + SoundStream *AudioStream = nullptr; + int SampleRate = 0; + int FrameSize = 0; + int64_t EndClockDiff = 0; + +public: + MovieAudioTrack() = default; + ~MovieAudioTrack() + { + if(AudioStream) + S_StopCustomStream(AudioStream); + } + + bool Start(int srate, int channels, MusicCustomStreamType sampletype, StreamCallback callback, void *ptr) + { + SampleRate = srate; + FrameSize = channels * ((sampletype == MusicSamples16bit) ? sizeof(int16_t) : sizeof(float)); + int bufsize = 40 * SampleRate / 1000 * FrameSize; + AudioStream = S_CreateCustomStream(bufsize, SampleRate, channels, sampletype, callback, ptr); + return !!AudioStream; + } + + void Finish() + { + if(AudioStream) + S_StopCustomStream(AudioStream); + AudioStream = nullptr; + } + + uint64_t GetClockTime(uint64_t clock) + { + // If there's no stream playing, report the frame clock adjusted by the audio + // end time. This ensures the returned clock keeps incrementing even after + // the audio stopped. + if(!AudioStream || EndClockDiff != 0) + return clock + EndClockDiff; + + auto pos = AudioStream->GetPlayPosition(); + int64_t postime = static_cast(pos.samplesplayed / double(SampleRate) * 1'000'000'000.0); + postime = std::max(0, postime - pos.latency.count()); + + if(AudioStream->IsEnded()) + { + // If the stream just ended, get the difference between the frame clock and + // the audio end time, so future calls keep incrementing the clock from this + // point. An alternative option may be to allow the AudioStream to hook into + // the audio device clock, which can keep incrementing at the same rate + // without the stream itself actually playing. + EndClockDiff = postime - clock; + } + + return static_cast(postime); + } + + SoundStream *GetAudioStream() const noexcept { return AudioStream; } + int GetSampleRate() const noexcept { return SampleRate; } + int GetFrameSize() const noexcept { return FrameSize; } +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class AnmPlayer : public MoviePlayer +{ + // This doesn't need its own class type + anim_t anim; + TArray buffer; + int numframes = 0; + int curframe = 1; + int frametime = 0; + int nextframetime = 0; + AnimTextures animtex; + const TArray animSnd; + int frameTicks[3]; + +public: + bool isvalid() { return numframes > 0; } + + AnmPlayer(FileReader& fr, TArray& ans, const int *frameticks, int flags_) + : animSnd(std::move(ans)) + { + memcpy(frameTicks, frameticks, 3 * sizeof(int)); + flags = flags_; + buffer = fr.ReadPadded(1); + fr.Close(); + + if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + { + return; + } + numframes = ANIM_NumFrames(&anim); + animtex.SetSize(AnimTexture::Paletted, 320, 200); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool Frame(uint64_t clock) override + { + int currentclock = int(clock * 120 / 1'000'000'000); + + if (currentclock < nextframetime - 1) + { + return true; + } + + animtex.SetFrame(ANIM_GetPalette(&anim), ANIM_DrawFrame(&anim, curframe)); + frametime = currentclock; + + int delay = 20; + if (curframe == 1) delay = frameTicks[0]; + else if (curframe < numframes - 2) delay = frameTicks[1]; + else delay = frameTicks[2]; + nextframetime += delay; + + bool nostopsound = (flags & NOSOUNDCUTOFF); + for (unsigned i = 0; i < animSnd.Size(); i+=2) + { + if (animSnd[i] == curframe) + { + auto sound = FSoundID::fromInt(animSnd[i+1]); + 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); + } + } + if (!nostopsound && curframe == numframes && soundEngine->GetSoundPlayingInfo(SOURCE_None, nullptr, INVALID_SOUND)) return true; + curframe++; + return curframe < numframes; + } + + void Stop() override + { + bool nostopsound = (flags & NOSOUNDCUTOFF); + if (!nostopsound) soundEngine->StopAllChannels(); + } + + + ~AnmPlayer() + { + buffer.Reset(); + animtex.Clean(); + } + + FTextureID GetTexture() override + { + return animtex.GetFrameID(); + } +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class MvePlayer : public MoviePlayer +{ + InterplayDecoder decoder; + MovieAudioTrack audioTrack; + bool failed = false; + + bool StreamCallback(SoundStream*, void *buff, int len) + { + return decoder.FillSamples(buff, len); + } + static bool StreamCallbackC(SoundStream *stream, void *buff, int len, void *userdata) + { return static_cast(userdata)->StreamCallback(stream, buff, len); } + +public: + bool isvalid() { return !failed; } + + MvePlayer(FileReader& fr) : decoder(SoundEnabled()) + { + failed = !decoder.Open(fr); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool Frame(uint64_t clock) override + { + if (failed) return false; + + if (!audioTrack.GetAudioStream() && decoder.HasAudio() && clock != 0) + { + S_StopMusic(true); + // start audio playback + if (!audioTrack.Start(decoder.GetSampleRate(), decoder.NumChannels(), MusicSamples16bit, StreamCallbackC, this)) + decoder.DisableAudio(); + } + + bool playon = decoder.RunFrame(audioTrack.GetClockTime(clock)); + return playon; + } + + ~MvePlayer() + { + audioTrack.Finish(); + + decoder.Close(); + } + + FTextureID GetTexture() override + { + return decoder.animTex().GetFrameID(); + } +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class VpxPlayer : public MoviePlayer +{ + bool failed = false; + FileReader fr; + AnimTextures animtex; + const TArray animSnd; + + ZMusic_MusicStream MusicStream = nullptr; + MovieAudioTrack AudioTrack; + + unsigned width, height; + TArray Pic; + TArray readBuf; + vpx_codec_ctx_t codec{}; + vpx_codec_iter_t iter = nullptr; + + uint32_t convnumer; + uint32_t convdenom; + + uint64_t nsecsperframe; + uint64_t nextframetime; + + int decstate = 0; + int framenum = 0; + int numframes; + int lastsoundframe = -1; +public: + int soundtrack = -1; + + bool StreamCallback(SoundStream*, void *buff, int len) + { + return ZMusic_FillStream(MusicStream, buff, len); + } + static bool StreamCallbackC(SoundStream *stream, void *buff, int len, void *userdata) + { return static_cast(userdata)->StreamCallback(stream, buff, len); } + +public: + bool isvalid() { return !failed; } + + VpxPlayer(FileReader& fr_, TArray& animSnd_, int flags_, int origframedelay, FString& error) : animSnd(std::move(animSnd_)) + { + fr = std::move(fr_); + flags = flags_; + + if (!ReadIVFHeader(origframedelay)) + { + // We should never get here, because any file failing this has been eliminated before this constructor got called. + error.Format("Failed reading IVF header\n"); + failed = true; + } + + 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)) + { + error.Format("Error initializing VPX codec.\n"); + failed = true; + } + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool ReadIVFHeader(int origframedelay) + { + // IVF format: http://wiki.multimedia.cx/index.php?title=IVF + uint32_t magic; fr.Read(&magic, 4); // do not byte swap! + if (magic != MAKE_ID('D', 'K', 'I', 'F')) return false; + uint16_t version = fr.ReadUInt16(); + if (version != 0) return false; + uint16_t length = fr.ReadUInt16(); + if (length != 32) return false; + fr.Read(&magic, 4); + if (magic != MAKE_ID('V', 'P', '8', '0')) return false; + + width = fr.ReadUInt16(); + height = fr.ReadUInt16(); + uint32_t fpsdenominator = fr.ReadUInt32(); + uint32_t fpsnumerator = fr.ReadUInt32(); + numframes = fr.ReadUInt32(); + if (numframes == 0) return false; + fr.Seek(4, FileReader::SeekCur); + + if (fpsdenominator > 1000 || 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; + + nsecsperframe = int64_t(fpsnumerator) * 1'000'000'000 / fpsdenominator; + nextframetime = 0; + + return true; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool ReadFrame() + { + int corrupted = 0; + int framesize = fr.ReadInt32(); + fr.Seek(8, FileReader::SeekCur); + if (framesize == 0) return false; + + readBuf.Resize(framesize); + if (fr.Read(readBuf.Data(), framesize) != framesize) return false; + if (vpx_codec_decode(&codec, readBuf.Data(), readBuf.Size(), NULL, 0) != VPX_CODEC_OK) return false; + if (vpx_codec_control(&codec, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) return false; + return true; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + vpx_image_t *GetFrameData() + { + vpx_image_t *img; + do + { + if (decstate == 0) // first time / begin + { + if (!ReadFrame()) return nullptr; + decstate = 1; + } + + img = vpx_codec_get_frame(&codec, &iter); + if (img == nullptr) + { + decstate = 0; + iter = nullptr; + } + } while (img == nullptr); + + return img->d_w == width && img->d_h == height? img : nullptr; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + void SetPixel(uint8_t* dest, uint8_t y, uint8_t u, uint8_t v) + { + dest[0] = y; + dest[1] = u; + 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; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + void Start() override + { + if (SoundStream *stream = AudioTrack.GetAudioStream()) + { + stream->SetPaused(false); + } + else if (soundtrack >= 0) + { + FileReader reader = fileSystem.OpenFileReader(soundtrack); + if (reader.isOpen()) + { + MusicStream = ZMusic_OpenSong(GetMusicReader(reader), MDEV_DEFAULT, nullptr); + } + if (!MusicStream) + { + Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false)); + } + } + animtex.SetSize(AnimTexture::YUV, width, height); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool Frame(uint64_t clock) override + { + if (!AudioTrack.GetAudioStream() && MusicStream && clock != 0) + { + S_StopMusic(true); + + bool ok = false; + SoundStreamInfo info{}; + ZMusic_GetStreamInfo(MusicStream, &info); + // if mBufferSize == 0, the music stream is played externally (e.g. + // Windows' MIDI synth), which we can't keep synced. Play anyway? + if (info.mBufferSize > 0 && ZMusic_Start(MusicStream, 0, false)) + { + ok = AudioTrack.Start(info.mSampleRate, abs(info.mNumChannels), + (info.mNumChannels < 0) ? MusicSamples16bit : MusicSamplesFloat, &StreamCallbackC, this); + } + if (!ok) + { + ZMusic_Close(MusicStream); + MusicStream = nullptr; + } + } + + clock = AudioTrack.GetClockTime(clock); + + bool stop = false; + if (clock >= nextframetime) + { + nextframetime += nsecsperframe; + + if (!CreateNextFrame()) + { + Printf(PRINT_BOLD, "Failed reading next frame\n"); + stop = true; + } + else + { + animtex.SetFrame(nullptr, Pic.Data()); + } + framenum++; + if (framenum >= numframes) stop = true; + + bool nostopsound = (flags & NOSOUNDCUTOFF); + int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum; + if (soundframe > lastsoundframe) + { + if (soundtrack == -1) + { + for (unsigned i = 0; i < animSnd.Size(); i += 2) + { + if (animSnd[i] == soundframe) + { + auto sound = FSoundID::fromInt(animSnd[i + 1]); + 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); + } + } + } + lastsoundframe = soundframe; + } + } + return !stop; + } + + void Stop() override + { + if (SoundStream *stream = AudioTrack.GetAudioStream()) + stream->SetPaused(true); + bool nostopsound = (flags & NOSOUNDCUTOFF); + if (!nostopsound) soundEngine->StopAllChannels(); + } + + ~VpxPlayer() + { + if(MusicStream) + { + AudioTrack.Finish(); + ZMusic_Close(MusicStream); + } + vpx_codec_destroy(&codec); + animtex.Clean(); + } + + FTextureID GetTexture() override + { + return animtex.GetFrameID(); + } +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +struct AudioData +{ + SmackerAudioInfo inf; + + int nWrite = 0; + int nRead = 0; +}; + +class SmkPlayer : public MoviePlayer +{ + SmackerHandle hSMK{}; + int numAudioTracks; + AudioData adata; + uint32_t nWidth, nHeight; + uint8_t palette[768]; + AnimTextures animtex; + TArray pFrame; + TArray audioBuffer; + int nFrames; + bool fullscreenScale; + uint64_t nFrameNs; + int nFrame = 0; + const TArray animSnd; + FString filename; + MovieAudioTrack AudioTrack; + bool hassound = false; + +public: + bool isvalid() { return hSMK.isValid; } + + bool StreamCallback(SoundStream* stream, void* buff, int len) + { + const int samplerate = AudioTrack.GetSampleRate(); + const int framesize = AudioTrack.GetFrameSize(); + + int avail = (adata.nWrite - adata.nRead) * 2; + + int wrote = 0; + while(wrote < len) + { + if (avail == 0) + { + auto read = Smacker_GetAudioData(hSMK, 0, audioBuffer.Data()); + if (read == 0) + { + if (wrote == 0) + return false; + break; + } + + adata.nWrite = read / 2; + avail = read; + } + + int todo = std::min(len-wrote, avail); + + memcpy((char*)buff+wrote, &audioBuffer[adata.nRead], todo); + adata.nRead += todo / 2; + if(adata.nRead == adata.nWrite) + adata.nRead = adata.nWrite = 0; + avail -= todo; + wrote += todo; + } + + if (wrote < len) + memset((char*)buff+wrote, 0, len-wrote); + return true; + } + static bool StreamCallbackC(SoundStream* stream, void* buff, int len, void* userdata) + { return static_cast(userdata)->StreamCallback(stream, buff, len); } + + + SmkPlayer(const char *fn, TArray& ans, int flags_) : animSnd(std::move(ans)) + { + hSMK = Smacker_Open(fn); + if (!hSMK.isValid) + { + return; + } + flags = flags_; + Smacker_GetFrameSize(hSMK, nWidth, nHeight); + pFrame.Resize(nWidth * nHeight + max(nWidth, nHeight)); + float frameRate = Smacker_GetFrameRate(hSMK); + nFrameNs = uint64_t(1'000'000'000 / frameRate); + nFrames = Smacker_GetNumFrames(hSMK); + Smacker_GetPalette(hSMK, palette); + + numAudioTracks = Smacker_GetNumAudioTracks(hSMK); + if (numAudioTracks && SoundEnabled()) + { + adata.nWrite = 0; + adata.nRead = 0; + adata.inf = Smacker_GetAudioTrackDetails(hSMK, 0); + if (adata.inf.idealBufferSize > 0) + { + audioBuffer.Resize(adata.inf.idealBufferSize / 2); + hassound = true; + } + for (int i = 1;i < numAudioTracks;++i) + Smacker_DisableAudioTrack(hSMK, i); + numAudioTracks = 1; + } + if (!hassound) + { + adata.inf = {}; + Smacker_DisableAudioTrack(hSMK, 0); + numAudioTracks = 0; + } + } + + //--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + + void Start() override + { + animtex.SetSize(AnimTexture::Paletted, nWidth, nHeight); + if (SoundStream *stream = AudioTrack.GetAudioStream()) + stream->SetPaused(false); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + bool Frame(uint64_t clock) override + { + if (!AudioTrack.GetAudioStream() && numAudioTracks && clock != 0) + { + S_StopMusic(true); + + if (!AudioTrack.Start(adata.inf.sampleRate, adata.inf.nChannels, MusicSamples16bit, StreamCallbackC, this)) + { + Smacker_DisableAudioTrack(hSMK, 0); + numAudioTracks = 0; + } + } + + clock = AudioTrack.GetClockTime(clock); + int frame = int(clock / nFrameNs); + + twod->ClearScreen(); + if (frame >= nFrame) + { + nFrame++; + Smacker_GetNextFrame(hSMK); + Smacker_GetPalette(hSMK, palette); + Smacker_GetFrame(hSMK, pFrame.Data()); + animtex.SetFrame(palette, pFrame.Data()); + + bool nostopsound = (flags & NOSOUNDCUTOFF); + if (!hassound) for (unsigned i = 0; i < animSnd.Size(); i += 2) + { + if (animSnd[i] == nFrame) + { + auto sound = FSoundID::fromInt(animSnd[i + 1]); + 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); + } + } + } + + return nFrame < nFrames; + } + + void Stop() override + { + if (SoundStream *stream = AudioTrack.GetAudioStream()) + stream->SetPaused(true); + bool nostopsound = (flags & NOSOUNDCUTOFF); + if (!nostopsound && !hassound) soundEngine->StopAllChannels(); + } + + ~SmkPlayer() + { + AudioTrack.Finish(); + Smacker_Close(hSMK); + animtex.Clean(); + } + + FTextureID GetTexture() override + { + return animtex.GetFrameID(); + } + +}; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +MoviePlayer* OpenMovie(const char* filename, TArray& ans, const int* frameticks, int flags, FString& error) +{ + FileReader fr; + // first try as .ivf - but only if sounds are provided - the decoder is video only. + if (ans.Size()) + { + auto fn = StripExtension(filename); + DefaultExtension(fn, ".ivf"); + fr = fileSystem.OpenFileReader(fn); + } + + if (!fr.isOpen()) fr = fileSystem.OpenFileReader(filename); + if (!fr.isOpen()) + { + size_t nLen = strlen(filename); + // Strip the drive letter and retry. + if (nLen >= 3 && isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/') + { + filename += 3; + fr = fileSystem.OpenFileReader(filename); + } + if (!fr.isOpen()) + { + error.Format("%s: Unable to open video\n", filename); + return nullptr; + } + } + char id[20] = {}; + + fr.Read(&id, 20); + fr.Seek(-20, FileReader::SeekCur); + + if (!memcmp(id, "LPF ", 4)) + { + auto anm = new AnmPlayer(fr, ans, frameticks, flags); + if (!anm->isvalid()) + { + error.Format("%s: invalid ANM file.\n", filename); + delete anm; + return nullptr; + } + return anm; + } + else if (!memcmp(id, "SMK2", 4)) + { + fr.Close(); + auto anm = new SmkPlayer(filename, ans, flags); + if (!anm->isvalid()) + { + error.Format("%s: invalid SMK file.\n", filename); + delete anm; + return nullptr; + } + return anm; + } + else if (!memcmp(id, "Interplay MVE File", 18)) + { + auto anm = new MvePlayer(fr); + if (!anm->isvalid()) + { + delete anm; + return nullptr; + } + return anm; + } + else if (!memcmp(id, "DKIF\0\0 \0VP80", 12)) + { + auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, flags, error); + if (!anm->isvalid()) + { + delete anm; + return nullptr; + } + // 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)); + return anm; + } + // add more formats here. + else + { + error.Format("%s: Unknown video format\n", filename); + return nullptr; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(_MoviePlayer, Create) +{ + PARAM_PROLOGUE; + PARAM_STRING(filename); + PARAM_POINTER(sndinf, TArray); + PARAM_INT(flags); + PARAM_INT(frametime); + PARAM_INT(firstframetime); + PARAM_INT(lastframetime); + + FString error; + 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); + if (!movie) + { + Printf(TEXTCOLOR_YELLOW "%s", error.GetChars()); + } + ACTION_RETURN_POINTER(movie); +} + +DEFINE_ACTION_FUNCTION(_MoviePlayer, Start) +{ + PARAM_SELF_STRUCT_PROLOGUE(MoviePlayer); + I_FreezeTime(true); + self->Start(); + I_FreezeTime(false); + return 0; +} + +DEFINE_ACTION_FUNCTION(_MoviePlayer, Frame) +{ + PARAM_SELF_STRUCT_PROLOGUE(MoviePlayer); + PARAM_FLOAT(clock); + ACTION_RETURN_INT(self->Frame(int64_t(clock))); +} + +DEFINE_ACTION_FUNCTION(_MoviePlayer, Destroy) +{ + PARAM_SELF_STRUCT_PROLOGUE(MoviePlayer); + self->Stop(); + delete self; + return 0; +} + +DEFINE_ACTION_FUNCTION(_MoviePlayer, GetTexture) +{ + PARAM_SELF_STRUCT_PROLOGUE(MoviePlayer); + ACTION_RETURN_INT(self->GetTexture().GetIndex()); +} diff --git a/src/common/cutscenes/playmve.cpp b/src/common/cutscenes/playmve.cpp new file mode 100644 index 000000000..70b56b43a --- /dev/null +++ b/src/common/cutscenes/playmve.cpp @@ -0,0 +1,1189 @@ +/* + * InterplayDecoder + * Copyright (C) 2020 sirlemonhead + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +/* This code is based on interplayvideo.c, dpcm.c and ipmovie.c from the FFmpeg project which can be obtained + * from http://www.ffmpeg.org/. Below is the license from interplayvideo.c + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Interplay MVE Video Decoder + * Copyright (C) 2003 The FFmpeg project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include "playmve.h" +#include "printf.h" +#include "v_draw.h" +#include "s_music.h" +#include "cmdlib.h" + + + + +static const int16_t delta_table[] = { + 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, 47, 51, 56, 61, + 66, 72, 79, 86, 94, 102, 112, 122, + 133, 145, 158, 173, 189, 206, 225, 245, + 267, 292, 318, 348, 379, 414, 452, 493, + 538, 587, 640, 699, 763, 832, 908, 991, + 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, + 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, + 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, + 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, + 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, + -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, + 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, + 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, + -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, + -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, + -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, + -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, + -1081, -991, -908, -832, -763, -699, -640, -587, + -538, -493, -452, -414, -379, -348, -318, -292, + -267, -245, -225, -206, -189, -173, -158, -145, + -133, -122, -112, -102, -94, -86, -79, -72, + -66, -61, -56, -51, -47, -43, -42, -41, + -40, -39, -38, -37, -36, -35, -34, -33, + -32, -31, -30, -29, -28, -27, -26, -25, + -24, -23, -22, -21, -20, -19, -18, -17, + -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1 +}; + + +// macros to fetch little-endian words from a bytestream +#define LE_16(x) ((uint16_t)((*(x)) | ((*((x)+1)) << 8))) +#define LE_32(x) (LE_16(x) | ((uint32_t)LE_16(x+2) << 16)) +#define LE_64(x) (LE_32(x) | ((uint64_t)LE_32(x+4) << 32)) + + +bool InterplayDecoder::FillSamples(void *buff, int len) +{ + for (int i = 0; i < len;) + { + if(audio.nRead < audio.nWrite) + { + int todo = std::min(audio.nWrite-audio.nRead, (len-i) / 2); + memcpy((char*)buff+i, &audio.samples[audio.nRead], todo*2); + audio.nRead += todo; + if (audio.nRead == audio.nWrite) + audio.nRead = audio.nWrite = 0; + i += todo*2; + continue; + } + + std::unique_lock plock(PacketMutex); + while (audio.Packets.empty()) + { + if (!bIsPlaying || ProcessNextChunk() >= CHUNK_SHUTDOWN) + { + bIsPlaying = false; + if (i == 0) + return false; + memset((char*)buff+i, 0, len-i); + return true; + } + } + AudioPacket pkt = std::move(audio.Packets.front()); + audio.Packets.pop_front(); + plock.unlock(); + + int nSamples = (int)pkt.nSize; + const uint8_t *samplePtr = pkt.pData.get(); + if (audio.bCompressed) + { + int predictor[2]; + + for (int ch = 0; ch < audio.nChannels; ch++) + { + predictor[ch] = (int16_t)LE_16(samplePtr); + samplePtr += 2; + + audio.samples[audio.nWrite++] = predictor[ch]; + } + + bool stereo = audio.nChannels == 2; + nSamples -= 2*audio.nChannels; + nSamples &= ~(int)stereo; + + int ch = 0; + for (int j = 0; j < nSamples; ++j) + { + predictor[ch] += delta_table[*samplePtr++]; + predictor[ch] = clamp(predictor[ch], -32768, 32767); + + audio.samples[audio.nWrite++] = predictor[ch]; + + // toggle channel + ch ^= stereo ? 1 : 0; + } + } + else if (audio.nBitDepth == 8) + { + for (int j = 0; j < nSamples; ++j) + audio.samples[audio.nWrite++] = ((*samplePtr++)-128) << 8; + } + else + { + nSamples /= 2; + for (int j = 0; j < nSamples; ++j) + { + audio.samples[audio.nWrite++] = (int16_t)LE_16(samplePtr); + samplePtr += 2; + } + } + } + return true; +} + +void InterplayDecoder::DisableAudio() +{ + if (bAudioEnabled) + { + std::unique_lock plock(PacketMutex); + bAudioEnabled = false; + audio.Packets.clear(); + } +} + + +InterplayDecoder::InterplayDecoder(bool soundenabled) +{ + bIsPlaying = false; + bAudioEnabled = soundenabled; + + nWidth = 0; + nHeight = 0; + nFrame = 0; + + memset(palette, 0, sizeof(palette)); + + nFps = 0.0; + nFrameDuration = 0; + nTimerRate = 0; + nTimerDiv = 0; + + pVideoBuffers[0] = nullptr; + pVideoBuffers[1] = nullptr; + + decodeMap.pData = nullptr; + decodeMap.nSize = 0; + + nCurrentVideoBuffer = 0; + nPreviousVideoBuffer = 1; + + videoStride = 0; +} + +InterplayDecoder::~InterplayDecoder() +{ + Close(); +} + +void InterplayDecoder::SwapFrames() +{ + int t = nPreviousVideoBuffer; + nPreviousVideoBuffer = nCurrentVideoBuffer; + nCurrentVideoBuffer = t; +} + +int InterplayDecoder::ProcessNextChunk() +{ + uint8_t chunkPreamble[CHUNK_PREAMBLE_SIZE]; + if (fr.Read(chunkPreamble, CHUNK_PREAMBLE_SIZE) != CHUNK_PREAMBLE_SIZE) { + Printf(TEXTCOLOR_RED "InterplayDecoder: could not read from file (EOF?)\n"); + return CHUNK_EOF; + } + + int chunkSize = LE_16(&chunkPreamble[0]); + int chunkType = LE_16(&chunkPreamble[2]); + + ChunkData.resize(chunkSize); + if (fr.Read(ChunkData.data(), chunkSize) != chunkSize) { + Printf(TEXTCOLOR_RED "InterplayDecoder: could not read from file (EOF?)\n"); + return CHUNK_BAD; + } + + const uint8_t *palPtr = nullptr; + const uint8_t *mapPtr = nullptr; + const uint8_t *vidPtr = nullptr; + int palStart = 0, palCount = 0; + int mapSize = 0, vidSize = 0; + + // iterate through individual opcodes + const uint8_t *chunkPtr = ChunkData.data(); + while (chunkSize > 0 && chunkType != CHUNK_BAD) + { + if (chunkSize < OPCODE_PREAMBLE_SIZE) + { + Printf(TEXTCOLOR_RED "InterplayDecoder: opcode size too small\n"); + return CHUNK_BAD; + } + int opcodeSize = LE_16(chunkPtr); + int opcodeType = chunkPtr[2]; + int opcodeVersion = chunkPtr[3]; + + chunkPtr += OPCODE_PREAMBLE_SIZE; + chunkSize -= OPCODE_PREAMBLE_SIZE; + if (chunkSize < opcodeSize) + { + Printf(TEXTCOLOR_RED "InterplayDecoder: opcode size too large for chunk\n"); + return CHUNK_BAD; + } + chunkSize -= opcodeSize; + + switch (opcodeType) + { + case OPCODE_END_OF_STREAM: + chunkPtr += opcodeSize; + break; + + case OPCODE_END_OF_CHUNK: + chunkPtr += opcodeSize; + break; + + case OPCODE_CREATE_TIMER: + nTimerRate = LE_32(chunkPtr); + nTimerDiv = LE_16(chunkPtr+4); + chunkPtr += 6; + nFrameDuration = ((uint64_t)nTimerRate * nTimerDiv) * 1000; + break; + + case OPCODE_INIT_AUDIO_BUFFERS: + { + // Skip 2 bytes + uint16_t flags = LE_16(chunkPtr+2); + audio.nSampleRate = LE_16(chunkPtr+4); + chunkPtr += 6; + + uint32_t nBufferBytes = (opcodeVersion == 0) ? LE_16(chunkPtr) : LE_32(chunkPtr); + chunkPtr += (opcodeVersion == 0) ? 2 : 4; + + audio.nChannels = (flags & 0x1) ? 2 : 1; + audio.nBitDepth = (flags & 0x2) ? 16 : 8; + audio.bCompressed = (opcodeVersion > 0 && (flags & 0x4)); + audio.samples = std::make_unique(nBufferBytes / (audio.nBitDepth/8)); + audio.nRead = audio.nWrite = 0; + break; + } + + case OPCODE_START_STOP_AUDIO: + chunkPtr += opcodeSize; + break; + + case OPCODE_INIT_VIDEO_BUFFERS: + { + assert(((opcodeVersion == 0 && opcodeSize >= 4) || + (opcodeVersion == 1 && opcodeSize >= 6) || + (opcodeVersion == 2 && opcodeSize >= 8)) && + opcodeSize <= 8 && ! videoStride); + + nWidth = LE_16(chunkPtr) * 8; + nHeight = LE_16(chunkPtr+2) * 8; + + int count, truecolour; + if (opcodeVersion > 0) + { + count = LE_16(chunkPtr+4); + if (opcodeVersion > 1) + { + truecolour = LE_16(chunkPtr+6); + assert(truecolour == 0); + } + } + chunkPtr += opcodeSize; + + pVideoBuffers[0] = new uint8_t[nWidth * nHeight]; + pVideoBuffers[1] = new uint8_t[nWidth * nHeight]; + + videoStride = nWidth; + + animtex.SetSize(AnimTexture::Paletted, nWidth, nHeight); + break; + } + + case OPCODE_UNKNOWN_06: + case OPCODE_UNKNOWN_0E: + case OPCODE_UNKNOWN_10: + case OPCODE_UNKNOWN_12: + case OPCODE_UNKNOWN_13: + case OPCODE_UNKNOWN_14: + case OPCODE_UNKNOWN_15: + chunkPtr += opcodeSize; + break; + + case OPCODE_SEND_BUFFER: + //int nPalStart = LE_16(chunkPtr); + //int nPalCount = LE_16(chunkPtr+2); + + { + VideoPacket pkt; + pkt.pData = std::make_unique(palCount*3 + mapSize + vidSize); + pkt.nPalStart = palStart; + pkt.nPalCount = palCount; + pkt.nDecodeMapSize = mapSize; + pkt.nVideoDataSize = vidSize; + + if (palPtr) + memcpy(pkt.pData.get(), palPtr, palCount*3); + if (mapPtr) + memcpy(pkt.pData.get() + palCount*3, mapPtr, mapSize); + if (vidPtr) + memcpy(pkt.pData.get() + palCount*3 + mapSize, vidPtr, vidSize); + pkt.bSendFlag = true; + VideoPackets.emplace_back(std::move(pkt)); + } + + palPtr = nullptr; + palStart = palCount = 0; + mapPtr = nullptr; + mapSize = 0; + vidPtr = nullptr; + vidSize = 0; + + chunkPtr += opcodeSize; + break; + + case OPCODE_AUDIO_FRAME: + { + uint16_t seqIndex = LE_16(chunkPtr); + uint16_t streamMask = LE_16(chunkPtr+2); + uint16_t nSamples = LE_16(chunkPtr+4); // number of samples this chunk(?) + chunkPtr += 6; + + // We only bother with stream 0 + if (!(streamMask & 1) || !bAudioEnabled) + { + chunkPtr += opcodeSize - 6; + break; + } + + AudioPacket pkt; + pkt.nSize = opcodeSize - 6; + pkt.pData = std::make_unique(pkt.nSize); + memcpy(pkt.pData.get(), chunkPtr, pkt.nSize); + audio.Packets.emplace_back(std::move(pkt)); + + chunkPtr += opcodeSize - 6; + break; + } + + case OPCODE_SILENCE_FRAME: + chunkPtr += opcodeSize; + break; + + case OPCODE_INIT_VIDEO_MODE: + chunkPtr += opcodeSize; + break; + + case OPCODE_CREATE_GRADIENT: + chunkPtr += opcodeSize; + Printf("InterplayDecoder: Create gradient not supported.\n"); + break; + + case OPCODE_SET_PALETTE: + if (opcodeSize > 0x304 || opcodeSize < 4) { + Printf("set_palette opcode with invalid size\n"); + chunkType = CHUNK_BAD; + break; + } + + palStart = LE_16(chunkPtr); + palCount = LE_16(chunkPtr+2); + palPtr = chunkPtr + 4; + if (palStart > 255 || palStart+palCount > 256) { + Printf("set_palette indices out of range (%d -> %d)\n", palStart, palStart+palCount-1); + chunkType = CHUNK_BAD; + break; + } + if (opcodeSize-4 < palCount*3) { + Printf("set_palette opcode too small (%d < %d)\n", opcodeSize-4, palCount*3); + chunkType = CHUNK_BAD; + break; + } + + chunkPtr += opcodeSize; + break; + + case OPCODE_SET_PALETTE_COMPRESSED: + chunkPtr += opcodeSize; + Printf("InterplayDecoder: Set palette compressed not supported.\n"); + break; + + case OPCODE_SET_DECODING_MAP: + mapPtr = chunkPtr; + mapSize = opcodeSize; + + chunkPtr += opcodeSize; + break; + + case OPCODE_VIDEO_DATA: + vidPtr = chunkPtr; + vidSize = opcodeSize; + + chunkPtr += opcodeSize; + break; + + default: + Printf("InterplayDecoder: Unknown opcode (0x%x v%d, %d bytes).\n", opcodeType, opcodeVersion, opcodeSize); + chunkPtr += opcodeSize; + break; + } + } + + if (chunkType < CHUNK_SHUTDOWN && (palPtr || mapPtr || vidPtr)) + { + VideoPacket pkt; + pkt.pData = std::make_unique(palCount*3 + mapSize + vidSize); + pkt.nPalStart = palStart; + pkt.nPalCount = palCount; + pkt.nDecodeMapSize = mapSize; + pkt.nVideoDataSize = vidSize; + + if (palPtr) + memcpy(pkt.pData.get(), palPtr, palCount*3); + if(mapPtr) + memcpy(pkt.pData.get() + palCount*3, mapPtr, mapSize); + if(vidPtr) + memcpy(pkt.pData.get() + palCount*3 + mapSize, vidPtr, vidSize); + pkt.bSendFlag = false; + VideoPackets.emplace_back(std::move(pkt)); + } + + return chunkType; +} + + +void InterplayDecoder::Close() +{ + bIsPlaying = false; + fr.Close(); + + if (decodeMap.pData) { + delete[] decodeMap.pData; + decodeMap.pData = nullptr; + } + + if (pVideoBuffers[0]) { + delete[] pVideoBuffers[0]; + pVideoBuffers[0] = nullptr; + } + if (pVideoBuffers[1]) { + delete[] pVideoBuffers[1]; + pVideoBuffers[1] = nullptr; + } + +} + +bool InterplayDecoder::Open(FileReader &fr_) +{ + // open the file (read only) + char lsig[20]; + + // check the file signature + fr_.Read((uint8_t*)lsig, sizeof(lsig)); + if (memcmp(lsig, "Interplay MVE File\x1A\0", sizeof(lsig)) != 0) + { + Printf(TEXTCOLOR_RED "InterplayDecoder: Unknown MVE signature\n "); + return false; + } + + // skip the next 6 bytes + fr_.Seek(6, FileReader::SeekCur); + fr = std::move(fr_); + + if (ProcessNextChunk() != CHUNK_INIT_VIDEO) + { + Printf(TEXTCOLOR_RED "InterplayDecoder: First chunk not CHUNK_INIT_VIDEO\n"); + return false; + } + + uint8_t chunkPreamble[CHUNK_PREAMBLE_SIZE]; + if (fr.Read(chunkPreamble, CHUNK_PREAMBLE_SIZE) != CHUNK_PREAMBLE_SIZE) { + Printf(TEXTCOLOR_RED "InterplayDecoder: could not read from file (EOF?)\n"); + return false; + } + fr.Seek(-CHUNK_PREAMBLE_SIZE, FileReader::SeekCur); + + int chunkType = LE_16(&chunkPreamble[2]); + if (chunkType == CHUNK_VIDEO) + bAudioEnabled = false; + else + { + if (ProcessNextChunk() != CHUNK_INIT_AUDIO) + { + Printf(TEXTCOLOR_RED "InterplayDecoder: Second non-video chunk not CHUNK_INIT_AUDIO\n"); + return false; + } + bAudioEnabled = audio.nSampleRate > 0; + } + + bIsPlaying = true; + + return true; +} + +bool InterplayDecoder::RunFrame(uint64_t clock) +{ + // handle timing - wait until we're ready to process the next frame. + if (nNextFrameTime > clock) { + return true; + } + nNextFrameTime += nFrameDuration; + + bool doFrame = false; + do + { + std::unique_lock plock(PacketMutex); + while (VideoPackets.empty()) + { + if (!bIsPlaying || ProcessNextChunk() >= CHUNK_SHUTDOWN) + { + bIsPlaying = false; + return false; + } + } + VideoPacket pkt = std::move(VideoPackets.front()); + VideoPackets.pop_front(); + plock.unlock(); + + const uint8_t *palData = pkt.pData.get(); + const uint8_t *mapData = palData + pkt.nPalCount*3; + const uint8_t *vidData = mapData + pkt.nDecodeMapSize; + + if (pkt.nPalCount > 0) + { + int nPalEnd = pkt.nPalStart + pkt.nPalCount; + for (int i = pkt.nPalStart; i < nPalEnd; i++) + { + palette[i].r = (*palData++) << 2; + palette[i].g = (*palData++) << 2; + palette[i].b = (*palData++) << 2; + palette[i].r |= palette[i].r >> 6; + palette[i].g |= palette[i].g >> 6; + palette[i].b |= palette[i].b >> 6; + } + } + + if (pkt.nDecodeMapSize > 0) + { + if (!decodeMap.pData) + { + decodeMap.pData = new uint8_t[pkt.nDecodeMapSize]; + decodeMap.nSize = pkt.nDecodeMapSize; + } + else + { + if (pkt.nDecodeMapSize != decodeMap.nSize) { + delete[] decodeMap.pData; + decodeMap.pData = new uint8_t[pkt.nDecodeMapSize]; + decodeMap.nSize = pkt.nDecodeMapSize; + } + } + + memcpy(decodeMap.pData, mapData, pkt.nDecodeMapSize); + } + + if (pkt.nVideoDataSize > 0 && decodeMap.nSize > 0) + { + auto pStart = vidData; + + // need to skip 14 bytes + ChunkPtr = pStart + 14; + + int i = 0; + for (uint32_t y = 0; y < nHeight; y += 8) + { + for (uint32_t x = 0; x < nWidth; x += 8) + { + uint32_t opcode; + + // alternate between getting low and high 4 bits + if (i & 1) { + opcode = decodeMap.pData[i >> 1] >> 4; + } + else { + opcode = decodeMap.pData[i >> 1] & 0x0F; + } + i++; + + int32_t offset = x + (y * videoStride); + + switch (opcode) + { + default: + break; + case 0: + DecodeBlock0(offset); + break; + case 1: + DecodeBlock1(offset); + break; + case 2: + DecodeBlock2(offset); + break; + case 3: + DecodeBlock3(offset); + break; + case 4: + DecodeBlock4(offset); + break; + case 5: + DecodeBlock5(offset); + break; + case 7: + DecodeBlock7(offset); + break; + case 8: + DecodeBlock8(offset); + break; + case 9: + DecodeBlock9(offset); + break; + case 10: + DecodeBlock10(offset); + break; + case 11: + DecodeBlock11(offset); + break; + case 12: + DecodeBlock12(offset); + break; + case 13: + DecodeBlock13(offset); + break; + case 14: + DecodeBlock14(offset); + break; + case 15: + DecodeBlock15(offset); + break; + } + } + } + + auto pEnd = ChunkPtr; + // we can end up with 1 byte left we need to skip + int nSkipBytes = pkt.nVideoDataSize - (int)(pEnd - pStart); + assert(nSkipBytes <= 1); + } + + doFrame = pkt.bSendFlag; + } while(!doFrame); + + animtex.SetFrame(&palette[0].r , GetCurrentFrame()); + + nFrame++; + SwapFrames(); + + return true; +} + +void InterplayDecoder::CopyBlock(uint8_t* pDest, uint8_t* pSrc) +{ + for (int y = 0; y < 8; y++) + { + memcpy(pDest, pSrc, 8); + pSrc += (intptr_t)videoStride; + pDest += (intptr_t)videoStride; + } +} + +void InterplayDecoder::DecodeBlock0(int32_t offset) +{ + // copy from the same offset but from the previous frame + uint8_t* pDest = GetCurrentFrame() + (intptr_t)offset; + uint8_t* pSrc = GetPreviousFrame() + (intptr_t)offset; + + CopyBlock(pDest, pSrc); +} + +void InterplayDecoder::DecodeBlock1(int32_t offset) +{ + // nothing to do for this. +} + +void InterplayDecoder::DecodeBlock2(int32_t offset) +{ + // copy block from 2 frames ago using a motion vector; need 1 more byte + uint8_t B = *ChunkPtr++; + + int x, y; + + if (B < 56) { + x = 8 + (B % 7); + y = B / 7; + } + else { + x = -14 + ((B - 56) % 29); + y = 8 + ((B - 56) / 29); + } + + uint8_t* pDest = GetCurrentFrame() + (intptr_t)offset; + uint8_t* pSrc = GetCurrentFrame() + (intptr_t)(int64_t)offset + (int64_t)x + (int64_t(y) * (int64_t)videoStride); + + CopyBlock(pDest, pSrc); +} + +void InterplayDecoder::DecodeBlock3(int32_t offset) +{ + // copy 8x8 block from current frame from an up/left block + uint8_t B = *ChunkPtr++; + + int x, y; + + // need 1 more byte for motion + if (B < 56) { + x = -(8 + (B % 7)); + y = -(B / 7); + } + else { + x = -(-14 + ((B - 56) % 29)); + y = -(8 + ((B - 56) / 29)); + } + + uint8_t* pDest = GetCurrentFrame() + (intptr_t)offset; + uint8_t* pSrc = GetCurrentFrame() + (intptr_t)(int64_t)offset + (int64_t)x + (int64_t(y) * (int64_t)videoStride); + + CopyBlock(pDest, pSrc); +} + +void InterplayDecoder::DecodeBlock4(int32_t offset) +{ + // copy a block from the previous frame; need 1 more byte + int x, y; + uint8_t B, BL, BH; + + B = *ChunkPtr++; + + BL = B & 0x0F; + BH = (B >> 4) & 0x0F; + x = -8 + BL; + y = -8 + BH; + + uint8_t* pDest = GetCurrentFrame() + (intptr_t)offset; + uint8_t* pSrc = GetPreviousFrame() + (intptr_t)(int64_t)offset + (int64_t)x + (int64_t(y) * (int64_t)videoStride); + + CopyBlock(pDest, pSrc); +} + +void InterplayDecoder::DecodeBlock5(int32_t offset) +{ + // copy a block from the previous frame using an expanded range; need 2 more bytes + int8_t x = *ChunkPtr++; + int8_t y = *ChunkPtr++; + + uint8_t* pDest = GetCurrentFrame() + (intptr_t)offset; + uint8_t* pSrc = GetPreviousFrame() + (intptr_t)(int64_t)offset + (int64_t)x + (int64_t(y) * (int64_t)videoStride); + + CopyBlock(pDest, pSrc); +} + +// Block6 is unknown and skipped + +void InterplayDecoder::DecodeBlock7(int32_t offset) +{ + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint32_t flags = 0; + + uint8_t P[2]; + P[0] = *ChunkPtr++; + P[1] = *ChunkPtr++; + + // 2-color encoding + if (P[0] <= P[1]) + { + // need 8 more bytes from the stream + for (int y = 0; y < 8; y++) + { + flags = (*ChunkPtr++) | 0x100; + for (; flags != 1; flags >>= 1) { + *pBuffer++ = P[flags & 1]; + } + pBuffer += (videoStride - 8); + } + } + else + { + // need 2 more bytes from the stream + flags = LE_16(ChunkPtr); + ChunkPtr += 2; + + for (int y = 0; y < 8; y += 2) + { + for (int x = 0; x < 8; x += 2, flags >>= 1) + { + pBuffer[x] = + pBuffer[x + 1] = + pBuffer[x + videoStride] = + pBuffer[x + 1 + videoStride] = P[flags & 1]; + } + pBuffer += videoStride * 2; + } + } +} + +void InterplayDecoder::DecodeBlock8(int32_t offset) +{ + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint32_t flags = 0; + uint8_t P[4]; + + // 2-color encoding for each 4x4 quadrant, or 2-color encoding on either top and bottom or left and right halves + P[0] = *ChunkPtr++; + P[1] = *ChunkPtr++; + + if (P[0] <= P[1]) + { + for (int y = 0; y < 16; y++) + { + // new values for each 4x4 block + if (!(y & 3)) + { + if (y) { + P[0] = *ChunkPtr++; + P[1] = *ChunkPtr++; + } + flags = LE_16(ChunkPtr); + ChunkPtr += 2; + } + + for (int x = 0; x < 4; x++, flags >>= 1) { + *pBuffer++ = P[flags & 1]; + } + + pBuffer += videoStride - 4; + // switch to right half + if (y == 7) pBuffer -= 8 * videoStride - 4; + } + } + else + { + flags = LE_32(ChunkPtr); + ChunkPtr += 4; + P[2] = *ChunkPtr++; + P[3] = *ChunkPtr++; + + if (P[2] <= P[3]) + { + // vertical split; left & right halves are 2-color encoded + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 4; x++, flags >>= 1) { + *pBuffer++ = P[flags & 1]; + } + + pBuffer += videoStride - 4; + + // switch to right half + if (y == 7) { + pBuffer -= 8 * videoStride - 4; + P[0] = P[2]; + P[1] = P[3]; + flags = LE_32(ChunkPtr); + ChunkPtr += 4; + } + } + } + else + { + // horizontal split; top & bottom halves are 2-color encoded + for (int y = 0; y < 8; y++) + { + if (y == 4) { + P[0] = P[2]; + P[1] = P[3]; + flags = LE_32(ChunkPtr); + ChunkPtr += 4; + } + + for (int x = 0; x < 8; x++, flags >>= 1) + *pBuffer++ = P[flags & 1]; + + pBuffer += (videoStride - 8); + } + } + } +} + +void InterplayDecoder::DecodeBlock9(int32_t offset) +{ + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint8_t P[4]; + + memcpy(P, ChunkPtr, 4); + ChunkPtr += 4; + + // 4-color encoding + if (P[0] <= P[1]) + { + if (P[2] <= P[3]) + { + // 1 of 4 colors for each pixel, need 16 more bytes + for (int y = 0; y < 8; y++) + { + // get the next set of 8 2-bit flags + int flags = LE_16(ChunkPtr); + ChunkPtr += 2; + + for (int x = 0; x < 8; x++, flags >>= 2) { + *pBuffer++ = P[flags & 0x03]; + } + + pBuffer += (videoStride - 8); + } + } + else + { + // 1 of 4 colors for each 2x2 block, need 4 more bytes + uint32_t flags = LE_32(ChunkPtr); + ChunkPtr += 4; + + for (int y = 0; y < 8; y += 2) + { + for (int x = 0; x < 8; x += 2, flags >>= 2) + { + pBuffer[x] = + pBuffer[x + 1] = + pBuffer[x + videoStride] = + pBuffer[x + 1 + videoStride] = P[flags & 0x03]; + } + + pBuffer += videoStride * 2; + } + } + } + else + { + // 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes + uint64_t flags = LE_64(ChunkPtr); + ChunkPtr += 8; + + if (P[2] <= P[3]) + { + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 8; x += 2, flags >>= 2) + { + pBuffer[x] = + pBuffer[x + 1] = P[flags & 0x03]; + } + pBuffer += videoStride; + } + } + else + { + for (int y = 0; y < 8; y += 2) + { + for (int x = 0; x < 8; x++, flags >>= 2) + { + pBuffer[x] = + pBuffer[x + videoStride] = P[flags & 0x03]; + } + pBuffer += videoStride * 2; + } + } + } +} + +void InterplayDecoder::DecodeBlock10(int32_t offset) +{ + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint8_t P[8]; + + memcpy(P, ChunkPtr, 4); + ChunkPtr += 4; + + // 4-color encoding for each 4x4 quadrant, or 4-color encoding on either top and bottom or left and right halves + if (P[0] <= P[1]) + { + int flags = 0; + + // 4-color encoding for each quadrant; need 32 bytes + for (int y = 0; y < 16; y++) + { + // new values for each 4x4 block + if (!(y & 3)) { + if (y) { + memcpy(P, ChunkPtr, 4); + ChunkPtr += 4; + } + flags = LE_32(ChunkPtr); + ChunkPtr += 4; + } + + for (int x = 0; x < 4; x++, flags >>= 2) { + *pBuffer++ = P[flags & 0x03]; + } + + pBuffer += videoStride - 4; + // switch to right half + if (y == 7) pBuffer -= 8 * videoStride - 4; + } + } + else + { + // vertical split? + int vert; + uint64_t flags = LE_64(ChunkPtr); + ChunkPtr += 8; + + memcpy(P + 4, ChunkPtr, 4); + ChunkPtr += 4; + vert = P[4] <= P[5]; + + // 4-color encoding for either left and right or top and bottom halves + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 4; x++, flags >>= 2) + *pBuffer++ = P[flags & 0x03]; + + if (vert) + { + pBuffer += videoStride - 4; + // switch to right half + if (y == 7) pBuffer -= 8 * videoStride - 4; + } + else if (y & 1) pBuffer += (videoStride - 8); + + // load values for second half + if (y == 7) { + memcpy(P, P + 4, 4); + flags = LE_64(ChunkPtr); + ChunkPtr += 8; + } + } + } +} + +void InterplayDecoder::DecodeBlock11(int32_t offset) +{ + // 64-color encoding (each pixel in block is a different color) + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + + for (int y = 0; y < 8; y++) + { + memcpy(pBuffer, ChunkPtr, 8); + ChunkPtr += 8; + pBuffer += videoStride; + } +} + +void InterplayDecoder::DecodeBlock12(int32_t offset) +{ + // 16-color block encoding: each 2x2 block is a different color + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + + for (int y = 0; y < 8; y += 2) + { + for (int x = 0; x < 8; x += 2) + { + pBuffer[x] = + pBuffer[x + 1] = + pBuffer[x + videoStride] = + pBuffer[x + 1 + videoStride] = *ChunkPtr++; + } + pBuffer += videoStride * 2; + } +} + +void InterplayDecoder::DecodeBlock13(int32_t offset) +{ + // 4-color block encoding: each 4x4 block is a different color + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint8_t P[2] = {}; + + for (int y = 0; y < 8; y++) + { + if (!(y & 3)) + { + P[0] = *ChunkPtr++; + P[1] = *ChunkPtr++; + } + + memset(pBuffer, P[0], 4); + memset(pBuffer + 4, P[1], 4); + pBuffer += videoStride; + } +} + +void InterplayDecoder::DecodeBlock14(int32_t offset) +{ + // 1-color encoding : the whole block is 1 solid color + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint8_t pix = *ChunkPtr++; + + for (int y = 0; y < 8; y++) + { + memset(pBuffer, pix, 8); + pBuffer += videoStride; + } +} + +void InterplayDecoder::DecodeBlock15(int32_t offset) +{ + // dithered encoding + uint8_t* pBuffer = GetCurrentFrame() + (intptr_t)offset; + uint8_t P[2]; + + P[0] = *ChunkPtr++; + P[1] = *ChunkPtr++; + + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 8; x += 2) + { + *pBuffer++ = P[y & 1]; + *pBuffer++ = P[!(y & 1)]; + } + pBuffer += (videoStride - 8); + } +} + +uint8_t* InterplayDecoder::GetCurrentFrame() +{ + return pVideoBuffers[nCurrentVideoBuffer]; +} + +uint8_t* InterplayDecoder::GetPreviousFrame() +{ + return pVideoBuffers[nPreviousVideoBuffer]; +} diff --git a/src/common/cutscenes/playmve.h b/src/common/cutscenes/playmve.h new file mode 100644 index 000000000..9cb299038 --- /dev/null +++ b/src/common/cutscenes/playmve.h @@ -0,0 +1,213 @@ +/* + * InterplayDecoder + * Copyright (C) 2020 sirlemonhead + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +/* This code is based on interplayvideo.c, dpcm.c and ipmovie.c from the FFmpeg project which can be obtained + * from http://www.ffmpeg.org/. Below is the license from interplayvideo.c + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Interplay MVE Video Decoder + * Copyright (C) 2003 The FFmpeg project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include +#include +#include + +#include "files.h" +#include "animtexture.h" +#include "s_music.h" + +#ifndef playmve_h_ +#define playmve_h_ + +class InterplayDecoder +{ +public: + enum + { + CHUNK_PREAMBLE_SIZE = 4, + OPCODE_PREAMBLE_SIZE = 4, + + CHUNK_INIT_AUDIO = 0x0000, + CHUNK_AUDIO_ONLY = 0x0001, + CHUNK_INIT_VIDEO = 0x0002, + CHUNK_VIDEO = 0x0003, + CHUNK_SHUTDOWN = 0x0004, + CHUNK_END = 0x0005, + /* these last types are used internally */ + CHUNK_DONE = 0xFFFC, + CHUNK_NOMEM = 0xFFFD, + CHUNK_EOF = 0xFFFE, + CHUNK_BAD = 0xFFFF, + + OPCODE_END_OF_STREAM = 0x00, + OPCODE_END_OF_CHUNK = 0x01, + OPCODE_CREATE_TIMER = 0x02, + OPCODE_INIT_AUDIO_BUFFERS = 0x03, + OPCODE_START_STOP_AUDIO = 0x04, + OPCODE_INIT_VIDEO_BUFFERS = 0x05, + OPCODE_UNKNOWN_06 = 0x06, + OPCODE_SEND_BUFFER = 0x07, + OPCODE_AUDIO_FRAME = 0x08, + OPCODE_SILENCE_FRAME = 0x09, + OPCODE_INIT_VIDEO_MODE = 0x0A, + OPCODE_CREATE_GRADIENT = 0x0B, + OPCODE_SET_PALETTE = 0x0C, + OPCODE_SET_PALETTE_COMPRESSED = 0x0D, + OPCODE_UNKNOWN_0E = 0x0E, + OPCODE_SET_DECODING_MAP = 0x0F, + OPCODE_UNKNOWN_10 = 0x10, + OPCODE_VIDEO_DATA = 0x11, + OPCODE_UNKNOWN_12 = 0x12, + OPCODE_UNKNOWN_13 = 0x13, + OPCODE_UNKNOWN_14 = 0x14, + OPCODE_UNKNOWN_15 = 0x15, + + PALETTE_COUNT = 256, + kAudioBlocks = 20 // alloc a lot of blocks - need to store lots of audio data before video frames start. + }; + + InterplayDecoder(bool soundenabled); + ~InterplayDecoder(); + + bool Open(FileReader &fr); + void Close(); + + bool RunFrame(uint64_t clock); + + bool FillSamples(void *buff, int len); + + bool HasAudio() const noexcept { return bAudioEnabled; } + int NumChannels() const noexcept { return audio.nChannels; } + int GetSampleRate() const noexcept { return audio.nSampleRate; } + void DisableAudio(); + + AnimTextures& animTex() { return animtex; } + +private: + struct AudioPacket + { + size_t nSize = 0; + std::unique_ptr pData; + }; + + struct VideoPacket + { + uint16_t nPalStart=0, nPalCount=0; + uint32_t nDecodeMapSize = 0; + uint32_t nVideoDataSize = 0; + bool bSendFlag = false; + std::unique_ptr pData; + }; + + struct AudioData + { + int nChannels = 0; + uint16_t nSampleRate = 0; + uint8_t nBitDepth = 0; + bool bCompressed = false; + + std::unique_ptr samples; + int nWrite = 0; + int nRead = 0; + + std::deque Packets; + }; + AudioData audio; + + struct DecodeMap + { + uint8_t* pData; + uint32_t nSize; + }; + + struct Palette + { + uint8_t r; + uint8_t g; + uint8_t b; + }; + + uint8_t* GetCurrentFrame(); + uint8_t* GetPreviousFrame(); + void SwapFrames(); + void CopyBlock(uint8_t* pDest, uint8_t* pSrc); + void DecodeBlock0(int32_t offset); + void DecodeBlock1(int32_t offset); + void DecodeBlock2(int32_t offset); + void DecodeBlock3(int32_t offset); + void DecodeBlock4(int32_t offset); + void DecodeBlock5(int32_t offset); + void DecodeBlock7(int32_t offset); + void DecodeBlock8(int32_t offset); + void DecodeBlock9(int32_t offset); + void DecodeBlock10(int32_t offset); + void DecodeBlock11(int32_t offset); + void DecodeBlock12(int32_t offset); + void DecodeBlock13(int32_t offset); + void DecodeBlock14(int32_t offset); + void DecodeBlock15(int32_t offset); + + std::mutex PacketMutex; + FileReader fr; + + bool bIsPlaying, bAudioEnabled; + + uint32_t nTimerRate, nTimerDiv; + uint32_t nWidth, nHeight, nFrame; + double nFps; + uint64_t nFrameDuration; + + std::vector ChunkData; + int ProcessNextChunk(); + + std::deque VideoPackets; + uint8_t* pVideoBuffers[2]; + uint32_t nCurrentVideoBuffer, nPreviousVideoBuffer; + int32_t videoStride; + + const uint8_t *ChunkPtr = nullptr; + DecodeMap decodeMap; + + AnimTextures animtex; + Palette palette[256]; + uint64_t nNextFrameTime = 0; +}; + +#endif diff --git a/src/common/cutscenes/screenjob.cpp b/src/common/cutscenes/screenjob.cpp new file mode 100644 index 000000000..97bc76862 --- /dev/null +++ b/src/common/cutscenes/screenjob.cpp @@ -0,0 +1,405 @@ +/* +** screenjob.cpp +** +** Generic cutscene display +** +**--------------------------------------------------------------------------- +** Copyright 2020 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 "types.h" +#include "screenjob.h" +#include "i_time.h" +#include "v_2ddrawer.h" +#include "animlib.h" +#include "v_draw.h" +#include "s_soundinternal.h" +#include "animtexture.h" +#include "gamestate.h" +#include "vm.h" +#include "c_bind.h" +#include "c_console.h" +#include "gamestate.h" +#include "printf.h" +#include "c_dispatch.h" +#include "s_music.h" +#include "m_argv.h" +#include "i_interface.h" + +CVAR(Bool, inter_subtitles, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); + +CutsceneState cutscene; +static int ticks; + +//============================================================================= +// +// +// +//============================================================================= + +void Job_Init() +{ + static bool done = false; + if (!done) + { + done = true; + GC::AddMarkerFunc([] { GC::Mark(cutscene.runner); }); + } + cutscene.runnerclass = PClass::FindClass("ScreenJobRunner"); + if (!cutscene.runnerclass) I_FatalError("ScreenJobRunner not defined"); + cutscene.runnerclasstype = NewPointer(cutscene.runnerclass); +} + +//============================================================================= +// +// +// +//============================================================================= + +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; + + auto func = PClass::FindFunction(clsname, funcname); + if (func == nullptr) + I_Error("Call to undefined function %s", qname); + if (validate) + { + // these conditions must be met by all functions for this interface. + if (func->Proto->ReturnTypes.Size() != 0) I_Error("Bad cutscene function %s. Return value not allowed", qname); + if (func->ImplicitArgs != 0) I_Error("Bad cutscene function %s. Must be static", qname); + } + return func; +} + +//============================================================================= +// +// +// +//============================================================================= + +void CallCreateFunction(const char* qname, DObject* runner) +{ + auto func = LookupFunction(qname); + if (func->Proto->ArgumentTypes.Size() != 1) I_Error("Bad cutscene function %s. Must receive precisely one argument.", qname); + if (func->Proto->ArgumentTypes[0] != cutscene.runnerclasstype) I_Error("Bad cutscene function %s. Must receive ScreenJobRunner reference.", qname); + VMValue val = runner; + VMCall(func, &val, 1, nullptr, 0); +} + +//============================================================================= +// +// +// +//============================================================================= + +DObject* CreateRunner(bool clearbefore) +{ + auto obj = cutscene.runnerclass->CreateNew(); + auto func = LookupFunction("ScreenJobRunner.Init", false); + VMValue val[3] = { obj, clearbefore, false }; + VMCall(func, val, 3, nullptr, 0); + return obj; +} + +//============================================================================= +// +// +// +//============================================================================= + +void AddGenericVideo(DObject* runner, const FString& fn, int soundid, int fps) +{ + auto func = LookupFunction("ScreenJobRunner.AddGenericVideo", false); + VMValue val[] = { runner, &fn, soundid, fps }; + VMCall(func, val, 4, nullptr, 0); +} + +//============================================================================= +// +// +// +//============================================================================= + +int CutsceneDef::GetSound() +{ + FSoundID id = INVALID_SOUND; + if (soundName.IsNotEmpty()) id = soundEngine->FindSound(soundName); + if (id == INVALID_SOUND) id = soundEngine->FindSoundByResID(soundID); + return id.index(); +} + +void CutsceneDef::Create(DObject* runner) +{ + if (function.IsNotEmpty()) + { + CallCreateFunction(function, runner); + } + else if (video.IsNotEmpty()) + { + AddGenericVideo(runner, video, GetSound(), framespersec); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void DeleteScreenJob() +{ + if (cutscene.runner) cutscene.runner->Destroy(); + cutscene.runner = nullptr; +} + +void EndScreenJob() +{ + DeleteScreenJob(); + if (cutscene.completion) cutscene.completion(false); + cutscene.completion = nullptr; +} + + +//============================================================================= +// +// +// +//============================================================================= + +bool ScreenJobResponder(event_t* ev) +{ + if (ev->type == EV_KeyDown) + { + // We never reach the key binding checks in G_Responder, so for the console we have to check for ourselves here. + auto binding = Bindings.GetBinding(ev->data1); + if (binding.CompareNoCase("toggleconsole") == 0) + { + C_ToggleConsole(); + return true; + } + if (binding.CompareNoCase("screenshot") == 0) + { + C_DoCommand("screenshot"); + return true; + } + } + FInputEvent evt = ev; + if (cutscene.runner) + { + ScaleOverrider ovr(twod); + IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, OnEvent) + { + int result = 0; + VMValue parm[] = { cutscene.runner, &evt }; + VMReturn ret(&result); + VMCall(func, parm, 2, &ret, 1); + return result; + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool ScreenJobTick() +{ + ticks++; + if (cutscene.runner) + { + ScaleOverrider ovr(twod); + IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, OnTick) + { + int result = 0; + VMValue parm[] = { cutscene.runner }; + VMReturn ret(&result); + VMCall(func, parm, 1, &ret, 1); + return result; + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +void ScreenJobDraw() +{ + double smoothratio = I_GetTimeFrac(); + + if (cutscene.runner) + { + twod->ClearScreen(); + ScaleOverrider ovr(twod); + IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, RunFrame) + { + VMValue parm[] = { cutscene.runner, smoothratio }; + VMCall(func, parm, 2, nullptr, 0); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool ScreenJobValidate() +{ + if (cutscene.runner) + { + ScaleOverrider ovr(twod); + IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, Validate) + { + int res; + VMValue parm[] = { cutscene.runner }; + VMReturn ret(&res); + VMCall(func, parm, 1, &ret, 1); + I_ResetFrameTime(); + return res; + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool StartCutscene(CutsceneDef& cs, int flags, const CompletionFunc& completion_) +{ + if ((cs.function.IsNotEmpty() || cs.video.IsNotEmpty()) && cs.function.CompareNoCase("none") != 0) + { + cutscene.completion = completion_; + cutscene.runner = CreateRunner(); + GC::WriteBarrier(cutscene.runner); + try + { + cs.Create(cutscene.runner); + if (!ScreenJobValidate()) + { + DeleteScreenJob(); + return false; + } + if (sysCallbacks.StartCutscene) sysCallbacks.StartCutscene(flags & SJ_BLOCKUI); + } + catch (...) + { + DeleteScreenJob(); + throw; + } + return true; + } + return false; +} + +bool StartCutscene(const char* s, int flags, const CompletionFunc& completion) +{ + CutsceneDef def; + def.function = s; + return StartCutscene(def, flags, completion); +} + +//============================================================================= +// +// initiates a screen wipe. Needs to call the game code for it. +// +//============================================================================= + +DEFINE_ACTION_FUNCTION(DScreenJobRunner, setTransition) +{ + PARAM_PROLOGUE; + PARAM_INT(type); + + if (type && sysCallbacks.SetTransition) sysCallbacks.SetTransition(type); + return 0; +} + +//============================================================================= +// +// to block wipes on cutscenes that cannot handle it +// +//============================================================================= + +bool CanWipe() +{ + if (cutscene.runner == nullptr) return true; + IFVM(ScreenJobRunner, CanWipe) + { + int can; + VMReturn ret(&can); + VMValue param = cutscene.runner; + VMCall(func, ¶m, 1, &ret, 1); + return can; + } + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +CCMD(testcutscene) +{ + if (argv.argc() < 2) + { + Printf("Usage: testcutscene \n"); + return; + } + try + { + if (StartCutscene(argv[1], 0, [](bool) {})) + { + C_HideConsole(); + } + } + catch (const CRecoverableError& err) + { + Printf(TEXTCOLOR_RED "Unable to play cutscene: %s\n", err.what()); + } +} + + + diff --git a/src/common/cutscenes/screenjob.h b/src/common/cutscenes/screenjob.h new file mode 100644 index 000000000..dce55e3b0 --- /dev/null +++ b/src/common/cutscenes/screenjob.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include "dobject.h" +#include "v_2ddrawer.h" +#include "d_eventbase.h" +#include "s_soundinternal.h" +#include "gamestate.h" +#include "zstring.h" +#include "c_cvars.h" + +EXTERN_CVAR(Bool, inter_subtitles) + +using CompletionFunc = std::function; + +void Job_Init(); + +enum +{ + SJ_BLOCKUI = 1, +}; + +struct CutsceneDef +{ + FString video; + FString function; + FString soundName; + int soundID = -1; // ResID not SoundID! + int framespersec = 0; // only relevant for ANM. + bool transitiononly = false; // only play when transitioning between maps, but not when starting on a map or ending a game. + + void Create(DObject* runner); + bool isdefined() { return video.IsNotEmpty() || function.IsNotEmpty(); } + int GetSound(); +}; + +void EndScreenJob(); +void DeleteScreenJob(); +bool ScreenJobResponder(event_t* ev); +bool ScreenJobTick(); +void ScreenJobDraw(); +bool ScreenJobValidate(); + +struct CutsceneDef; +bool StartCutscene(const char* s, int flags, const CompletionFunc& completion); +bool StartCutscene(CutsceneDef& cs, int flags, const CompletionFunc& completion_); +bool CanWipe(); + +VMFunction* LookupFunction(const char* qname, bool validate = true); +void CallCreateFunction(const char* qname, DObject* runner); +DObject* CreateRunner(bool clearbefore = true); +void AddGenericVideo(DObject* runner, const FString& fn, int soundid, int fps); + +struct CutsceneState +{ + DObject* runner; + PClass* runnerclass; + PType* runnerclasstype; + CompletionFunc completion; +}; + +extern CutsceneState cutscene; diff --git a/src/common/engine/cycler.cpp b/src/common/engine/cycler.cpp index 1d0d28486..1dbf1fce0 100644 --- a/src/common/engine/cycler.cpp +++ b/src/common/engine/cycler.cpp @@ -97,20 +97,20 @@ void FCycler::Update(double diff) { double mult, angle; double step = m_end - m_start; - + if (!m_shouldCycle) { return; } - + m_time += diff; if (m_time >= m_cycle) { m_time = m_cycle; } - + mult = m_time / m_cycle; - + switch (m_cycleType) { case CYCLE_Linear: @@ -149,7 +149,7 @@ void FCycler::Update(double diff) } break; } - + if (m_time == m_cycle) { m_time = 0.; diff --git a/src/common/engine/cycler.h b/src/common/engine/cycler.h index 0b49e644d..a2789f9ca 100644 --- a/src/common/engine/cycler.h +++ b/src/common/engine/cycler.h @@ -23,7 +23,7 @@ public: FCycler() = default; FCycler(const FCycler &other) = default; FCycler &operator=(const FCycler &other) = default; - + void Update(double diff); void SetParams(double start, double end, double cycle, bool update = false); void ShouldCycle(bool sc) { m_shouldCycle = sc; } diff --git a/src/common/engine/d_event.cpp b/src/common/engine/d_event.cpp index 3a779a5fc..f10ff0b19 100644 --- a/src/common/engine/d_event.cpp +++ b/src/common/engine/d_event.cpp @@ -44,15 +44,12 @@ #include "gamestate.h" #include "i_interface.h" -bool G_Responder(event_t* ev); - int eventhead; int eventtail; event_t events[MAXEVENTS]; -CVAR(Float, m_sensitivity_x, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CVAR(Float, m_sensitivity_y, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Float, m_sensitivity_x, 4.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Float, m_sensitivity_y, 2.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) //========================================================================== @@ -67,25 +64,44 @@ CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) void D_ProcessEvents (void) { - event_t *ev; + FixedBitArray keywasdown; + TArray delayedevents; + + keywasdown.Zero(); while (eventtail != eventhead) { - ev = &events[eventtail]; + event_t *ev = &events[eventtail]; eventtail = (eventtail + 1) & (MAXEVENTS - 1); + + if (ev->type == EV_KeyUp && keywasdown[ev->data1]) + { + delayedevents.Push(ev); + continue; + } + if (ev->type == EV_None) continue; if (ev->type == EV_DeviceChange) UpdateJoystickMenu(I_UpdateDeviceList()); - if (gamestate != GS_INTRO) // GS_INTRO blocks the UI. + // allow the game to intercept Escape before dispatching it. + if (ev->type != EV_KeyDown || ev->data1 != KEY_ESCAPE || !sysCallbacks.WantEscape || !sysCallbacks.WantEscape()) { - if (C_Responder(ev)) - continue; // console ate the event - if (M_Responder(ev)) - continue; // menu ate the event + if (gamestate != GS_INTRO) // GS_INTRO blocks the UI. + { + if (C_Responder(ev)) + continue; // console ate the event + if (M_Responder(ev)) + continue; // menu ate the event + } } - G_Responder (ev); + if (sysCallbacks.G_Responder(ev) && ev->type == EV_KeyDown) keywasdown.Set(ev->data1); + } + + for (auto ev: delayedevents) + { + D_PostEvent(ev); } } @@ -123,7 +139,7 @@ void D_RemoveNextCharEvent() } } } - + //========================================================================== // @@ -150,24 +166,11 @@ void D_PostEvent(event_t* ev) void PostMouseMove(int xx, int yy) { - static float lastx = 0, lasty = 0; event_t ev{}; - float x = float(xx) * m_sensitivity_x; - float y = -float(yy) * m_sensitivity_y; + ev.x = float(xx) * m_sensitivity_x; + ev.y = -float(yy) * m_sensitivity_y; - if (m_filter) - { - ev.x = (x + lastx) / 2; - ev.y = (y + lasty) / 2; - } - else - { - ev.x = x; - ev.y = y; - } - lastx = x; - lasty = y; if (ev.x || ev.y) { ev.type = EV_Mouse; diff --git a/src/gamestate.h b/src/common/engine/gamestate.h similarity index 97% rename from src/gamestate.h rename to src/common/engine/gamestate.h index 21652392a..5f674a33b 100644 --- a/src/gamestate.h +++ b/src/common/engine/gamestate.h @@ -14,6 +14,8 @@ enum gamestate_t : int GS_STARTUP, // [RH] Console is fullscreen, and game is just starting GS_TITLELEVEL, // [RH] A combination of GS_LEVEL and GS_DEMOSCREEN GS_INTRO, + GS_CUTSCENE, + GS_MENUSCREEN = GS_DEMOSCREEN, GS_FORCEWIPE = -1, @@ -22,4 +24,5 @@ enum gamestate_t : int GS_FORCEWIPEMELT = -4 }; + extern gamestate_t gamestate; diff --git a/src/common/engine/i_interface.cpp b/src/common/engine/i_interface.cpp index 613c3d5de..580dde407 100644 --- a/src/common/engine/i_interface.cpp +++ b/src/common/engine/i_interface.cpp @@ -1,8 +1,38 @@ #include "i_interface.h" +#include "st_start.h" +#include "gamestate.h" +#include "startupinfo.h" +#include "c_cvars.h" +#include "gstrings.h" + +static_assert(sizeof(void*) == 8, "32 builds are not supported"); // Some global engine variables taken out of the backend code. +FStartupScreen* StartWindow; SystemCallbacks sysCallbacks; FString endoomName; bool batchrun; float menuBlurAmount; +bool AppActive = true; +int chatmodeon; +gamestate_t gamestate = GS_STARTUP; +bool ToggleFullscreen; +int paused; +bool pauseext; + +FStartupInfo GameStartupInfo; + +CVAR(Bool, queryiwad, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(String, defaultiwad, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, vid_fps, false, 0) + +EXTERN_CVAR(Bool, ui_generic) + +CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) +{ + GStrings.UpdateLanguage(self); + UpdateGenericUI(ui_generic); + if (sysCallbacks.LanguageChanged) sysCallbacks.LanguageChanged(self); +} + diff --git a/src/common/engine/i_interface.h b/src/common/engine/i_interface.h index dd3ea5862..48cd2b95d 100644 --- a/src/common/engine/i_interface.h +++ b/src/common/engine/i_interface.h @@ -2,14 +2,18 @@ #include "zstring.h" #include "intrect.h" +#include "name.h" struct event_t; class FRenderState; class FGameTexture; +class FTextureID; enum EUpscaleFlags : int; +class FConfigFile; struct SystemCallbacks { + bool (*G_Responder)(event_t* ev); // this MUST be set, otherwise nothing will work bool (*WantGuiCapture)(); bool (*WantLeftButton)(); bool (*NetGame)(); @@ -34,6 +38,15 @@ struct SystemCallbacks void (*FontCharCreated)(FGameTexture* base, FGameTexture* untranslated); void (*ToggleFullConsole)(); void (*StartCutscene)(bool blockui); + void (*SetTransition)(int type); + bool (*CheckCheatmode)(bool printmsg, bool sponly); + void (*HudScaleChanged)(); + bool (*SetSpecialMenu)(FName& menu, int param); + void (*OnMenuOpen)(bool makesound); + void (*LanguageChanged)(const char*); + bool (*OkForLocalization)(FTextureID, const char*); + FConfigFile* (*GetConfig)(); + bool (*WantEscape)(); }; extern SystemCallbacks sysCallbacks; @@ -49,5 +62,7 @@ extern FString endoomName; extern bool batchrun; extern float menuBlurAmount; extern bool generic_ui; +extern int paused; +extern bool pauseext; void UpdateGenericUI(bool cvar); diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 94388656f..07dc7fdd9 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -7,7 +7,7 @@ // // 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 3 of the License, or +// 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, @@ -75,7 +75,7 @@ #include "cmdlib.h" #include "printf.h" #include "i_interface.h" -#include "templates.h" + #include "i_net.h" @@ -172,7 +172,7 @@ FString GetPlayerName(int num) SOCKET UDPsocket (void) { SOCKET s; - + // allocate a socket s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == INVALID_SOCKET) @@ -193,7 +193,7 @@ void BindToLocalPort (SOCKET s, u_short port) address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); - + v = bind (s, (sockaddr *)&address, sizeof(address)); if (v == SOCKET_ERROR) I_FatalError ("BindToPort: %s", neterror ()); @@ -292,9 +292,9 @@ void PacketGet (void) if (err == WSAECONNRESET) { // The remote node aborted unexpectedly, so pretend it sent an exit packet - if (StartScreen != NULL) + if (StartWindow != NULL) { - StartScreen->NetMessage ("The connection from %s was dropped.\n", + I_NetMessage ("The connection from %s was dropped.\n", GetPlayerName(node).GetChars()); } else @@ -459,7 +459,7 @@ void StartNetwork (bool autoPort) netgame = true; multiplayer = true; - + // create communication socket mysocket = UDPsocket (); BindToLocalPort (mysocket, autoPort ? 0 : DOOMPORT); @@ -511,7 +511,7 @@ static void SendConAck (int num_connected, int num_needed) { PreSend (&packet, 4, &sendaddress[node]); } - StartScreen->NetProgress (doomcom.numnodes); + I_NetProgress (doomcom.numnodes); } bool Host_CheckForConnects (void *userdata) @@ -536,7 +536,7 @@ bool Host_CheckForConnects (void *userdata) if (node == -1) { const uint8_t *s_addr_bytes = (const uint8_t *)&from->sin_addr; - StartScreen->NetMessage ("Got extra connect from %d.%d.%d.%d:%d", + I_NetMessage ("Got extra connect from %d.%d.%d.%d:%d", s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3], from->sin_port); packet.Message = PRE_ALLFULL; @@ -549,7 +549,7 @@ bool Host_CheckForConnects (void *userdata) { node = doomcom.numnodes++; sendaddress[node] = *from; - StartScreen->NetMessage ("Got connect from node %d.", node); + I_NetMessage ("Got connect from node %d.", node); } // Let the new guest (and everyone else) know we got their message. @@ -561,7 +561,7 @@ bool Host_CheckForConnects (void *userdata) node = FindNode (from); if (node >= 0) { - StartScreen->NetMessage ("Got disconnect from node %d.", node); + I_NetMessage ("Got disconnect from node %d.", node); doomcom.numnodes--; while (node < doomcom.numnodes) { @@ -708,10 +708,10 @@ bool HostGame (int i) doomcom.numnodes = 1; - StartScreen->NetInit ("Waiting for players", numplayers); + I_NetInit ("Waiting for players", numplayers); // Wait for numplayers-1 different connections - if (!StartScreen->NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) + if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) { SendAbort(); return false; @@ -719,30 +719,30 @@ bool HostGame (int i) // Now inform everyone of all machines involved in the game memset (gotack, 0, sizeof(gotack)); - StartScreen->NetMessage ("Sending all here."); - StartScreen->NetInit ("Done waiting", 1); + I_NetMessage ("Sending all here."); + I_NetInit ("Done waiting", 1); - if (!StartScreen->NetLoop (Host_SendAllHere, (void *)gotack)) + if (!I_NetLoop (Host_SendAllHere, (void *)gotack)) { SendAbort(); return false; } // Now go - StartScreen->NetMessage ("Go"); + I_NetMessage ("Go"); packet.Fake = PRE_FAKE; packet.Message = PRE_GO; for (node = 1; node < doomcom.numnodes; node++) { // If we send the packets eight times to each guest, // hopefully at least one of them will get through. - for (int i = 8; i != 0; --i) + for (int ii = 8; ii != 0; --ii) { PreSend (&packet, 2, &sendaddress[node]); } } - StartScreen->NetMessage ("Total players: %d", doomcom.numnodes); + I_NetMessage ("Total players: %d", doomcom.numnodes); doomcom.id = DOOMCOM_ID; doomcom.numplayers = doomcom.numnodes; @@ -776,9 +776,9 @@ bool Guest_ContactHost (void *userdata) { if (packet.Message == PRE_CONACK) { - StartScreen->NetMessage ("Total players: %d", packet.NumNodes); - StartScreen->NetInit ("Waiting for other players", packet.NumNodes); - StartScreen->NetProgress (packet.NumPresent); + I_NetMessage ("Total players: %d", packet.NumNodes); + I_NetInit ("Waiting for other players", packet.NumNodes); + I_NetProgress (packet.NumPresent); return true; } else if (packet.Message == PRE_DISCONNECT) @@ -795,7 +795,7 @@ bool Guest_ContactHost (void *userdata) } // In case the progress bar could not be marqueed, bump it. - StartScreen->NetProgress (0); + I_NetProgress (0); return false; } @@ -814,7 +814,7 @@ bool Guest_WaitForOthers (void *userdata) switch (packet.Message) { case PRE_CONACK: - StartScreen->NetProgress (packet.NumPresent); + I_NetProgress (packet.NumPresent); break; case PRE_ALLHERE: @@ -825,7 +825,7 @@ bool Guest_WaitForOthers (void *userdata) doomcom.numnodes = packet.NumNodes + 2; sendplayer[0] = packet.ConsoleNum; // My player number doomcom.consoleplayer = packet.ConsoleNum; - StartScreen->NetMessage ("Console player number: %d", doomcom.consoleplayer); + I_NetMessage ("Console player number: %d", doomcom.consoleplayer); for (node = 0; node < packet.NumNodes; node++) { sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; @@ -839,14 +839,14 @@ bool Guest_WaitForOthers (void *userdata) } } - StartScreen->NetMessage ("Received All Here, sending ACK."); + I_NetMessage ("Received All Here, sending ACK."); packet.Fake = PRE_FAKE; packet.Message = PRE_ALLHEREACK; PreSend (&packet, 2, &sendaddress[1]); break; case PRE_GO: - StartScreen->NetMessage ("Received \"Go.\""); + I_NetMessage ("Received \"Go.\""); return true; case PRE_DISCONNECT: @@ -878,22 +878,22 @@ bool JoinGame (int i) // Let host know we are here - StartScreen->NetInit ("Contacting host", 0); + I_NetInit ("Contacting host", 0); - if (!StartScreen->NetLoop (Guest_ContactHost, NULL)) + if (!I_NetLoop (Guest_ContactHost, NULL)) { SendAbort(); return false; } // Wait for everyone else to connect - if (!StartScreen->NetLoop (Guest_WaitForOthers, 0)) + if (!I_NetLoop (Guest_WaitForOthers, 0)) { SendAbort(); return false; } - - StartScreen->NetMessage ("Total players: %d", doomcom.numnodes); + + I_NetMessage ("Total players: %d", doomcom.numnodes); doomcom.id = DOOMCOM_ID; doomcom.numplayers = doomcom.numnodes; @@ -1026,6 +1026,43 @@ void I_NetCmd (void) I_Error ("Bad net cmd: %i\n",doomcom.command); } +void I_NetMessage(const char* text, ...) +{ + // todo: use better abstraction once everything is migrated to in-game start screens. +#if defined _WIN32 || defined __APPLE__ + va_list ap; + va_start(ap, text); + VPrintf(PRINT_HIGH, text, ap); + Printf("\n"); + va_end(ap); +#else + FString str; + va_list argptr; + + va_start(argptr, text); + str.VFormat(text, argptr); + va_end(argptr); + fprintf(stderr, "\r%-40s\n", str.GetChars()); +#endif +} + +// todo: later these must be dispatched by the main menu, not the start screen. +void I_NetProgress(int val) +{ + StartWindow->NetProgress(val); +} +void I_NetInit(const char* msg, int num) +{ + StartWindow->NetInit(msg, num); +} +bool I_NetLoop(bool (*timer_callback)(void*), void* userdata) +{ + return StartWindow->NetLoop(timer_callback, userdata); +} +void I_NetDone() +{ + StartWindow->NetDone(); +} #ifdef __WIN32__ const char *neterror (void) { diff --git a/src/common/engine/i_net.h b/src/common/engine/i_net.h index 87d720014..c52072c86 100644 --- a/src/common/engine/i_net.h +++ b/src/common/engine/i_net.h @@ -6,6 +6,11 @@ // Called by D_DoomMain. int I_InitNetwork (void); void I_NetCmd (void); +void I_NetMessage(const char*, ...); +void I_NetProgress(int val); +void I_NetInit(const char* msg, int num); +bool I_NetLoop(bool (*timer_callback)(void*), void* userdata); +void I_NetDone(); enum ENetConstants { @@ -76,7 +81,7 @@ struct doomcom_t // packet data to be sent uint8_t data[MAX_MSGLEN]; - + }; extern doomcom_t doomcom; diff --git a/src/common/engine/i_specialpaths.h b/src/common/engine/i_specialpaths.h index 4d61bc3d7..01710b672 100644 --- a/src/common/engine/i_specialpaths.h +++ b/src/common/engine/i_specialpaths.h @@ -16,6 +16,7 @@ FString M_GetDemoPath(); FString M_GetNormalizedPath(const char* path); + #ifdef __APPLE__ FString M_GetMacAppSupportPath(const bool create = true); void M_GetMacSearchDirectories(FString& user_docs, FString& user_app_support, FString& local_app_support); diff --git a/src/common/engine/m_joy.cpp b/src/common/engine/m_joy.cpp index 578287ad5..dec49377f 100644 --- a/src/common/engine/m_joy.cpp +++ b/src/common/engine/m_joy.cpp @@ -35,7 +35,8 @@ #include #include "vectors.h" #include "m_joy.h" -#include "gameconfigfile.h" +#include "configfile.h" +#include "i_interface.h" #include "d_eventbase.h" #include "cmdlib.h" #include "printf.h" @@ -61,9 +62,9 @@ EXTERN_CVAR(Bool, joy_xinput) CUSTOM_CVARD(Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the joystick if it is present") { #ifdef _WIN32 - joy_ps2raw.Callback(); - joy_dinput.Callback(); - joy_xinput.Callback(); + joy_ps2raw->Callback(); + joy_dinput->Callback(); + joy_xinput->Callback(); #endif } @@ -92,10 +93,11 @@ IJoystickConfig::~IJoystickConfig() // //========================================================================== -static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create) +static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create, FConfigFile* GameConfig) { FString id = "Joy:"; id += joy->GetIdentifier(); + if (!GameConfig) return false; return GameConfig->SetSection(id, create); } @@ -107,13 +109,14 @@ static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create) bool M_LoadJoystickConfig(IJoystickConfig *joy) { + FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; char key[32]; const char *value; int axislen; int numaxes; joy->SetDefaultConfig(); - if (!M_SetJoystickConfigSection(joy, false)) + if (!M_SetJoystickConfigSection(joy, false, GameConfig)) { return false; } @@ -166,10 +169,11 @@ bool M_LoadJoystickConfig(IJoystickConfig *joy) void M_SaveJoystickConfig(IJoystickConfig *joy) { + FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; char key[32], value[32]; int axislen, numaxes; - if (M_SetJoystickConfigSection(joy, true)) + if (GameConfig != NULL && M_SetJoystickConfigSection(joy, true, GameConfig)) { GameConfig->ClearCurrentSection(); if (!joy->IsSensitivityDefault()) diff --git a/src/common/engine/m_joy.h b/src/common/engine/m_joy.h index 016aa78d6..fc99379b0 100644 --- a/src/common/engine/m_joy.h +++ b/src/common/engine/m_joy.h @@ -21,7 +21,7 @@ enum EJoyAxis struct NOVTABLE IJoystickConfig { virtual ~IJoystickConfig() = 0; - + virtual FString GetName() = 0; virtual float GetSensitivity() = 0; virtual void SetSensitivity(float scale) = 0; diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 489507061..411db2bda 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -1,3 +1,5 @@ +// common names + // 'None' must always be the first name. xx(None) xx(Null) @@ -8,37 +10,10 @@ xx(Object) xx(Actor) xx(Class) xx(Thinker) +xx(Crosshairs) xx(Untranslated) -xx(Doom) -xx(Heretic) -xx(Hexen) -xx(Strife) -xx(Raven) - -// blood spawning -xx(Blood) -xx(BloodSplatter) -xx(AxeBlood) -xx(Spray) - -// Invulnerability types -xx(Ghost) -xx(Reflective) - -// Iron Feet types -//xx(Normal) // defined below -xx(Full) - -// Invisibility types -xx(Additive) -xx(Cumulative) -xx(Fuzzy) -xx(Opaque) -xx(Stencil) -xx(AddStencil) - // Render styles xx(Normal) xx(SoulTrans) @@ -55,245 +30,10 @@ xx(ColorBlend) xx(ColorAdd) xx(Multiply) -// Healingradius types -xx(Mana) -xx(Armor) - -// Per-actor sound channels -xx(Auto) -xx(Weapon) -xx(Voice) -xx(Item) -xx(Body) -xx(SoundSlot5) -xx(SoundSlot6) -xx(SoundSlot7) - -// Hexen sound sequence names -xx(Platform) -xx(PlatformMetal) -xx(Silence) -xx(Lava) -xx(Water) -xx(Ice) -xx(Earth) -xx(PlatformMetal2) -xx(DoorNormal) -xx(DoorHeavy) -xx(DoorMetal) -xx(DoorCreak) -xx(DoorMetal2) -xx(Wind) - -xx(PointPusher) -xx(PointPuller) - -xx(UpperStackLookOnly) -xx(LowerStackLookOnly) -xx(StackPoint) -xx(SkyCamCompat) - -xx(BasicArmorBonus) -xx(BasicArmorPickup) -xx(SaveAmount) -xx(SavePercent) -xx(MaxAbsorb) -xx(MaxFullAbsorb) -xx(MaxAmount) -xx(ActualSaveAmount) -xx(ArmorType) -xx(HexenArmor) -xx(Slots) -xx(SlotsIncrement) -xx(InterHubAmount) -xx(Icon) -xx(AltHUDIcon) -xx(PickupFlash) - -xx(BulletPuff) -xx(StrifePuff) -xx(MaulerPuff) - -// Special bosses A_BossDeath knows about -xx(Fatso) -xx(Arachnotron) -xx(BaronOfHell) -xx(Cyberdemon) -xx(SpiderMastermind) -xx(Ironlich) -xx(Minotaur) -xx(Sorcerer2) - -// Bots check this -xx(Megasphere) -xx(MegasphereHealth) - -// Standard player classes -xx(DoomPlayer) -xx(HereticPlayer) -xx(StrifePlayer) -xx(FighterPlayer) -xx(ClericPlayer) -xx(MagePlayer) -xx(ChexPlayer) -xx(ChickenPlayer) -xx(PigPlayer) - -// Flechette names for the different Hexen player classes -xx(ArtiPoisonBag1) -xx(ArtiPoisonBag2) -xx(ArtiPoisonBag3) - -// Strife quests -xx(QuestItem) -xx(Sigil) -xx(GiveSigilPiece) -xx(SetWeapon) -xx(SetSprite) - -// Armor -xx(BasicArmor) - -// Doom ammo types -xx(Clip) - -xx(PuzzleItem) -xx(PuzzleItemNumber) -xx(HealthPickup) -xx(autousemode) -xx(Ammo) -xx(WeaponGiver) -xx(DehackedPickup) -xx(PowerTargeter) -xx(PowerInvulnerable) -xx(PowerStrength) -xx(PowerInvisibility) -xx(PowerIronFeet) -xx(PowerLightAmp) -xx(PowerWeaponLevel2) -xx(PowerFlight) -xx(PowerSpeed) -xx(PowerTorch) -xx(PowerHighJump) -xx(PowerReflection) -xx(PowerDrain) -xx(Reflection) -xx(CustomInventory) -xx(Inventory) -xx(StateProvider) -xx(CallTryPickup) -xx(QuestItem25) -xx(QuestItem28) -xx(PowerDoubleFiringSpeed) -xx(PowerInfiniteAmmo) -xx(PowerBuddha) - -xx(TeleportDest) -xx(TeleportDest2) - -// Standard animator names. -xx(Spawn) -xx(See) -xx(Pain) -xx(Melee) -xx(Missile) -xx(Crash) -xx(Death) -xx(Raise) -xx(Wound) -xx(Heal) -xx(Crush) -xx(Yes) -xx(No) -xx(Greetings) -xx(Idle) -xx(GenericFreezeDeath) -xx(GenericCrush) - -// Bounce state names -xx(Bounce) -xx(Wall) -xx(Floor) -xx(Ceiling) -xx(Creature) - -// Compatible death names for the decorate parser. -xx(XDeath) -xx(Burn) -//xx(Ice) // already defined above -xx(Disintegrate) -xx(Smash) - -// Weapon animator names. -xx(Select) -xx(Deselect) -xx(DeadLowered) -xx(Ready) -xx(Fire) -xx(Hold) -xx(AltFire) -xx(AltHold) -xx(Flash) -xx(AltFlash) -xx(Reload) -xx(Zoom) -xx(User1) -xx(User2) -xx(User3) -xx(User4) - -// State names used by ASwitchableDecoration -xx(Active) -xx(Inactive) - -// State names used by ACustomInventory -xx(Pickup) -xx(Use) -xx(Drop) - -xx(Fist) -//xx(Berserk) -xx(Chainsaw) -xx(Pistol) -xx(Shotgun) -xx(SSG) -xx(Chaingun) -xx(Rocket) -xx(Plasma) -xx(BFG) -//xx(Railgun) -xx(Dagger) - -// Damage types -//xx(Fire) already defined above -//xx(Ice) -//xx(Disintegrate) -xx(Drowning) -xx(Slime) -//xx(Crush) -xx(Telefrag) -xx(Falling) -xx(Suicide) -xx(Exit) -xx(Railgun) -xx(Poison) -xx(Electric) -xx(BFGSplash) -xx(DrainLife) // A weapon like the Sigil that drains your life away. -xx(Massacre) // For death by a cheater! -//(Melee) already defined above, so don't define it again -xx(InstantDeath) // Strife "instant death" -xx(PoisonCloud) // makes monsters howl. -xx(Hitscan) // for normal guns and the like -xx(Quake) - -// Special death name for getting killed excessively. Could be used as -// a damage type if you wanted to force an extreme death. -xx(Extreme) -xx(MDK) -xx(Cast) // 'damage type' for the cast call - -// Special names for thingdef_exp.cpp +// Special names for compiler backend +xx(Name) +xx(Clamp) +xx(Abs) xx(Random) xx(FRandom) xx(Random2) @@ -307,7 +47,9 @@ xx(GetParentClass) xx(GetClassName) xx(IsAbstract) xx(GetDefaultByType) +xx(Floor) xx(Exp) +xx(Log) xx(Log10) xx(Ceil) xx(ACos) @@ -322,543 +64,39 @@ xx(TanH) xx(Round) xx(ATan2) xx(VectorAngle) -xx(New) -xx(Alpha) -xx(Angle) -xx(Args) -xx(CeilingZ) -xx(FloorZ) -xx(Health) -xx(Pitch) -xx(SpecialName) -xx(Special) -xx(TID) -xx(TIDtoHate) -xx(WaterLevel) -xx(X) -xx(Y) -xx(Z) -xx(XY) -xx(MomX) -xx(MomY) -xx(MomZ) -xx(Threshold) -xx(DefThreshold) -xx(Abs) -xx(TeleportSpecial) -xx(Teleport) -xx(ACS_NamedExecuteWithResult) -xx(CallACS) xx(Sqrt) -xx(CheckClass) -xx(IsPointerEqual) -xx(Pick) -xx(Mass) -xx(VelX) -xx(VelY) -xx(VelZ) -xx(Accuracy) -xx(Stamina) -xx(Radius) -xx(ReactionTime) -xx(MeleeRange) -xx(Speed) -xx(FastSpeed) -xx(HowlSound) -xx(Clamp) -xx(VisibleStartAngle) -xx(VisibleStartPitch) -xx(VisibleEndAngle) -xx(VisibleEndPitch) -xx(Format) -xx(PickupMsg) -xx(Respawnable) -xx(ExplosionDamage) -xx(ExplosionRadius) -xx(DontHurtShooter) +xx(New) -// Various actor names which are used internally -xx(MapSpot) -xx(PatrolPoint) -xx(PatrolSpecial) -xx(Communicator) -xx(PowerScanner) - -// Textmap properties -//xx(X) -//xx(Y) -xx(ZFloor) -xx(ZCeiling) -xx(Height) -//xx(Tid) -//xx(Angle) -xx(Type) -//xx(Special) -xx(Arg0) -xx(Arg1) -xx(Arg2) -xx(Arg3) -xx(Arg4) -xx(Arg0Str) -xx(Arg1Str) -xx(Id) -xx(MoreIds) -xx(V1) -xx(V2) - -xx(Sidefront) -xx(Sideback) -xx(Offsetx) -xx(Offsety) -xx(Texturetop) -xx(Texturebottom) -xx(Texturemiddle) -xx(Sector) -xx(Heightfloor) -xx(Heightceiling) -xx(Lightlevel) -xx(Texturefloor) -xx(Textureceiling) -xx(Nodecals) - -xx(Skill1) -xx(Skill2) -xx(Skill3) -xx(Skill4) -xx(Skill5) -xx(Skill6) -xx(Skill7) -xx(Skill8) -xx(Skill9) -xx(Skill10) -xx(Skill11) -xx(Skill12) -xx(Skill13) -xx(Skill14) -xx(Skill15) -xx(Skill16) -xx(Medium) -xx(Hard) -xx(Ambush) -xx(Dormant) -xx(Class0) -xx(Class1) -xx(Class2) -xx(Class3) -xx(Class4) -xx(Class5) -xx(Class6) -xx(Class7) -xx(Class8) -xx(Class9) -xx(Class10) -xx(Class11) -xx(Class12) -xx(Class13) -xx(Class14) -xx(Class15) -xx(Class16) -xx(Single) -xx(Coop) -xx(Dm) -xx(Translucent) -xx(Invisible) -xx(Friend) -xx(Strifeally) -xx(Standing) -xx(Countsecret) -xx(NoCount) -xx(Score) -xx(Roll) -xx(Scale) -xx(ScaleX) -xx(ScaleY) -xx(FriendlySeeBlocks) -xx(Floatbobphase) -xx(Floatbobstrength) -xx(Target) -xx(Master) -xx(Tracer) - -xx(Blocking) -xx(Blockmonsters) -xx(Twosided) -xx(Dontpegtop) -xx(Dontpegbottom) -xx(Secret) -xx(Blocksound) -xx(Dontdraw) -xx(Mapped) -xx(Monsteractivate) -xx(Blockplayers) -xx(Blockeverything) -xx(Zoneboundary) -xx(Jumpover) -xx(Blockfloaters) -xx(Blocklandmonsters) -xx(Clipmidtex) -xx(Wrapmidtex) -xx(Midtex3d) -xx(Checkswitchrange) -xx(Firstsideonly) -xx(Transparent) -xx(Passuse) -xx(Repeatspecial) -xx(Conversation) -xx(Locknumber) -xx(Midtex3dimpassible) -xx(Revealed) -xx(AutomapStyle) -xx(DrawFullHeight) - -xx(Playercross) -xx(Playeruse) -xx(Playeruseback) -xx(Monstercross) -xx(Impact) -xx(Playerpush) -xx(Missilecross) -xx(Anycross) -xx(Monsteruse) -xx(Monsterpush) - -xx(ZDoom) -xx(ZDoomTranslated) -xx(Vavoom) -xx(GZDoom) -xx(Eternity) - -xx(Xpanningfloor) -xx(Ypanningfloor) -xx(Xpanningceiling) -xx(Ypanningceiling) -xx(Xscalefloor) -xx(Yscalefloor) -xx(Xscaleceiling) -xx(Yscaleceiling) -xx(Rotationfloor) -xx(Rotationceiling) -xx(Lightfloor) -xx(Lightceiling) -xx(Lightfloorabsolute) -xx(Lightceilingabsolute) -xx(Gravity) -xx(Lightcolor) -xx(Fadecolor) -xx(Color_Floor) -xx(Color_Ceiling) -xx(Color_Walltop) -xx(Color_Wallbottom) -xx(Color_Sprites) -xx(ColorAdd_Floor) -xx(ColorAdd_Ceiling) -xx(ColorAdd_Sprites) -xx(ColorAdd_Walls) -xx(NoSkyWalls) -xx(Desaturation) -xx(SoundSequence) -xx(Silent) -xx(Nofallingdamage) -xx(Dropactors) -xx(NoRespawn) -xx(Alphafloor) -xx(Alphaceiling) -xx(Renderstylefloor) -xx(Renderstyleceiling) -xx(Waterzone) -xx(portal_ceil_blocksound) -xx(portal_ceil_disabled) -xx(portal_ceil_nopass) -xx(portal_ceil_norender) -xx(portal_ceil_overlaytype) -xx(portal_ceil_useglobaltex) -xx(portal_floor_blocksound) -xx(portal_floor_disabled) -xx(portal_floor_nopass) -xx(portal_floor_norender) -xx(portal_floor_overlaytype) -xx(portal_floor_useglobaltex) -xx(scroll_ceil_x) -xx(scroll_ceil_y) -xx(scroll_ceil_type) -xx(scroll_floor_x) -xx(scroll_floor_y) -xx(scroll_floor_type) - -xx(offsetx_top) -xx(offsety_top) -xx(offsetx_mid) -xx(offsety_mid) -xx(offsetx_bottom) -xx(offsety_bottom) -xx(scalex_top) -xx(scaley_top) -xx(scalex_mid) -xx(scaley_mid) -xx(scalex_bottom) -xx(scaley_bottom) -xx(light) -xx(lightabsolute) -xx(lightfog) -xx(nofakecontrast) -xx(smoothlighting) -xx(blockprojectiles) -xx(blockuse) -xx(hidden) -xx(blocksight) -xx(blockhitscan) - -xx(nogradient_top) -xx(flipgradient_top) -xx(clampgradient_top) -xx(useowncolors_top) -xx(uppercolor_top) -xx(lowercolor_top) -xx(nogradient_mid) -xx(flipgradient_mid) -xx(clampgradient_mid) -xx(useowncolors_mid) -xx(uppercolor_mid) -xx(lowercolor_mid) -xx(nogradient_bottom) -xx(flipgradient_bottom) -xx(clampgradient_bottom) -xx(useowncolors_bottom) -xx(uppercolor_bottom) -xx(lowercolor_bottom) -xx(useowncoloradd_top) -xx(coloradd_top) -xx(useowncoloradd_mid) -xx(coloradd_mid) -xx(useowncoloradd_bottom) -xx(coloradd_bottom) -xx(colorization_top) -xx(colorization_mid) -xx(colorization_bottom) -xx(colorization_floor) -xx(colorization_ceiling) - -xx(Renderstyle) - -xx(ceilingplane_a) -xx(ceilingplane_b) -xx(ceilingplane_c) -xx(ceilingplane_d) -xx(floorplane_a) -xx(floorplane_b) -xx(floorplane_c) -xx(floorplane_d) -xx(damageamount) -xx(damagetype) -xx(damageinterval) -xx(leakiness) -xx(damageterraineffect) -xx(damagehazard) -xx(floorterrain) -xx(ceilingterrain) -xx(floor_reflect) -xx(ceiling_reflect) -xx(floorglowcolor) -xx(floorglowheight) -xx(ceilingglowcolor) -xx(ceilingglowheight) -xx(fogdensity) xx(Static) xx(Staticconst) -xx(DeathmatchStatusScreen) -xx(CoopStatusScreen) -xx(DoomStatusScreen) -xx(RavenStatusScreen) -xx(DoomStatusScreenSized) -xx(RavenStatusScreenSized) -xx(StatusbarWidget) -xx(StatusbarHead) -xx(StatusbarCondition) -xx(Next) -xx(Prev) -xx(Children) -xx(Owner) -xx(FlameThrower) -xx(HealthFloor) -xx(HealthCeiling) -xx(Health3D) -xx(DamageSpecial) -xx(DeathSpecial) -xx(HealthFloorGroup) -xx(HealthCeilingGroup) -xx(Health3DGroup) -xx(HealthGroup) +// compatibility crap that GZDoom needs in the backend. +xx(ACS_NamedExecuteWithResult) +xx(__decorate_internal_int__) +xx(__decorate_internal_bool__) +xx(__decorate_internal_float__) -// USDF keywords -xx(Amount) -xx(Text) -xx(Displaycost) -xx(Yesmessage) -xx(Nomessage) -xx(Log) -xx(Giveitem) -xx(Nextpage) -xx(Closedialog) -xx(Cost) -xx(Page) -xx(Count) -xx(Name) -xx(Panel) -xx(Dialog) -xx(Ifitem) -xx(Choice) -xx(Link) -xx(Goodbye) -xx(Require) -xx(Exclude) -xx(Userstring) -xx(Sky) -xx(Pagename) +// 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) +xx(SoundSlot5) +xx(SoundSlot6) +xx(SoundSlot7) -// Special menus -xx(Mainmenu) -xx(MainmenuTextOnly) -xx(Episodemenu) -xx(Playerclassmenu) -xx(HexenDefaultPlayerclassmenu) -xx(ListMenuItemBloodDripDrawer) -xx(Skillmenu) -xx(Startgame) -xx(StartgameNoSkill) -xx(StartgameConfirm) -xx(StartgameConfirmed) -xx(Loadgamemenu) -xx(Savegamemenu) -xx(Readthismenu) -xx(Optionsmenu) -xx(OptionsmenuSimple) -xx(OptionsmenuFull) -xx(Quitmenu) -xx(Savemenu) -xx(Playermenu) -xx(EndGameMenu) -xx(IngameMenu) -xx(HelpMenu) -xx(SoundMenu) -xx(ConfirmPlayerReset) -xx(HuntMenu) -xx(WeaponMenu) -xx(TargetMenu) -xx(UsermapMenu) -xx(EngineCredits) -xx(EngineCredits2) -xx(CreditsMenu) -xx(MultiMenu) +xx(LevelLocals) +xx(Level) -xx(CustomGameMenu) -xx(CustomSubMenu1) -xx(CustomSubMenu2) -xx(CustomSubMenu3) -xx(CustomSubMenu4) -xx(CustomSubMenu5) -xx(CustomSubMenu6) -xx(CustomSubMenu7) - -xx(Playerbox) -xx(Team) -xx(Color) -xx(Red) -xx(Green) -xx(Blue) -xx(Skin) -xx(Gender) -xx(Autoaim) -xx(Switch) -xx(Playerdisplay) -xx(Controlmessage) -xx(Crosshairs) -xx(Colorpickermenu) -xx(Mididevices) -xx(Aldevices) -xx(Alresamplers) -xx(CustomizeControls) -xx(MessageOptions) -xx(AutomapOptions) -xx(ScoreboardOptions) -xx(MapColorMenu) -xx(GameplayOptions) -xx(CompatibilityOptions) -xx(MouseOptions) -xx(JoystickOptions) -xx(SoundOptions) -xx(AdvSoundOptions) -xx(ModReplayerOptions) -xx(VideoOptions) -xx(JoystickConfigMenu) -xx(VMEnterText) -xx(VMTestText) -xx(VideoModeMenu) -xx(res_0) -xx(res_1) -xx(res_2) -xx(res_3) -xx(res_4) -xx(res_5) -xx(res_6) -xx(res_7) -xx(res_8) -xx(res_9) -xx(AlwaysRun) - -// end sequences -xx(Inter_Chess) -xx(Inter_Strife) -xx(Inter_Strife_Good) -xx(Inter_Strife_Sad) -xx(Inter_Strife_Bad) -xx(Inter_Strife_Lose) -xx(Inter_Strife_MAP03) -xx(Inter_Strife_MAP10) -xx(Multiplayer) - -// more stuff -xx(ColorSet) -xx(NeverSwitchOnPickup) -xx(MoveBob) -xx(StillBob) -xx(ClassicFlight) -xx(WBobSpeed) -xx(WBobFire) -xx(PlayerClass) -xx(MonsterClass) -xx(MorphedMonster) -xx(Wi_NoAutostartMap) - -xx(Duration) -xx(MorphStyle) -xx(MorphFlash) -xx(UnMorphFlash) -xx(Powerup) -xx(EffectTics) -xx(PowerupGiver) -xx(BlendColor) -xx(Strength) -xx(Mode) -xx(PowerupType) -xx(PlayerPawn) -xx(Key) - -// Decorate compatibility functions -xx(BuiltinTypeCheck) -xx(BuiltinRandom) -xx(BuiltinRandom2) -xx(BuiltinFRandom) -xx(BuiltinCallLineSpecial) -xx(BuiltinNameToClass) -xx(BuiltinFindMultiNameState) -xx(BuiltinFindSingleNameState) -xx(BuiltinHandleRuntimeState) -xx(BuiltinGetDefault) -xx(BuiltinClassCast) -xx(BuiltinFormat) -xx(Damage) -xx(Noattack) +xy(menu_cursor, "menu/cursor") +xy(menu_choose, "menu/choose") +xy(menu_backup, "menu/backup") +xy(menu_clear, "menu/clear") +xy(menu_dismiss, "menu/dismiss") +xy(menu_change, "menu/change") +xy(menu_advance, "menu/advance") // basic type names xx(Default) @@ -880,6 +118,7 @@ xx(Double) xx(String) xx(Vector) xx(Map) +xx(MapIterator) xx(Array) xx(Include) xx(Sound) @@ -887,6 +126,12 @@ xx(State) xx(Fixed) xx(Vector2) xx(Vector3) +xx(Vector4) +xx(Quat) +xx(FVector2) +xx(FVector3) +xx(FVector4) +xx(FQuat) xx(let) xx(Min) @@ -908,17 +153,25 @@ xx(self) xx(invoker) xx(stateinfo) -xx(__decorate_internal_int__) -xx(__decorate_internal_bool__) -xx(__decorate_internal_float__) -xx(ResolveState) - xx(DamageFunction) xx(Length) +xx(LengthSquared) +xx(Sum) xx(Unit) +xx(Angle) +xx(PlusZ) +xx(ToVector) xx(Size) xx(Push) xx(Insert) +xx(InsertNew) +xx(Remove) +xx(Get) +xx(GetValue) +xx(GetKey) +xx(SetValue) +xx(CheckKey) +xx(Value) xx(Copy) xx(Move) xx(Voidptr) @@ -931,18 +184,7 @@ xx(IsNull) xx(Exists) xx(SetInvalid) xx(SetNull) - -xx(A_Punch) -xx(A_FirePistol) -xx(A_FireShotgun) -xx(A_FireShotgun2) -xx(A_FireCGun) -xx(A_FireMissile) -xx(A_Saw) -xx(A_FirePlasma) -xx(A_FireBFG) -xx(A_FireOldBFG) -xx(A_FireRailgun) +xx(Key) // color channels xx(a) @@ -950,27 +192,12 @@ xx(r) xx(g) xx(b) -// Special translation names -xx(RainPillar1) -xx(RainPillar2) -xx(RainPillar3) -xx(RainPillar4) -xx(RainPillar5) -xx(RainPillar6) -xx(RainPillar7) -xx(RainPillar8) - -xx(Player1) -xx(Player2) -xx(Player3) -xx(Player4) -xx(Player5) -xx(Player6) -xx(Player7) -xx(Player8) -xx(PlayerChunk) -xx(RestrictedToPlayerClass) -xx(ForbiddenToPlayerClass) +xx(X) +xx(Y) +xx(Z) +xx(W) +xx(XY) +xx(XYZ) xx(Prototype) xx(Void) @@ -987,6 +214,34 @@ xx(Both) xx(Physical) xx(Visual) +// blacklisted former CVARs (used by common menu code) +xx(snd_waterlp) +xx(snd_output) +xx(snd_output_format) +xx(snd_speakermode) +xx(snd_resampler) +xx(AlwaysRun) + +// menu names +xx(Mainmenu) +xx(Episodemenu) +xx(Skillmenu) +xx(Startgame) +xx(StartgameConfirm) +xx(StartgameConfirmed) +xx(Loadgamemenu) +xx(Savegamemenu) +xx(Optionsmenu) +xx(OptionsmenuSimple) +xx(OptionsmenuFull) +xx(Quitmenu) +xx(Savemenu) +xx(EndGameMenu) +xx(HelpMenu) +xx(SoundMenu) +xx(ConfirmPlayerReset) +xx(JoystickOptions) + xx(OptionMenuItemSubmenu) xx(OptionMenuItemCommand) xx(OptionMenuItemControlBase) @@ -997,118 +252,17 @@ xx(OptionMenuItemColorPicker) xx(OptionMenuItemStaticText) xx(OptionMenuItemStaticTextSwitchable) -// blacklisted former CVARs -xx(snd_waterlp) -xx(snd_output) -xx(snd_output_format) -xx(snd_speakermode) -xx(snd_resampler) +xx(Color) -// ScriptUtil entry points -xx(ScriptUtil) -xx(SetMarineWeapon) -xx(SetMarineSprite) -xx(GiveInventory) -xx(TakeInventory) -xx(ClearInventory) +xx(Mididevices) +xx(Aldevices) +xx(Alresamplers) -// Weapon member fields that need direct access -xx(Ammo1) -xx(Ammo2) -xx(AmmoType1) -xx(AmmoType2) -xx(AmmoGive1) -xx(AmmoGive2) -xx(AmmoUse1) -xx(SisterWeapon) -xx(BobStyle) -xx(Kickback) -xx(MinSelAmmo1) -xx(bDehAmmo) -xx(FOVScale) -xx(LookScale) -xx(YAdjust) -xx(Crosshair) -xx(WeaponFlags) -xx(DropTime) -xx(PickupSound) +// Decorate compatibility functions +xx(BuiltinRandom) +xx(BuiltinRandom2) +xx(BuiltinFRandom) +xx(BuiltinNameToClass) +xx(BuiltinClassCast) -// PlayerPawn member fields -xx(ColorRangeStart) -xx(ColorRangeEnd) -xx(InvFirst) -xx(ForwardMove1) -xx(ForwardMove2) -xx(SideMove1) -xx(SideMove2) -xx(Face) -xx(Slot) -xx(SoundClass) -xx(ViewBob) -xx(DamageFade) -xx(MaxHealth) -xx(crouchsprite) -xx(UseRange) -xx(AttackZOffset) -xx(SpawnMask) -xx(ScoreIcon) -xx(ViewHeight) -xx(ViewAngle) -xx(ViewPitch) -xx(ViewRoll) -xx(FallingScreamMinSpeed) -xx(FallingScreamMaxSpeed) -xx(GruntSpeed) -xx(JumpZ) -xx(MugShotMaxHealth) -xx(BonusHealth) -xx(PlayerFlags) -xx(InvSel) -xx(FullHeight) - -xx(BlueCard) -xx(YellowCard) -xx(RedCard) -xx(BlueSkull) -xx(YellowSkull) -xx(RedSkull) -xx(DynamicLight) -xx(SpotInnerAngle) -xx(SpotOuterAngle) -xx(lightflags) -xx(lighttype) -xx(InternalDynamicLight) -xx(_a_chase_default) -xx(MapMarker) -xx(Spawn2) -xx(LevelLocals) -xx(Level) -xx(PlayerTeam) -xx(PlayerColors) -xx(PlayerSkin) -xx(NewPlayerMenu) -xx(AltHud) -xx(GameScreen) -xx(ListM) - -// summary -xx(cwidth) -xx(cheight) -xx(wrapwidth) -xx(scalefactorx) -xx(scalefactory) -xx(scalemode) - -xy(menu_cursor, "menu/cursor") -xy(menu_choose, "menu/choose") -xy(menu_backup, "menu/backup") -xy(menu_clear, "menu/clear") -xy(menu_dismiss, "menu/dismiss") -xy(menu_change, "menu/change") -xy(menu_advance, "menu/advance") - -xx(zoomsize) xx(ScreenJobRunner) -xx(RazeStatusBar) -xx(RipSound) -xx(Archvile) diff --git a/src/common/engine/palettecontainer.cpp b/src/common/engine/palettecontainer.cpp index 41a92735d..9648f2528 100644 --- a/src/common/engine/palettecontainer.cpp +++ b/src/common/engine/palettecontainer.cpp @@ -37,7 +37,7 @@ #include "m_crc32.h" #include "printf.h" #include "colormatcher.h" -#include "templates.h" + #include "palettecontainer.h" #include "files.h" @@ -234,7 +234,7 @@ void PaletteContainer::UpdateTranslation(int trans, FRemapTable* remap) int PaletteContainer::AddTranslation(int slot, FRemapTable* remap, int count) { - uint32_t id; + uint32_t id = 0; for (int i = 0; i < count; i++) { auto newremap = AddRemap(&remap[i]); @@ -265,7 +265,7 @@ FRemapTable *PaletteContainer::TranslationToTable(int translation) unsigned int type = GetTranslationType(translation); unsigned int index = GetTranslationIndex(translation); - if (type < 0 || type >= TranslationTables.Size() || index >= NumTranslations(type)) + if (type >= TranslationTables.Size() || index >= NumTranslations(type)) { return uniqueRemaps[0]; // this is the identity table. } @@ -565,9 +565,9 @@ bool FRemapTable::AddDesaturation(int start, int end, double r1, double g1, doub GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].b * 37) / 256.0; - PalEntry pe = PalEntry( MIN(255, int(r1 + intensity*r2)), - MIN(255, int(g1 + intensity*g2)), - MIN(255, int(b1 + intensity*b2))); + PalEntry pe = PalEntry( min(255, int(r1 + intensity*r2)), + min(255, int(g1 + intensity*g2)), + min(255, int(b1 + intensity*b2))); int cc = GPalette.Remap[c]; @@ -649,7 +649,6 @@ bool FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) bool FRemapTable::AddToTranslation(const char *range) { int start,end; - bool desaturated = false; FScanner sc; sc.OpenMem("translation", range, int(strlen(range))); diff --git a/src/common/engine/palettecontainer.h b/src/common/engine/palettecontainer.h index 10883a374..e1d0befd3 100644 --- a/src/common/engine/palettecontainer.h +++ b/src/common/engine/palettecontainer.h @@ -15,7 +15,9 @@ enum struct FRemapTable { FRemapTable(int count = 256) { NumEntries = count; } + FRemapTable(const FRemapTable& o) = default; + FRemapTable& operator=(const FRemapTable& o) = default; bool operator==(const FRemapTable& o); void MakeIdentity(); @@ -135,16 +137,19 @@ public: FRemapTable* GetTranslation(int slot, int index) { + if (TranslationTables.Size() <= (unsigned)slot) return nullptr; return TranslationTables[slot].GetVal(index); } void ClearTranslationSlot(int slot) { + if (TranslationTables.Size() <= (unsigned)slot) return; TranslationTables[slot].Clear(); } unsigned NumTranslations(int slot) const { + if (TranslationTables.Size() <= (unsigned)slot) return 0; return TranslationTables[slot].Size(); } diff --git a/src/common/engine/printf.h b/src/common/engine/printf.h index 69d3e7d45..98af91ff8 100644 --- a/src/common/engine/printf.h +++ b/src/common/engine/printf.h @@ -75,8 +75,8 @@ enum }; -void I_Error(const char *fmt, ...) ATTRIBUTE((format(printf,1,2))); -void I_FatalError(const char* fmt, ...) ATTRIBUTE((format(printf, 1, 2))); +[[noreturn]] void I_Error(const char *fmt, ...) ATTRIBUTE((format(printf,1,2))); +[[noreturn]] void I_FatalError(const char* fmt, ...) ATTRIBUTE((format(printf, 1, 2))); // This really could need some cleanup - the main problem is that it'd create // lots of potential for merge conflicts. @@ -88,7 +88,7 @@ int Printf (const char *format, ...) ATTRIBUTE((format(printf,1,2))); int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3))); void I_DebugPrint(const char* cp); -void debugprintf(const char* f, ...); // Prints to the debugger's log. +void I_DebugPrintf(const char* fmt, ...); // Prints to the debugger's log. // flag to silence non-error output extern bool batchrun; diff --git a/src/common/engine/renderstyle.cpp b/src/common/engine/renderstyle.cpp index 1a29292ea..e31538b4f 100644 --- a/src/common/engine/renderstyle.cpp +++ b/src/common/engine/renderstyle.cpp @@ -32,7 +32,7 @@ ** */ -#include "templates.h" +#include "basics.h" #include "renderstyle.h" #include "c_cvars.h" diff --git a/src/common/engine/renderstyle.h b/src/common/engine/renderstyle.h index 70ad5d561..272f23ba5 100644 --- a/src/common/engine/renderstyle.h +++ b/src/common/engine/renderstyle.h @@ -39,10 +39,7 @@ #undef OPAQUE #endif -enum -{ - OPAQUE = 65536, -}; +constexpr int OPAQUE = 65536; enum ETexMode { diff --git a/src/common/engine/sc_man.cpp b/src/common/engine/sc_man.cpp index f24f25d92..1568f677b 100644 --- a/src/common/engine/sc_man.cpp +++ b/src/common/engine/sc_man.cpp @@ -40,11 +40,11 @@ #include "engineerrors.h" #include "sc_man.h" #include "cmdlib.h" -#include "templates.h" + #include "printf.h" #include "name.h" #include "v_text.h" -#include "templates.h" + #include "zstring.h" #include "name.h" #include @@ -99,106 +99,23 @@ void VersionInfo::operator=(const char *string) // //========================================================================== -FScanner::FScanner() +FScanner::FScanner(TMap* extsymbols) : symbols(extsymbols? *extsymbols : mysymbols) { ScriptOpen = false; } -//========================================================================== -// -// FScanner Destructor -// -//========================================================================== - -FScanner::~FScanner() -{ - // Humm... Nothing to do in here. -} - -//========================================================================== -// -// FScanner Copy Constructor -// -//========================================================================== - -FScanner::FScanner(const FScanner &other) -{ - ScriptOpen = false; - *this = other; -} - //========================================================================== // // FScanner OpenLumpNum Constructor // //========================================================================== -FScanner::FScanner(int lumpnum) +FScanner::FScanner(int lumpnum, TMap* extsymbols) : symbols(extsymbols ? *extsymbols : mysymbols) { ScriptOpen = false; OpenLumpNum(lumpnum); } -//========================================================================== -// -// FScanner :: operator = -// -//========================================================================== - -FScanner &FScanner::operator=(const FScanner &other) -{ - if (this == &other) - { - return *this; - } - if (!other.ScriptOpen) - { - Close(); - return *this; - } - - // Copy protected members - ScriptOpen = true; - ScriptName = other.ScriptName; - ScriptBuffer = other.ScriptBuffer; - ScriptPtr = other.ScriptPtr; - ScriptEndPtr = other.ScriptEndPtr; - AlreadyGot = other.AlreadyGot; - AlreadyGotLine = other.AlreadyGotLine; - LastGotToken = other.LastGotToken; - LastGotPtr = other.LastGotPtr; - LastGotLine = other.LastGotLine; - CMode = other.CMode; - Escape = other.Escape; - StateMode = other.StateMode; - StateOptions = other.StateOptions; - - // Copy public members - if (other.String == other.StringBuffer) - { - memcpy(StringBuffer, other.StringBuffer, sizeof(StringBuffer)); - BigStringBuffer = ""; - String = StringBuffer; - } - else - { - // Past practice means the string buffer must be writeable, which - // removes some of the benefit from using an FString to store - // the big string buffer. - BigStringBuffer = other.BigStringBuffer; - String = BigStringBuffer.LockBuffer(); - } - StringLen = other.StringLen; - TokenType = other.TokenType; - Number = other.Number; - Float = other.Float; - Line = other.Line; - End = other.End; - Crossed = other.Crossed; - - return *this; -} - //========================================================================== // // FScanner :: Open @@ -857,7 +774,7 @@ bool FScanner::CheckFloat (bool evaluate) UnGet(); return false; } - + Float = strtod (String, &stopper); if (*stopper != 0) { @@ -1131,9 +1048,7 @@ FString FScanner::TokenName (int token, const char *string) } else { - FString work; - work.Format ("Unknown(%d)", token); - return work; + work.Format("Unknown(%d)", token); } return work; } @@ -1231,7 +1146,7 @@ void FScanner::AddSymbol(const char *name, int64_t value) { Symbol sym; sym.tokenType = TK_IntConst; - sym.Number = int(value); + sym.Number = value; sym.Float = double(value); symbols.Insert(name, sym); } diff --git a/src/common/engine/sc_man.h b/src/common/engine/sc_man.h index 1caa177a2..4d66b5f21 100644 --- a/src/common/engine/sc_man.h +++ b/src/common/engine/sc_man.h @@ -12,19 +12,19 @@ struct VersionInfo uint16_t minor; uint32_t revision; - bool operator <=(const VersionInfo& o) const + constexpr bool operator <=(const VersionInfo& o) const { return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision); } - bool operator >=(const VersionInfo& o) const + constexpr bool operator >=(const VersionInfo& o) const { return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision); } - bool operator > (const VersionInfo& o) const + constexpr bool operator > (const VersionInfo& o) const { return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision); } - bool operator < (const VersionInfo& o) const + constexpr bool operator < (const VersionInfo& o) const { return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision); } @@ -32,7 +32,7 @@ struct VersionInfo }; // Cannot be a constructor because Lemon would puke on it. -inline VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0) +constexpr VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0) { return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re }; } @@ -54,16 +54,18 @@ public: double Float; }; + using SymbolMap = TMap; - TMap symbols; + SymbolMap mysymbols; + SymbolMap& symbols; + TMap& GetSymbols() { return symbols; } // Methods ------------------------------------------------------ - FScanner(); - FScanner(const FScanner &other); - FScanner(int lumpnum); - ~FScanner(); - - FScanner &operator=(const FScanner &other); + FScanner(TMap* extsymbols = nullptr); + FScanner(const FScanner& other) = delete; + FScanner& operator=(const FScanner& other) = delete; + FScanner(int lumpnum, TMap* extsymbols = nullptr); + ~FScanner() = default; void Open(const char *lumpname); bool OpenFile(const char *filename); @@ -115,6 +117,13 @@ public: void MustGetNumber(bool evaluate = false); bool CheckNumber(bool evaluate = false); + bool GetNumber(int16_t& var, bool evaluate = false) + { + if (!GetNumber(evaluate)) return false; + var = Number; + return true; + } + bool GetNumber(int& var, bool evaluate = false) { if (!GetNumber(evaluate)) return false; @@ -155,11 +164,11 @@ public: void MustGetFloat(bool evaluate = false); bool CheckFloat(bool evaluate = false); - double *LookupConstant(FName name) + Symbol *LookupSymbol(FName name) { - return constants.CheckKey(name); + return symbols.CheckKey(name); } - + // Token based variant bool CheckValue(bool allowfloat, bool evaluate = true); void MustGetValue(bool allowfloat, bool evaluate = true); diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index b10f48081..59c3c7712 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -102,14 +102,14 @@ std2: ":" { RET(':'); } ";" { RET(';'); } "}" { StateMode = 0; StateOptions = false; RET('}'); } - + WSP+ { goto std1; } "\n" { goto newline; } - + TOKS = (NWS\[/":;}]); TOKS* ([/] (TOKS\[*]) TOKS*)* { RET(TK_NonWhitespace); } - + */ } else if (tokens) // A well-defined scanner, based on the c.re example. @@ -167,6 +167,7 @@ std2: 'vector2' { RET(TK_Vector2); } 'vector3' { RET(TK_Vector3); } 'map' { RET(TK_Map); } + 'mapiterator' { RET(TK_MapIterator); } 'array' { RET(TK_Array); } 'in' { RET(TK_In); } 'sizeof' { RET(TK_SizeOf); } @@ -174,7 +175,7 @@ std2: /* Other keywords from UnrealScript */ 'abstract' { RET(TK_Abstract); } - 'foreach' { RET(TK_ForEach); } + 'foreach' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_ForEach : TK_Identifier); } 'true' { RET(TK_True); } 'false' { RET(TK_False); } 'none' { RET(TK_None); } @@ -202,6 +203,7 @@ std2: 'super' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Super : TK_Identifier); } 'stop' { RET(TK_Stop); } 'null' { RET(TK_Null); } + 'nullptr' { RET(ParseVersion >= MakeVersion(4, 9, 0)? TK_Null : TK_Identifier); } 'is' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Is : TK_Identifier); } 'replaces' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Replaces : TK_Identifier); } @@ -222,7 +224,7 @@ std2: 'canraise' { RET(StateOptions ? TK_CanRaise : TK_Identifier); } 'offset' { RET(StateOptions ? TK_Offset : TK_Identifier); } 'light' { RET(StateOptions ? TK_Light : TK_Identifier); } - + /* other DECORATE top level keywords */ '#include' { RET(TK_Include); } diff --git a/src/common/engine/sc_man_tokens.h b/src/common/engine/sc_man_tokens.h index 5aa6360fe..d93e5be62 100644 --- a/src/common/engine/sc_man_tokens.h +++ b/src/common/engine/sc_man_tokens.h @@ -128,6 +128,7 @@ xx(TK_Replaces, "'replaces'") xx(TK_Vector2, "'vector2'") xx(TK_Vector3, "'vector3'") xx(TK_Map, "'map'") +xx(TK_MapIterator, "'mapiterator'") xx(TK_Array, "'array'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp index 505bd044d..8c68b5a3b 100644 --- a/src/common/engine/serializer.cpp +++ b/src/common/engine/serializer.cpp @@ -290,6 +290,28 @@ bool FSerializer::BeginObject(const char *name) // //========================================================================== +bool FSerializer::HasObject(const char* name) +{ + if (isReading()) + { + auto val = r->FindKey(name); + if (val != nullptr) + { + if (val->IsObject()) + { + return true; + } + } + } + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + void FSerializer::EndObject() { if (isWriting()) @@ -601,7 +623,7 @@ void FSerializer::WriteObjects() void FSerializer::ReadObjects(bool hubtravel) { bool founderrors = false; - + if (isReading() && BeginArray("objects")) { // Do not link any thinker that's being created here. This will be done by deserializing the thinker list later. @@ -619,7 +641,6 @@ void FSerializer::ReadObjects(bool hubtravel) if (BeginObject(nullptr)) { FString clsname; // do not deserialize the class type directly so that we can print appropriate errors. - int pindex = -1; Serialize(*this, "classtype", clsname, nullptr); PClass *cls = PClass::FindClass(clsname); @@ -643,6 +664,7 @@ void FSerializer::ReadObjects(bool hubtravel) if (!founderrors) { // Reset to start; + unsigned size = r->mObjects.Size(); r->mObjects.Last().mIndex = 0; for (unsigned i = 0; i < r->mDObjects.Size(); i++) @@ -652,7 +674,6 @@ void FSerializer::ReadObjects(bool hubtravel) { if (obj != nullptr) { - int pindex = -1; try { obj->SerializeUserVars(*this); @@ -660,8 +681,9 @@ void FSerializer::ReadObjects(bool hubtravel) } catch (CRecoverableError &err) { + r->mObjects.Clamp(size); // close all inner objects. // In case something in here throws an error, let's continue and deal with it later. - Printf(TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); + Printf(PRINT_NONOTIFY | PRINT_BOLD, TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); mErrors++; } } @@ -1310,9 +1332,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI if (!arc.soundNamesAreUnique) { //If sound name here is not reliable, we need to save by index instead. - int id = sid; + int id = sid.index(); Serialize(arc, key, id, nullptr); - if (arc.isReading()) sid = FSoundID(id); + if (arc.isReading()) sid = FSoundID::fromInt(id); } else if (arc.isWriting()) { @@ -1332,16 +1354,16 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI assert(val->IsString() || val->IsNull()); if (val->IsString()) { - sid = UnicodeToString(val->GetString()); + sid = S_FindSound(UnicodeToString(val->GetString())); } else if (val->IsNull()) { - sid = 0; + sid = NO_SOUND; } else { Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key); - sid = 0; + sid = NO_SOUND; arc.mErrors++; } } diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index 400a6f4aa..63bfb3529 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -85,6 +85,7 @@ public: void ReadObjects(bool hubtravel); bool BeginObject(const char *name); void EndObject(); + bool HasObject(const char* name); bool BeginArray(const char *name); void EndArray(); unsigned GetSize(const char *group); @@ -110,7 +111,7 @@ public: { return w != nullptr; } - + bool canSkip() const; template @@ -158,7 +159,7 @@ public: template FSerializer &Array(const char *key, T *obj, T *def, int count, bool fullcompare = false) { - if (!save_full && fullcompare && isWriting() && def != nullptr && !memcmp(obj, def, count * sizeof(T))) + if (!save_full && fullcompare && isWriting() && key != nullptr && def != nullptr && !memcmp(obj, def, count * sizeof(T))) { return *this; } @@ -234,7 +235,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def); FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def); -template +template >*/> FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **) { DObject *v = static_cast(value); @@ -301,6 +302,11 @@ FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray& v return arc.SerializeMemory(key, value.Storage(), value.StorageSize()); } +inline FSerializer& Serialize(FSerializer& arc, const char* key, BitArray& value, BitArray* def) +{ + return arc.SerializeMemory(key, value.Storage().Data(), value.Storage().Size()); +} + 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); @@ -320,10 +326,25 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, DVector2 &p, DV return arc.Array(key, &p[0], def? &(*def)[0] : nullptr, 2, true); } +inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector4& p, FVector4* def) +{ + return arc.Array(key, &p[0], def ? &(*def)[0] : nullptr, 4, true); +} + +inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector3& p, FVector3* def) +{ + return arc.Array(key, &p[0], def ? &(*def)[0] : nullptr, 3, true); +} + +inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector2& p, FVector2* def) +{ + return arc.Array(key, &p[0], def ? &(*def)[0] : nullptr, 2, true); +} + template inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle &p, TAngle *def) { - return Serialize(arc, key, p.Degrees, def? &def->Degrees : nullptr); + return Serialize(arc, key, p.Degrees__(), def ? &def->Degrees__() : nullptr); } inline FSerializer &Serialize(FSerializer &arc, const char *key, PalEntry &pe, PalEntry *def) diff --git a/src/common/engine/serializer_internal.h b/src/common/engine/serializer_internal.h index e05d5785c..31cf76c1a 100644 --- a/src/common/engine/serializer_internal.h +++ b/src/common/engine/serializer_internal.h @@ -42,7 +42,7 @@ struct FWriter rapidjson::StringBuffer mOutString; TArray mDObjects; TMap mObjectMap; - + FWriter(bool pretty) { if (!pretty) @@ -193,7 +193,7 @@ struct FReader rapidjson::Value *FindKey(const char *key) { FJSONObject &obj = mObjects.Last(); - + if (obj.mObject->IsObject()) { if (key == nullptr) diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index 1456e051c..8e02987d6 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); + static FStartupScreen *CreateInstance(int max_progress, bool showprogress); FStartupScreen(int max_progress) { @@ -47,14 +47,13 @@ public: CurPos = 0; NotchPos = 0; } - + virtual ~FStartupScreen() = default; virtual void Progress() {} virtual void NetInit(const char *message, int num_players) {} virtual void NetProgress(int count) {} - virtual void NetMessage(const char *format, ...) {} // cover for printf virtual void NetDone() {} virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; } virtual void AppendStatusLine(const char* status) {} @@ -77,118 +76,12 @@ public: void NetDone(); bool NetLoop(bool (*timer_callback)(void*), void* userdata); protected: - long long NetMarqueeMode; int NetMaxPos, NetCurPos; }; -class FGraphicalStartupScreen : public FBasicStartupScreen -{ -public: - FGraphicalStartupScreen(int max_progress); - ~FGraphicalStartupScreen(); -}; - -class FHereticStartupScreen : public FGraphicalStartupScreen -{ -public: - FHereticStartupScreen(int max_progress, long &hr); - - void Progress(); - void LoadingStatus(const char *message, int colors); - void AppendStatusLine(const char *status); -protected: - void SetWindowSize(); - - int ThermX, ThermY, ThermWidth, ThermHeight; - int HMsgY, SMsgX; -}; - -class FHexenStartupScreen : public FGraphicalStartupScreen -{ -public: - FHexenStartupScreen(int max_progress, long &hr); - ~FHexenStartupScreen(); - - void Progress(); - void NetProgress(int count); - void NetDone(); - void SetWindowSize(); - - // Hexen's notch graphics, converted to chunky pixels. - uint8_t * NotchBits; - uint8_t * NetNotchBits; -}; - -class FStrifeStartupScreen : public FGraphicalStartupScreen -{ -public: - FStrifeStartupScreen(int max_progress, long &hr); - ~FStrifeStartupScreen(); - - void Progress(); -protected: - void DrawStuff(int old_laser, int new_laser); - void SetWindowSize(); - - uint8_t *StartupPics[4+2+1]; -}; - -extern FStartupScreen *StartScreen; - -void DeleteStartupScreen(); -extern void ST_Endoom(); - -// The entire set of functions here uses native Windows types. These are recreations of those types so that the code doesn't need to be changed more than necessary - -struct BitmapInfoHeader -{ - uint32_t biSize; - int32_t biWidth; - int32_t biHeight; - uint16_t biPlanes; - uint16_t biBitCount; - uint32_t biCompression; - uint32_t biSizeImage; - int32_t biXPelsPerMeter; - int32_t biYPelsPerMeter; - uint32_t biClrUsed; - uint32_t biClrImportant; -}; - -struct RgbQuad -{ - uint8_t rgbBlue; - uint8_t rgbGreen; - uint8_t rgbRed; - uint8_t rgbReserved; -}; - - -struct BitmapInfo -{ - BitmapInfoHeader bmiHeader; - RgbQuad bmiColors[1]; -}; - -extern BitmapInfo* StartupBitmap; - - -void ST_Util_PlanarToChunky4(uint8_t* dest, const uint8_t* src, int width, int height); -void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y, int bytewidth, int height); -void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int bytewidth, int height); -BitmapInfo* ST_Util_CreateBitmap(int width, int height, int color_bits); -uint8_t* ST_Util_BitsForBitmap(BitmapInfo* bitmap_info); -void ST_Util_FreeBitmap(BitmapInfo* bitmap_info); -void ST_Util_BitmapColorsFromPlaypal(BitmapInfo* bitmap_info); -uint8_t* ST_Util_LoadFont(const char* filename); -void ST_Util_FreeFont(uint8_t* font); -BitmapInfo* ST_Util_AllocTextBitmap(const uint8_t* font); -void ST_Util_DrawTextScreen(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font); -void ST_Util_DrawChar(BitmapInfo* screen, const uint8_t* font, int x, int y, uint8_t charnum, uint8_t attrib); -void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font, bool on); - +extern FStartupScreen *StartWindow; //=========================================================================== // @@ -200,10 +93,10 @@ void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen inline void DeleteStartupScreen() { - if (StartScreen != nullptr) + if (StartWindow != nullptr) { - delete StartScreen; - StartScreen = nullptr; + delete StartWindow; + StartWindow = nullptr; } } diff --git a/src/common/engine/startupinfo.h b/src/common/engine/startupinfo.h index d24e07d68..c0dd608c1 100644 --- a/src/common/engine/startupinfo.h +++ b/src/common/engine/startupinfo.h @@ -11,6 +11,8 @@ struct FStartupInfo FString Song; FString con; FString def; + FString DiscordAppId = nullptr; + FString SteamAppId = nullptr; int Type; int LoadLights = -1; int LoadBrightmaps = -1; diff --git a/src/common/engine/stats.h b/src/common/engine/stats.h index 3e048ac16..c7473531e 100644 --- a/src/common/engine/stats.h +++ b/src/common/engine/stats.h @@ -35,6 +35,9 @@ #define __STATS_H__ #include "zstring.h" +#if defined __i386__ +#include "x86.h" +#endif #if !defined _WIN32 && !defined __APPLE__ @@ -45,6 +48,7 @@ public: cycle_t &operator= (const cycle_t &o) { return *this; } void Reset() {} void Clock() {} + void ResetAndClock() {} void Unclock() {} double Time() { return 0; } double TimeMS() { return 0; } @@ -54,6 +58,45 @@ public: #include +// [MK] try to use RDTSC on linux if possible +// avoids excess latency of clock_gettime() on some platforms +#ifdef __linux__ +extern bool PerfAvailable; +extern double PerfToSec, PerfToMillisec; + +inline uint64_t rdtsc() +{ +#ifdef __amd64__ + uint64_t tsc; + asm volatile("rdtsc; shlq $32, %%rdx; orq %%rdx, %%rax":"=a"(tsc)::"%rdx"); + return tsc; +#elif defined __ppc__ + unsigned int lower, upper, temp; + do + { + asm volatile ("mftbu %0 \n mftb %1 \n mftbu %2 \n" + : "=r"(upper), "=r"(lower), "=r"(temp)); + } + while (upper != temp); + return (static_cast(upper) << 32) | lower; +#elif defined __aarch64__ + uint64_t vct; + asm volatile("mrs %0, cntvct_el0":"=r"(vct)); + return vct; +#elif defined __i386__ + if (CPU.bRDTSC) + { + uint64_t tsc; + asm volatile ("\trdtsc\n" : "=A" (tsc)); + return tsc; + } + return 0; +#else + return 0; +#endif // __amd64__ +} +#endif + class cycle_t { public: @@ -61,28 +104,50 @@ public: { Sec = 0; } - + void Clock() { +#ifdef __linux__ + if ( PerfAvailable ) + { + int64_t time = rdtsc(); + Sec -= time * PerfToSec; + return; + } +#endif timespec ts; - + clock_gettime(CLOCK_MONOTONIC, &ts); Sec -= ts.tv_sec + ts.tv_nsec * 1e-9; } - + + void ResetAndClock() + { + Reset(); + Clock(); + } + void Unclock() { +#ifdef __linux__ + if ( PerfAvailable ) + { + int64_t time = rdtsc(); + Sec += time * PerfToSec; + return; + } +#endif timespec ts; - + clock_gettime(CLOCK_MONOTONIC, &ts); Sec += ts.tv_sec + ts.tv_nsec * 1e-9; } - + double Time() { return Sec; } - + double TimeMS() { return Sec * 1e3; @@ -132,15 +197,16 @@ inline uint64_t rdtsc() unsigned int lower, upper, temp; do { - asm volatile ("mftbu %0 \n mftb %1 \n mftbu %2 \n" + asm volatile ("mftbu %0 \n mftb %1 \n mftbu %2 \n" : "=r"(upper), "=r"(lower), "=r"(temp)); } while (upper != temp); return (static_cast(upper) << 32) | lower; #elif defined __aarch64__ - // TODO: Implement and test on ARM64 - return 0; -#else // i386 + uint64_t vct; + asm volatile("mrs %0, cntvct_el0":"=r"(vct)); + return vct; +#elif defined __i386__ // i386 if (CPU.bRDTSC) { uint64_t tsc; @@ -148,6 +214,8 @@ inline uint64_t rdtsc() return tsc; } return 0; +#else + return 0; #endif // __amd64__ } #endif @@ -159,24 +227,29 @@ public: { Counter = 0; } - + + void ResetAndClock() + { + Counter = -static_cast(rdtsc()); + } + void Clock() { int64_t time = rdtsc(); Counter -= time; } - + void Unclock(bool checkvar = true) { int64_t time = rdtsc(); Counter += time; } - + double Time() { return Counter * PerfToSec; } - + double TimeMS() { return Counter * PerfToMillisec; diff --git a/src/common/engine/stringtable.cpp b/src/common/engine/stringtable.cpp index b36e6e409..92819c144 100644 --- a/src/common/engine/stringtable.cpp +++ b/src/common/engine/stringtable.cpp @@ -639,7 +639,7 @@ bool FStringTable::MatchDefaultString(const char *name, const char *content) con // This only compares the first line to avoid problems with bad linefeeds. For the few cases where this feature is needed it is sufficient. auto c = GetLanguageString(name, FStringTable::default_table); if (!c) return false; - + // 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); diff --git a/src/common/engine/stringtable.h b/src/common/engine/stringtable.h index 0467b27ed..d75864303 100644 --- a/src/common/engine/stringtable.h +++ b/src/common/engine/stringtable.h @@ -91,7 +91,7 @@ public: allStrings.Insert(override_table, map); UpdateLanguage(nullptr); } - + 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; @@ -110,7 +110,7 @@ private: StringMacroMap allMacros; LangMap allStrings; TArray> currentLanguageSet; - + void LoadLanguage (int lumpnum, const TArray &buffer); TArray> parseCSV(const TArray &buffer); bool ParseLanguageCSV(int lumpnum, const TArray &buffer); @@ -127,7 +127,7 @@ public: if (*str == '$') return str; return FString("$") + str; } - + static FString MakeMacro(const char *str, size_t len) { if (*str == '$') return FString(str, len); diff --git a/src/common/engine/v_colortables.cpp b/src/common/engine/v_colortables.cpp index 36849862b..b891ff142 100644 --- a/src/common/engine/v_colortables.cpp +++ b/src/common/engine/v_colortables.cpp @@ -57,7 +57,7 @@ ColorTable256k RGB256k; void BuildTransTable (const PalEntry *palette) { int r, g, b; - + // create the RGB555 lookup table for (r = 0; r < 32; r++) for (g = 0; g < 32; g++) @@ -68,16 +68,16 @@ void BuildTransTable (const PalEntry *palette) for (g = 0; g < 64; g++) for (b = 0; b < 64; b++) RGB256k.RGB[r][g][b] = ColorMatcher.Pick ((r<<2)|(r>>4), (g<<2)|(g>>4), (b<<2)|(b>>4)); - + int x, y; - + // create the swizzled palette for (x = 0; x < 65; x++) for (y = 0; y < 256; y++) Col2RGB8[x][y] = (((palette[y].r*x)>>4)<<20) | ((palette[y].g*x)>>4) | (((palette[y].b*x)>>4)<<10); - + // create the swizzled palette with the lsb of red and blue forced to 0 // (for green, a 1 is okay since it never gets added into) for (x = 1; x < 64; x++) @@ -90,7 +90,7 @@ void BuildTransTable (const PalEntry *palette) } Col2RGB8_LessPrecision[0] = Col2RGB8[0]; Col2RGB8_LessPrecision[64] = Col2RGB8[64]; - + // create the inverse swizzled palette for (x = 0; x < 65; x++) for (y = 0; y < 256; y++) diff --git a/src/common/filesystem/file_directory.cpp b/src/common/filesystem/file_directory.cpp index 8c7b57876..80b9f6e57 100644 --- a/src/common/filesystem/file_directory.cpp +++ b/src/common/filesystem/file_directory.cpp @@ -41,8 +41,6 @@ #include "printf.h" #include "findfile.h" - - //========================================================================== // // Zip Lump @@ -120,7 +118,7 @@ int FDirectory::AddDirectory(const char *dirpath) FString dirmatch = dirpath; findstate_t find; dirmatch += '*'; - + handle = I_FindFirst(dirmatch.GetChars(), &find); if (handle == ((void *)(-1))) { diff --git a/src/common/filesystem/file_grp.cpp b/src/common/filesystem/file_grp.cpp index 1bf3bd7a4..7128c1307 100644 --- a/src/common/filesystem/file_grp.cpp +++ b/src/common/filesystem/file_grp.cpp @@ -42,7 +42,7 @@ // //========================================================================== -struct GrpInfo +struct GrpHeader { uint32_t Magic[3]; uint32_t NumLumps; @@ -95,17 +95,17 @@ FGrpFile::FGrpFile(const char *filename, FileReader &file) bool FGrpFile::Open(bool quiet, LumpFilterInfo*) { - GrpInfo header; + GrpHeader header; Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); - + GrpLump *fileinfo = new GrpLump[NumLumps]; Reader.Read (fileinfo, NumLumps * sizeof(GrpLump)); Lumps.Resize(NumLumps); - int Position = sizeof(GrpInfo) + NumLumps * sizeof(GrpLump); + int Position = sizeof(GrpHeader) + NumLumps * sizeof(GrpLump); for(uint32_t i = 0; i < NumLumps; i++) { diff --git a/src/common/filesystem/file_pak.cpp b/src/common/filesystem/file_pak.cpp index 13aafa985..3a868766c 100644 --- a/src/common/filesystem/file_pak.cpp +++ b/src/common/filesystem/file_pak.cpp @@ -95,7 +95,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t); header.dirofs = LittleLong(header.dirofs); - + TArray fileinfo(NumLumps, true); Reader.Seek (header.dirofs, FileReader::SeekSet); Reader.Read (fileinfo.Data(), NumLumps * sizeof(dpackfile_t)); diff --git a/src/common/filesystem/file_rff.cpp b/src/common/filesystem/file_rff.cpp index c69b50246..3e512b62d 100644 --- a/src/common/filesystem/file_rff.cpp +++ b/src/common/filesystem/file_rff.cpp @@ -34,7 +34,7 @@ */ #include "resourcefile.h" -#include "templates.h" + #include "printf.h" //========================================================================== @@ -219,9 +219,9 @@ int FRFFLump::FillCache() if (Flags & LUMPF_COMPRESSED) { - int cryptlen = MIN (LumpSize, 256); + int cryptlen = min (LumpSize, 256); uint8_t *data = (uint8_t *)Cache; - + for (int i = 0; i < cryptlen; ++i) { data[i] ^= i >> 1; diff --git a/src/common/filesystem/file_wad.cpp b/src/common/filesystem/file_wad.cpp index 054b0721a..8af39b5f8 100644 --- a/src/common/filesystem/file_wad.cpp +++ b/src/common/filesystem/file_wad.cpp @@ -206,7 +206,7 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) 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) { @@ -279,7 +279,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name int numstartmarkers = 0, numendmarkers = 0; unsigned int i; TArray markers; - + for(i = 0; i < NumLumps; i++) { if (IsMarker(i, startmarker)) @@ -302,20 +302,20 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", 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; - for(unsigned int i = 0; i < end; i++) + for(unsigned int ii = 0; ii < end; ii++) { - if (Lumps[i].LumpSize == 4096) + if (Lumps[ii].LumpSize == 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[i].getName()); - Lumps[i].Flags |= LUMPF_MAYBEFLAT; + DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[ii].getName()); + Lumps[ii].Flags |= LUMPF_MAYBEFLAT; } } } @@ -428,18 +428,19 @@ void FWadFile::SkinHack () 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') + lump->getName()[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->getName()[4] == '\0')) { hasmap = true; } diff --git a/src/common/filesystem/file_whres.cpp b/src/common/filesystem/file_whres.cpp index 1c573ad38..969aaafab 100644 --- a/src/common/filesystem/file_whres.cpp +++ b/src/common/filesystem/file_whres.cpp @@ -95,10 +95,10 @@ FWHResFile::FWHResFile(const char *filename, FileReader &file) bool FWHResFile::Open(bool quiet, LumpFilterInfo*) { int directory[1024]; - + Reader.Seek(-4096, FileReader::SeekEnd); Reader.Read(directory, 4096); - + int nl =1024/3; Lumps.Resize(nl); @@ -135,10 +135,10 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, Lu { int directory[1024]; int nl =1024/3; - + file.Seek(-4096, FileReader::SeekEnd); file.Read(directory, 4096); - + int checkpos = 0; for(int k = 0; k < nl; k++) { diff --git a/src/common/filesystem/file_zip.cpp b/src/common/filesystem/file_zip.cpp index b3acb8d13..e14305b52 100644 --- a/src/common/filesystem/file_zip.cpp +++ b/src/common/filesystem/file_zip.cpp @@ -36,7 +36,7 @@ #include #include "file_zip.h" #include "cmdlib.h" -#include "templates.h" + #include "printf.h" #include "w_zip.h" @@ -115,7 +115,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer) // //----------------------------------------------------------------------- -static uint32_t Zip_FindCentralDir(FileReader &fin) +static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64) { unsigned char buf[BUFREADCOMMENT + 4]; uint32_t FileSize; @@ -124,7 +124,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin) uint32_t uPosFound=0; FileSize = (uint32_t)fin.GetLength(); - uMaxBack = MIN(0xffff, FileSize); + uMaxBack = min(0xffff, FileSize); uBackRead = 4; while (uBackRead < uMaxBack) @@ -137,7 +137,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin) uBackRead += BUFREADCOMMENT; uReadPos = FileSize - uBackRead; - uReadSize = MIN((BUFREADCOMMENT + 4), (FileSize - uReadPos)); + uReadSize = min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; @@ -145,15 +145,18 @@ static uint32_t Zip_FindCentralDir(FileReader &fin) for (i = (int)uReadSize - 3; (i--) > 0;) { - if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6) + if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6 && !*zip64 && uPosFound == 0) { + *zip64 = false; uPosFound = uReadPos + i; - break; + } + if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 6 && buf[i+3] == 6) + { + *zip64 = true; + uPosFound = uReadPos + i; + return uPosFound; } } - - if (uPosFound != 0) - break; } return uPosFound; } @@ -172,8 +175,8 @@ FZipFile::FZipFile(const char * filename, FileReader &file) bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) { - uint32_t centraldir = Zip_FindCentralDir(Reader); - FZipEndOfCentralDirectory info; + bool zip64 = false; + uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); int skipped = 0; Lumps = NULL; @@ -184,25 +187,50 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) return false; } - // 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) + uint64_t dirsize, DirectoryOffset; + if (!zip64) { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); - return false; - } + FZipEndOfCentralDirectory info; + // Read the central directory info. + Reader.Seek(centraldir, FileReader::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); - NumLumps = LittleShort(info.NumEntries); + // 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... - int dirsize = LittleLong(info.DirectorySize); void *directory = malloc(dirsize); - Reader.Seek(LittleLong(info.DirectoryOffset), FileReader::SeekSet); + Reader.Seek(DirectoryOffset, FileReader::SeekSet); Reader.Read(directory, dirsize); char *dirptr = (char*)directory; @@ -238,6 +266,8 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) 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. @@ -266,7 +296,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* 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) == name.Len() - strlen(p)) + if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == ptrdiff_t(name.Len() - strlen(p))) { foundspeciallump = true; break; @@ -305,7 +335,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); // skip Directories - if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) + if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0)) { skipped++; continue; @@ -335,9 +365,39 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) 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 = LittleLong(zip_fh->UncompressedSize); + 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; @@ -346,8 +406,8 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) 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 = LittleLong(zip_fh->CompressedSize); - lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); + lump_p->CompressedSize = CompressedSize; + lump_p->Position = LocalHeaderOffset; lump_p->CheckEmbedded(filter); lump_p++; @@ -463,7 +523,7 @@ int FZipLump::GetFileOffset() { if (Method != METHOD_STORED) return -1; if (NeedFileStart) SetLumpAddress(); - return Position; + return (int)Position; } //========================================================================== @@ -585,15 +645,15 @@ int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompress dir.ModTime = LittleShort(dostime.first); dir.ModDate = LittleShort(dostime.second); dir.CRC32 = content.mCRC32; - dir.CompressedSize = LittleLong(content.mCompressedSize); - dir.UncompressedSize = LittleLong(content.mSize); + 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.LocalHeaderOffset = LittleLong(position); + dir.LocalHeaderOffset32 = LittleLong(position); if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) || zip_file->Write(filename, strlen(filename)) != strlen(filename)) diff --git a/src/common/filesystem/file_zip.h b/src/common/filesystem/file_zip.h index 330e7289d..c6a42d9a4 100644 --- a/src/common/filesystem/file_zip.h +++ b/src/common/filesystem/file_zip.h @@ -15,7 +15,7 @@ struct FZipLump : public FResourceLump uint8_t Method; bool NeedFileStart; int CompressedSize; - int Position; + int64_t Position; unsigned CRC32; virtual FileReader *GetReader(); diff --git a/src/common/filesystem/filesystem.cpp b/src/common/filesystem/filesystem.cpp index 47932334d..f18ad5138 100644 --- a/src/common/filesystem/filesystem.cpp +++ b/src/common/filesystem/filesystem.cpp @@ -47,8 +47,6 @@ #include "printf.h" #include "md5.h" -extern FILE* hashfile; - // MACROS ------------------------------------------------------------------ #define NULL_INDEX (0xffffffff) @@ -208,7 +206,7 @@ void FileSystem::InitSingleFile(const char* filename, bool quiet) InitMultipleFiles(filenames, true); } -void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, LumpFilterInfo* filter) +void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, LumpFilterInfo* filter, bool allowduplicates, FILE* hashfile) { int numfiles; @@ -216,16 +214,31 @@ void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, Lump DeleteAll(); numfiles = 0; + // first, check for duplicates + if (allowduplicates) + { + for (unsigned i=0;iGetHash().GetChars()); MoveLumpsInFolder(path); } - + NumEntries = FileInfo.Size(); if (NumEntries == 0) { @@ -284,7 +297,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in FileInfo.Last().resourceId = id; return FileInfo.Size()-1; } - + //========================================================================== // // AddFile @@ -295,7 +308,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) +void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter, FILE* hashfile) { int startlump; bool isdir = false; @@ -333,7 +346,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L startlump = NumEntries; FResourceFile *resfile; - + if (!isdir) resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter); else @@ -363,7 +376,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L FString path; path.Format("%s:%s", filename, lump->getName()); auto embedded = lump->NewReader(); - AddFile(path, &embedded, quiet, filter); + AddFile(path, &embedded, quiet, filter, hashfile); } } @@ -828,7 +841,7 @@ int FileSystem::GetFileFlags (int lump) uint32_t FileSystem::LumpNameHash (const char *s) { - const uint32_t *table = GetCRCTable ();; + const uint32_t *table = GetCRCTable (); uint32_t hash = 0xffffffff; int i; @@ -946,10 +959,10 @@ void FileSystem::MoveLumpsInFolder(const char *path) { return; } - + auto len = strlen(path); auto rfnum = FileInfo.Last().rfnum; - + unsigned i; for (i = 0; i < FileInfo.Size(); i++) { @@ -1022,7 +1035,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in { if (anyns || lump_p->Namespace == ns_global) { - + for(const char **name = names; *name != NULL; name++) { if (!strnicmp(*name, lump_p->shortName.String, 8)) @@ -1512,7 +1525,7 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept { return 0; } - + return Files[rfnum]->LumpCount(); } @@ -1669,3 +1682,20 @@ 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/filesystem.h b/src/common/filesystem/filesystem.h index 5924e86c1..2dc80f7ff 100644 --- a/src/common/filesystem/filesystem.h +++ b/src/common/filesystem/filesystem.h @@ -68,8 +68,8 @@ public: void SetMaxIwadNum(int x) { MaxIwadIndex = x; } void InitSingleFile(const char *filename, bool quiet = false); - void InitMultipleFiles (TArray &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr); - void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter); + 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) {} diff --git a/src/common/filesystem/resourcefile.cpp b/src/common/filesystem/resourcefile.cpp index cc2a27345..3b8e39915 100644 --- a/src/common/filesystem/resourcefile.cpp +++ b/src/common/filesystem/resourcefile.cpp @@ -306,11 +306,11 @@ int lumpcmp(const void * a, const void * b) 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++) { @@ -382,9 +382,9 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, 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) { @@ -490,7 +490,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize { uint32_t min, max, mid, inside; FResourceLump *lump; - int cmp; + int cmp = 0; end = start = 0; @@ -499,7 +499,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize lumps = (uint8_t *)lumps - lumpsize; // Binary search to find any match at all. - min = 1, max = maxlump; + mid = min = 1, max = maxlump; while (min <= max) { mid = min + (max - min) / 2; diff --git a/src/common/filesystem/resourcefile.h b/src/common/filesystem/resourcefile.h index 5e9276c76..d64c278e8 100644 --- a/src/common/filesystem/resourcefile.h +++ b/src/common/filesystem/resourcefile.h @@ -6,6 +6,7 @@ #include #include "files.h" +#include "zstring.h" struct LumpFilterInfo { diff --git a/src/common/filesystem/w_zip.h b/src/common/filesystem/w_zip.h index cdf75867d..ddc065f07 100644 --- a/src/common/filesystem/w_zip.h +++ b/src/common/filesystem/w_zip.h @@ -17,6 +17,22 @@ struct FZipEndOfCentralDirectory uint16_t ZipCommentLength; } FORCE_PACKED; +struct FZipEndOfCentralDirectory64 +{ + uint32_t Magic; + uint64_t StructSize; + uint16_t VersionMadeBy; + uint16_t VersionNeeded; + uint32_t DiskNumber; + uint32_t FirstDisk; + uint64_t NumEntries; + uint64_t NumEntriesOnAllDisks; + uint64_t DirectorySize; + uint64_t DirectoryOffset; + uint16_t ZipCommentLength; +} FORCE_PACKED; + + // FZipFileInfo struct FZipCentralDirectoryInfo { @@ -28,18 +44,28 @@ struct FZipCentralDirectoryInfo uint16_t ModTime; uint16_t ModDate; uint32_t CRC32; - uint32_t CompressedSize; - uint32_t UncompressedSize; + uint32_t CompressedSize32; + uint32_t UncompressedSize32; uint16_t NameLength; uint16_t ExtraLength; uint16_t CommentLength; uint16_t StartingDiskNumber; uint16_t InternalAttributes; uint32_t ExternalAttributes; - uint32_t LocalHeaderOffset; + uint32_t LocalHeaderOffset32; // file name and other variable length info follows } FORCE_PACKED; +struct FZipCentralDirectoryInfo64BitExt +{ + uint16_t Type; + uint16_t Length; + uint64_t UncompressedSize; + uint64_t CompressedSize; + uint64_t LocalHeaderOffset; + uint32_t DiskNo; +} FORCE_PACKED; + // FZipLocalHeader struct FZipLocalFileHeader { @@ -57,7 +83,6 @@ struct FZipLocalFileHeader // file name and other variable length info follows } FORCE_PACKED; - #pragma pack() #define ZIP_LOCALFILE MAKE_ID('P','K',3,4) diff --git a/src/common/fonts/font.cpp b/src/common/fonts/font.cpp index 6ddbe41d4..98763724f 100644 --- a/src/common/fonts/font.cpp +++ b/src/common/fonts/font.cpp @@ -40,7 +40,7 @@ #include #include -#include "templates.h" + #include "m_swap.h" #include "v_font.h" #include "printf.h" @@ -59,6 +59,7 @@ #include "fontinternals.h" +TArray sheetBitmaps; //========================================================================== @@ -86,10 +87,10 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla TMap charMap; int minchar = INT_MAX; int maxchar = INT_MIN; - + // 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; if (filetemplate != nullptr) { @@ -97,16 +98,16 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla // 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); - + //if (nametemplate == nullptr) { FStringf infpath("fonts/%s/font.inf", filetemplate); - + unsigned index = folderdata.FindEx([=](const FolderEntry &entry) { return infpath.CompareNoCase(entry.name) == 0; }); - + if (index < folderdata.Size()) { FScanner sc; @@ -182,7 +183,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla } } } - + if (FixedWidth > 0) { ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale); @@ -292,12 +293,12 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla auto position = strtoll(base.GetChars(), &endp, 16); if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff))) { - auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); - if (lump.isValid()) + auto texlump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); + if (texlump.isValid()) { if ((int)position < minchar) minchar = (int)position; if ((int)position > maxchar) maxchar = (int)position; - auto tex = TexMan.GetGameTexture(lump); + auto tex = TexMan.GetGameTexture(texlump); tex->SetScale((float)Scale.X, (float)Scale.Y); charMap.Insert((int)position, tex); Type = Folder; @@ -313,10 +314,10 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla for (i = 0; i < count; i++) { - auto lump = charMap.CheckKey(FirstChar + i); - if (lump != nullptr) + auto charlump = charMap.CheckKey(FirstChar + i); + if (charlump != nullptr) { - auto pic = *lump; + auto pic = *charlump; if (pic != nullptr) { double fheight = pic->GetDisplayHeight(); @@ -367,10 +368,32 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla } } +class FSheetTexture : public FImageSource +{ + unsigned baseSheet; + int X, Y; + +public: + + FSheetTexture(unsigned source, int x, int y, int width, int height) + { + baseSheet = source; + Width = width; + Height = height; + X = x; + Y = y; + } + + int CopyPixels(FBitmap* dest, int conversion) + { + auto& pic = sheetBitmaps[baseSheet]; + dest->CopyPixelDataRGB(0, 0, pic.GetPixels() + 4 * (X + pic.GetWidth() * Y), Width, Height, 4, pic.GetWidth() * 4, 0, CF_BGRA); + return 0; + } + +}; void FFont::ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale) { - // all valid lumps must be named with a hex number that represents the Unicode character index for its first character, - TArray part(1, true); TMap charMap; int minchar = INT_MAX; int maxchar = INT_MIN; @@ -391,16 +414,17 @@ void FFont::ReadSheetFont(TArray &folderdata, int width, int height if (minchar > position) minchar = int(position); if (maxchar < maxinsheet) maxchar = maxinsheet; + FBitmap* sheetimg = &sheetBitmaps[sheetBitmaps.Reserve(1)]; + sheetimg->Create(tex->GetTexelWidth(), tex->GetTexelHeight()); + tex->GetTexture()->GetImage()->CopyPixels(sheetimg, FImageSource::normal); + for (int y = 0; y < numtex_y; y++) { for (int x = 0; x < numtex_x; x++) { - part[0].OriginX = -width * x; - part[0].OriginY = -height * y; - part[0].TexImage = static_cast(tex->GetTexture()); - FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false); - FImageTexture *tex = new FImageTexture(image); - auto gtex = MakeGameTexture(tex, nullptr, ETextureType::FontChar); + auto image = new FSheetTexture(sheetBitmaps.Size() - 1, x * width, y * height, width, height); + FImageTexture *imgtex = new FImageTexture(image); + auto gtex = MakeGameTexture(imgtex, nullptr, ETextureType::FontChar); gtex->SetWorldPanning(true); gtex->SetOffsets(0, 0, 0); gtex->SetOffsets(1, 0, 0); @@ -424,7 +448,6 @@ void FFont::ReadSheetFont(TArray &folderdata, int width, int height LastChar = maxchar; auto count = maxchar - minchar + 1; Chars.Resize(count); - int fontheight = 0; for (int i = 0; i < count; i++) { @@ -560,10 +583,10 @@ FFont *FFont::FindFont (FName name) void RecordTextureColors (FImageSource *pic, uint32_t *usedcolors) { int x; - + auto pixels = pic->GetPalettedPixels(false); auto size = pic->GetWidth() * pic->GetHeight(); - + for(x = 0;x < size; x++) { usedcolors[pixels[x]]++; @@ -686,7 +709,7 @@ int 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; - assert(Translations.Size() == NumTextColors); + assert(Translations.Size() == (unsigned)NumTextColors); if (noTranslate) { @@ -728,7 +751,7 @@ int FFont::GetCharCode(int code, bool needpic) const { return code; } - + // Use different substitution logic based on the fonts content: // In a font which has both upper and lower case, prefer unaccented small characters over capital ones. // In a pure upper-case font, do not check for lower case replacements. @@ -806,7 +829,7 @@ FGameTexture *FFont::GetChar (int code, int translation, int *const width) const code -= FirstChar; xmove = Chars[code].XMove; } - + if (width != nullptr) { *width = xmove; @@ -936,7 +959,7 @@ int FFont::StringWidth(const uint8_t *string, int spacing) const } } - return std::max(maxw, w); + return max(maxw, w); } //========================================================================== diff --git a/src/common/fonts/hexfont.cpp b/src/common/fonts/hexfont.cpp index 612d3d326..643b44d4d 100644 --- a/src/common/fonts/hexfont.cpp +++ b/src/common/fonts/hexfont.cpp @@ -58,11 +58,12 @@ struct HexDataSource // //========================================================================== - void ParseDefinition(int lumpnum) + void ParseDefinition(FResourceLump* font) { FScanner sc; - sc.OpenLumpNum(lumpnum); + auto data = font->Lock(); + sc.OpenMem("newconsolefont.hex", (const char*)data, font->Size()); sc.SetCMode(true); glyphdata.Push(0); // ensure that index 0 can be used as 'not present'. while (sc.GetString()) @@ -96,6 +97,7 @@ struct HexDataSource lumb = i * 255 / 17; SmallPal[i] = PalEntry(255, lumb, lumb, lumb); } + font->Unlock(); } }; @@ -107,7 +109,7 @@ class FHexFontChar : public FImageSource public: FHexFontChar(uint8_t *sourcedata, int swidth, int width, int height); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap* bmp, int conversion); protected: @@ -142,10 +144,10 @@ FHexFontChar::FHexFontChar (uint8_t *sourcedata, int swidth, int width, int heig // //========================================================================== -TArray FHexFontChar::CreatePalettedPixels(int) +PalettedPixels FHexFontChar::CreatePalettedPixels(int) { int destSize = Width * Height; - TArray Pixels(destSize, true); + PalettedPixels Pixels(destSize); uint8_t *dest_p = Pixels.Data(); const uint8_t *src_p = SourceData; @@ -188,7 +190,7 @@ class FHexFontChar2 : public FHexFontChar public: FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap* bmp, int conversion); }; @@ -214,10 +216,10 @@ FHexFontChar2::FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int hei // //========================================================================== -TArray FHexFontChar2::CreatePalettedPixels(int) +PalettedPixels FHexFontChar2::CreatePalettedPixels(int) { int destSize = Width * Height; - TArray Pixels(destSize, true); + PalettedPixels Pixels(destSize); uint8_t *dest_p = Pixels.Data(); assert(SourceData); @@ -266,7 +268,7 @@ int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion) class FHexFont : public FFont { - + public: //========================================================================== // @@ -283,14 +285,14 @@ public: assert(lump >= 0); FontName = fontname; - + FirstChar = hexdata.FirstChar; LastChar = hexdata.LastChar; FontHeight = 16; SpaceWidth = 9; GlobalKerning = 0; - + Chars.Resize(LastChar - FirstChar + 1); for (int i = FirstChar; i <= LastChar; i++) { @@ -325,7 +327,7 @@ public: else Translations[i] = LuminosityTranslation(i * 2 + 1, minlum, maxlum); } } - + }; @@ -400,7 +402,7 @@ public: FFont *CreateHexLumpFont (const char *fontname, int lump) { - if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump); + assert(hexdata.FirstChar != INT_MAX); return new FHexFont(fontname, lump); } @@ -412,6 +414,34 @@ FFont *CreateHexLumpFont (const char *fontname, int lump) FFont *CreateHexLumpFont2(const char *fontname, int lump) { - if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump); + assert(hexdata.FirstChar != INT_MAX); return new FHexFont2(fontname, lump); } + +//========================================================================== +// +// +// +//========================================================================== + +uint8_t* GetHexChar(int codepoint) +{ + assert(hexdata.FirstChar != INT_MAX); + + if (hexdata.glyphmap[codepoint] > 0) + { + auto offset = hexdata.glyphmap[codepoint]; + return &hexdata.glyphdata[offset]; + } + return nullptr; +} + +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); + delete resf; +} diff --git a/src/common/fonts/singlelumpfont.cpp b/src/common/fonts/singlelumpfont.cpp index 7725cdb2d..d3bee25a3 100644 --- a/src/common/fonts/singlelumpfont.cpp +++ b/src/common/fonts/singlelumpfont.cpp @@ -96,7 +96,7 @@ protected: void LoadFON1 (int lump, const uint8_t *data); void LoadFON2 (int lump, const uint8_t *data); void LoadBMF (int lump, const uint8_t *data); - + enum { FONT1, @@ -259,7 +259,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data) LastChar = data[7]; ActiveColors = data[10]+1; RescalePalette = data[9] == 0; - + count = LastChar - FirstChar + 1; Chars.Resize(count); TArray widths2(count, true); @@ -309,9 +309,9 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data) } Palette[0] = 0; - for (int i = 1; i < ActiveColors; i++) + for (int pp = 1; pp < ActiveColors; pp++) { - Palette[i] = PalEntry(255, palette[i * 3], palette[i * 3 + 1], palette[i * 3 + 2]); + Palette[pp] = PalEntry(255, palette[pp * 3], palette[pp * 3 + 1], palette[pp * 3 + 2]); } data_p = palette + ActiveColors*3; diff --git a/src/common/fonts/specialfont.cpp b/src/common/fonts/specialfont.cpp index b00a19ad3..9c35f2a8a 100644 --- a/src/common/fonts/specialfont.cpp +++ b/src/common/fonts/specialfont.cpp @@ -102,12 +102,12 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FGameTexture if (charlumps[i] != nullptr) { - auto pic = charlumps[i]; - Chars[i].OriginalPic = MakeGameTexture(pic->GetTexture(), nullptr, ETextureType::FontChar); - Chars[i].OriginalPic->CopySize(pic, true); + auto charpic = charlumps[i]; + Chars[i].OriginalPic = MakeGameTexture(charpic->GetTexture(), nullptr, ETextureType::FontChar); + Chars[i].OriginalPic->CopySize(charpic, true); TexMan.AddGameTexture(Chars[i].OriginalPic); Chars[i].XMove = (int)Chars[i].OriginalPic->GetDisplayWidth(); - if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(pic, Chars[i].OriginalPic); + if (sysCallbacks.FontCharCreated) sysCallbacks.FontCharCreated(charpic, Chars[i].OriginalPic); } else { diff --git a/src/common/fonts/v_font.cpp b/src/common/fonts/v_font.cpp index 0042f48c3..f51813aeb 100644 --- a/src/common/fonts/v_font.cpp +++ b/src/common/fonts/v_font.cpp @@ -39,7 +39,7 @@ #include #include -#include "templates.h" + #include "m_swap.h" #include "v_font.h" #include "filesystem.h" @@ -73,6 +73,7 @@ static int TranslationMapCompare (const void *a, const void *b); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int PrintColors[]; +extern TArray sheetBitmaps; // PUBLIC DATA DEFINITIONS ------------------------------------------------- FFont* SmallFont, * SmallFont2, * BigFont, * BigUpper, * ConFont, * IntermissionFont, * NewConsoleFont, * NewSmallFont, @@ -92,6 +93,7 @@ TArray TranslationColors; FFont *V_GetFont(const char *name, const char *fontlumpname) { + if (name == nullptr) return nullptr; if (!stricmp(name, "DBIGFONT")) name = "BigFont"; else if (!stricmp(name, "CONFONT")) name = "ConsoleFont"; // several mods have used the name CONFONT directly and effectively duplicated the font. else if (!stricmp(name, "INDEXFON")) name = "IndexFont"; // Same here - for whatever reason some people had to use its 8 character name... @@ -106,10 +108,10 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) int lump = -1; int folderfile = -1; - + TArray 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)) { @@ -119,7 +121,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) lump = fileSystem.CheckNumForFullName(fontlumpname? fontlumpname : name, true); - + if (lump != -1 && fileSystem.GetFileContainer(lump) >= folderfile) { uint32_t head; @@ -725,9 +727,9 @@ static void CalcDefaultTranslation(FFont* base, int index) auto lum = otherluminosity[i]; if (lum >= 0 && lum <= 1) { - int index = int(lum * 255); - remap[index] = GPalette.BaseColors[i]; - remap[index].a = 255; + int lumidx = int(lum * 255); + remap[lumidx] = GPalette.BaseColors[i]; + remap[lumidx].a = 255; } } @@ -769,7 +771,7 @@ static void CalcDefaultTranslation(FFont* base, int index) lowindex = highindex++; } } - + } //========================================================================== @@ -862,6 +864,7 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int void V_InitFonts() { + sheetBitmaps.Clear(); CreateLuminosityTranslationRanges(); V_InitCustomFonts(); @@ -928,6 +931,7 @@ void V_ClearFonts() } FFont::FirstFont = nullptr; AlternativeSmallFont = OriginalSmallFont = CurrentConsoleFont = NewSmallFont = NewConsoleFont = SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = nullptr; + sheetBitmaps.Clear(); } //========================================================================== diff --git a/src/common/fonts/v_font.h b/src/common/fonts/v_font.h index 72fd49e29..343cbaf5d 100644 --- a/src/common/fonts/v_font.h +++ b/src/common/fonts/v_font.h @@ -208,7 +208,6 @@ protected: friend void V_InitFonts(); }; - extern FFont *SmallFont, *SmallFont2, *BigFont, *BigUpper, *ConFont, *IntermissionFont, *NewConsoleFont, *NewSmallFont, *CurrentConsoleFont, *OriginalSmallFont, *AlternativeSmallFont, *OriginalBigFont, *AlternativeBigFont; void V_InitFonts(); diff --git a/src/common/fonts/v_text.cpp b/src/common/fonts/v_text.cpp index dc182f89d..b7467a8ab 100644 --- a/src/common/fonts/v_text.cpp +++ b/src/common/fonts/v_text.cpp @@ -88,7 +88,6 @@ TArray V_BreakLines (FFont *font, int maxwidth, const uint8_t *str { if (*string == '[') { - const uint8_t* start = string; while (*string != ']' && *string != '\0') { string++; @@ -266,7 +265,6 @@ DEFINE_ACTION_FUNCTION(FFont, BreakLines) bool generic_ui; -EXTERN_CVAR(String, language) bool CheckFontComplete(FFont* font) { diff --git a/src/common/menu/joystickmenu.cpp b/src/common/menu/joystickmenu.cpp index 4baea836f..21c667d31 100644 --- a/src/common/menu/joystickmenu.cpp +++ b/src/common/menu/joystickmenu.cpp @@ -160,12 +160,12 @@ void UpdateJoystickMenu(IJoystickConfig *selected) it = opt->GetItem("ConnectMessage2"); if (it != nullptr) it->SetValue(0, !use_joystick); - for (int i = 0; i < (int)Joysticks.Size(); ++i) + for (int ii = 0; ii < (int)Joysticks.Size(); ++ii) { - it = CreateOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]); + it = CreateOptionMenuItemJoyConfigMenu(Joysticks[ii]->GetName(), Joysticks[ii]); GC::WriteBarrier(opt, it); opt->mItems.Push(it); - if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); + if (ii == itemnum) opt->mSelectedItem = opt->mItems.Size(); } if (opt->mSelectedItem >= (int)opt->mItems.Size()) { @@ -179,15 +179,15 @@ void UpdateJoystickMenu(IJoystickConfig *selected) auto p = CurrentMenu->PointerVar("mJoy"); if (p != nullptr) { - unsigned i; - for (i = 0; i < Joysticks.Size(); ++i) + unsigned ii; + for (ii = 0; ii < Joysticks.Size(); ++ii) { - if (Joysticks[i] == p) + if (Joysticks[ii] == p) { break; } } - if (i == Joysticks.Size()) + if (ii == Joysticks.Size()) { CurrentMenu->Close(); } diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp index bbfe2f4a5..c5890080c 100644 --- a/src/common/menu/menu.cpp +++ b/src/common/menu/menu.cpp @@ -55,11 +55,8 @@ #include "i_time.h" #include "printf.h" -void M_StartControlPanel(bool makeSound, bool scaleoverride = false); - int DMenu::InMenu; static ScaleOverrider *CurrentScaleOverrider; -extern int chatmodeon; // // Todo: Move these elsewhere // @@ -114,8 +111,6 @@ extern PClass *DefaultOptionMenuClass; #define KEY_REPEAT_DELAY (GameTicRate*5/12) #define KEY_REPEAT_RATE (3) -bool OkForLocalization(FTextureID texnum, const char* substitute); - //============================================================================ // // @@ -271,7 +266,7 @@ DMenu::DMenu(DMenu *parent) DontDim = false; GC::WriteBarrier(this, parent); } - + //============================================================================= // // @@ -435,8 +430,10 @@ bool DMenu::TranslateKeyboardEvents() // //============================================================================= -void M_DoStartControlPanel (bool scaleoverride) + +void M_StartControlPanel (bool makesound, bool scaleoverride) { + if (sysCallbacks.OnMenuOpen) sysCallbacks.OnMenuOpen(makesound); // intro might call this repeatedly if (CurrentMenu != nullptr) return; @@ -505,11 +502,9 @@ DEFINE_ACTION_FUNCTION(DMenu, ActivateMenu) // //============================================================================= -bool M_SetSpecialMenu(FName& menu, int param); // game specific checks - void M_SetMenu(FName menu, int param) { - if (!M_SetSpecialMenu(menu, param)) return; + if (sysCallbacks.SetSpecialMenu && !sysCallbacks.SetSpecialMenu(menu, param)) return; DMenuDescriptor **desc = MenuDescriptors.CheckKey(menu); if (desc != nullptr) @@ -930,7 +925,7 @@ void M_Init (void) catch (CVMAbortException &err) { err.MaybePrintMessage(); - Printf("%s", err.stacktrace.GetChars()); + Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", err.stacktrace.GetChars()); I_FatalError("Failed to initialize menus"); } M_CreateMenus(); @@ -1038,6 +1033,8 @@ DEFINE_FIELD(DListMenuDescriptor, mFontColor2) DEFINE_FIELD(DListMenuDescriptor, mAnimatedTransition) DEFINE_FIELD(DListMenuDescriptor, mAnimated) DEFINE_FIELD(DListMenuDescriptor, mCenter) +DEFINE_FIELD(DListMenuDescriptor, mDontDim) +DEFINE_FIELD(DListMenuDescriptor, mDontBlur) DEFINE_FIELD(DListMenuDescriptor, mVirtWidth) DEFINE_FIELD(DListMenuDescriptor, mVirtHeight) @@ -1050,6 +1047,9 @@ DEFINE_FIELD(DOptionMenuDescriptor, mScrollPos) DEFINE_FIELD(DOptionMenuDescriptor, mIndent) DEFINE_FIELD(DOptionMenuDescriptor, mPosition) DEFINE_FIELD(DOptionMenuDescriptor, mDontDim) +DEFINE_FIELD(DOptionMenuDescriptor, mDontBlur) +DEFINE_FIELD(DOptionMenuDescriptor, mAnimatedTransition) +DEFINE_FIELD(DOptionMenuDescriptor, mAnimated) DEFINE_FIELD(DOptionMenuDescriptor, mFont) DEFINE_FIELD(FOptionMenuSettings, mTitleColor) @@ -1068,6 +1068,8 @@ DEFINE_FIELD(DImageScrollerDescriptor,textFont) DEFINE_FIELD(DImageScrollerDescriptor, textScale) DEFINE_FIELD(DImageScrollerDescriptor, mAnimatedTransition) DEFINE_FIELD(DImageScrollerDescriptor, mAnimated) +DEFINE_FIELD(DImageScrollerDescriptor, mDontDim) +DEFINE_FIELD(DImageScrollerDescriptor, mDontBlur) DEFINE_FIELD(DImageScrollerDescriptor, virtWidth) DEFINE_FIELD(DImageScrollerDescriptor, virtHeight) diff --git a/src/common/menu/menu.h b/src/common/menu/menu.h index a8ed61061..3bd23b3b8 100644 --- a/src/common/menu/menu.h +++ b/src/common/menu/menu.h @@ -91,9 +91,12 @@ public: bool mFromEngine; bool mAnimated; bool mAnimatedTransition; + bool mDontDim; + bool mDontBlur; int mVirtWidth; int mVirtHeight; bool mCustomSizeSet; + bool mForceList; void Reset(); }; @@ -123,6 +126,9 @@ public: int mIndent; int mPosition; bool mDontDim; + bool mDontBlur; + bool mAnimatedTransition; + bool mAnimated; FFont *mFont; void CalcIndent(); @@ -142,6 +148,8 @@ public: double textScale; bool mAnimatedTransition; bool mAnimated; + bool mDontDim; + bool mDontBlur; int virtWidth, virtHeight; }; @@ -303,7 +311,7 @@ void M_ActivateMenu(DMenu *menu); void M_ClearMenus (); void M_PreviousMenu (); void M_ParseMenuDefs(); -void M_DoStartControlPanel(bool scaleoverride); +void M_StartControlPanel(bool makeSound, bool scaleoverride = false); void M_SetMenu(FName menu, int param = -1); void M_StartMessage(const char *message, int messagemode, FName action = NAME_None); DMenu *StartPickerMenu(DMenu *parent, const char *name, FColorCVar *cvar); diff --git a/src/common/menu/menudef.cpp b/src/common/menu/menudef.cpp index ef3397df0..7076f8b7b 100644 --- a/src/common/menu/menudef.cpp +++ b/src/common/menu/menudef.cpp @@ -50,7 +50,7 @@ #include "texturemanager.h" #include "printf.h" #include "i_interface.h" -#include "templates.h" + bool CheckSkipGameOptionBlock(FScanner& sc); @@ -250,6 +250,12 @@ static bool CheckSkipOptionBlock(FScanner &sc) filter = true; #endif } + else if (sc.Compare("SWRender")) + { +#ifndef NO_SWRENDERER + filter = true; +#endif + } } while (sc.CheckString(",")); sc.MustGetStringName(")"); @@ -340,6 +346,10 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s { desc->mCenter = true; } + else if (sc.Compare("Selecteditem")) + { + desc->mSelectedItem = desc->mItems.Size() - 1; + } else if (sc.Compare("animatedtransition")) { desc->mAnimatedTransition = true; @@ -348,6 +358,14 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s { desc->mAnimated = true; } + else if (sc.Compare("DontDim")) + { + desc->mDontDim = true; + } + else if (sc.Compare("DontBlur")) + { + desc->mDontBlur = true; + } else if (sc.Compare("MouseWindow")) { sc.MustGetNumber(); @@ -409,6 +427,10 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s } } } + else if (sc.Compare("ForceList")) + { + desc->mForceList = true; + } else { // all item classes from which we know that they support sized scaling. @@ -563,8 +585,8 @@ static void DoParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc, bool &s // NB: index has been incremented, so we're not affecting the newly inserted item here. for (unsigned int i = insertIndex; i < desc->mItems.Size(); i++) { - auto item = desc->mItems[i]; - if (item->GetClass()->IsDescendantOf("ListMenuItemSelectable")) + auto litem = desc->mItems[i]; + if (litem->GetClass()->IsDescendantOf("ListMenuItemSelectable")) { desc->mItems[i]->mYpos += desc->mLinespacing; } @@ -660,9 +682,9 @@ static bool FindMatchingItem(DMenuItemBase *desc) MenuDescriptorList::Pair *pair; while (it.NextPair(pair)) { - for (auto it : pair->Value->mItems) + for (auto item : pair->Value->mItems) { - if (it->mAction == name && GetGroup(it) == grp) return true; + if (item->mAction == name && GetGroup(item) == grp) return true; } } return false; @@ -749,6 +771,17 @@ static void ParseListMenu(FScanner &sc) desc->mFromEngine = fileSystem.GetFileContainer(sc.LumpNum) == 0; // flags menu if the definition is from the IWAD. desc->mVirtWidth = -2; desc->mCustomSizeSet = false; + desc->mAnimatedTransition = false; + desc->mAnimated = false; + desc->mDontDim = false; + desc->mDontBlur = false; + desc->mForceList = false; + if (DefaultListMenuSettings->mCustomSizeSet) + { + desc->mVirtHeight = DefaultListMenuSettings->mVirtHeight; + desc->mVirtWidth = DefaultListMenuSettings->mVirtWidth; + desc->mCustomSizeSet = true; + } ParseListMenuBody(sc, desc, -1); ReplaceMenu(sc, desc); @@ -999,6 +1032,22 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc, int i sc.MustGetNumber(); desc->mIndent = sc.Number; } + else if (sc.Compare("AnimatedTransition")) + { + desc->mAnimatedTransition = true; + } + else if (sc.Compare("Animated")) + { + desc->mAnimated = true; + } + else if (sc.Compare("DontDim")) + { + desc->mDontDim = true; + } + else if (sc.Compare("DontBlur")) + { + desc->mDontBlur = true; + } else { bool success = false; @@ -1012,13 +1061,19 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc, int i { auto &args = func->Variants[0].Proto->ArgumentTypes; TArray params; + int start = 1; params.Push(0); + if (args.Size() > 1 && args[1] == NewPointer(PClass::FindClass("OptionMenuDescriptor"))) + { + params.Push(desc); + start = 2; + } auto TypeCVar = NewPointer(NewStruct("CVar", nullptr, true)); // Note that this array may not be reallocated so its initial size must be the maximum possible elements. TArray strings(args.Size()); - for (unsigned i = 1; i < args.Size(); i++) + for (unsigned i = start; i < args.Size(); i++) { sc.MustGetString(); if (args[i] == TypeString) @@ -1034,6 +1089,24 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc, int i { params.Push(V_GetColor(sc)); } + else if (args[i] == TypeFont) + { + auto f = V_GetFont(sc.String); + if (f == nullptr) + { + sc.ScriptError("Unknown font %s", sc.String); + } + params.Push(f); + } + else if (args[i] == TypeTextureID) + { + auto f = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch); + if (!f.Exists()) + { + sc.ScriptMessage("Unknown texture %s", sc.String); + } + params.Push(f.GetIndex()); + } else if (args[i]->isIntCompatible()) { char *endp; @@ -1144,7 +1217,10 @@ static void ParseOptionMenu(FScanner &sc) desc->mPosition = DefaultOptionMenuSettings->mPosition; desc->mScrollTop = DefaultOptionMenuSettings->mScrollTop; desc->mIndent = DefaultOptionMenuSettings->mIndent; - desc->mDontDim = DefaultOptionMenuSettings->mDontDim; + desc->mDontDim = false; + desc->mDontBlur = false; + desc->mAnimatedTransition = false; + desc->mAnimated = false; desc->mProtected = sc.CheckString("protected"); ParseOptionMenuBody(sc, desc, -1); @@ -1212,6 +1288,16 @@ static void ParseImageScrollerBody(FScanner& sc, DImageScrollerDescriptor* desc) ParseImageScrollerBody(sc, desc); } } + else if (sc.Compare("Class")) + { + sc.MustGetString(); + PClass* cls = PClass::FindClass(sc.String); + if (cls == nullptr || !cls->IsDescendantOf("ImageScrollerMenu")) + { + sc.ScriptError("Unknown menu class '%s'", sc.String); + } + desc->mClass = cls; + } else if (sc.Compare("animatedtransition")) { desc->mAnimatedTransition = true; @@ -1220,6 +1306,14 @@ static void ParseImageScrollerBody(FScanner& sc, DImageScrollerDescriptor* desc) { desc->mAnimated = true; } + else if (sc.Compare("DontDim")) + { + desc->mDontDim = true; + } + else if (sc.Compare("DontBlur")) + { + desc->mDontBlur = true; + } else if (sc.Compare("textBackground")) { sc.MustGetString(); @@ -1284,6 +1378,24 @@ static void ParseImageScrollerBody(FScanner& sc, DImageScrollerDescriptor* desc) { params.Push(V_GetColor(sc)); } + else if (args[i] == TypeFont) + { + auto f = V_GetFont(sc.String); + if (f == nullptr) + { + sc.ScriptError("Unknown font %s", sc.String); + } + params.Push(f); + } + else if (args[i] == TypeTextureID) + { + auto f = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch); + if (!f.Exists()) + { + sc.ScriptMessage("Unknown texture %s", sc.String); + } + params.Push(f.GetIndex()); + } else if (args[i]->isIntCompatible()) { char* endp; @@ -1377,7 +1489,10 @@ static void ParseImageScroller(FScanner& sc) desc->textBackgroundBrightness = 0xffffffff; desc->textFont = SmallFont; desc->textScale = 1; + desc->mDontDim = false; + desc->mDontBlur = false; desc->mAnimatedTransition = false; + desc->mAnimated = false; desc->virtWidth = 320; desc->virtHeight = 200; @@ -1492,7 +1607,7 @@ static void InitMusicMenus() { DMenuDescriptor **advmenu = MenuDescriptors.CheckKey("AdvSoundOptions"); auto soundfonts = sfmanager.GetList(); - std::tuple sfmenus[] = { std::make_tuple("GusConfigMenu", SF_SF2 | SF_GUS, "midi_config"), + std::tuple sfmenus[] = { std::make_tuple("GusConfigMenu", SF_GUS, "midi_config"), std::make_tuple("WildMidiConfigMenu", SF_GUS, "wildmidi_config"), std::make_tuple("TimidityConfigMenu", SF_SF2 | SF_GUS, "timidity_config"), std::make_tuple("FluidPatchsetMenu", SF_SF2, "fluid_patchset"), diff --git a/src/common/menu/messagebox.cpp b/src/common/menu/messagebox.cpp index 8b43d8d76..8b8334b02 100644 --- a/src/common/menu/messagebox.cpp +++ b/src/common/menu/messagebox.cpp @@ -40,7 +40,6 @@ #include "vm.h" #include "menustate.h" -void M_StartControlPanel(bool makeSound, bool scaleoverride = false); FName MessageBoxClass = NAME_MessageBoxMenu; CVAR(Bool, m_quickexit, false, CVAR_ARCHIVE) diff --git a/src/common/menu/resolutionmenu.cpp b/src/common/menu/resolutionmenu.cpp index 6074d018a..1920927bb 100644 --- a/src/common/menu/resolutionmenu.cpp +++ b/src/common/menu/resolutionmenu.cpp @@ -83,8 +83,8 @@ CCMD (menu_resolution_commit_changes) vid_fullscreen = true; vid_scalemode = 5; vid_scalefactor = 1.; - vid_scale_customwidth = menu_resolution_custom_width; - vid_scale_customheight = menu_resolution_custom_height; + vid_scale_customwidth = *menu_resolution_custom_width; + vid_scale_customheight = *menu_resolution_custom_height; vid_scale_custompixelaspect = 1.0; } } diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 935b6dedd..5dc22ec76 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -46,8 +46,11 @@ #include "findfile.h" #include "v_draw.h" #include "savegamemanager.h" +#include "m_argv.h" +#include "i_specialpaths.h" - +CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +FString SavegameFolder; //============================================================================= // @@ -151,8 +154,6 @@ int FSavegameManagerBase::InsertSaveNode(FSaveGameNode *node) void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave) { - FSaveGameNode *node; - if (file.IsEmpty()) return; @@ -180,7 +181,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit } } - node = new FSaveGameNode; + auto node = new FSaveGameNode; node->SaveTitle = title; node->Filename = file; node->bOldVersion = false; @@ -461,6 +462,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, SavegameCount) FSaveGameNode *FSavegameManagerBase::GetSavegame(int i) { + if ((unsigned)i >= SaveGames.Size()) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Bad savegame index"); return SaveGames[i]; } @@ -539,3 +541,56 @@ DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, WindowSize); DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, quickSaveSlot); DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, SaveCommentString); +//============================================================================= +// +// todo: cache this - it never changes once set up. +// +//============================================================================= + +FString G_GetSavegamesFolder() +{ + FString name; + bool usefilter; + + if (const char* const dir = Args->CheckValue("-savedir")) + { + name = dir; + usefilter = false; //-savedir specifies an absolute save directory path. + } + else + { + name = **save_dir ? save_dir : M_GetSavegamesPath(); + usefilter = true; + } + + const size_t len = name.Len(); + if (len > 0) + { + FixPathSeperator(name); + if (name[len - 1] != '/') + name << '/'; + } + + if (usefilter && SavegameFolder.IsNotEmpty()) + name << SavegameFolder << '/'; + + name = NicePath(name); + CreatePath(name); + return name; +} + +//============================================================================= +// +// +// +//============================================================================= + +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.Substitute("\\", "/"); + return name; +} + diff --git a/src/common/menu/savegamemanager.h b/src/common/menu/savegamemanager.h index 754ddce23..20b466b53 100644 --- a/src/common/menu/savegamemanager.h +++ b/src/common/menu/savegamemanager.h @@ -59,3 +59,6 @@ public: }; +extern FString SavegameFolder; // specifies a subdirectory for the current IWAD. +FString G_GetSavegamesFolder(); +FString G_BuildSaveName(const char* prefix); diff --git a/src/common/models/bonecomponents.h b/src/common/models/bonecomponents.h new file mode 100644 index 000000000..1e65389ea --- /dev/null +++ b/src/common/models/bonecomponents.h @@ -0,0 +1,16 @@ +#pragma once +#include "dobject.h" +#include "tarray.h" +#include "TRS.h" +#include "matrix.h" + + +class DBoneComponents : public DObject +{ + DECLARE_CLASS(DBoneComponents, DObject); +public: + TArray> trscomponents; + TArray> trsmatrix; + + DBoneComponents() = default; +}; diff --git a/src/common/models/model.cpp b/src/common/models/model.cpp index eea099045..c93fa7876 100644 --- a/src/common/models/model.cpp +++ b/src/common/models/model.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -36,12 +36,14 @@ #include "model_md2.h" #include "model_md3.h" #include "model_kvx.h" +#include "model_iqm.h" #include "i_time.h" #include "voxels.h" #include "texturemanager.h" #include "modelrenderer.h" +TArray savedModelFiles; TDeletingArray Models; TArray SpriteModelFrames; @@ -98,7 +100,7 @@ static int FindGFXFile(FString & fn) for (const char ** extp=extensions; *extp; extp++) { - int lump = fileSystem.CheckNumForFullName(fn + *extp); + lump = fileSystem.CheckNumForFullName(fn + *extp); if (lump >= best) best = lump; } return best; @@ -119,7 +121,7 @@ FTextureID LoadSkin(const char * path, const char * fn) int texlump = FindGFXFile(buffer); const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump); - return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny); + return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup); } //=========================================================================== @@ -149,17 +151,18 @@ int ModelFrameHash(FSpriteModelFrame * smf) // //=========================================================================== -unsigned FindModel(const char * path, const char * modelfile) +unsigned FindModel(const char * path, const char * modelfile, bool silent) { FModel * model = nullptr; FString fullname; - fullname.Format("%s%s", path, modelfile); + if (path) fullname.Format("%s%s", path, modelfile); + else fullname = modelfile; int lump = fileSystem.CheckNumForFullName(fullname); if (lump<0) { - Printf("FindModel: '%s' not found\n", fullname.GetChars()); + Printf(PRINT_HIGH, "FindModel: '%s' not found\n", fullname.GetChars()); return -1; } @@ -206,6 +209,10 @@ unsigned FindModel(const char * path, const char * modelfile) { model = new FMD3Model; } + else if (!memcmp(buffer, "INTERQUAKEMODEL\0", 16)) + { + model = new IQMModel; + } if (model != nullptr) { @@ -225,7 +232,7 @@ unsigned FindModel(const char * path, const char * modelfile) } else { - Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars()); + Printf(PRINT_HIGH, "LoadModel: Unknown model format in '%s'\n", fullname.GetChars()); return -1; } } diff --git a/src/common/models/model.h b/src/common/models/model.h index 7e005a2d8..dc4d64476 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -3,7 +3,10 @@ #include #include "textureid.h" #include "i_modelvertexbuffer.h" +#include "matrix.h" +#include "TRS.h" +class DBoneComponents; class FModelRenderer; class FGameTexture; class IModelVertexBuffer; @@ -12,6 +15,7 @@ struct FSpriteModelFrame; FTextureID LoadSkin(const char* path, const char* fn); void FlushModels(); +extern TArray savedModelFiles; extern TDeletingArray Models; extern TArray SpriteModelFrames; @@ -25,6 +29,7 @@ struct FSpriteModelFrame TArray skinIDs; TArray surfaceskinIDs; TArray modelframes; + TArray animationIDs; float xscale, yscale, zscale; // [BB] Added zoffset, rotation parameters and flags. // Added xoffset, yoffset @@ -52,6 +57,13 @@ enum ModelRendererType NumModelRendererTypes }; +enum EFrameError +{ + FErr_NotFound = -1, + FErr_Voxel = -2, + FErr_Singleframe = -3 +}; + class FModel { public: @@ -59,20 +71,19 @@ public: virtual ~FModel(); virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; - virtual int FindFrame(const char * name) = 0; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) = 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; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; - virtual void AddSkins(uint8_t *hitlist) = 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 {}; }; void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } void DestroyVertexBuffer(); - const FSpriteModelFrame *curSpriteMDLFrame; - int curMDLIndex; - void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; }; - + bool hasSurfaces = false; FString mFileName; private: @@ -80,5 +91,5 @@ private: }; int ModelFrameHash(FSpriteModelFrame* smf); -unsigned FindModel(const char* path, const char* modelfile); +unsigned FindModel(const char* path, const char* modelfile, bool silent = false); diff --git a/src/common/models/model_iqm.h b/src/common/models/model_iqm.h new file mode 100644 index 000000000..3ab956689 --- /dev/null +++ b/src/common/models/model_iqm.h @@ -0,0 +1,223 @@ +#pragma once + +#include +#include "model.h" +#include "vectors.h" +#include "matrix.h" +#include "common/rendering/i_modelvertexbuffer.h" +#include "m_swap.h" + +class DBoneComponents; + +struct IQMMesh +{ + FString Name; + FString Material; + uint32_t FirstVertex; + uint32_t NumVertices; + uint32_t FirstTriangle; + uint32_t NumTriangles; + FTextureID Skin; +}; + +enum IQMVertexArrayType +{ + IQM_POSITION = 0, // float, 3 + IQM_TEXCOORD = 1, // float, 2 + IQM_NORMAL = 2, // float, 3 + IQM_TANGENT = 3, // float, 4 + IQM_BLENDINDEXES = 4, // ubyte, 4 + IQM_BLENDWEIGHTS = 5, // ubyte, 4 + IQM_COLOR = 6, // ubyte, 4 + IQM_CUSTOM = 0x10 +}; + +enum IQMVertexArrayFormat +{ + IQM_BYTE = 0, + IQM_UBYTE = 1, + IQM_SHORT = 2, + IQM_USHORT = 3, + IQM_INT = 4, + IQM_UINT = 5, + IQM_HALF = 6, + IQM_FLOAT = 7, + IQM_DOUBLE = 8, +}; + +struct IQMVertexArray +{ + IQMVertexArrayType Type; + uint32_t Flags; + IQMVertexArrayFormat Format; + uint32_t Size; + uint32_t Offset; +}; + +struct IQMTriangle +{ + uint32_t Vertex[3]; +}; + +struct IQMAdjacency +{ + uint32_t Triangle[3]; +}; + +struct IQMJoint +{ + FString Name; + int32_t Parent; // parent < 0 means this is a root bone + FVector3 Translate; + FVector4 Quaternion; + FVector3 Scale; +}; + +struct IQMPose +{ + int32_t Parent; // parent < 0 means this is a root bone + uint32_t ChannelMask; // mask of which 10 channels are present for this joint pose + float ChannelOffset[10]; + float ChannelScale[10]; + // channels 0..2 are translation and channels 3..6 are quaternion rotation + // rotation is in relative/parent local space + // channels 7..9 are scale + // output = (input*scale)*rotation + translation +}; + +struct IQMAnim +{ + FString Name; + uint32_t FirstFrame; + uint32_t NumFrames; + float Framerate; + bool Loop; +}; + +struct IQMBounds +{ + float BBMins[3]; + float BBMaxs[3]; + float XYRadius; + float Radius; +}; + +class IQMFileReader; + +class IQMModel : public FModel +{ +public: + IQMModel(); + ~IQMModel(); + + 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 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; + +private: + void LoadGeometry(); + void UnloadGeometry(); + + void LoadPosition(IQMFileReader& reader, const IQMVertexArray& vertexArray); + void LoadTexcoord(IQMFileReader& reader, const IQMVertexArray& vertexArray); + void LoadNormal(IQMFileReader& reader, const IQMVertexArray& vertexArray); + void LoadBlendIndexes(IQMFileReader& reader, const IQMVertexArray& vertexArray); + void LoadBlendWeights(IQMFileReader& reader, const IQMVertexArray& vertexArray); + + int mLumpNum = -1; + TArray Meshes; + TArray Triangles; + TArray Adjacency; + TArray Joints; + TArray Poses; + TArray Anims; + TArray Bounds; + TArray VertexArrays; + uint32_t NumVertices = 0; + + TArray Vertices; + + TArray baseframe; + TArray inversebaseframe; + TArray TRSData; +}; + +struct IQMReadErrorException { }; + +class IQMFileReader +{ +public: + IQMFileReader(const void* buffer, int length) : buffer((const char*)buffer), length(length) { } + + uint8_t ReadUByte() + { + uint8_t value; + Read(&value, sizeof(uint8_t)); + return value; + } + + int32_t ReadInt32() + { + int32_t value; + Read(&value, sizeof(int32_t)); + value = LittleLong(value); + return value; + } + + int16_t ReadInt16() + { + int16_t value; + Read(&value, sizeof(int16_t)); + value = LittleShort(value); + return value; + } + + uint32_t ReadUInt32() + { + return ReadInt32(); + } + + uint16_t ReadUInt16() + { + return ReadInt16(); + } + + float ReadFloat() + { + float value; + Read(&value, sizeof(float)); + return value; + } + + FString ReadName(const TArray& textBuffer) + { + uint32_t nameOffset = ReadUInt32(); + if (nameOffset >= textBuffer.Size()) + throw IQMReadErrorException(); + return textBuffer.Data() + nameOffset; + } + + void Read(void* data, int size) + { + if (pos + size > length || size < 0 || size > 0x0fffffff) + throw IQMReadErrorException(); + memcpy(data, buffer + pos, size); + pos += size; + } + + void SeekTo(int newPos) + { + if (newPos < 0 || newPos > length) + throw IQMReadErrorException(); + pos = newPos; + } + +private: + const char* buffer = nullptr; + int length = 0; + int pos = 0; +}; diff --git a/src/common/models/model_kvx.h b/src/common/models/model_kvx.h index 36db774c7..c801e5c01 100644 --- a/src/common/models/model_kvx.h +++ b/src/common/models/model_kvx.h @@ -15,9 +15,9 @@ struct FVoxelVertexHash // Returns the hash value for a key. hash_t Hash(const FModelVertex &key) { - int ix = xs_RoundToInt(key.x); - int iy = xs_RoundToInt(key.y); - int iz = xs_RoundToInt(key.z); + int ix = int(key.x); + int iy = int(key.y); + int iz = int(key.z); return (hash_t)(ix + (iy<<9) + (iz<<18)); } @@ -48,7 +48,7 @@ protected: unsigned int mNumIndices; TArray mVertices; TArray mIndices; - + void MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &check); void AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, uint8_t color, FVoxelMap &check); unsigned int AddVertex(FModelVertex &vert, FVoxelMap &check); @@ -58,9 +58,9 @@ public: ~FVoxelModel(); bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; void Initialize(); - virtual int FindFrame(const char * name) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) override; - virtual void AddSkins(uint8_t *hitlist) 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 AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(FModelRenderer *renderer) override; float getAspectFactor(float vscale) override; diff --git a/src/common/models/model_md2.h b/src/common/models/model_md2.h index c04445535..9ead5e60b 100644 --- a/src/common/models/model_md2.h +++ b/src/common/models/model_md2.h @@ -111,11 +111,11 @@ public: } virtual ~FDMDModel(); - virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); - virtual int FindFrame(const char * name); - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0); + 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 LoadGeometry(); - virtual void AddSkins(uint8_t *hitlist); + virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void UnloadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); diff --git a/src/common/models/model_md3.h b/src/common/models/model_md3.h index 3e6630a5a..b53cd3ebb 100644 --- a/src/common/models/model_md3.h +++ b/src/common/models/model_md3.h @@ -65,11 +65,11 @@ class FMD3Model : public FModel public: FMD3Model() = default; - virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); - virtual int FindFrame(const char * name); - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0); + 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; void LoadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); - virtual void AddSkins(uint8_t *hitlist); + 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 ed190c1cd..fa41ec0fc 100644 --- a/src/common/models/model_obj.h +++ b/src/common/models/model_obj.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -97,10 +97,10 @@ public: FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {} ~FOBJModel(); bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; - int FindFrame(const char* name) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation=0) 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 BuildVertexBuffer(FModelRenderer* renderer) override; - void AddSkins(uint8_t* hitlist) override; + void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; }; #endif diff --git a/src/common/models/model_ue1.h b/src/common/models/model_ue1.h index 967488355..9b529b44c 100644 --- a/src/common/models/model_ue1.h +++ b/src/common/models/model_ue1.h @@ -25,17 +25,16 @@ public: }; bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; - int FindFrame(const char * name) override; - void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) 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 BuildVertexBuffer(FModelRenderer *renderer) override; - void AddSkins(uint8_t *hitlist) override; + void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void LoadGeometry(); void UnloadGeometry(); FUE1Model() { mDataLump = -1; mAnivLump = -1; - mDataLoaded = false; dhead = NULL; dpolys = NULL; ahead = NULL; @@ -49,7 +48,6 @@ public: private: int mDataLump, mAnivLump; - bool mDataLoaded; // raw data structures struct d3dhead @@ -105,9 +103,10 @@ private: int numFrames; int numPolys; int numGroups; - TArray specialPolys; // for future model attachment support, unused for now + bool hasWeaponTriangle; TArray verts; TArray polys; TArray groups; + //TArray weapondata; // pseudo-bone generated from weapon triangle (not yet implemented) }; diff --git a/src/common/models/modelrenderer.h b/src/common/models/modelrenderer.h index 38786afe6..18c49f641 100644 --- a/src/common/models/modelrenderer.h +++ b/src/common/models/modelrenderer.h @@ -24,6 +24,6 @@ public: virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) = 0; virtual void DrawArrays(int start, int count) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0; - virtual void SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size) = 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 new file mode 100644 index 000000000..9d4ab2652 --- /dev/null +++ b/src/common/models/models_iqm.cpp @@ -0,0 +1,616 @@ + +#include "filesystem.h" +#include "cmdlib.h" +#include "model_iqm.h" +#include "texturemanager.h" +#include "modelrenderer.h" +#include "engineerrors.h" +#include "dobject.h" +#include "bonecomponents.h" + +IMPLEMENT_CLASS(DBoneComponents, false, false); + + +IQMModel::IQMModel() +{ +} + +IQMModel::~IQMModel() +{ +} + +bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int length) +{ + mLumpNum = lumpnum; + + try + { + IQMFileReader reader(buffer, length); + + char magic[16]; + reader.Read(magic, 16); + if (memcmp(magic, "INTERQUAKEMODEL\0", 16) != 0) + return false; + + uint32_t version = reader.ReadUInt32(); + if (version != 2) + return false; + + uint32_t filesize = reader.ReadUInt32(); + uint32_t flags = reader.ReadUInt32(); + uint32_t num_text = reader.ReadUInt32(); + uint32_t ofs_text = reader.ReadUInt32(); + uint32_t num_meshes = reader.ReadUInt32(); + uint32_t ofs_meshes = reader.ReadUInt32(); + uint32_t num_vertexarrays = reader.ReadUInt32(); + uint32_t num_vertices = reader.ReadUInt32(); + uint32_t ofs_vertexarrays = reader.ReadUInt32(); + uint32_t num_triangles = reader.ReadUInt32(); + uint32_t ofs_triangles = reader.ReadUInt32(); + uint32_t ofs_adjacency = reader.ReadUInt32(); + uint32_t num_joints = reader.ReadUInt32(); + uint32_t ofs_joints = reader.ReadUInt32(); + uint32_t num_poses = reader.ReadUInt32(); + uint32_t ofs_poses = reader.ReadUInt32(); + uint32_t num_anims = reader.ReadUInt32(); + uint32_t ofs_anims = reader.ReadUInt32(); + uint32_t num_frames = reader.ReadUInt32(); + uint32_t num_framechannels = reader.ReadUInt32(); + uint32_t ofs_frames = reader.ReadUInt32(); + uint32_t ofs_bounds = reader.ReadUInt32(); + uint32_t num_comment = reader.ReadUInt32(); + uint32_t ofs_comment = reader.ReadUInt32(); + 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; + + TArray text(num_text, true); + reader.SeekTo(ofs_text); + reader.Read(text.Data(), text.Size()); + text[text.Size() - 1] = 0; + + Meshes.Resize(num_meshes); + Triangles.Resize(num_triangles); + Adjacency.Resize(num_triangles); + Joints.Resize(num_joints); + Poses.Resize(num_poses); + Anims.Resize(num_anims); + Bounds.Resize(num_frames); + VertexArrays.Resize(num_vertexarrays); + NumVertices = num_vertices; + + reader.SeekTo(ofs_meshes); + for (IQMMesh& mesh : Meshes) + { + mesh.Name = reader.ReadName(text); + mesh.Material = reader.ReadName(text); + mesh.FirstVertex = reader.ReadUInt32(); + mesh.NumVertices = reader.ReadUInt32(); + mesh.FirstTriangle = reader.ReadUInt32(); + mesh.NumTriangles = reader.ReadUInt32(); + mesh.Skin = LoadSkin(path, mesh.Material.GetChars()); + } + + reader.SeekTo(ofs_triangles); + for (IQMTriangle& triangle : Triangles) + { + triangle.Vertex[0] = reader.ReadUInt32(); + triangle.Vertex[1] = reader.ReadUInt32(); + triangle.Vertex[2] = reader.ReadUInt32(); + } + + reader.SeekTo(ofs_adjacency); + for (IQMAdjacency& adj : Adjacency) + { + adj.Triangle[0] = reader.ReadUInt32(); + adj.Triangle[1] = reader.ReadUInt32(); + adj.Triangle[2] = reader.ReadUInt32(); + } + + reader.SeekTo(ofs_joints); + for (IQMJoint& joint : Joints) + { + joint.Name = reader.ReadName(text); + joint.Parent = reader.ReadInt32(); + joint.Translate.X = reader.ReadFloat(); + joint.Translate.Y = reader.ReadFloat(); + joint.Translate.Z = reader.ReadFloat(); + joint.Quaternion.X = reader.ReadFloat(); + joint.Quaternion.Y = reader.ReadFloat(); + joint.Quaternion.Z = reader.ReadFloat(); + joint.Quaternion.W = reader.ReadFloat(); + joint.Quaternion.MakeUnit(); + joint.Scale.X = reader.ReadFloat(); + joint.Scale.Y = reader.ReadFloat(); + joint.Scale.Z = reader.ReadFloat(); + } + + reader.SeekTo(ofs_poses); + for (IQMPose& pose : Poses) + { + pose.Parent = reader.ReadInt32(); + pose.ChannelMask = reader.ReadUInt32(); + for (int i = 0; i < 10; i++) pose.ChannelOffset[i] = reader.ReadFloat(); + for (int i = 0; i < 10; i++) pose.ChannelScale[i] = reader.ReadFloat(); + } + + reader.SeekTo(ofs_anims); + for (IQMAnim& anim : Anims) + { + anim.Name = reader.ReadName(text); + anim.FirstFrame = reader.ReadUInt32(); + anim.NumFrames = reader.ReadUInt32(); + anim.Framerate = reader.ReadFloat(); + anim.Loop = !!(reader.ReadUInt32() & 1); + } + + baseframe.Resize(num_joints); + inversebaseframe.Resize(num_joints); + + for (uint32_t i = 0; i < num_joints; i++) + { + const IQMJoint& j = Joints[i]; + + VSMatrix m, invm; + m.loadIdentity(); + m.translate(j.Translate.X, j.Translate.Y, j.Translate.Z); + m.multQuaternion(j.Quaternion); + m.scale(j.Scale.X, j.Scale.Y, j.Scale.Z); + m.inverseMatrix(invm); + if (j.Parent >= 0) + { + baseframe[i] = baseframe[j.Parent]; + baseframe[i].multMatrix(m); + inversebaseframe[i] = invm; + inversebaseframe[i].multMatrix(inversebaseframe[j.Parent]); + } + else + { + baseframe[i] = m; + inversebaseframe[i] = invm; + } + } + + TRSData.Resize(num_frames * num_poses); + reader.SeekTo(ofs_frames); + for (uint32_t i = 0; i < num_frames; i++) + { + for (uint32_t j = 0; j < num_poses; j++) + { + const IQMPose& p = Poses[j]; + + FVector3 translate; + translate.X = p.ChannelOffset[0]; if (p.ChannelMask & 0x01) translate.X += reader.ReadUInt16() * p.ChannelScale[0]; + translate.Y = p.ChannelOffset[1]; if (p.ChannelMask & 0x02) translate.Y += reader.ReadUInt16() * p.ChannelScale[1]; + translate.Z = p.ChannelOffset[2]; if (p.ChannelMask & 0x04) translate.Z += reader.ReadUInt16() * p.ChannelScale[2]; + + FVector4 quaternion; + quaternion.X = p.ChannelOffset[3]; if (p.ChannelMask & 0x08) quaternion.X += reader.ReadUInt16() * p.ChannelScale[3]; + quaternion.Y = p.ChannelOffset[4]; if (p.ChannelMask & 0x10) quaternion.Y += reader.ReadUInt16() * p.ChannelScale[4]; + quaternion.Z = p.ChannelOffset[5]; if (p.ChannelMask & 0x20) quaternion.Z += reader.ReadUInt16() * p.ChannelScale[5]; + quaternion.W = p.ChannelOffset[6]; if (p.ChannelMask & 0x40) quaternion.W += reader.ReadUInt16() * p.ChannelScale[6]; + quaternion.MakeUnit(); + + FVector3 scale; + scale.X = p.ChannelOffset[7]; if (p.ChannelMask & 0x80) scale.X += reader.ReadUInt16() * p.ChannelScale[7]; + scale.Y = p.ChannelOffset[8]; if (p.ChannelMask & 0x100) scale.Y += reader.ReadUInt16() * p.ChannelScale[8]; + scale.Z = p.ChannelOffset[9]; if (p.ChannelMask & 0x200) scale.Z += reader.ReadUInt16() * p.ChannelScale[9]; + + TRSData[i * num_poses + j].translation = translate; + TRSData[i * num_poses + j].rotation = quaternion; + TRSData[i * num_poses + j].scaling = scale; + } + } + + //If a model doesn't have an animation loaded, it will crash. We don't want that! + if (num_frames <= 0) + { + num_frames = 1; + TRSData.Resize(num_joints); + + for (uint32_t j = 0; j < num_joints; j++) + { + FVector3 translate; + translate.X = Joints[j].Translate.X; + translate.Y = Joints[j].Translate.Y; + translate.Z = Joints[j].Translate.Z; + + FVector4 quaternion; + quaternion.X = Joints[j].Quaternion.X; + quaternion.Y = Joints[j].Quaternion.Y; + quaternion.Z = Joints[j].Quaternion.Z; + quaternion.W = Joints[j].Quaternion.W; + quaternion.MakeUnit(); + + FVector3 scale; + scale.X = Joints[j].Scale.X; + scale.Y = Joints[j].Scale.Y; + scale.Z = Joints[j].Scale.Z; + + TRSData[j].translation = translate; + TRSData[j].rotation = quaternion; + TRSData[j].scaling = scale; + } + } + + reader.SeekTo(ofs_bounds); + for (IQMBounds& bound : Bounds) + { + bound.BBMins[0] = reader.ReadFloat(); + bound.BBMins[1] = reader.ReadFloat(); + bound.BBMins[2] = reader.ReadFloat(); + bound.BBMaxs[0] = reader.ReadFloat(); + bound.BBMaxs[1] = reader.ReadFloat(); + bound.BBMaxs[2] = reader.ReadFloat(); + bound.XYRadius = reader.ReadFloat(); + bound.Radius = reader.ReadFloat(); + } + + reader.SeekTo(ofs_vertexarrays); + for (IQMVertexArray& vertexArray : VertexArrays) + { + vertexArray.Type = (IQMVertexArrayType)reader.ReadUInt32(); + vertexArray.Flags = reader.ReadUInt32(); + vertexArray.Format = (IQMVertexArrayFormat)reader.ReadUInt32(); + vertexArray.Size = reader.ReadUInt32(); + vertexArray.Offset = reader.ReadUInt32(); + } + + return true; + } + catch (IQMReadErrorException) + { + return false; + } +} + +void IQMModel::LoadGeometry() +{ + try + { + FileData lumpdata = fileSystem.ReadFile(mLumpNum); + IQMFileReader reader(lumpdata.GetMem(), (int)lumpdata.GetSize()); + + Vertices.Resize(NumVertices); + for (IQMVertexArray& vertexArray : VertexArrays) + { + reader.SeekTo(vertexArray.Offset); + if (vertexArray.Type == IQM_POSITION) + { + LoadPosition(reader, vertexArray); + } + else if (vertexArray.Type == IQM_TEXCOORD) + { + LoadTexcoord(reader, vertexArray); + } + else if (vertexArray.Type == IQM_NORMAL) + { + LoadNormal(reader, vertexArray); + } + else if (vertexArray.Type == IQM_BLENDINDEXES) + { + LoadBlendIndexes(reader, vertexArray); + } + else if (vertexArray.Type == IQM_BLENDWEIGHTS) + { + LoadBlendWeights(reader, vertexArray); + } + } + } + catch (IQMReadErrorException) + { + } +} + +void IQMModel::LoadPosition(IQMFileReader& reader, const IQMVertexArray& vertexArray) +{ + float lu = 0.0f, lv = 0.0f, lindex = -1.0f; + if (vertexArray.Format == IQM_FLOAT && vertexArray.Size == 3) + { + for (FModelVertex& v : Vertices) + { + v.x = reader.ReadFloat(); + v.z = reader.ReadFloat(); + v.y = reader.ReadFloat(); + + v.lu = lu; + v.lv = lv; + v.lindex = lindex; + } + } + else + { + I_FatalError("Unsupported IQM_POSITION vertex format"); + } +} + +void IQMModel::LoadTexcoord(IQMFileReader& reader, const IQMVertexArray& vertexArray) +{ + if (vertexArray.Format == IQM_FLOAT && vertexArray.Size == 2) + { + for (FModelVertex& v : Vertices) + { + v.u = reader.ReadFloat(); + v.v = reader.ReadFloat(); + } + } + else + { + I_FatalError("Unsupported IQM_TEXCOORD vertex format"); + } +} + +void IQMModel::LoadNormal(IQMFileReader& reader, const IQMVertexArray& vertexArray) +{ + if (vertexArray.Format == IQM_FLOAT && vertexArray.Size == 3) + { + for (FModelVertex& v : Vertices) + { + float x = reader.ReadFloat(); + float y = reader.ReadFloat(); + float z = reader.ReadFloat(); + + v.SetNormal(x, z, y); + } + } + else + { + I_FatalError("Unsupported IQM_NORMAL vertex format"); + } +} + +void IQMModel::LoadBlendIndexes(IQMFileReader& reader, const IQMVertexArray& vertexArray) +{ + if (vertexArray.Format == IQM_UBYTE && vertexArray.Size == 4) + { + for (FModelVertex& v : Vertices) + { + int x = reader.ReadUByte(); + int y = reader.ReadUByte(); + int z = reader.ReadUByte(); + int w = reader.ReadUByte(); + v.SetBoneSelector(x, y, z, w); + } + } + else if (vertexArray.Format == IQM_INT && vertexArray.Size == 4) + { + for (FModelVertex& v : Vertices) + { + int x = reader.ReadInt32(); + int y = reader.ReadInt32(); + int z = reader.ReadInt32(); + int w = reader.ReadInt32(); + v.SetBoneSelector(x, y, z, w); + } + } + else + { + I_FatalError("Unsupported IQM_BLENDINDEXES vertex format"); + } +} + +void IQMModel::LoadBlendWeights(IQMFileReader& reader, const IQMVertexArray& vertexArray) +{ + if (vertexArray.Format == IQM_UBYTE && vertexArray.Size == 4) + { + for (FModelVertex& v : Vertices) + { + int x = reader.ReadUByte(); + int y = reader.ReadUByte(); + int z = reader.ReadUByte(); + int w = reader.ReadUByte(); + v.SetBoneWeight(x, y, z, w); + } + } + else if (vertexArray.Format == IQM_FLOAT && vertexArray.Size == 4) + { + for (FModelVertex& v : Vertices) + { + uint8_t x = (int)clamp(reader.ReadFloat() * 255.0f, 0.0f, 255.0f); + uint8_t y = (int)clamp(reader.ReadFloat() * 255.0f, 0.0f, 255.0f); + uint8_t z = (int)clamp(reader.ReadFloat() * 255.0f, 0.0f, 255.0f); + uint8_t w = (int)clamp(reader.ReadFloat() * 255.0f, 0.0f, 255.0f); + v.SetBoneWeight(x, y, z, w); + } + } + else + { + I_FatalError("Unsupported IQM_BLENDWEIGHTS vertex format"); + } +} + +void IQMModel::UnloadGeometry() +{ + Vertices.Reset(); +} + +int IQMModel::FindFrame(const char* name, bool nodefault) +{ + // [MK] allow looking up frames by animation name plus offset (using a colon as separator) + const char* colon = strrchr(name,':'); + size_t nlen = (colon==nullptr)?strlen(name):(colon-name); + for (unsigned i = 0; i < Anims.Size(); i++) + { + if (!strnicmp(name, Anims[i].Name.GetChars(), nlen)) + { + // if no offset is given, return the first frame + if (colon == nullptr) return Anims[i].FirstFrame; + unsigned offset = atoi(colon+1); + if (offset >= Anims[i].NumFrames) return FErr_NotFound; + return Anims[i].FirstFrame+offset; + } + } + 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) +{ + renderer->SetupFrame(this, 0, 0, NumVertices, boneData, boneStartPosition); + + FGameTexture* lastSkin = nullptr; + for (unsigned i = 0; i < Meshes.Size(); i++) + { + FGameTexture* meshSkin = skin; + + if (!meshSkin) + { + if (surfaceskinids && surfaceskinids[i].isValid()) + { + meshSkin = TexMan.GetGameTexture(surfaceskinids[i], true); + } + else if (Meshes[i].Skin.isValid()) + { + meshSkin = TexMan.GetGameTexture(Meshes[i].Skin, true); + } + else + { + continue; + } + } + + if (meshSkin->isValid()) + { + if (meshSkin != lastSkin) + { + renderer->SetMaterial(meshSkin, false, translation); + lastSkin = meshSkin; + } + renderer->DrawElements(Meshes[i].NumTriangles * 3, Meshes[i].FirstTriangle * 3 * sizeof(unsigned int)); + } + } +} + +void IQMModel::BuildVertexBuffer(FModelRenderer* renderer) +{ + if (!GetVertexBuffer(renderer->GetType())) + { + LoadGeometry(); + + auto vbuf = renderer->CreateVertexBuffer(true, true); + SetVertexBuffer(renderer->GetType(), vbuf); + + FModelVertex* vertptr = vbuf->LockVertexBuffer(Vertices.Size()); + memcpy(vertptr, Vertices.Data(), Vertices.Size() * sizeof(FModelVertex)); + vbuf->UnlockVertexBuffer(); + + unsigned int* indxptr = vbuf->LockIndexBuffer(Triangles.Size() * 3); + memcpy(indxptr, Triangles.Data(), Triangles.Size() * sizeof(unsigned int) * 3); + vbuf->UnlockIndexBuffer(); + + UnloadGeometry(); + } +} + +void IQMModel::AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) +{ + for (unsigned i = 0; i < Meshes.Size(); i++) + { + if (surfaceskinids && surfaceskinids[i].isValid()) + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; + } +} + +const TArray* IQMModel::AttachAnimationData() +{ + return &TRSData; +} + +const TArray IQMModel::CalculateBones(int frame1, int frame2, double inter, const TArray* animationData, DBoneComponents* boneComponentData, int index) +{ + const TArray& animationFrames = animationData ? *animationData : TRSData; + if (Joints.Size() > 0) + { + int numbones = Joints.Size(); + + if (boneComponentData->trscomponents[index].Size() != numbones) + boneComponentData->trscomponents[index].Resize(numbones); + if (boneComponentData->trsmatrix[index].Size() != numbones) + boneComponentData->trsmatrix[index].Resize(numbones); + + frame1 = clamp(frame1, 0, ((int)animationFrames.Size() - 1) / numbones); + frame2 = clamp(frame2, 0, ((int)animationFrames.Size() - 1) / numbones); + + int offset1 = frame1 * numbones; + int offset2 = frame2 * numbones; + float t = (float)inter; + float invt = 1.0f - t; + + float swapYZ[16] = { 0.0f }; + swapYZ[0 + 0 * 4] = 1.0f; + swapYZ[1 + 2 * 4] = 1.0f; + swapYZ[2 + 1 * 4] = 1.0f; + swapYZ[3 + 3 * 4] = 1.0f; + + TArray bones(numbones, true); + TArray modifiedBone(numbones, true); + for (int i = 0; i < numbones; i++) + { + 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) + { + 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; + + if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent]) + { + boneComponentData->trscomponents[index][i] = bone; + modifiedBone[i] = true; + } + else if (boneComponentData->trscomponents[index][i].Equals(bone)) + { + bones[i] = boneComponentData->trsmatrix[index][i]; + modifiedBone[i] = false; + continue; + } + else + { + boneComponentData->trscomponents[index][i] = bone; + modifiedBone[i] = true; + } + + VSMatrix m; + m.loadIdentity(); + m.translate(bone.translation.X, bone.translation.Y, bone.translation.Z); + m.multQuaternion(bone.rotation); + m.scale(bone.scaling.X, bone.scaling.Y, bone.scaling.Z); + + VSMatrix& result = bones[i]; + if (Joints[i].Parent >= 0) + { + result = bones[Joints[i].Parent]; + result.multMatrix(swapYZ); + result.multMatrix(baseframe[Joints[i].Parent]); + result.multMatrix(m); + result.multMatrix(inversebaseframe[i]); + } + else + { + result.loadMatrix(swapYZ); + result.multMatrix(m); + result.multMatrix(inversebaseframe[i]); + } + result.multMatrix(swapYZ); + } + + boneComponentData->trsmatrix[index] = bones; + + return bones; + } + return {}; +} diff --git a/src/common/models/models_md2.cpp b/src/common/models/models_md2.cpp index c3439faea..4f2a12d4e 100644 --- a/src/common/models/models_md2.cpp +++ b/src/common/models/models_md2.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -217,10 +217,10 @@ void FDMDModel::LoadGeometry() memcpy(lods[i].triangles, buffer + lodInfo[i].offsetTriangles, lodInfo[i].numTriangles * sizeof(FTriangle)); for (int j = 0; j < lodInfo[i].numTriangles; j++) { - for (int k = 0; k < 3; k++) + for (int kk = 0; kk < 3; kk++) { - lods[i].triangles[j].textureIndices[k] = LittleShort(lods[i].triangles[j].textureIndices[k]); - lods[i].triangles[j].vertexIndices[k] = LittleShort(lods[i].triangles[j].vertexIndices[k]); + lods[i].triangles[j].textureIndices[kk] = LittleShort(lods[i].triangles[j].textureIndices[kk]); + lods[i].triangles[j].vertexIndices[kk] = LittleShort(lods[i].triangles[j].vertexIndices[kk]); } } } @@ -306,7 +306,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer) FTriangle *tri = lods[0].triangles; - for (int i = 0; i < lodInfo[0].numTriangles; i++) + for (int ii = 0; ii < lodInfo[0].numTriangles; ii++) { for (int j = 0; j < 3; j++) { @@ -332,7 +332,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FDMDModel::AddSkins(uint8_t *hitlist) +void FDMDModel::AddSkins(uint8_t *hitlist, const FTextureID*) { for (int i = 0; i < info.numSkins; i++) { @@ -348,13 +348,13 @@ void FDMDModel::AddSkins(uint8_t *hitlist) // FDMDModel::FindFrame // //=========================================================================== -int FDMDModel::FindFrame(const char * name) +int FDMDModel::FindFrame(const char* name, bool nodefault) { for (int i=0;i& boneData, int boneStartPosition) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; @@ -376,13 +376,11 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f renderer->SetInterpolation(inter); renderer->SetMaterial(skin, false, translation); - renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3); + renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3, {}, -1); renderer->DrawArrays(0, lodInfo[0].numTriangles * 3); renderer->SetInterpolation(0.f); } - - //=========================================================================== // // Internal data structures of MD2 files - only used during loading @@ -536,15 +534,15 @@ void FMD2Model::LoadGeometry() } lods[0].triangles = new FTriangle[lodInfo[0].numTriangles]; - + int cnt = lodInfo[0].numTriangles; memcpy(lods[0].triangles, buffer + lodInfo[0].offsetTriangles, sizeof(FTriangle) * cnt); for (int j = 0; j < cnt; j++) { - for (int k = 0; k < 3; k++) + for (int kk = 0; kk < 3; kk++) { - lods[0].triangles[j].textureIndices[k] = LittleShort(lods[0].triangles[j].textureIndices[k]); - lods[0].triangles[j].vertexIndices[k] = LittleShort(lods[0].triangles[j].vertexIndices[k]); + lods[0].triangles[j].textureIndices[kk] = LittleShort(lods[0].triangles[j].textureIndices[kk]); + lods[0].triangles[j].vertexIndices[kk] = LittleShort(lods[0].triangles[j].vertexIndices[kk]); } } } @@ -552,4 +550,3 @@ void FMD2Model::LoadGeometry() FMD2Model::~FMD2Model() { } - diff --git a/src/common/models/models_md3.cpp b/src/common/models/models_md3.cpp index c40f78e1e..e716a6f26 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -133,7 +133,8 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le auto numFrames = LittleLong(hdr->Num_Frames); auto numSurfaces = LittleLong(hdr->Num_Surfaces); - + hasSurfaces = numSurfaces > 1; + numTags = LittleLong(hdr->Num_Tags); md3_frame_t * frm = (md3_frame_t*)(buffer + LittleLong(hdr->Ofs_Frames)); @@ -141,7 +142,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le Frames.Resize(numFrames); for (unsigned i = 0; i < numFrames; i++) { - strncpy(Frames[i].Name, frm[i].Name, 16); + strncpy(Frames[i].Name, frm[i].Name, 15); for (int j = 0; j < 3; j++) Frames[i].origin[j] = frm[i].localorigin[j]; } @@ -164,15 +165,15 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le md3_shader_t * shader = (md3_shader_t*)(((char*)ss) + LittleLong(ss->Ofs_Shaders)); s->Skins.Resize(s->numSkins); - for (unsigned i = 0; i < s->numSkins; i++) + for (unsigned ii = 0; ii < s->numSkins; ii++) { // [BB] According to the MD3 spec, Name is supposed to include the full path. // ... and since some tools seem to output backslashes, these need to be replaced with forward slashes to work. - FixPathSeperator(shader[i].Name); - s->Skins[i] = LoadSkin("", shader[i].Name); + FixPathSeperator(shader[ii].Name); + s->Skins[ii] = LoadSkin("", shader[ii].Name); // [BB] Fall back and check if Name is relative. - if (!s->Skins[i].isValid()) - s->Skins[i] = LoadSkin(path, shader[i].Name); + if (!s->Skins[ii].isValid()) + s->Skins[ii] = LoadSkin(path, shader[ii].Name); } } mLumpNum = lumpnum; @@ -203,31 +204,31 @@ void FMD3Model::LoadGeometry() md3_triangle_t * tris = (md3_triangle_t*)(((char*)ss) + LittleLong(ss->Ofs_Triangles)); s->Tris.Resize(s->numTriangles); - for (unsigned i = 0; i < s->numTriangles; i++) for (int j = 0; j < 3; j++) + for (unsigned ii = 0; ii < s->numTriangles; ii++) for (int j = 0; j < 3; j++) { - s->Tris[i].VertIndex[j] = LittleLong(tris[i].vt_index[j]); + s->Tris[ii].VertIndex[j] = LittleLong(tris[ii].vt_index[j]); } // Load texture coordinates md3_texcoord_t * tc = (md3_texcoord_t*)(((char*)ss) + LittleLong(ss->Ofs_Texcoord)); s->Texcoords.Resize(s->numVertices); - for (unsigned i = 0; i < s->numVertices; i++) + for (unsigned ii = 0; ii < s->numVertices; ii++) { - s->Texcoords[i].s = tc[i].s; - s->Texcoords[i].t = tc[i].t; + s->Texcoords[ii].s = tc[ii].s; + s->Texcoords[ii].t = tc[ii].t; } // Load vertices and texture coordinates md3_vertex_t * vt = (md3_vertex_t*)(((char*)ss) + LittleLong(ss->Ofs_XYZNormal)); s->Vertices.Resize(s->numVertices * Frames.Size()); - for (unsigned i = 0; i < s->numVertices * Frames.Size(); i++) + for (unsigned ii = 0; ii < s->numVertices * Frames.Size(); ii++) { - s->Vertices[i].x = LittleShort(vt[i].x) / 64.f; - s->Vertices[i].y = LittleShort(vt[i].y) / 64.f; - s->Vertices[i].z = LittleShort(vt[i].z) / 64.f; - UnpackVector(LittleShort(vt[i].n), s->Vertices[i].nx, s->Vertices[i].ny, s->Vertices[i].nz); + s->Vertices[ii].x = LittleShort(vt[ii].x) / 64.f; + s->Vertices[ii].y = LittleShort(vt[ii].y) / 64.f; + s->Vertices[ii].z = LittleShort(vt[ii].z) / 64.f; + UnpackVector(LittleShort(vt[ii].n), s->Vertices[ii].nx, s->Vertices[ii].ny, s->Vertices[ii].nz); } } } @@ -302,14 +303,13 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FMD3Model::AddSkins(uint8_t *hitlist) +void FMD3Model::AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) { for (unsigned i = 0; i < Surfaces.Size(); i++) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && surfaceskinids[i].isValid()) { - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; } MD3Surface * surf = &Surfaces[i]; @@ -329,13 +329,13 @@ void FMD3Model::AddSkins(uint8_t *hitlist) // //=========================================================================== -int FMD3Model::FindFrame(const char * name) +int FMD3Model::FindFrame(const char* name, bool nodefault) { for (unsigned i = 0; i < Frames.Size(); i++) { if (!stricmp(name, Frames[i].Name)) return i; } - return -1; + return FErr_NotFound; } //=========================================================================== @@ -344,7 +344,7 @@ int FMD3Model::FindFrame(const char * name) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; @@ -358,17 +358,13 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f FGameTexture *surfaceSkin = skin; if (!surfaceSkin) { - if (curSpriteMDLFrame) + if (surfaceskinids && surfaceskinids[i].isValid()) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) - { - surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); - } - else if (surf->numSkins > 0 && surf->Skins[0].isValid()) - { - surfaceSkin = TexMan.GetGameTexture(surf->Skins[0], true); - } + surfaceSkin = TexMan.GetGameTexture(surfaceskinids[i], true); + } + else if (surf->numSkins > 0 && surf->Skins[0].isValid()) + { + surfaceSkin = TexMan.GetGameTexture(surf->Skins[0], true); } if (!surfaceSkin) @@ -378,7 +374,7 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(surfaceSkin, false, translation); - renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices); + renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices, {}, -1); renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int)); } renderer->SetInterpolation(0.f); diff --git a/src/common/models/models_obj.cpp b/src/common/models/models_obj.cpp index 05d10b5cf..e1d777c81 100644 --- a/src/common/models/models_obj.cpp +++ b/src/common/models/models_obj.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -222,6 +222,8 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length curSurface->faceStart = aggSurfFaceCount; surfaces.Push(*curSurface); delete curSurface; + hasSurfaces = surfaces.Size() > 1; + if (uvs.Size() == 0) { // Needed so that OBJs without UVs can work @@ -542,7 +544,7 @@ inline FVector3 FOBJModel::RealignVector(FVector3 vecToRealign) */ inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign) { - vecToRealign.Y *= -1; + vecToRealign.Y = 1-vecToRealign.Y; return vecToRealign; } @@ -613,9 +615,9 @@ FVector3 FOBJModel::CalculateNormalSmooth(unsigned int vidx, unsigned int smooth * @param name The name of the frame * @return The index of the frame */ -int FOBJModel::FindFrame(const char* name) +int FOBJModel::FindFrame(const char* name, bool nodefault) { - return 0; // OBJs are not animated. + return nodefault ? FErr_Singleframe : 0; // OBJs are not animated. } /** @@ -623,24 +625,26 @@ int FOBJModel::FindFrame(const char* name) * * @param renderer The model renderer * @param skin The loaded skin for the surface - * @param frameno Unused - * @param frameno2 Unused - * @param inter Unused + * @param frameno The first frame to interpolate between. Only prevents the model from rendering if it is < 0, since OBJ models are static. + * @param frameno2 The second frame to interpolate between. + * @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) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int 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; + for (unsigned int i = 0; i < surfaces.Size(); i++) { OBJSurface *surf = &surfaces[i]; FGameTexture *userSkin = skin; - if (!userSkin && curSpriteMDLFrame) + if (!userSkin) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && surfaceskinids[i].isValid()) { - userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); + userSkin = TexMan.GetGameTexture(surfaceskinids[i], true); } else if (surf->skin.isValid()) { @@ -655,7 +659,7 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(userSkin, false, translation); - renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3); + renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3, {}, -1); renderer->DrawArrays(0, surf->numTris * 3); } } @@ -665,18 +669,17 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f * * @param hitlist The list of textures */ -void FOBJModel::AddSkins(uint8_t* hitlist) +void FOBJModel::AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) { for (size_t i = 0; i < surfaces.Size(); i++) { - size_t ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && i < MD3_MAX_SURFACES && surfaceskinids[i].isValid()) { // Precache skins manually reassigned by the user. // On OBJs with lots of skins, such as Doom map OBJs exported from GZDB, // there may be too many skins for the user to manually change, unless // the limit is bumped or surfaceskinIDs is changed to a TArray. - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; return; // No need to precache skin that was replaced } diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index 68be56e61..5db36a672 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -1,21 +1,25 @@ // //--------------------------------------------------------------------------- // -// Copyright(C) 2018 Marisa Kirisame -// All rights reserved. +// Copyright (c) 2018-2022 Marisa Kirisame, UnSX Team // -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// 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: // -// 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 Lesser General Public License for more details. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ +// 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. // //-------------------------------------------------------------------------- // @@ -44,6 +48,7 @@ float unpackuvert( uint32_t n, int c ) bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length ) { int lumpnum2; + hasSurfaces = true; FString realfilename = fileSystem.GetFileFullName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { @@ -160,13 +165,17 @@ void FUE1Model::LoadGeometry() // populate poly groups (subdivided by texture number and type) // this method minimizes searches in the group list as much as possible // while still doing a single pass through the poly list + groups.Reset(); int curgroup = -1; UE1Group Group; + hasWeaponTriangle = false; + int weapontri = -1; for ( int i=0; i= numFrames) return FErr_NotFound; + return index; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation ) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) { // the moment of magic - if ( (frame >= numFrames) || (frame2 >= numFrames) ) return; + if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return; renderer->SetInterpolation(inter); int vsize, fsize = 0, vofs = 0; for ( int i=0; isurfaceskinIDs[ssIndex].isValid()) - sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); + int ssIndex = groups[i].texNum; + if (surfaceskinids && surfaceskinids[ssIndex].isValid()) + sskin = TexMan.GetGameTexture(surfaceskinids[ssIndex], true); if ( !sskin ) { vofs += vsize; @@ -254,7 +264,7 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f // TODO: Handle per-group render styles and other flags once functions for it are implemented // Future note: poly renderstyles should always be enforced unless the actor itself has a style other than Normal renderer->SetMaterial(sskin,false,translation); - renderer->SetupFrame(this, vofs+frame*fsize,vofs+frame2*fsize,vsize); + renderer->SetupFrame(this, vofs + frame * fsize, vofs + frame2 * fsize, vsize, {}, -1); renderer->DrawArrays(0,vsize); vofs += vsize; } @@ -265,8 +275,7 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) { if (GetVertexBuffer(renderer->GetType())) return; - if ( !mDataLoaded ) - LoadGeometry(); + LoadGeometry(); int vsize = 0; for ( int i=0; iUnlockVertexBuffer(); + UnloadGeometry(); // don't forget this, save precious RAM } -void FUE1Model::AddSkins( uint8_t *hitlist ) +void FUE1Model::AddSkins( uint8_t *hitlist, const FTextureID* surfaceskinids) { for (int i = 0; i < numGroups; i++) { - int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + int ssIndex = groups[i].texNum; + if (surfaceskinids && surfaceskinids[ssIndex].isValid()) + hitlist[surfaceskinids[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; } } FUE1Model::~FUE1Model() { - UnloadGeometry(); + groups.Reset(); } diff --git a/src/common/models/models_voxel.cpp b/src/common/models/models_voxel.cpp index 2be0521ad..f723d1fe4 100644 --- a/src/common/models/models_voxel.cpp +++ b/src/common/models/models_voxel.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -58,7 +58,7 @@ public: FVoxelTexture(FVoxel *voxel); int CopyPixels(FBitmap *bmp, int conversion) override; - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; protected: FVoxel *SourceVox; @@ -84,10 +84,10 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) // //=========================================================================== -TArray FVoxelTexture::CreatePalettedPixels(int conversion) +PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion) { // GetPixels gets called when a translated palette is used so we still need to implement it here. - TArray Pixels(256, true); + PalettedPixels Pixels(256); uint8_t *pp = SourceVox->Palette.Data(); if(pp != NULL) @@ -100,7 +100,7 @@ TArray FVoxelTexture::CreatePalettedPixels(int conversion) pe.b = (pp[2] << 2) | (pp[2] >> 4); // Alphatexture handling is just for completeness, but rather unlikely to be used ever. Pixels[i] = conversion == luminance ? pe.r : ColorMatcher.Pick(pe); - + } } else @@ -205,13 +205,12 @@ void FVoxelModel::AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3 float PivotX = mVoxel->Mips[0].Pivot.X; float PivotY = mVoxel->Mips[0].Pivot.Y; float PivotZ = mVoxel->Mips[0].Pivot.Z; - int h = mVoxel->Mips[0].SizeZ; FModelVertex vert; unsigned int indx[4]; vert.packedNormal = 0; // currently this is not being used for voxels. - vert.u = (((col & 15) * 255 / 16) + 7) / 255.f; - vert.v = (((col / 16) * 255 / 16) + 7) / 255.f; + vert.u = (((col & 15) + 0.5f) / 16.f); + vert.v = (((col / 16) + 0.5f) / 16.f); vert.x = x1 - PivotX; vert.z = -y1 + PivotY; @@ -286,8 +285,8 @@ void FVoxelModel::MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &chec } if (cull & 32) { - int z = ztop+zleng-1; - AddFace(x+1, y, z+1, x, y, z+1, x+1, y+1, z+1, x, y+1, z+1, voxptr->col[zleng-1], check); + int zz = ztop+zleng-1; + AddFace(x+1, y, zz+1, x, y, zz+1, x+1, y+1, zz+1, x, y+1, zz+1, voxptr->col[zleng-1], check); } } @@ -357,7 +356,7 @@ void FVoxelModel::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FVoxelModel::AddSkins(uint8_t *hitlist) +void FVoxelModel::AddSkins(uint8_t *hitlist, const FTextureID*) { hitlist[mPalette.GetIndex()] |= FTextureManager::HIT_Flat; } @@ -379,9 +378,9 @@ bool FVoxelModel::Load(const char * fn, int lumpnum, const char * buffer, int le // //=========================================================================== -int FVoxelModel::FindFrame(const char * name) +int FVoxelModel::FindFrame(const char* name, bool nodefault) { - return 0; + return nodefault ? FErr_Voxel : 0; // -2, not -1 because voxels are special. } //=========================================================================== @@ -401,10 +400,9 @@ float FVoxelModel::getAspectFactor(float stretch) // //=========================================================================== -void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*, const TArray& boneData, int boneStartPosition) { renderer->SetMaterial(skin, true, translation); - renderer->SetupFrame(this, 0, 0, 0); + renderer->SetupFrame(this, 0, 0, 0, {}, -1); renderer->DrawElements(mNumIndices, 0); } - diff --git a/src/common/models/voxels.cpp b/src/common/models/voxels.cpp index 12c070b0d..d8d2b2245 100644 --- a/src/common/models/voxels.cpp +++ b/src/common/models/voxels.cpp @@ -314,10 +314,11 @@ FVoxelDef *R_LoadVoxelDef(int lumpnum, int spin) else { FVoxelDef *voxdef = new FVoxelDef; + *voxdef = {}; voxdef->Voxel = vox; voxdef->Scale = 1.; voxdef->DroppedSpin = voxdef->PlacedSpin = spin; - voxdef->AngleOffset = 90.; + voxdef->AngleOffset = DAngle::fromDeg(90.); Voxels.Push(vox); VoxelDefs.Push(voxdef); diff --git a/src/common/models/voxels.h b/src/common/models/voxels.h index b4a1cdfcd..52299434a 100644 --- a/src/common/models/voxels.h +++ b/src/common/models/voxels.h @@ -4,7 +4,10 @@ #include // [RH] Voxels from Build -#define MAXVOXMIPS 5 +enum +{ + MAXVOXMIPS = 5, +}; struct kvxslab_t { @@ -70,6 +73,9 @@ struct FVoxelDef int VoxeldefIndex; // Needed by GZDoom double Scale; DAngle AngleOffset;// added to actor's angle to compensate for wrong-facing voxels + bool PitchFromMomentum; + bool UseActorPitch; + bool UseActorRoll; }; extern TDeletingArray Voxels; // used only to auto-delete voxels on exit. diff --git a/src/common/objects/autosegs.cpp b/src/common/objects/autosegs.cpp index 4d5bdba74..11fce1005 100644 --- a/src/common/objects/autosegs.cpp +++ b/src/common/objects/autosegs.cpp @@ -74,6 +74,7 @@ AUTOSEG_VARIABLE(TypeInfos, AUTOSEG_CREG) AUTOSEG_VARIABLE(ClassFields, AUTOSEG_FREG) AUTOSEG_VARIABLE(Properties, AUTOSEG_GREG) AUTOSEG_VARIABLE(MapInfoOptions, AUTOSEG_YREG) +AUTOSEG_VARIABLE(CVarDecl, AUTOSEG_VREG) #undef AUTOSEG_VARIABLE #undef AUTOSEG_STOP diff --git a/src/common/objects/autosegs.h b/src/common/objects/autosegs.h index df996d2f0..838553dd4 100644 --- a/src/common/objects/autosegs.h +++ b/src/common/objects/autosegs.h @@ -47,6 +47,12 @@ #define NO_SANITIZE #endif +#if defined _MSC_VER +#define NO_SANITIZE_M __declspec(no_sanitize_address) +#else +#define NO_SANITIZE_M +#endif + class FAutoSeg { const char *name; @@ -102,14 +108,14 @@ public: } template - void ForEach(Func func, std::enable_if_t> * = nullptr) + void NO_SANITIZE_M ForEach(Func func, std::enable_if_t> * = nullptr) { using CallableType = decltype(&Func::operator()); using ArgType = typename ArgumentType::Type; for (void **it = begin; it < end; ++it) { - if (*it) + if (intptr_t(it) > 0xffff && *it && intptr_t(*it) > 0xffff) { func(reinterpret_cast(*it)); } @@ -117,14 +123,14 @@ public: } template - void ForEach(Func func, std::enable_if_t> * = nullptr) + void NO_SANITIZE_M ForEach(Func func, std::enable_if_t> * = nullptr) { using CallableType = decltype(&Func::operator()); using ArgType = typename ArgumentType::Type; for (void **it = begin; it < end; ++it) { - if (*it) + if (intptr_t(it) > 0xffff && *it && intptr_t(*it) > 0xffff) { if (!func(reinterpret_cast(*it))) { @@ -142,6 +148,7 @@ namespace AutoSegs extern FAutoSeg ClassFields; extern FAutoSeg Properties; extern FAutoSeg MapInfoOptions; + extern FAutoSeg CVarDecl; } #define AUTOSEG_AREG areg @@ -149,6 +156,7 @@ namespace AutoSegs #define AUTOSEG_FREG freg #define AUTOSEG_GREG greg #define AUTOSEG_YREG yreg +#define AUTOSEG_VREG vreg #define AUTOSEG_STR(string) AUTOSEG_STR2(string) #define AUTOSEG_STR2(string) #string @@ -161,12 +169,14 @@ namespace AutoSegs #define SECTION_FREG AUTOSEG_MACH_SECTION(AUTOSEG_FREG) #define SECTION_GREG AUTOSEG_MACH_SECTION(AUTOSEG_GREG) #define SECTION_YREG AUTOSEG_MACH_SECTION(AUTOSEG_YREG) +#define SECTION_VREG AUTOSEG_MACH_SECTION(AUTOSEG_VREG) #else #define SECTION_AREG AUTOSEG_STR(AUTOSEG_AREG) #define SECTION_CREG AUTOSEG_STR(AUTOSEG_CREG) #define SECTION_FREG AUTOSEG_STR(AUTOSEG_FREG) #define SECTION_GREG AUTOSEG_STR(AUTOSEG_GREG) #define SECTION_YREG AUTOSEG_STR(AUTOSEG_YREG) +#define SECTION_VREG AUTOSEG_STR(AUTOSEG_VREG) #endif #endif diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index 8516229de..ba4f0a0f1 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -42,6 +42,7 @@ #include "types.h" #include "i_time.h" #include "printf.h" +#include "maps.h" //========================================================================== // @@ -229,7 +230,6 @@ DObject::DObject () ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; - GC::AllocCount++; } DObject::DObject (PClass *inClass) @@ -239,7 +239,6 @@ DObject::DObject (PClass *inClass) ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; - GC::AllocCount++; } //========================================================================== @@ -267,7 +266,7 @@ DObject::~DObject () Release(); } } - + if (nullptr != type) { type->DestroySpecials(this); @@ -277,7 +276,6 @@ DObject::~DObject () void DObject::Release() { - if (GC::AllocCount > 0) GC::AllocCount--; DObject **probe; // Unlink this object from the GC list. @@ -345,6 +343,17 @@ DEFINE_ACTION_FUNCTION(DObject, Destroy) // //========================================================================== +template +static void PropagateMarkMap(M *map) +{ + TMapIterator it(*map); + typename M::Pair * p; + while(it.NextPair(p)) + { + GC::Mark(&p->Value); + } +} + size_t DObject::PropagateMark() { const PClass *info = GetClass(); @@ -378,6 +387,27 @@ size_t DObject::PropagateMark() offsets++; } + { + const std::pair *maps = info->MapPointers; + if (maps == NULL) + { + const_cast(info)->BuildMapPointers(); + maps = info->MapPointers; + } + 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++; + } + + } return info->Size; } return 0; @@ -496,6 +526,11 @@ DEFINE_ACTION_FUNCTION(DObject, MSTime) ACTION_RETURN_INT((uint32_t)I_msTime()); } +DEFINE_ACTION_FUNCTION_NATIVE(DObject, MSTimef, I_msTimeF) +{ + ACTION_RETURN_FLOAT(I_msTimeF()); +} + void *DObject::ScriptVar(FName field, PType *type) { auto cls = GetClass(); @@ -513,5 +548,4 @@ void *DObject::ScriptVar(FName field, PType *type) } // This is only for internal use so I_Error is fine. I_Error("Variable %s not found in %s\n", field.GetChars(), cls->TypeName.GetChars()); - return nullptr; } diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index 58b27c4b7..9baffc3a3 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -3,7 +3,7 @@ ** The garbage collector. Based largely on Lua's. ** **--------------------------------------------------------------------------- -** Copyright 2008 Randy Heit +** Copyright 2008-2022 Marisa Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -57,7 +57,7 @@ // HEADER FILES ------------------------------------------------------------ #include "dobject.h" -#include "templates.h" + #include "c_dispatch.h" #include "menu.h" #include "stats.h" @@ -82,23 +82,66 @@ ** infinity, where each step performs a full collection.) You can also ** change this value dynamically. */ -#define DEFAULT_GCMUL 400 // GC runs 'quadruple the speed' of memory allocation +#ifndef _DEBUG +#define DEFAULT_GCMUL 600 // GC runs gcmul% the speed of memory allocation +#else +// Higher in debug builds to account for the extra time spent freeing objects +#define DEFAULT_GCMUL 800 +#endif -// Number of sectors to mark for each step. +// Minimum step size +#define GCMINSTEPSIZE (sizeof(DObject) * 16) -#define GCSTEPSIZE 1024u -#define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 +// Sweeps traverse objects in chunks of this size +#define GCSWEEPGRANULARITY 40 + +// Cost of deleting an object +#ifndef _DEBUG +#define GCDELETECOST 75 +#else +// Freeing memory is much more costly in debug builds +#define GCDELETECOST 230 +#endif + +// Cost of destroying an object +#define GCDESTROYCOST 15 // TYPES ------------------------------------------------------------------- +class FAveragizer +{ + // Number of allocations to track + static inline constexpr unsigned HistorySize = 512; + + size_t History[HistorySize]; + size_t TotalAmount; + int TotalCount; + unsigned NewestPos; + +public: + FAveragizer(); + void AddAlloc(size_t alloc); + size_t GetAverage(); +}; + +struct FStepStats +{ + cycle_t Clock[GC::GCS_COUNT]; + size_t BytesCovered[GC::GCS_COUNT]; + int Count[GC::GCS_COUNT]; + + void Format(FString &out); + void Reset(); +}; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static size_t CalcStepSize(); + // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -106,25 +149,50 @@ namespace GC { size_t AllocBytes; +size_t RunningAllocBytes; +size_t RunningDeallocBytes; size_t Threshold; size_t Estimate; -size_t AllocCount; DObject *Gray; DObject *Root; DObject *SoftRoots; DObject **SweepPos; +DObject *ToDestroy; uint32_t CurrentWhite = OF_White0 | OF_Fixed; EGCState State = GCS_Pause; int Pause = DEFAULT_GCPAUSE; int StepMul = DEFAULT_GCMUL; -int StepCount; -size_t Dept; +FStepStats StepStats; +FStepStats PrevStepStats; bool FinalGC; +bool HadToDestroy; // PRIVATE DATA DEFINITIONS ------------------------------------------------ +static FAveragizer AllocHistory;// Tracks allocation rate over time +static cycle_t GCTime; // Track time spent in GC + // CODE -------------------------------------------------------------------- +//========================================================================== +// +// CheckGC +// +// Check if it's time to collect, and do a collection step if it is. +// Also does some bookkeeping. Should be called fairly consistantly. +// +//========================================================================== + +void CheckGC() +{ + AllocHistory.AddAlloc(RunningAllocBytes); + RunningAllocBytes = 0; + if (State > GCS_Pause || AllocBytes >= Threshold) + { + Step(); + } +} + //========================================================================== // // SetThreshold @@ -135,7 +203,7 @@ bool FinalGC; void SetThreshold() { - Threshold = (Estimate / 100) * Pause; + Threshold = (std::min(Estimate, AllocBytes) / 100) * Pause; } //========================================================================== @@ -159,55 +227,72 @@ size_t PropagateMark() //========================================================================== // -// SweepList +// SweepObjects // -// Runs a limited sweep on a list, returning the location where to resume -// the sweep at next time. (FIXME: Horrible Engrish in this description.) +// Runs a limited sweep on the object list, returning the number of bytes +// swept. // //========================================================================== -static DObject **SweepList(DObject **p, size_t count, size_t *finalize_count) +static size_t SweepObjects(size_t count) { DObject *curr; int deadmask = OtherWhite(); - size_t finalized = 0; + size_t swept = 0; - while ((curr = *p) != NULL && count-- > 0) + while ((curr = *SweepPos) != nullptr && count-- > 0) { + swept += curr->GetClass()->Size; if ((curr->ObjectFlags ^ OF_WhiteBits) & deadmask) // not dead? { assert(!curr->IsDead() || (curr->ObjectFlags & OF_Fixed)); curr->MakeWhite(); // make it white (for next cycle) - p = &curr->ObjNext; + SweepPos = &curr->ObjNext; } - else // must erase 'curr' + else { assert(curr->IsDead()); - *p = curr->ObjNext; if (!(curr->ObjectFlags & OF_EuthanizeMe)) - { // The object must be destroyed before it can be finalized. - // Note that thinkers must already have been destroyed. If they get here without - // having been destroyed first, it means they somehow became unattached from the - // thinker lists. If I don't maintain the invariant that all live thinkers must - // be in a thinker list, then I need to add write barriers for every time a - // thinker pointer is changed. This seems easier and perfectly reasonable, since - // a live thinker that isn't on a thinker list isn't much of a thinker. - - // However, this can happen during deletion of the thinker list while cleaning up - // from a savegame error so we can't assume that any thinker that gets here is an error. - - curr->Destroy(); + { // The object must be destroyed before it can be deleted. + curr->GCNext = ToDestroy; + ToDestroy = curr; + SweepPos = &curr->ObjNext; + } + else + { // must erase 'curr' + *SweepPos = curr->ObjNext; + curr->ObjectFlags |= OF_Cleanup; + delete curr; + swept += GCDELETECOST; } - curr->ObjectFlags |= OF_Cleanup; - delete curr; - finalized++; } } - if (finalize_count != NULL) + return swept; +} + +//========================================================================== +// +// DestroyObjects +// +// Destroys up to count objects on a list linked on GCNext, returning the +// size of objects destroyed, for updating the estimate. +// +//========================================================================== + +static size_t DestroyObjects(size_t count) +{ + DObject *curr; + size_t bytes_destroyed = 0; + + while ((curr = ToDestroy) != nullptr && count-- > 0) { - *finalize_count = finalized; + assert(!(curr->ObjectFlags & OF_EuthanizeMe)); + bytes_destroyed += curr->GetClass()->Size + GCDESTROYCOST; + ToDestroy = curr->GCNext; + curr->GCNext = nullptr; + curr->Destroy(); } - return p; + return bytes_destroyed; } //========================================================================== @@ -254,6 +339,20 @@ void MarkArray(DObject **obj, size_t count) } } +//========================================================================== +// +// CalcStepSize +// +// Decide how big a step should be, based on the current allocation rate. +// +//========================================================================== + +static size_t CalcStepSize() +{ + size_t avg = AllocHistory.GetAverage(); + return std::max(GCMINSTEPSIZE, avg * StepMul / 100); +} + //========================================================================== // // MarkRoot @@ -271,15 +370,18 @@ void AddMarkerFunc(GCMarkerFunc func) static void MarkRoot() { - Gray = NULL; + PrevStepStats = StepStats; + StepStats.Reset(); + + Gray = nullptr; for (auto func : markers) func(); // Mark soft roots. - if (SoftRoots != NULL) + if (SoftRoots != nullptr) { DObject **probe = &SoftRoots->ObjNext; - while (*probe != NULL) + while (*probe != nullptr) { DObject *soft = *probe; probe = &soft->ObjNext; @@ -291,7 +393,6 @@ static void MarkRoot() } // Time to propagate the marks. State = GCS_Propagate; - StepCount = 0; } //========================================================================== @@ -312,6 +413,21 @@ static void Atomic() Estimate = AllocBytes; } +//========================================================================== +// +// SweepDone +// +// Sets up the Destroy phase, if there are any dead objects that haven't +// been destroyed yet, or skips to the Done state. +// +//========================================================================== + +static void SweepDone() +{ + HadToDestroy = ToDestroy != nullptr; + State = HadToDestroy ? GCS_Destroy : GCS_Done; +} + //========================================================================== // // SingleStep @@ -329,7 +445,7 @@ static size_t SingleStep() return 0; case GCS_Propagate: - if (Gray != NULL) + if (Gray != nullptr) { return PropagateMark(); } @@ -340,21 +456,30 @@ static size_t SingleStep() } case GCS_Sweep: { - size_t old = AllocBytes; - size_t finalize_count; - SweepPos = SweepList(SweepPos, GCSWEEPMAX, &finalize_count); - if (*SweepPos == NULL) + RunningDeallocBytes = 0; + size_t swept = SweepObjects(GCSWEEPGRANULARITY); + Estimate -= RunningDeallocBytes; + if (*SweepPos == nullptr) { // Nothing more to sweep? - State = GCS_Finalize; + SweepDone(); } - //assert(old >= AllocBytes); - Estimate -= MAX(0, old - AllocBytes); - return (GCSWEEPMAX - finalize_count) * GCSWEEPCOST + finalize_count * GCFINALIZECOST; + return swept; } - case GCS_Finalize: + case GCS_Destroy: { + size_t destroy_size; + destroy_size = DestroyObjects(GCSWEEPGRANULARITY); + Estimate -= destroy_size; + if (ToDestroy == nullptr) + { // Nothing more to destroy? + State = GCS_Done; + } + return destroy_size; + } + + case GCS_Done: State = GCS_Pause; // end collection - Dept = 0; + SetThreshold(); return 0; default: @@ -367,43 +492,52 @@ static size_t SingleStep() // // Step // -// Performs enough single steps to cover GCSTEPSIZE * StepMul% bytes of -// memory. +// Performs enough single steps to cover bytes of memory. +// Some of those bytes might be "fake" to account for the cost of freeing +// or destroying object. // //========================================================================== void Step() { - size_t lim = (GCSTEPSIZE/100) * StepMul; - size_t olim; - if (lim == 0) - { - lim = (~(size_t)0) / 2; // no limit - } - Dept += AllocBytes - Threshold; + GCTime.ResetAndClock(); + + auto enter_state = State; + StepStats.Count[enter_state]++; + StepStats.Clock[enter_state].Clock(); + + size_t did = 0; + size_t lim = CalcStepSize(); + do { - olim = lim; - lim -= SingleStep(); - } while (olim > lim && State != GCS_Pause); - if (State != GCS_Pause) - { - if (Dept < GCSTEPSIZE) + size_t done = SingleStep(); + did += done; + if (done < lim) { - Threshold = AllocBytes + GCSTEPSIZE; // - lim/StepMul + lim -= done; } else { - Dept -= GCSTEPSIZE; - Threshold = AllocBytes; + lim = 0; } - } - else - { - assert(AllocBytes >= Estimate); - SetThreshold(); - } - StepCount++; + if (State != enter_state) + { + // Finish stats on old state + StepStats.Clock[enter_state].Unclock(); + StepStats.BytesCovered[enter_state] += did; + + // Start stats on new state + did = 0; + enter_state = State; + StepStats.Clock[enter_state].Clock(); + StepStats.Count[enter_state]++; + } + } while (lim && State != GCS_Pause); + + StepStats.Clock[enter_state].Unclock(); + StepStats.BytesCovered[enter_state] += did; + GCTime.Unclock(); } //========================================================================== @@ -416,25 +550,34 @@ void Step() void FullGC() { - if (State <= GCS_Propagate) + bool ContinueCheck = true; + while (ContinueCheck) { - // Reset sweep mark to sweep all elements (returning them to white) - SweepPos = &Root; - // Reset other collector lists - Gray = NULL; - State = GCS_Sweep; + ContinueCheck = false; + if (State <= GCS_Propagate) + { + // Reset sweep mark to sweep all elements (returning them to white) + SweepPos = &Root; + // Reset other collector lists + Gray = nullptr; + State = GCS_Sweep; + } + // Finish any pending GC stages + while (State != GCS_Pause) + { + SingleStep(); + } + // Loop until everything that can be destroyed and freed is + do + { + MarkRoot(); + while (State != GCS_Pause) + { + SingleStep(); + } + ContinueCheck |= HadToDestroy; + } while (HadToDestroy); } - // Finish any pending sweep phase - while (State != GCS_Finalize) - { - SingleStep(); - } - MarkRoot(); - while (State != GCS_Pause) - { - SingleStep(); - } - SetThreshold(); } //========================================================================== @@ -448,9 +591,9 @@ void FullGC() void Barrier(DObject *pointing, DObject *pointed) { - assert(pointing == NULL || (pointing->IsBlack() && !pointing->IsDead())); + assert(pointing == nullptr || (pointing->IsBlack() && !pointing->IsDead())); assert(pointed->IsWhite() && !pointed->IsDead()); - assert(State != GCS_Finalize && State != GCS_Pause); + assert(State != GCS_Destroy && State != GCS_Pause); assert(!(pointed->ObjectFlags & OF_Released)); // if a released object gets here, something must be wrong. if (pointed->ObjectFlags & OF_Released) return; // don't do anything with non-GC'd objects. // The invariant only needs to be maintained in the propagate state. @@ -462,7 +605,7 @@ void Barrier(DObject *pointing, DObject *pointed) } // In other states, we can mark the pointing object white so this // barrier won't be triggered again, saving a few cycles in the future. - else if (pointing != NULL) + else if (pointing != nullptr) { pointing->MakeWhite(); } @@ -470,13 +613,13 @@ void Barrier(DObject *pointing, DObject *pointed) void DelSoftRootHead() { - if (SoftRoots != NULL) + if (SoftRoots != nullptr) { // Don't let the destructor print a warning message SoftRoots->ObjectFlags |= OF_YesReallyDelete; delete SoftRoots; } - SoftRoots = NULL; + SoftRoots = nullptr; } //========================================================================== @@ -493,7 +636,7 @@ void AddSoftRoot(DObject *obj) DObject **probe; // Are there any soft roots yet? - if (SoftRoots == NULL) + if (SoftRoots == nullptr) { // Create a new object to root the soft roots off of, and stick // it at the end of the object list, so we know that anything @@ -501,17 +644,17 @@ void AddSoftRoot(DObject *obj) SoftRoots = Create(); SoftRoots->ObjectFlags |= OF_Fixed; probe = &Root; - while (*probe != NULL) + while (*probe != nullptr) { probe = &(*probe)->ObjNext; } Root = SoftRoots->ObjNext; - SoftRoots->ObjNext = NULL; + SoftRoots->ObjNext = nullptr; *probe = SoftRoots; } // Mark this object as rooted and move it after the SoftRoots marker. probe = &Root; - while (*probe != NULL && *probe != obj) + while (*probe != nullptr && *probe != obj) { probe = &(*probe)->ObjNext; } @@ -534,14 +677,14 @@ void DelSoftRoot(DObject *obj) { DObject **probe; - if (!(obj->ObjectFlags & OF_Rooted)) + if (obj == nullptr || !(obj->ObjectFlags & OF_Rooted)) { // Not rooted, so nothing to do. return; } obj->ObjectFlags &= ~OF_Rooted; // Move object out of the soft roots part of the list. probe = &SoftRoots; - while (*probe != NULL && *probe != obj) + while (*probe != nullptr && *probe != obj) { probe = &(*probe)->ObjNext; } @@ -555,6 +698,52 @@ void DelSoftRoot(DObject *obj) } +//========================================================================== +// +// FAveragizer - Constructor +// +//========================================================================== + +FAveragizer::FAveragizer() +{ + NewestPos = 0; + TotalAmount = 0; + TotalCount = 0; + memset(History, 0, sizeof(History)); +} + +//========================================================================== +// +// FAveragizer :: AddAlloc +// +//========================================================================== + +void FAveragizer::AddAlloc(size_t alloc) +{ + NewestPos = (NewestPos + 1) & (HistorySize - 1); + if (TotalCount < HistorySize) + { + TotalCount++; + } + else + { + TotalAmount -= History[NewestPos]; + } + History[NewestPos] = alloc; + TotalAmount += alloc; +} + +//========================================================================== +// +// FAveragizer :: GetAverage +// +//========================================================================== + +size_t FAveragizer::GetAverage() +{ + return TotalCount != 0 ? TotalAmount / TotalCount : 0; +} + //========================================================================== // // STAT gc @@ -569,21 +758,66 @@ ADD_STAT(gc) " Pause ", "Propagate", " Sweep ", - "Finalize " }; + " Destroy ", + " Done " + }; FString out; - out.Format("[%s] Alloc:%6zuK Thresh:%6zuK Est:%6zuK Steps: %d", + double time = GC::State != GC::GCS_Pause ? GC::GCTime.TimeMS() : 0; + + GC::PrevStepStats.Format(out); + out << "\n"; + GC::StepStats.Format(out); + out.AppendFormat("\n%.2fms [%s] Rate:%3zuK (%3zuK) Alloc:%6zuK Est:%6zuK Thresh:%6zuK", + time, StateStrings[GC::State], + (GC::AllocHistory.GetAverage() + 1023) >> 10, + (GC::CalcStepSize() + 1023) >> 10, (GC::AllocBytes + 1023) >> 10, - (GC::Threshold + 1023) >> 10, (GC::Estimate + 1023) >> 10, - GC::StepCount); - if (GC::State != GC::GCS_Pause) - { - out.AppendFormat(" %zuK", (GC::Dept + 1023) >> 10); - } + (GC::Threshold + 1023) >> 10); return out; } +//========================================================================== +// +// FStepStats :: Reset +// +//========================================================================== + +void FStepStats::Reset() +{ + for (unsigned i = 0; i < countof(Count); ++i) + { + Count[i] = 0; + BytesCovered[i] = 0; + Clock[i].Reset(); + } +} + +//========================================================================== +// +// FStepStats :: Format +// +// Appends its stats to the given FString. +// +//========================================================================== + +void FStepStats::Format(FString &out) +{ + // Because everything in the default green is hard to distinguish, + // each stage has its own color. + for (int i = GC::GCS_Propagate; i < GC::GCS_Done; ++i) + { + int count = Count[i]; + double time = Clock[i].TimeMS(); + out.AppendFormat(TEXTCOLOR_ESCAPESTR "%c[%c%6zuK %4d*%.2fms]", + "-NKB"[i], /* Color codes */ + "-PSD"[i], /* Stage prefixes: (P)ropagate, (S)weep, (D)estroy */ + (BytesCovered[i] + 1023) >> 10, count, count != 0 ? time / count : time); + } + out << TEXTCOLOR_GREEN; +} + //========================================================================== // // CCMD gc @@ -625,7 +859,7 @@ CCMD(gc) } else { - GC::Pause = MAX(1,atoi(argv[2])); + GC::Pause = max(1,atoi(argv[2])); } } else if (stricmp(argv[1], "stepmul") == 0) @@ -636,7 +870,7 @@ CCMD(gc) } else { - GC::StepMul = MAX(100, atoi(argv[2])); + GC::StepMul = max(100, atoi(argv[2])); } } } diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index d01e52cf6..a844a16db 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -37,14 +37,20 @@ namespace GC GCS_Pause, GCS_Propagate, GCS_Sweep, - GCS_Finalize + GCS_Destroy, + GCS_Done, + + GCS_COUNT }; // Number of bytes currently allocated through M_Malloc/M_Realloc. extern size_t AllocBytes; - // Number of allocated objects since last CheckGC call. - extern size_t AllocCount; + // Number of bytes allocated since last collection step. + extern size_t RunningAllocBytes; + + // Number of bytes freed since last collection step. + extern size_t RunningDeallocBytes; // Amount of memory to allocate before triggering a collection. extern size_t Threshold; @@ -79,9 +85,6 @@ namespace GC return CurrentWhite ^ OF_WhiteBits; } - // Frees all objects, whether they're dead or not. - void FreeAll(); - // Does one collection step. void Step(); @@ -107,18 +110,19 @@ namespace GC return obj = NULL; } - // Check if it's time to collect, and do a collection step if it is. - static inline bool CheckGC() + // Handles a read barrier for a const pointer. This does not alter the source data, but only returns NULL if the object is destroyed. + template inline T* ReadBarrier(const T*& obj) { - AllocCount = 0; - if (AllocBytes >= Threshold) + if (obj == NULL || !(obj->ObjectFlags & OF_EuthanizeMe)) { - Step(); - return true; + return obj; } - return false; + return NULL; } + // Check if it's time to collect, and do a collection step if it is. + void CheckGC(); + // Forces a collection to start now. static inline void StartCollection() { @@ -158,6 +162,10 @@ namespace GC { MarkArray((DObject **)(obj), count); } + template void MarkArray(TObjPtr* obj, size_t count) + { + MarkArray((DObject**)(obj), count); + } template void MarkArray(TArray &arr) { MarkArray(&arr[0], arr.Size()); @@ -166,6 +174,32 @@ namespace GC using GCMarkerFunc = void(*)(); void AddMarkerFunc(GCMarkerFunc func); + // Report an allocation to the GC + static inline void ReportAlloc(size_t alloc) + { + AllocBytes += alloc; + RunningAllocBytes += alloc; + } + + // Report a deallocation to the GC + static inline void ReportDealloc(size_t dealloc) + { + AllocBytes -= dealloc; + RunningDeallocBytes += dealloc; + } + + // Report a reallocation to the GC + static inline void ReportRealloc(size_t oldsize, size_t newsize) + { + if (oldsize < newsize) + { + ReportAlloc(newsize - oldsize); + } + else + { + ReportDealloc(oldsize - newsize); + } + } } // A template class to help with handling read barriers. It does not @@ -180,27 +214,21 @@ class TObjPtr DObject *o; }; public: - TObjPtr() = default; - TObjPtr(const TObjPtr &q) = default; - TObjPtr(T q) noexcept - : pp(q) - { - } - T operator=(T q) + constexpr TObjPtr& operator=(T q) noexcept { pp = q; return *this; } - T operator=(std::nullptr_t nul) + constexpr TObjPtr& operator=(std::nullptr_t nul) noexcept { o = nullptr; return *this; } // To allow NULL, too. - T operator=(const int val) + TObjPtr& operator=(const int val) noexcept { assert(val == 0); o = nullptr; @@ -208,42 +236,48 @@ public: } // To allow NULL, too. In Clang NULL is a long. - T operator=(const long val) + TObjPtr& operator=(const long val) noexcept { assert(val == 0); o = nullptr; return *this; } - T Get() noexcept + constexpr T Get() noexcept { return GC::ReadBarrier(pp); } - T ForceGet() noexcept //for situations where the read barrier needs to be skipped. + constexpr T Get() const noexcept + { + auto ppp = pp; + return GC::ReadBarrier(ppp); + } + + constexpr T ForceGet() const noexcept //for situations where the read barrier needs to be skipped. { return pp; } - operator T() noexcept + constexpr operator T() noexcept { return GC::ReadBarrier(pp); } - T &operator*() noexcept + constexpr T &operator*() noexcept { T q = GC::ReadBarrier(pp); assert(q != NULL); return *q; } - T operator->() noexcept + constexpr T operator->() noexcept { return GC::ReadBarrier(pp); } - bool operator!=(T u) noexcept + constexpr bool operator!=(T u) noexcept { return GC::ReadBarrier(o) != u; } - bool operator==(T u) noexcept + constexpr bool operator==(T u) noexcept { return GC::ReadBarrier(o) == u; } @@ -255,6 +289,17 @@ public: friend class DObject; }; +// This is only needed because some parts of GCC do not treat a class with any constructor as trivial. +// TObjPtr needs to be fully trivial, though - some parts in the engine depend on it. +template +constexpr TObjPtr MakeObjPtr(T t) noexcept +{ + // since this exists to replace the constructor we cannot initialize in the declaration as this would require the constructor we want to avoid. + TObjPtr tt; + tt = t; + return tt; +} + // Use barrier_cast instead of static_cast when you need to cast // the contents of a TObjPtr to a related type. template inline T barrier_cast(TObjPtr &o) diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index b74820ed4..b39c930f8 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -82,6 +82,8 @@ DEFINE_GLOBAL(WP_NOCHANGE); // 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}; + //========================================================================== // // PClass :: WriteValue @@ -187,7 +189,7 @@ bool PClass::ReadAllFields(FSerializer &ar, void *addr) const // //========================================================================== -static int cregcmp (const void *a, const void *b) NO_SANITIZE +static NO_SANITIZE_M int cregcmp (const void *a, const void *b) NO_SANITIZE { const PClass *class1 = *(const PClass **)a; const PClass *class2 = *(const PClass **)b; @@ -250,6 +252,7 @@ void PClass::StaticShutdown () // Make a full garbage collection here so that all destroyed but uncollected higher level objects // that still exist are properly taken down before the low level data is deleted. GC::FullGC(); + GC::FullGC(); Namespaces.ReleaseSymbols(); @@ -528,7 +531,7 @@ void PClass::Derive(PClass *newclass, FName name) // //========================================================================== -PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycreated) +PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycreated, int fileno) { assert(size >= Size); PClass *type; @@ -568,7 +571,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycre type->Size = size; if (size != TentativeClass) { - NewClassType(type); + NewClassType(type, fileno); if (newlycreated) *newlycreated = true; type->Virtuals = Virtuals; } @@ -588,13 +591,13 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycre // //========================================================================== -PField *PClass::AddField(FName name, PType *type, uint32_t flags) +PField *PClass::AddField(FName name, PType *type, uint32_t flags, int fileno) { PField *field; if (!(flags & VARF_Meta)) { unsigned oldsize = Size; - field = VMType->Symbols.AddField(name, type, flags, Size); + field = VMType->Symbols.AddField(name, type, flags, Size, nullptr, fileno); // Only initialize the defaults if they have already been created. // For ZScript this is not the case, it will first define all fields before @@ -609,7 +612,7 @@ PField *PClass::AddField(FName name, PType *type, uint32_t flags) { // Same as above, but a different data storage. unsigned oldsize = MetaSize; - field = VMType->Symbols.AddField(name, type, flags, MetaSize); + field = VMType->Symbols.AddField(name, type, flags, MetaSize, nullptr, fileno); if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) { @@ -877,6 +880,68 @@ void PClass::BuildArrayPointers() } } +//========================================================================== +// +// PClass :: BuildMapPointers +// +// same as above, but creates a list to dynamic object arrays +// +//========================================================================== + +void PClass::BuildMapPointers() +{ + 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; + } + else + { + ParentClass->BuildMapPointers(); + + TArray> ScriptPointers; + + // Collect all arrays to pointers in scripted fields. + for (auto field : Fields) + { + if (!(field->Flags & VARF_Native)) + { + field->Type->SetPointerMap(Defaults, unsigned(field->Offset), &ScriptPointers); + } + } + + if (ScriptPointers.Size() == 0) + { // No new pointers: Just use the same ArrayPointers as the parent. + MapPointers = ParentClass->MapPointers; + } + 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++) + { + } + + // Concatenate them into a new array + std::pair *flat = (std::pair*)ClassDataAllocator.Alloc(sizeof(std::pair) * (numSuperPointers + ScriptPointers.Size() + 1)); + if (numSuperPointers > 0) + { + memcpy(flat, ParentClass->MapPointers, sizeof(std::pair)*numSuperPointers); + } + if (ScriptPointers.Size() > 0) + { + memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(std::pair) * ScriptPointers.Size()); + } + flat[numSuperPointers + ScriptPointers.Size()] = TheMapEnd; + MapPointers = flat; + } + } +} + //========================================================================== // // PClass :: NativeClass diff --git a/src/common/objects/dobjtype.h b/src/common/objects/dobjtype.h index f7996d89d..c8464a030 100644 --- a/src/common/objects/dobjtype.h +++ b/src/common/objects/dobjtype.h @@ -45,7 +45,7 @@ public: bool ReadAllFields(FSerializer &ar, void *addr) const; int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType); PSymbol *FindSymbol(FName symname, bool searchparents) const; - PField *AddField(FName name, PType *type, uint32_t flags); + PField *AddField(FName name, PType *type, uint32_t flags, int fileno = 0); void InitializeDefaults(); static void StaticInit(); @@ -56,6 +56,7 @@ public: 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. uint8_t *Defaults = nullptr; uint8_t *Meta = nullptr; // Per-class static script data unsigned Size = sizeof(DObject); @@ -79,11 +80,12 @@ public: ~PClass(); void InsertIntoHash(bool native); DObject *CreateNew(); - PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr); + PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0); void InitializeActorInfo(); void BuildFlatPointers(); void BuildArrayPointers(); + void BuildMapPointers(); void DestroySpecials(void *addr); void DestroyMeta(void *addr); const PClass *NativeClass() const; diff --git a/src/common/platform/posix/cocoa/i_input.mm b/src/common/platform/posix/cocoa/i_input.mm index c329da3b9..46b380431 100644 --- a/src/common/platform/posix/cocoa/i_input.mm +++ b/src/common/platform/posix/cocoa/i_input.mm @@ -55,8 +55,7 @@ CVAR(Bool, use_mouse, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -extern int paused, chatmodeon; -extern constate_e ConsoleState; +extern int paused; extern bool ToggleFullscreen; bool GUICapture; @@ -429,7 +428,7 @@ void ProcessKeyboardEventInMenu(NSEvent* theEvent) event.subtype = EV_GUI_Char; event.data1 = realchar; event.data2 = event.data3 & GKM_ALT; - + D_PostEvent(&event); } } @@ -644,7 +643,7 @@ void ProcessMouseButtonEvent(NSEvent* theEvent) break; } - event.data1 = MIN(KEY_MOUSE1 + [theEvent buttonNumber], NSInteger(KEY_MOUSE8)); + event.data1 = min(KEY_MOUSE1 + [theEvent buttonNumber], NSInteger(KEY_MOUSE8)); D_PostEvent(&event); } @@ -667,9 +666,9 @@ void ProcessMouseWheelEvent(NSEvent* theEvent) { return; } - + event_t event = {}; - + if (GUICapture) { event.type = EV_GUI_Event; @@ -681,7 +680,7 @@ void ProcessMouseWheelEvent(NSEvent* theEvent) event.type = isZeroDelta ? EV_KeyUp : EV_KeyDown; event.data1 = delta > 0.0f ? KEY_MWHEELUP : KEY_MWHEELDOWN; } - + D_PostEvent(&event); } diff --git a/src/common/platform/posix/cocoa/i_joystick.cpp b/src/common/platform/posix/cocoa/i_joystick.cpp index 9a003acac..733380366 100644 --- a/src/common/platform/posix/cocoa/i_joystick.cpp +++ b/src/common/platform/posix/cocoa/i_joystick.cpp @@ -39,7 +39,7 @@ #include "i_system.h" #include "m_argv.h" #include "m_joy.h" -#include "templates.h" + #include "v_text.h" #include "printf.h" #include "keydef.h" @@ -1127,7 +1127,7 @@ void IOKitJoystickManager::AddDevices(const IONotificationPortRef notificationPo } IOObjectRelease(device); - + PostDeviceChangeEvent(); } } diff --git a/src/common/platform/posix/cocoa/i_main.mm b/src/common/platform/posix/cocoa/i_main.mm index 727edef78..3e257a5ce 100644 --- a/src/common/platform/posix/cocoa/i_main.mm +++ b/src/common/platform/posix/cocoa/i_main.mm @@ -55,7 +55,6 @@ // --------------------------------------------------------------------------- -CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) EXTERN_CVAR(Int, vid_defwidth ) EXTERN_CVAR(Int, vid_defheight) EXTERN_CVAR(Bool, vid_vsync ) @@ -90,10 +89,10 @@ static bool ReadSystemVersionFromPlist(NSOperatingSystemVersion& version) if (stat(plistPath, &dummy) != 0) return false; - + char commandLine[1024] = {}; snprintf(commandLine, sizeof commandLine, "defaults read %s ProductVersion", plistPath); - + FILE *const versionFile = popen(commandLine, "r"); if (versionFile == nullptr) @@ -146,7 +145,7 @@ void I_DetectOS() } const char* name = "Unknown version"; - + switch (version.majorVersion) { case 10: @@ -165,6 +164,9 @@ void I_DetectOS() case 12: name = "macOS Monterey"; break; + case 13: + name = "macOS Ventura"; + break; } char release[16] = "unknown"; @@ -183,7 +185,7 @@ void I_DetectOS() #else "Unknown"; #endif - + Printf("%s running %s %d.%d.%d (%s) %s\n", model, name, int(version.majorVersion), int(version.minorVersion), int(version.patchVersion), release, architecture); @@ -211,13 +213,6 @@ int DoMain(int argc, char** argv) setenv("LC_NUMERIC", "C", 1); setlocale(LC_ALL, "C"); - // Set reasonable default values for video settings - - const NSSize screenSize = [[NSScreen mainScreen] frame].size; - vid_defwidth = static_cast(screenSize.width); - vid_defheight = static_cast(screenSize.height); - vid_vsync = true; - Args = new FArgs(argc, argv); NSString* exePath = [[NSBundle mainBundle] executablePath]; @@ -266,14 +261,14 @@ ApplicationController* appCtrl; - (void)keyDown:(NSEvent*)theEvent { // Empty but present to avoid playing of 'beep' alert sound - + ZD_UNUSED(theEvent); } - (void)keyUp:(NSEvent*)theEvent { // Empty but present to avoid playing of 'beep' alert sound - + ZD_UNUSED(theEvent); } @@ -283,7 +278,7 @@ extern bool AppActive; - (void)applicationDidBecomeActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - + S_SetSoundPaused(1); AppActive = true; @@ -292,8 +287,8 @@ extern bool AppActive; - (void)applicationWillResignActive:(NSNotification*)aNotification { ZD_UNUSED(aNotification); - - S_SetSoundPaused(i_soundinbackground); + + S_SetSoundPaused(0); AppActive = false; } diff --git a/src/common/platform/posix/cocoa/i_system.mm b/src/common/platform/posix/cocoa/i_system.mm index 76a38cbcf..3338f54db 100644 --- a/src/common/platform/posix/cocoa/i_system.mm +++ b/src/common/platform/posix/cocoa/i_system.mm @@ -121,7 +121,7 @@ void I_ShowFatalError(const char *message) } -int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad) +int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad, int&) { if (!showwin) { @@ -170,3 +170,26 @@ unsigned int I_MakeRNGSeed() { return static_cast(arc4random()); } + +FString I_GetCWD() +{ + NSString *currentpath = [[NSFileManager defaultManager] currentDirectoryPath]; + return currentpath.UTF8String; +} + +bool I_ChDir(const char* path) +{ + return [[NSFileManager defaultManager] changeCurrentDirectoryPath:[NSString stringWithUTF8String:path]]; +} + +void I_OpenShellFolder(const char* folder) +{ + NSFileManager *filemgr = [NSFileManager defaultManager]; + NSString *currentpath = [filemgr currentDirectoryPath]; + + [filemgr changeCurrentDirectoryPath:[NSString stringWithUTF8String:folder]]; + Printf("Opening folder: %s\n", folder); + std::system("open ."); + [filemgr changeCurrentDirectoryPath:currentpath]; +} + diff --git a/src/common/platform/posix/cocoa/i_video.mm b/src/common/platform/posix/cocoa/i_video.mm index 193466f0d..9a2737ccf 100644 --- a/src/common/platform/posix/cocoa/i_video.mm +++ b/src/common/platform/posix/cocoa/i_video.mm @@ -34,9 +34,8 @@ #include "gl_load.h" #ifdef HAVE_VULKAN -#define VK_USE_PLATFORM_MACOS_MVK -#define VK_USE_PLATFORM_METAL_EXT -#include "volk/volk.h" +#include +#include #endif #include "i_common.h" @@ -58,12 +57,11 @@ #endif #ifdef HAVE_VULKAN -#include "vulkan/system/vk_framebuffer.h" -#endif -#ifdef HAVE_SOFTPOLY -#include "poly_framebuffer.h" +#include "vulkan/system/vk_renderdevice.h" #endif +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); + extern bool ToggleFullscreen; @implementation NSWindow(ExitAppOnClose) @@ -101,7 +99,6 @@ extern bool ToggleFullscreen; EXTERN_CVAR(Bool, vid_hidpi) EXTERN_CVAR(Int, vid_defwidth) EXTERN_CVAR(Int, vid_defheight) -EXTERN_CVAR(Int, vid_preferbackend) EXTERN_CVAR(Bool, vk_debug) CVAR(Bool, mvk_debug, false, 0) @@ -376,14 +373,12 @@ class CocoaVideo : public IVideo public: CocoaVideo() { - ms_isVulkanEnabled = vid_preferbackend == 1 && NSAppKitVersionNumber >= 1404; // NSAppKitVersionNumber10_11 + ms_isVulkanEnabled = V_GetBackend() == 1 && NSAppKitVersionNumber >= 1404; // NSAppKitVersionNumber10_11 } ~CocoaVideo() { -#ifdef HAVE_VULKAN - delete m_vulkanDevice; -#endif + m_vulkanSurface.reset(); ms_window = nil; } @@ -437,8 +432,20 @@ public: try { - m_vulkanDevice = new VulkanDevice(); - fb = new VulkanFrameBuffer(nullptr, vid_fullscreen, m_vulkanDevice); + VulkanInstanceBuilder builder; + builder.DebugLayer(vk_debug); + builder.RequireExtension(VK_KHR_SURFACE_EXTENSION_NAME); // KHR_surface, required + builder.OptionalExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME); // EXT_metal_surface, optional, preferred + builder.OptionalExtension(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); // MVK_macos_surface, optional, deprecated + auto vulkanInstance = builder.Create(); + + VkSurfaceKHR surfacehandle = nullptr; + if (!I_CreateVulkanSurface(vulkanInstance->Instance, &surfacehandle)) + VulkanError("I_CreateVulkanSurface failed"); + + m_vulkanSurface = std::make_shared(vulkanInstance, surfacehandle); + + fb = new VulkanRenderDevice(nullptr, vid_fullscreen, m_vulkanSurface); } catch (std::exception const&) { @@ -449,24 +456,13 @@ public: } else #endif - -#ifdef HAVE_SOFTPOLY - if (vid_preferbackend == 2) - { - SetupOpenGLView(ms_window, OpenGLProfile::Legacy); - fb = new PolyFrameBuffer(nullptr, vid_fullscreen); - } - else -#endif - { - SetupOpenGLView(ms_window, OpenGLProfile::Core); - } + SetupOpenGLView(ms_window, OpenGLProfile::Core); if (fb == nullptr) { #ifdef HAVE_GLES2 - if( (Args->CheckParm ("-gles2_renderer")) || (vid_preferbackend == 3) ) + if(V_GetBackend() == 2) fb = new OpenGLESRenderer::OpenGLFrameBuffer(0, vid_fullscreen); else #endif @@ -499,7 +495,7 @@ public: private: #ifdef HAVE_VULKAN - VulkanDevice *m_vulkanDevice = nullptr; + std::shared_ptr m_vulkanSurface; #endif static CocoaWindow* ms_window; @@ -832,7 +828,7 @@ bool I_SetCursor(FGameTexture *cursorpic) if (NULL != cursorpic && cursorpic->isValid()) { // Create bitmap image representation - + auto sbuffer = cursorpic->GetTexture()->CreateTexBuffer(0); const NSInteger imageWidth = sbuffer.mWidth; @@ -873,11 +869,11 @@ bool I_SetCursor(FGameTexture *cursorpic) cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:NSMakePoint(0.0f, 0.0f)]; } - + SystemBaseFrameBuffer::SetCursor(cursor); - + [pool release]; - + return true; } @@ -923,63 +919,6 @@ void I_GetVulkanDrawableSize(int *width, int *height) } } -bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names) -{ - static std::vector extensions; - - if (extensions.empty()) - { - uint32_t extensionPropertyCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &extensionPropertyCount, nullptr); - - std::vector extensionProperties(extensionPropertyCount); - vkEnumerateInstanceExtensionProperties(nullptr, &extensionPropertyCount, extensionProperties.data()); - - static const char* const EXTENSION_NAMES[] = - { - VK_KHR_SURFACE_EXTENSION_NAME, // KHR_surface, required - VK_EXT_METAL_SURFACE_EXTENSION_NAME, // EXT_metal_surface, optional, preferred - VK_MVK_MACOS_SURFACE_EXTENSION_NAME, // MVK_macos_surface, optional, deprecated - }; - - for (const VkExtensionProperties ¤tProperties : extensionProperties) - { - for (const char *const extensionName : EXTENSION_NAMES) - { - if (strcmp(currentProperties.extensionName, extensionName) == 0) - { - extensions.push_back(extensionName); - } - } - } - } - - static const unsigned int extensionCount = static_cast(extensions.size()); - assert(extensionCount >= 2); // KHR_surface + at least one of the platform surface extentions - - if (count == nullptr && names == nullptr) - { - return false; - } - else if (names == nullptr) - { - *count = extensionCount; - return true; - } - else - { - const bool result = *count >= extensionCount; - *count = std::min(*count, extensionCount); - - for (unsigned int i = 0; i < *count; ++i) - { - names[i] = extensions[i]; - } - - return result; - } -} - bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) { NSView *const view = CocoaVideo::GetWindow().contentView; diff --git a/src/common/platform/posix/cocoa/st_console.mm b/src/common/platform/posix/cocoa/st_console.mm index af26ae172..1c45776e6 100644 --- a/src/common/platform/posix/cocoa/st_console.mm +++ b/src/common/platform/posix/cocoa/st_console.mm @@ -510,7 +510,7 @@ void FConsoleWindow::NetProgress(const int count) if (m_netMaxPos > 1) { [m_netCountText setStringValue:[NSString stringWithFormat:@"%d / %d", m_netCurPos, m_netMaxPos]]; - [m_netProgressBar setDoubleValue:MIN(m_netCurPos, m_netMaxPos)]; + [m_netProgressBar setDoubleValue:min(m_netCurPos, m_netMaxPos)]; } } diff --git a/src/common/platform/posix/cocoa/st_start.mm b/src/common/platform/posix/cocoa/st_start.mm index 044c36986..8e4ae4bf9 100644 --- a/src/common/platform/posix/cocoa/st_start.mm +++ b/src/common/platform/posix/cocoa/st_start.mm @@ -42,22 +42,6 @@ #include "engineerrors.h" -FStartupScreen *StartScreen; - - -CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (self < 0) - { - self = 0; - } - else if (self > 2) - { - self = 2; - } -} - - // --------------------------------------------------------------------------- @@ -121,18 +105,6 @@ void FBasicStartupScreen::NetProgress(const int count) FConsoleWindow::GetInstance().NetProgress(count); } -void FBasicStartupScreen::NetMessage(const char* const format, ...) -{ - va_list args; - va_start(args, format); - - FString message; - message.VFormat(format, args); - va_end(args); - - Printf("%s\n", message.GetChars()); -} - void FBasicStartupScreen::NetDone() { FConsoleWindow::GetInstance().NetDone(); @@ -160,16 +132,7 @@ bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const user // --------------------------------------------------------------------------- -FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress) +FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress, bool showprogress) { - return new FBasicStartupScreen(maxProgress, true); -} - - -// --------------------------------------------------------------------------- - - -void ST_Endoom() -{ - throw CExitEvent(0); + return new FBasicStartupScreen(maxProgress, showprogress); } diff --git a/src/common/platform/posix/i_system.h b/src/common/platform/posix/i_system.h index b73261eaf..02acf0e3e 100644 --- a/src/common/platform/posix/i_system.h +++ b/src/common/platform/posix/i_system.h @@ -38,7 +38,7 @@ void I_PrintStr (const char *str); void I_SetIWADInfo (); // Pick from multiple IWADs to use -int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad); +int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad, int&); // [RH] Checks the registry for Steam's install path, so we can scan its // directories for IWADs if the user purchased any through Steam. @@ -49,7 +49,7 @@ TArray I_GetGogPaths(); TArray I_GetBethesdaPath(); // The ini could not be saved at exit -bool I_WriteIniFailed (); +bool I_WriteIniFailed (const char* filename); class FGameTexture; bool I_SetCursor(FGameTexture *); @@ -69,4 +69,8 @@ inline int I_GetNumaNodeCount() { return 1; } inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max(std::thread::hardware_concurrency(), 1); } inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { } +FString I_GetCWD(); +bool I_ChDir(const char* path); +void I_OpenShellFolder(const char*); + #endif diff --git a/src/common/platform/posix/i_system_posix.cpp b/src/common/platform/posix/i_system_posix.cpp index 698ea1c69..786706600 100644 --- a/src/common/platform/posix/i_system_posix.cpp +++ b/src/common/platform/posix/i_system_posix.cpp @@ -36,21 +36,14 @@ #include "cmdlib.h" #include "i_system.h" -#include "gameconfigfile.h" -bool I_WriteIniFailed() +bool I_WriteIniFailed(const char * filename) { - printf("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno)); + printf("The config file %s could not be saved:\n%s\n", filename, strerror(errno)); return false; // return true to retry } -TArray I_GetGogPaths() -{ - // GOG's Doom games are Windows only at the moment - return TArray(); -} - TArray I_GetBethesdaPath() { // Bethesda.net Launcher is Windows only at the moment diff --git a/src/common/platform/posix/osx/i_specialpaths.mm b/src/common/platform/posix/osx/i_specialpaths.mm index ff435b769..d51bd4ca5 100644 --- a/src/common/platform/posix/osx/i_specialpaths.mm +++ b/src/common/platform/posix/osx/i_specialpaths.mm @@ -256,7 +256,7 @@ FString M_GetDocumentsPath() FString M_GetDemoPath() { FString path = GetSpecialPath(NSDocumentDirectory); - + if (path.IsNotEmpty()) { path += "/" GAME_DIR "/Demos/"; diff --git a/src/common/platform/posix/osx/iwadpicker_cocoa.mm b/src/common/platform/posix/osx/iwadpicker_cocoa.mm index 4ff7d737b..e72aa5aad 100644 --- a/src/common/platform/posix/osx/iwadpicker_cocoa.mm +++ b/src/common/platform/posix/osx/iwadpicker_cocoa.mm @@ -446,7 +446,7 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad if (ret >= 0) { NSString* parametersToAppend = [picker commandLineParameters]; - + if (0 != [parametersToAppend length]) { RestartWithParameters(wads[ret], parametersToAppend); diff --git a/src/common/platform/posix/sdl/crashcatcher.c b/src/common/platform/posix/sdl/crashcatcher.c index 698707027..c88e0fe8a 100644 --- a/src/common/platform/posix/sdl/crashcatcher.c +++ b/src/common/platform/posix/sdl/crashcatcher.c @@ -15,6 +15,8 @@ #include #endif +int I_FileAvailable(const char* filename); + static const char crash_switch[] = "--cc-handle-crash"; @@ -363,12 +365,11 @@ static void crash_handler(const char *logfile) if(logfile) { - const char *str; char buf[512]; - if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) + if(I_FileAvailable("kdialog")) snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile); - else if((str=getenv("GNOME_DESKTOP_SESSION_ID")) && str[0] != '\0') + else if(I_FileAvailable("gxmessage")) snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile); else snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile); diff --git a/src/common/platform/posix/sdl/hardware.cpp b/src/common/platform/posix/sdl/hardware.cpp index ea008169e..46daca4f9 100644 --- a/src/common/platform/posix/sdl/hardware.cpp +++ b/src/common/platform/posix/sdl/hardware.cpp @@ -67,6 +67,7 @@ void I_InitGraphics () #ifdef __APPLE__ SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0"); #endif // __APPLE__ + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0) { @@ -78,7 +79,7 @@ void I_InitGraphics () extern IVideo *gl_CreateVideo(); Video = gl_CreateVideo(); - + if (Video == NULL) I_FatalError ("Failed to initialize display"); } diff --git a/src/common/platform/posix/sdl/i_input.cpp b/src/common/platform/posix/sdl/i_input.cpp index a102b38a8..02cf31e45 100644 --- a/src/common/platform/posix/sdl/i_input.cpp +++ b/src/common/platform/posix/sdl/i_input.cpp @@ -56,8 +56,7 @@ static bool NativeMouse = true; CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -extern int WaitingForKey, chatmodeon; -extern constate_e ConsoleState; +extern int WaitingForKey; static const SDL_Keycode DIKToKeySym[256] = { @@ -73,8 +72,8 @@ static const SDL_Keycode DIKToKeySym[256] = SDLK_KP_8, SDLK_KP_9, SDLK_KP_MINUS, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_PLUS, SDLK_KP_1, SDLK_KP_2, SDLK_KP_3, SDLK_KP_0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11, SDLK_F12, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, SDLK_F16, + SDLK_F17, SDLK_F18, SDLK_F19, SDLK_F20, SDLK_F21, SDLK_F22, SDLK_F23, SDLK_F24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -109,8 +108,8 @@ static const SDL_Scancode DIKToKeyScan[256] = SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_5, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_KP_1, SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F11, SDL_SCANCODE_F12, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, - SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_UNKNOWN, - SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_F16, + SDL_SCANCODE_F17, SDL_SCANCODE_F18, SDL_SCANCODE_F19, SDL_SCANCODE_F20, SDL_SCANCODE_F21, SDL_SCANCODE_F22, SDL_SCANCODE_F23, SDL_SCANCODE_F24, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, @@ -205,7 +204,7 @@ static void MouseRead () static void I_CheckNativeMouse () { bool focus = SDL_GetKeyboardFocus() != NULL; - + bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame(); bool wantNative = !focus || (!use_mouse || GUICapture || !captureModeInGame); @@ -228,7 +227,7 @@ void MessagePump (const SDL_Event &sev) static int lastx = 0, lasty = 0; int x, y; event_t event = { 0,0,0,0,0,0,0 }; - + switch (sev.type) { case SDL_QUIT: @@ -369,7 +368,7 @@ void MessagePump (const SDL_Event &sev) { break; } - + event.type = sev.type == SDL_KEYDOWN ? EV_KeyDown : EV_KeyUp; // Try to look up our key mapped key for conversion to DirectInput. @@ -448,7 +447,7 @@ void MessagePump (const SDL_Event &sev) if (GUICapture) { int size; - + int unichar = utf8_decode((const uint8_t*)sev.text.text, &size); if (size != 4) { @@ -474,7 +473,7 @@ void MessagePump (const SDL_Event &sev) void I_GetEvent () { SDL_Event sev; - + while (SDL_PollEvent (&sev)) { MessagePump (sev); diff --git a/src/common/platform/posix/sdl/i_joystick.cpp b/src/common/platform/posix/sdl/i_joystick.cpp index fe4b25eb6..0fa33ba63 100644 --- a/src/common/platform/posix/sdl/i_joystick.cpp +++ b/src/common/platform/posix/sdl/i_joystick.cpp @@ -34,7 +34,7 @@ #include "basics.h" #include "cmdlib.h" -#include "templates.h" + #include "m_joy.h" #include "keydef.h" diff --git a/src/common/platform/posix/sdl/i_main.cpp b/src/common/platform/posix/sdl/i_main.cpp index b52561fdf..196504b54 100644 --- a/src/common/platform/posix/sdl/i_main.cpp +++ b/src/common/platform/posix/sdl/i_main.cpp @@ -171,10 +171,12 @@ int main (int argc, char **argv) } printf("\n"); - + Args = new FArgs(argc, argv); - // Should we even be doing anything with progdir on Unix systems? +#ifdef PROGDIR + progdir = PROGDIR; +#else char program[PATH_MAX]; if (realpath (argv[0], program) == NULL) strcpy (program, argv[0]); @@ -188,7 +190,8 @@ int main (int argc, char **argv) { progdir = "./"; } - +#endif + I_StartupJoysticks(); const int result = GameMain(); diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index 922c228a3..e81c97f68 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -47,6 +47,13 @@ #include #include +#ifdef __linux__ +#include +#include +#include +#include "printf.h" +#endif + #include #include "version.h" @@ -62,7 +69,7 @@ #ifndef NO_GTK bool I_GtkAvailable (); -int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad); +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); @@ -72,12 +79,26 @@ double PerfToSec, PerfToMillisec; CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE); CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE); -extern FStartupScreen *StartScreen; +extern FStartupScreen *StartWindow; void I_SetIWADInfo() { } +extern "C" int I_FileAvailable(const char* filename) +{ + FString cmd = "which {0} >/dev/null 2>&1"; + cmd.Substitute("{0}", filename); + + if (FILE* f = popen(cmd.GetChars(), "r")) + { + int status = pclose(f); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; + } + + return 0; +} + // // I_Error // @@ -92,8 +113,7 @@ void Unix_I_FatalError(const char* errortext) // Close window or exit fullscreen and release mouse capture SDL_QuitSubSystem(SDL_INIT_VIDEO); - const char *str; - if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) + if(I_FileAvailable("kdialog")) { FString cmd; cmd << "kdialog --title \"" GAMENAME " " << GetVersionString() @@ -131,8 +151,54 @@ void I_ShowFatalError(const char *message) #endif } +bool PerfAvailable; + void CalculateCPUSpeed() { + PerfAvailable = false; + PerfToMillisec = PerfToSec = 0.; +#ifdef __aarch64__ + // [MK] on aarch64 rather than having to calculate cpu speed, there is + // already an independent frequency for the perf timer + uint64_t frq; + asm volatile("mrs %0, cntfrq_el0":"=r"(frq)); + PerfAvailable = true; + PerfToSec = 1./frq; + PerfToMillisec = PerfToSec*1000.; +#elif defined(__linux__) + // [MK] read from perf values if we can + struct perf_event_attr pe; + memset(&pe,0,sizeof(struct perf_event_attr)); + pe.type = PERF_TYPE_HARDWARE; + pe.size = sizeof(struct perf_event_attr); + pe.config = PERF_COUNT_HW_INSTRUCTIONS; + pe.disabled = 1; + pe.exclude_kernel = 1; + pe.exclude_hv = 1; + int fd = syscall(__NR_perf_event_open, &pe, 0, -1, -1, 0); + if (fd == -1) + { + return; + } + void *addr = mmap(nullptr, 4096, PROT_READ, MAP_SHARED, fd, 0); + if (addr == nullptr) + { + close(fd); + return; + } + struct perf_event_mmap_page *pc = (struct perf_event_mmap_page *)addr; + if (pc->cap_user_time != 1) + { + close(fd); + return; + } + double mhz = (1000LU << pc->time_shift) / (double)pc->time_mult; + PerfAvailable = true; + PerfToSec = .000001/mhz; + PerfToMillisec = PerfToSec*1000.; + if (!batchrun) Printf("CPU speed: %.0f MHz\n", mhz); + close(fd); +#endif } void CleanProgressBar() @@ -159,7 +225,7 @@ void RedrawProgressBar(int CurPos, int MaxPos) memset(progressBuffer,'.',512); progressBuffer[sizeOfWindow.ws_col - 1] = 0; int lengthOfStr = 0; - + while (curProgVal-- > 0) { progressBuffer[lengthOfStr++] = '='; @@ -182,7 +248,9 @@ void I_PrintStr(const char *cp) if (*srcp == 0x1c && con_printansi && terminal) { srcp += 1; - EColorRange range = V_ParseFontColor((const uint8_t*&)srcp, CR_UNTRANSLATED, CR_YELLOW); + const uint8_t* scratch = (const uint8_t*)srcp; // GCC does not like direct casting of the parameter. + EColorRange range = V_ParseFontColor(scratch, CR_UNTRANSLATED, CR_YELLOW); + srcp = (char*)scratch; if (range != CR_UNDEFINED) { PalEntry color = V_LogColorFromColorRange(range); @@ -206,7 +274,7 @@ void I_PrintStr(const char *cp) else if (v < 0.90) attrib = 0x7; else attrib = 0xF; } - + printData.AppendFormat("\033[%um",((attrib & 0x8) ? 90 : 30) + (attrib & 0x7)); } else printData.AppendFormat("\033[38;2;%u;%u;%um",color.r,color.g,color.b); @@ -222,14 +290,14 @@ void I_PrintStr(const char *cp) else break; } } - - if (StartScreen) CleanProgressBar(); + + if (StartWindow) CleanProgressBar(); fputs(printData.GetChars(),stdout); if (terminal) fputs("\033[0m",stdout); - if (StartScreen) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos); + if (StartWindow) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos); } -int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) +int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) { int i; @@ -239,8 +307,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) } #ifndef __APPLE__ - const char *str; - if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) + if(I_FileAvailable("kdialog")) { FString cmd("kdialog --title \"" GAMENAME " "); cmd << GetVersionString() << ": Select an IWAD to use\"" @@ -294,14 +361,14 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) #ifndef NO_GTK if (I_GtkAvailable()) { - return I_PickIWad_Gtk (wads, numwads, showwin, defaultiwad); + return I_PickIWad_Gtk (wads, numwads, showwin, defaultiwad, autoloadflags); } #endif #ifdef __APPLE__ return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad); #endif - + if (!isatty(fileno(stdin))) { return defaultiwad; @@ -339,6 +406,23 @@ FString I_GetFromClipboard (bool use_primary_selection) return ""; } +FString I_GetCWD() +{ + char* curdir = get_current_dir_name(); + if (!curdir) + { + return ""; + } + FString ret(curdir); + free(curdir); + return ret; +} + +bool I_ChDir(const char* path) +{ + return chdir(path) == 0; +} + // Return a random seed, preferably one with lots of entropy. unsigned int I_MakeRNGSeed() { @@ -360,3 +444,21 @@ unsigned int I_MakeRNGSeed() } return seed; } + +void I_OpenShellFolder(const char* infolder) +{ + char* curdir = get_current_dir_name(); + + if (!chdir(infolder)) + { + Printf("Opening folder: %s\n", infolder); + std::system("xdg-open ."); + chdir(curdir); + } + else + { + Printf("Unable to open directory '%s\n", infolder); + } + free(curdir); +} + diff --git a/src/common/platform/posix/sdl/i_system.mm b/src/common/platform/posix/sdl/i_system.mm index 50faf94a8..f9212f08c 100644 --- a/src/common/platform/posix/sdl/i_system.mm +++ b/src/common/platform/posix/sdl/i_system.mm @@ -5,13 +5,13 @@ void Mac_I_FatalError(const char* errortext) { // Close window or exit fullscreen and release mouse capture SDL_Quit(); - + const CFStringRef errorString = CFStringCreateWithCStringNoCopy( kCFAllocatorDefault, errortext, kCFStringEncodingASCII, kCFAllocatorNull ); if ( NULL != errorString ) { CFOptionFlags dummy; - + CFUserNotificationDisplayAlert( 0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, CFSTR( "Fatal Error" ), errorString, CFSTR( "Exit" ), NULL, NULL, &dummy ); CFRelease( errorString ); diff --git a/src/common/platform/posix/sdl/sdlglvideo.cpp b/src/common/platform/posix/sdl/sdlglvideo.cpp index 73ca00b99..326a5c9d9 100644 --- a/src/common/platform/posix/sdl/sdlglvideo.cpp +++ b/src/common/platform/posix/sdl/sdlglvideo.cpp @@ -53,13 +53,13 @@ #ifdef HAVE_GLES2 #include "gles_framebuffer.h" #endif - -#ifdef HAVE_VULKAN -#include "vulkan/system/vk_framebuffer.h" -#endif -#ifdef HAVE_SOFTPOLY -#include "poly_framebuffer.h" +#ifdef HAVE_VULKAN +#include "vulkan/system/vk_renderdevice.h" +#include +#include +#include +#include #endif // MACROS ------------------------------------------------------------------ @@ -81,8 +81,8 @@ EXTERN_CVAR (Int, vid_adapter) EXTERN_CVAR (Int, vid_displaybits) EXTERN_CVAR (Int, vid_defwidth) EXTERN_CVAR (Int, vid_defheight) -EXTERN_CVAR (Int, vid_preferbackend) EXTERN_CVAR (Bool, cl_capfps) +EXTERN_CVAR(Bool, vk_debug) // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -95,8 +95,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(Bool, i_soundinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(String, vid_sdl_render_driver, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -206,7 +204,7 @@ public: private: #ifdef HAVE_VULKAN - VulkanDevice *device = nullptr; + std::shared_ptr surface; #endif }; @@ -235,157 +233,6 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) } #endif -#ifdef HAVE_SOFTPOLY -namespace -{ - SDL_Renderer* polyrendertarget = nullptr; - SDL_Texture* polytexture = nullptr; - int polytexturew = 0; - int polytextureh = 0; - bool polyvsync = false; - bool polyfirstinit = true; -} - -void I_PolyPresentInit() -{ - assert(Priv::softpolyEnabled); - assert(Priv::window != nullptr); - - if (strcmp(vid_sdl_render_driver, "") != 0) - { - SDL_SetHint(SDL_HINT_RENDER_DRIVER, vid_sdl_render_driver); - } -} - -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) -{ - // When vsync changes we need to reinitialize - if (polyrendertarget && polyvsync != vsync) - { - I_PolyPresentDeinit(); - } - - if (!polyrendertarget) - { - polyvsync = vsync; - - polyrendertarget = SDL_CreateRenderer(Priv::window, -1, vsync ? SDL_RENDERER_PRESENTVSYNC : 0); - if (!polyrendertarget) - { - I_FatalError("Could not create render target for softpoly: %s\n", SDL_GetError()); - } - - // Tell the user which render driver is being used, but don't repeat - // outselves if we're just changing vsync. - if (polyfirstinit) - { - polyfirstinit = false; - - SDL_RendererInfo rendererInfo; - if (SDL_GetRendererInfo(polyrendertarget, &rendererInfo) == 0) - { - Printf("Using render driver %s\n", rendererInfo.name); - } - else - { - Printf("Failed to query render driver\n"); - } - } - - // Mask color - SDL_SetRenderDrawColor(polyrendertarget, 0, 0, 0, 255); - } - - if (!polytexture || polytexturew != w || polytextureh != h) - { - if (polytexture) - { - SDL_DestroyTexture(polytexture); - polytexture = nullptr; - polytexturew = polytextureh = 0; - } - if ((polytexture = SDL_CreateTexture(polyrendertarget, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h)) == nullptr) - I_Error("Failed to create %dx%d render target texture.", w, h); - polytexturew = w; - polytextureh = h; - } - - uint8_t* pixels; - SDL_LockTexture(polytexture, nullptr, (void**)&pixels, &pitch); - return pixels; -} - -void I_PolyPresentUnlock(int x, int y, int width, int height) -{ - SDL_UnlockTexture(polytexture); - - int ClientWidth, ClientHeight; - SDL_GetRendererOutputSize(polyrendertarget, &ClientWidth, &ClientHeight); - - SDL_Rect clearrects[4]; - int count = 0; - if (y > 0) - { - clearrects[count].x = 0; - clearrects[count].y = 0; - clearrects[count].w = ClientWidth; - clearrects[count].h = y; - count++; - } - if (y + height < ClientHeight) - { - clearrects[count].x = 0; - clearrects[count].y = y + height; - clearrects[count].w = ClientWidth; - clearrects[count].h = ClientHeight - clearrects[count].y; - count++; - } - if (x > 0) - { - clearrects[count].x = 0; - clearrects[count].y = y; - clearrects[count].w = x; - clearrects[count].h = height; - count++; - } - if (x + width < ClientWidth) - { - clearrects[count].x = x + width; - clearrects[count].y = y; - clearrects[count].w = ClientWidth - clearrects[count].x; - clearrects[count].h = height; - count++; - } - - if (count > 0) - SDL_RenderFillRects(polyrendertarget, clearrects, count); - - SDL_Rect dstrect; - dstrect.x = x; - dstrect.y = y; - dstrect.w = width; - dstrect.h = height; - SDL_RenderCopy(polyrendertarget, polytexture, nullptr, &dstrect); - - SDL_RenderPresent(polyrendertarget); -} - -void I_PolyPresentDeinit() -{ - if (polytexture) - { - SDL_DestroyTexture(polytexture); - polytexture = nullptr; - } - - if (polyrendertarget) - { - SDL_DestroyRenderer(polyrendertarget); - polyrendertarget = nullptr; - } -} -#endif - SDLVideo::SDLVideo () { @@ -396,18 +243,13 @@ SDLVideo::SDLVideo () } // Fail gracefully if we somehow reach here after linking against a SDL2 library older than 2.0.6. - SDL_version sdlver; - SDL_GetVersion(&sdlver); - if (!(sdlver.patch >= 6)) + if (!SDL_VERSION_ATLEAST(2, 0, 6)) { I_FatalError("Only SDL 2.0.6 or later is supported."); } -#ifdef HAVE_SOFTPOLY - Priv::softpolyEnabled = vid_preferbackend == 2; -#endif #ifdef HAVE_VULKAN - Priv::vulkanEnabled = vid_preferbackend == 1; + Priv::vulkanEnabled = V_GetBackend() == 1; if (Priv::vulkanEnabled) { @@ -419,22 +261,12 @@ SDLVideo::SDLVideo () } } #endif -#ifdef HAVE_SOFTPOLY - if (Priv::softpolyEnabled) - { - Priv::CreateWindow(SDL_WINDOW_HIDDEN); - if (Priv::window == nullptr) - { - I_FatalError("Could not create SoftPoly window:\n%s\n",SDL_GetError()); - } - } -#endif } SDLVideo::~SDLVideo () { #ifdef HAVE_VULKAN - delete device; + surface.reset(); #endif } @@ -448,9 +280,24 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () { try { - assert(device == nullptr); - device = new VulkanDevice(); - fb = new VulkanFrameBuffer(nullptr, vid_fullscreen, device); + unsigned int count = 64; + const char* names[64]; + if (!I_GetVulkanPlatformExtensions(&count, names)) + VulkanError("I_GetVulkanPlatformExtensions failed"); + + VulkanInstanceBuilder builder; + builder.DebugLayer(vk_debug); + for (unsigned int i = 0; i < count; i++) + builder.RequireExtension(names[i]); + auto instance = builder.Create(); + + VkSurfaceKHR surfacehandle = nullptr; + if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle)) + VulkanError("I_CreateVulkanSurface failed"); + + surface = std::make_shared(instance, surfacehandle); + + fb = new VulkanRenderDevice(nullptr, vid_fullscreen, surface); } catch (CVulkanError const &error) { @@ -465,16 +312,10 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () } #endif -#ifdef HAVE_SOFTPOLY - if (Priv::softpolyEnabled) - { - fb = new PolyFrameBuffer(nullptr, vid_fullscreen); - } -#endif if (fb == nullptr) { #ifdef HAVE_GLES2 - if( (Args->CheckParm ("-gles2_renderer")) || (vid_preferbackend == 3) ) + if (V_GetBackend() == 2) fb = new OpenGLESRenderer::OpenGLFrameBuffer(0, vid_fullscreen); else #endif @@ -507,17 +348,7 @@ int SystemBaseFrameBuffer::GetClientWidth() { int width = 0; -#ifdef HAVE_SOFTPOLY - if (Priv::softpolyEnabled) - { - if (polyrendertarget) - SDL_GetRendererOutputSize(polyrendertarget, &width, nullptr); - else - SDL_GetWindowSize(Priv::window, &width, nullptr); - return width; - } -#endif - + #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); SDL_Vulkan_GetDrawableSize(Priv::window, &width, nullptr); @@ -530,17 +361,6 @@ int SystemBaseFrameBuffer::GetClientHeight() { int height = 0; -#ifdef HAVE_SOFTPOLY - if (Priv::softpolyEnabled) - { - if (polyrendertarget) - SDL_GetRendererOutputSize(polyrendertarget, nullptr, &height); - else - SDL_GetWindowSize(Priv::window, nullptr, &height); - return height; - } -#endif - #ifdef HAVE_VULKAN assert(Priv::vulkanEnabled); SDL_Vulkan_GetDrawableSize(Priv::window, nullptr, &height); @@ -721,7 +541,7 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event) break; case SDL_WINDOWEVENT_FOCUS_LOST: - S_SetSoundPaused(i_soundinbackground); + S_SetSoundPaused(0); AppActive = false; break; diff --git a/src/common/platform/posix/sdl/st_start.cpp b/src/common/platform/posix/sdl/st_start.cpp index 6d41fa629..d372e79bc 100644 --- a/src/common/platform/posix/sdl/st_start.cpp +++ b/src/common/platform/posix/sdl/st_start.cpp @@ -56,7 +56,6 @@ class FTTYStartupScreen : public FStartupScreen void Progress(); void NetInit(const char *message, int num_players); void NetProgress(int count); - void NetMessage(const char *format, ...); // cover for printf void NetDone(); bool NetLoop(bool (*timer_callback)(void *), void *userdata); protected: @@ -71,22 +70,6 @@ class FTTYStartupScreen : public FStartupScreen extern void RedrawProgressBar(int CurPos, int MaxPos); extern void CleanProgressBar(); -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -FStartupScreen *StartScreen; - -CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < 0) self = 0; - else if (self > 2) self=2; -} - // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' }; @@ -102,7 +85,7 @@ static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' }; // //========================================================================== -FStartupScreen *FStartupScreen::CreateInstance(int max_progress) +FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool) { return new FTTYStartupScreen(max_progress); } @@ -214,27 +197,6 @@ void FTTYStartupScreen::NetDone() } } -//=========================================================================== -// -// FTTYStartupScreen :: NetMessage -// -// Call this between NetInit() and NetDone() instead of Printf() to -// display messages, because the progress meter is mixed in the same output -// stream as normal messages. -// -//=========================================================================== - -void FTTYStartupScreen::NetMessage(const char *format, ...) -{ - FString str; - va_list argptr; - - va_start (argptr, format); - str.VFormat (format, argptr); - va_end (argptr); - fprintf (stderr, "\r%-40s\n", str.GetChars()); -} - //=========================================================================== // // FTTYStartupScreen :: NetProgress @@ -331,7 +293,3 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) } } -void ST_Endoom() -{ - throw CExitEvent(0); -} diff --git a/src/common/platform/posix/unix/gtk_dialogs.cpp b/src/common/platform/posix/unix/gtk_dialogs.cpp index 6a3042e44..05f79dddc 100644 --- a/src/common/platform/posix/unix/gtk_dialogs.cpp +++ b/src/common/platform/posix/unix/gtk_dialogs.cpp @@ -64,6 +64,8 @@ typedef enum #include "printf.h" EXTERN_CVAR (Bool, queryiwad); +EXTERN_CVAR (Int, vid_preferbackend); +EXTERN_CVAR (Bool, vid_fullscreen); namespace Gtk { @@ -95,6 +97,9 @@ DYN_GTK_SYM(gtk_button_box_set_layout); DYN_GTK_SYM(gtk_button_new_with_label); DYN_GTK_SYM(gtk_cell_renderer_text_new); DYN_GTK_SYM(gtk_check_button_new_with_label); +DYN_GTK_SYM(gtk_radio_button_new_with_label); +DYN_GTK_SYM(gtk_radio_button_new_with_label_from_widget); +DYN_GTK_SYM(gtk_radio_button_get_type); DYN_GTK_SYM(gtk_container_add); DYN_GTK_SYM(gtk_container_get_type); DYN_GTK_SYM(gtk_container_set_border_width); @@ -190,137 +195,133 @@ static void ClickedOK(GtkButton *button, gpointer func_data) gtk_main_quit(); } -static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) +class ZUIWidget { - GtkWidget *window; - GtkWidget *vbox = nullptr; - GtkWidget *hbox = nullptr; - GtkWidget *bbox = nullptr; - GtkWidget *widget; - GtkWidget *tree; - GtkWidget *check; - GtkListStore *store; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *selection; - GtkTreeIter iter, defiter; - int close_style = 0; - int i; - char caption[100]; +public: + virtual ~ZUIWidget() = default; - // Create the dialog window. - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - mysnprintf(caption, countof(caption), GAMENAME " %s: Select an IWAD to use", GetVersionString()); - gtk_window_set_title (GTK_WINDOW(window), caption); - gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER); - gtk_window_set_gravity (GTK_WINDOW(window), GDK_GRAVITY_CENTER); - gtk_container_set_border_width (GTK_CONTAINER(window), 10); - g_signal_connect (window, "delete_event", G_CALLBACK(gtk_main_quit), NULL); - g_signal_connect (window, "key_press_event", G_CALLBACK(CheckEscape), NULL); + GtkWidget *widget = nullptr; +}; - // Create the vbox container. - if (gtk_box_new) // Gtk3 - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); - else if (gtk_vbox_new) // Gtk2 - vbox = gtk_vbox_new (FALSE, 10); - - gtk_container_add (GTK_CONTAINER(window), vbox); - - // Create the top label. - widget = gtk_label_new (GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:"); - gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0); - - if (gtk_widget_set_halign && gtk_widget_set_valign) // Gtk3 +class ZUIWindow : public ZUIWidget +{ +public: + ZUIWindow(const char* title) { - gtk_widget_set_halign (widget, GTK_ALIGN_START); - gtk_widget_set_valign (widget, GTK_ALIGN_START); + widget = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title (GTK_WINDOW(widget), title); + gtk_window_set_position (GTK_WINDOW(widget), GTK_WIN_POS_CENTER); + gtk_window_set_gravity (GTK_WINDOW(widget), GDK_GRAVITY_CENTER); + + gtk_container_set_border_width (GTK_CONTAINER(widget), 15); + + g_signal_connect (widget, "delete_event", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect (widget, "key_press_event", G_CALLBACK(CheckEscape), NULL); } - else if (gtk_misc_set_alignment && gtk_misc_get_type) // Gtk2 - gtk_misc_set_alignment (GTK_MISC(widget), 0, 0); - // Create a list store with all the found IWADs. - store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); - for (i = 0; i < numwads; ++i) + ~ZUIWindow() { - const char *filepart = strrchr (wads[i].Path, '/'); - if (filepart == NULL) - filepart = wads[i].Path; - else - filepart++; - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - 0, filepart, - 1, wads[i].Name.GetChars(), - 2, i, - -1); - if (i == defaultiwad) + if (GTK_IS_WINDOW(widget)) { - defiter = iter; + gtk_widget_destroy (widget); + // If we don't do this, then the X window might not actually disappear. + while (g_main_context_iteration (NULL, FALSE)) {} } } - // Create the tree view control to show the list. - tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("IWAD", renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Game", renderer, "text", 1, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column); - gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(tree), true, true, 0); - g_signal_connect(G_OBJECT(tree), "button_press_event", G_CALLBACK(DoubleClickChecker), &close_style); - g_signal_connect(G_OBJECT(tree), "key_press_event", G_CALLBACK(AllowDefault), window); + void AddWidget(ZUIWidget* child) + { + gtk_container_add (GTK_CONTAINER(widget), child->widget); + } - // Select the default IWAD. - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree)); - gtk_tree_selection_select_iter (selection, &defiter); + void RunModal() + { + gtk_widget_show_all (widget); + gtk_main (); + } +}; - // Create the hbox for the bottom row. - if (gtk_box_new) // Gtk3 - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - else if (gtk_hbox_new) // Gtk2 - hbox = gtk_hbox_new (FALSE, 0); +class ZUIVBox : public ZUIWidget +{ +public: + ZUIVBox() + { + if (gtk_box_new) // Gtk3 + widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); + else if (gtk_vbox_new) // Gtk2 + widget = gtk_vbox_new (FALSE, 10); + } - gtk_box_pack_end (GTK_BOX(vbox), hbox, false, false, 0); + void PackStart(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_start (GTK_BOX(widget), child->widget, expand, fill, padding); + } - // Create the "Don't ask" checkbox. - check = gtk_check_button_new_with_label ("Don't ask me this again"); - gtk_box_pack_start (GTK_BOX(hbox), check, false, false, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check), !showwin); + void PackEnd(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_end (GTK_BOX(widget), child->widget, expand, fill, padding); + } +}; - // Create the OK/Cancel button box. - if (gtk_button_box_new) // Gtk3 - bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); - else if (gtk_hbutton_box_new) // Gtk2 - bbox = gtk_hbutton_box_new (); +class ZUILabel : public ZUIWidget +{ +public: + ZUILabel(const char* text) + { + widget = gtk_label_new (text); - gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX(bbox), 10); - gtk_box_pack_end (GTK_BOX(hbox), bbox, false, false, 0); + if (gtk_widget_set_halign && gtk_widget_set_valign) // Gtk3 + { + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_widget_set_valign (widget, GTK_ALIGN_START); + } + else if (gtk_misc_set_alignment && gtk_misc_get_type) // Gtk2 + gtk_misc_set_alignment (GTK_MISC(widget), 0, 0); + } +}; - // Create the OK button. - widget = gtk_button_new_with_label ("OK"); +class ZUIListView : public ZUIWidget +{ +public: + ZUIListView(WadStuff *wads, int numwads, int defaultiwad) + { + // Create a list store with all the found IWADs. + 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, '/'); + if (filepart == NULL) + filepart = wads[i].Path; + else + filepart++; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, filepart, + 1, wads[i].Name.GetChars(), + 2, i, + -1); + if (i == defaultiwad) + { + defiter = iter; + } + } - gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0); + // Create the tree view control to show the list. + widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)); + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("IWAD", renderer, "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(widget), column); + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Game", renderer, "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(widget), column); - gtk_widget_set_can_default (widget, true); + // Select the default IWAD. + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(widget)); + gtk_tree_selection_select_iter (selection, &defiter); + } - gtk_widget_grab_default (widget); - g_signal_connect (widget, "clicked", G_CALLBACK(ClickedOK), &close_style); - g_signal_connect (widget, "activate", G_CALLBACK(ClickedOK), &close_style); - - // Create the cancel button. - widget = gtk_button_new_with_label ("Cancel"); - - gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0); - g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window); - - // Finally we can show everything. - gtk_widget_show_all (window); - - gtk_main (); - - if (close_style == 1) + int GetSelectedIndex() { GtkTreeModel *model; GValue value = { 0, { {0} } }; @@ -328,96 +329,287 @@ static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) // Find out which IWAD was selected. gtk_tree_selection_get_selected (selection, &model, &iter); gtk_tree_model_get_value (GTK_TREE_MODEL(model), &iter, 2, &value); - i = g_value_get_int (&value); + int i = g_value_get_int (&value); g_value_unset (&value); + return i; + } + + void ConnectButtonPress(int *close_style) + { + g_signal_connect(G_OBJECT(widget), "button_press_event", G_CALLBACK(DoubleClickChecker), &close_style); + } + + void ConnectKeyPress(ZUIWindow* window) + { + g_signal_connect(G_OBJECT(widget), "key_press_event", G_CALLBACK(AllowDefault), window->widget); + } + + GtkListStore *store = nullptr; + GtkCellRenderer *renderer = nullptr; + GtkTreeViewColumn *column = nullptr; + GtkTreeSelection *selection = nullptr; + GtkTreeIter iter, defiter; +}; + +class ZUIHBox : public ZUIWidget +{ +public: + ZUIHBox() + { + // Create the hbox for the bottom row. + if (gtk_box_new) // Gtk3 + widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + else if (gtk_hbox_new) // Gtk2 + widget = gtk_hbox_new (FALSE, 0); + } + + void PackStart(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_start (GTK_BOX(widget), child->widget, expand, fill, padding); + } + + void PackEnd(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_end (GTK_BOX(widget), child->widget, expand, fill, padding); + } +}; + +class ZUICheckButton : public ZUIWidget +{ +public: + ZUICheckButton(const char* text) + { + widget = gtk_check_button_new_with_label (text); + } + + void SetChecked(bool value) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), value); + } + + int GetChecked() + { + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)); + } +}; + +class ZUIRadioButton : public ZUIWidget +{ +public: + ZUIRadioButton(const char* text) + { + widget = gtk_radio_button_new_with_label (nullptr, text); + } + + ZUIRadioButton(ZUIRadioButton* group, const char* text) + { + widget = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(group->widget), text); + } + + void SetChecked(bool value) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), value); + } + + int GetChecked() + { + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)); + } +}; + +class ZUIButtonBox : public ZUIWidget +{ +public: + ZUIButtonBox() + { + if (gtk_button_box_new) // Gtk3 + widget = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); + else if (gtk_hbutton_box_new) // Gtk2 + widget = gtk_hbutton_box_new (); + + gtk_button_box_set_layout (GTK_BUTTON_BOX(widget), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX(widget), 10); + } + + void PackStart(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_start (GTK_BOX(widget), child->widget, expand, fill, padding); + } + + void PackEnd(ZUIWidget* child, bool expand, bool fill, int padding) + { + gtk_box_pack_end (GTK_BOX(widget), child->widget, expand, fill, padding); + } +}; + +class ZUIButton : public ZUIWidget +{ +public: + ZUIButton(const char* text, bool defaultButton) + { + widget = gtk_button_new_with_label (text); + + if (defaultButton) + { + gtk_widget_set_can_default (widget, true); + } + } + + void GrabDefault() + { + gtk_widget_grab_default (widget); + } + + void ConnectClickedOK(int *close_style) + { + g_signal_connect (widget, "clicked", G_CALLBACK(ClickedOK), close_style); + g_signal_connect (widget, "activate", G_CALLBACK(ClickedOK), close_style); + } + + void ConnectClickedExit(ZUIWindow* window) + { + g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window->widget); + } +}; + +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); + + ZUIHBox hboxOptions; + + ZUIVBox vboxVideo; + ZUILabel videoSettings("Video settings"); + ZUIRadioButton opengl("OpenGL"); + ZUIRadioButton vulkan(&opengl, "Vulkan"); + ZUIRadioButton openglES(&opengl, "OpenGL ES"); + 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(&listview, 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(&opengl, false, false, 0); + vboxVideo.PackStart(&vulkan, false, false, 0); + vboxVideo.PackStart(&openglES, 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); + + switch (vid_preferbackend) + { + case 0: opengl.SetChecked(true); break; + case 1: vulkan.SetChecked(true); break; + case 2: openglES.SetChecked(true); break; + default: break; + } + + 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 = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check)); + queryiwad = !dontAskAgain.GetChecked(); + + if (opengl.GetChecked()) vid_preferbackend = 0; + if (vulkan.GetChecked()) vid_preferbackend = 1; + if (openglES.GetChecked()) vid_preferbackend = 2; + + 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 { - i = -1; + return -1; } - - if (GTK_IS_WINDOW(window)) - { - gtk_widget_destroy (window); - // If we don't do this, then the X window might not actually disappear. - while (g_main_context_iteration (NULL, FALSE)) {} - } - - return i; } static void ShowError(const char* errortext) { - GtkWidget *window; - GtkWidget *widget; - GtkWidget *vbox = nullptr; - GtkWidget *bbox = nullptr; + ZUIWindow window("Fatal error"); + ZUIVBox vbox; + ZUILabel label(errortext); + ZUIButtonBox bbox; + ZUIButton exitButton("Exit", true); - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW(window), "Fatal error"); - gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER); - gtk_window_set_gravity (GTK_WINDOW(window), GDK_GRAVITY_CENTER); - gtk_window_set_resizable (GTK_WINDOW(window), false); - gtk_container_set_border_width (GTK_CONTAINER(window), 10); - g_signal_connect (window, "delete_event", G_CALLBACK(gtk_main_quit), NULL); - g_signal_connect (window, "key_press_event", G_CALLBACK(CheckEscape), NULL); + window.AddWidget(&vbox); + vbox.PackStart(&label, true, true, 0); + vbox.PackEnd(&bbox, false, false, 0); + bbox.PackEnd(&exitButton, false, false, 0); - // Create the vbox container. - if (gtk_box_new) // Gtk3 - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); - else if (gtk_vbox_new) // Gtk2 - vbox = gtk_vbox_new (FALSE, 10); + exitButton.ConnectClickedExit(&window); - gtk_container_add (GTK_CONTAINER(window), vbox); - - // Create the label. - widget = gtk_label_new ((const gchar *) errortext); - gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0); - - if (gtk_widget_set_halign && gtk_widget_set_valign) // Gtk3 - { - gtk_widget_set_halign (widget, GTK_ALIGN_START); - gtk_widget_set_valign (widget, GTK_ALIGN_START); - } - else if (gtk_misc_set_alignment && gtk_misc_get_type) // Gtk2 - gtk_misc_set_alignment (GTK_MISC(widget), 0, 0); - - // Create the Exit button box. - if (gtk_button_box_new) // Gtk3 - bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); - else if (gtk_hbutton_box_new) // Gtk2 - bbox = gtk_hbutton_box_new (); - - gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX(bbox), 10); - gtk_box_pack_end (GTK_BOX(vbox), bbox, false, false, 0); - - // Create the cancel button. - widget = gtk_button_new_with_label ("Exit"); - gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0); - g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window); - - // Finally we can show everything. - gtk_widget_show_all (window); - - gtk_main (); - - if (GTK_IS_WINDOW(window)) - { - gtk_widget_destroy (window); - // If we don't do this, then the X window might not actually disappear. - while (g_main_context_iteration (NULL, FALSE)) {} - } + exitButton.GrabDefault(); + window.RunModal(); } } // namespace Gtk -int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad) +int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) { - return Gtk::PickIWad (wads, numwads, showwin, defaultiwad); + return Gtk::PickIWad (wads, numwads, showwin, defaultiwad, autoloadflags); } void I_ShowFatalError_Gtk(const char* errortext) { diff --git a/src/common/platform/win32/base_sysfb.cpp b/src/common/platform/win32/base_sysfb.cpp index 3cb8858a3..4d0219316 100644 --- a/src/common/platform/win32/base_sysfb.cpp +++ b/src/common/platform/win32/base_sysfb.cpp @@ -39,7 +39,7 @@ #include "gl_sysfb.h" #include "hardware.h" -#include "templates.h" + #include "version.h" #include "c_console.h" #include "v_video.h" @@ -50,9 +50,7 @@ #include "base_sysfb.h" #include "win32basevideo.h" #include "c_dispatch.h" - - -extern HWND Window; +#include "i_mainwindow.h" extern "C" { __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; @@ -85,7 +83,7 @@ EXTERN_CVAR(Int, vid_defheight) EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings); scrwidth = (int)displaysettings.dmPelsWidth; scrheight = (int)displaysettings.dmPelsHeight; - GetWindowRect(Window, &rect); + GetWindowRect(mainwindow.GetHandle(), &rect); cx = scrwidth / 2; cy = scrheight / 2; if (in_w > 0) winw = in_w; @@ -139,11 +137,11 @@ void SystemBaseFrameBuffer::SaveWindowedPos() } // Make sure we only save the window position if it's not fullscreen. static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX; - if ((GetWindowLong(Window, GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE) + if ((GetWindowLong(mainwindow.GetHandle(), GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE) { RECT wrect; - if (GetWindowRect(Window, &wrect)) + if (GetWindowRect(mainwindow.GetHandle(), &wrect)) { // If (win_x,win_y) specify to center the window, don't change them // if the window is still centered. @@ -171,7 +169,7 @@ void SystemBaseFrameBuffer::SaveWindowedPos() win_h = wrect.bottom - wrect.top; } - win_maximized = IsZoomed(Window) == TRUE; + win_maximized = IsZoomed(mainwindow.GetHandle()) == TRUE; } } @@ -204,10 +202,10 @@ void SystemBaseFrameBuffer::RestoreWindowedPos() } KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight); } - SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED); + SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED); if (win_maximized && !Args->CheckParm("-0")) - ShowWindow(Window, SW_MAXIMIZE); + ShowWindow(mainwindow.GetHandle(), SW_MAXIMIZE); } //========================================================================== @@ -226,8 +224,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h) { LONG style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW; LONG exStyle = WS_EX_WINDOWEDGE; - SetWindowLong(Window, GWL_STYLE, style); - SetWindowLong(Window, GWL_EXSTYLE, exStyle); + SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style); + SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle); int winx, winy, winw, winh, scrwidth, scrheight; @@ -250,8 +248,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h) if (!vid_fullscreen) { - ShowWindow(Window, SW_SHOWNORMAL); - SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED); + ShowWindow(mainwindow.GetHandle(), SW_SHOWNORMAL); + SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED); win_maximized = false; SetSize(GetClientWidth(), GetClientHeight()); SaveWindowedPos(); @@ -279,7 +277,7 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall) RECT r; LONG style, exStyle; - RECT monRect; + RECT monRect = {}; if (!m_Fullscreen && fullscreen && !initialcall) SaveWindowedPos(); if (m_Monitor) @@ -302,9 +300,9 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall) } } - ShowWindow(Window, SW_SHOW); + ShowWindow(mainwindow.GetHandle(), SW_SHOW); - GetWindowRect(Window, &r); + GetWindowRect(mainwindow.GetHandle(), &r); style = WS_VISIBLE | WS_CLIPSIBLINGS; exStyle = 0; @@ -316,13 +314,13 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall) exStyle |= WS_EX_WINDOWEDGE; } - SetWindowLong(Window, GWL_STYLE, style); - SetWindowLong(Window, GWL_EXSTYLE, exStyle); + SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style); + SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle); if (fullscreen) { - SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - MoveWindow(Window, monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE); + SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + MoveWindow(mainwindow.GetHandle(), monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE); // And now, seriously, it IS in the right place. Promise. } @@ -352,9 +350,9 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer(void *hMonitor, bool fullscreen) : m_displayDeviceName = 0; PositionWindow(fullscreen, true); - HDC hDC = GetDC(Window); + HDC hDC = GetDC(mainwindow.GetHandle()); - ReleaseDC(Window, hDC); + ReleaseDC(mainwindow.GetHandle(), hDC); } //========================================================================== @@ -367,10 +365,10 @@ SystemBaseFrameBuffer::~SystemBaseFrameBuffer() { if (!m_Fullscreen) SaveWindowedPos(); - ShowWindow (Window, SW_SHOW); - SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW); - SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE); - SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + ShowWindow (mainwindow.GetHandle(), SW_SHOW); + SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW); + SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, WS_EX_WINDOWEDGE); + SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); static_cast(Video)->Shutdown(); } @@ -407,13 +405,13 @@ void SystemBaseFrameBuffer::ToggleFullscreen(bool yes) int SystemBaseFrameBuffer::GetClientWidth() { RECT rect = { 0 }; - GetClientRect(Window, &rect); + GetClientRect(mainwindow.GetHandle(), &rect); return rect.right - rect.left; } int SystemBaseFrameBuffer::GetClientHeight() { RECT rect = { 0 }; - GetClientRect(Window, &rect); + GetClientRect(mainwindow.GetHandle(), &rect); return rect.bottom - rect.top; } diff --git a/src/common/platform/win32/gl_sysfb.cpp b/src/common/platform/win32/gl_sysfb.cpp index 17822d213..61073e968 100644 --- a/src/common/platform/win32/gl_sysfb.cpp +++ b/src/common/platform/win32/gl_sysfb.cpp @@ -39,7 +39,7 @@ #include "gl_sysfb.h" #include "hardware.h" -#include "templates.h" + #include "version.h" #include "c_console.h" #include "v_video.h" @@ -49,8 +49,7 @@ #include "m_argv.h" #include "engineerrors.h" #include "win32glvideo.h" - -extern HWND Window; +#include "i_mainwindow.h" extern "C" PROC zd_wglGetProcAddress(LPCSTR name); @@ -71,13 +70,13 @@ PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc; SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen) { - if (!static_cast(Video)->InitHardware(Window, 0)) + if (!static_cast(Video)->InitHardware(mainwindow.GetHandle(), 0)) { I_FatalError("Unable to initialize OpenGL"); return; } - HDC hDC = GetDC(Window); + HDC hDC = GetDC(mainwindow.GetHandle()); const char *wglext = nullptr; myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT"); @@ -102,7 +101,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst SwapInterval = -1; } } - ReleaseDC(Window, hDC); + ReleaseDC(mainwindow.GetHandle(), hDC); } //========================================================================== @@ -113,7 +112,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst EXTERN_CVAR(Bool, vid_vsync); CUSTOM_CVAR(Bool, gl_control_tear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { - vid_vsync.Callback(); + vid_vsync->Callback(); } void SystemGLFrameBuffer::SetVSync (bool vsync) diff --git a/src/common/platform/win32/hardware.cpp b/src/common/platform/win32/hardware.cpp index 3cadc1ced..1933bb521 100644 --- a/src/common/platform/win32/hardware.cpp +++ b/src/common/platform/win32/hardware.cpp @@ -44,18 +44,12 @@ #include "version.h" #include "printf.h" #include "win32glvideo.h" -#ifdef HAVE_SOFTPOLY -#include "win32polyvideo.h" -#endif #ifdef HAVE_VULKAN #include "win32vulkanvideo.h" #endif #include "engineerrors.h" #include "i_system.h" - -EXTERN_CVAR(Int, vid_preferbackend) - -extern HWND Window; +#include "i_mainwindow.h" IVideo *Video; @@ -111,18 +105,18 @@ void I_InitGraphics () // todo: implement ATI version of this. this only works for nvidia notebooks, for now. currentgpuswitch = vid_gpuswitch; if (currentgpuswitch == 1) - putenv("SHIM_MCCOMPAT=0x800000001"); // discrete + _putenv("SHIM_MCCOMPAT=0x800000001"); // discrete else if (currentgpuswitch == 2) - putenv("SHIM_MCCOMPAT=0x800000000"); // integrated + _putenv("SHIM_MCCOMPAT=0x800000000"); // integrated // If the focus window is destroyed, it doesn't go back to the active window. // (e.g. because the net pane was up, and a button on it had focus) - if (GetFocus() == NULL && GetActiveWindow() == Window) + if (GetFocus() == NULL && GetActiveWindow() == mainwindow.GetHandle()) { // Make sure it's in the foreground and focused. (It probably is // already foregrounded but may not be focused.) - SetForegroundWindow(Window); - SetFocus(Window); + SetForegroundWindow(mainwindow.GetHandle()); + SetFocus(mainwindow.GetHandle()); // Note that when I start a 2-player game on the same machine, the // window for the game that isn't focused, active, or foregrounded // still receives a WM_ACTIVATEAPP message telling it that it's the @@ -131,15 +125,8 @@ void I_InitGraphics () // are the active app. Huh? } -#ifdef HAVE_SOFTPOLY - if (vid_preferbackend == 2) - { - Video = new Win32PolyVideo(); - } - else -#endif #ifdef HAVE_VULKAN - if (vid_preferbackend == 1) + if (V_GetBackend() == 1) { // first try Vulkan, if that fails OpenGL try @@ -158,12 +145,8 @@ void I_InitGraphics () Video = new Win32GLVideo(); } -#ifdef HAVE_SOFTPOLY - if (Video == NULL) - Video = new Win32PolyVideo(); -#endif // we somehow STILL don't have a display!! if (Video == NULL) I_FatalError ("Failed to initialize display"); - + } diff --git a/src/common/platform/win32/i_crash.cpp b/src/common/platform/win32/i_crash.cpp index 90c0658f1..b90663597 100644 --- a/src/common/platform/win32/i_crash.cpp +++ b/src/common/platform/win32/i_crash.cpp @@ -34,6 +34,7 @@ // HEADER FILES ------------------------------------------------------------ +#pragma warning(disable:4996) #define WIN32_LEAN_AND_MEAN #include #include @@ -64,6 +65,7 @@ #include "zstring.h" #include "printf.h" #include "cmdlib.h" +#include "i_mainwindow.h" #include #include @@ -211,9 +213,6 @@ struct MiniDumpThreadData // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- -void I_FlushBufferedConsoleStuff(); - // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void AddFile (HANDLE file, const char *filename); @@ -339,7 +338,7 @@ static HANDLE WriteMyMiniDump (void) MINIDUMP_EXCEPTION_INFORMATION exceptor = { DbgThreadID, &CrashPointers, FALSE }; WCHAR dbghelpPath[MAX_PATH+12], *bs; WRITEDUMP pMiniDumpWriteDump; - HANDLE file; + HANDLE file = INVALID_HANDLE_VALUE; BOOL good = FALSE; HMODULE dbghelp = NULL; @@ -444,41 +443,6 @@ void Writef (HANDLE file, const char *format, ...) // //========================================================================== -static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb) -{ - DWORD 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) - { - 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 - { - pp = 0; - } - } - - if (!WriteFile((HANDLE)cookie, buffer, cb, &didwrite, NULL)) - { - return 1; - } - *pcb = didwrite; - return 0; -} //========================================================================== // @@ -488,15 +452,21 @@ static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG // //========================================================================== -HANDLE WriteLogFile(HWND edit) +HANDLE WriteLogFile() { HANDLE file; file = CreateTempFile(); if (file != INVALID_HANDLE_VALUE) { - EDITSTREAM streamer = { (DWORD_PTR)file, 0, WriteLogFileStreamer }; - SendMessage(edit, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer); + 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; } @@ -509,7 +479,7 @@ HANDLE WriteLogFile(HWND edit) // //========================================================================== -void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog) +void CreateCrashLog (const char *custominfo, DWORD customsize) { // Do not collect information more than once. if (NumFiles != 0) @@ -559,11 +529,7 @@ void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog) AddFile (file, "local.txt"); } } - if (richlog != NULL) - { - I_FlushBufferedConsoleStuff(); - AddFile (WriteLogFile(richlog), "log.rtf"); - } + AddFile (WriteLogFile(), "log.rtf"); CloseHandle (DbgProcess); } @@ -709,14 +675,14 @@ HANDLE WriteTextReport () ctxt->Rip, ctxt->Rsp, ctxt->SegCs, ctxt->SegSs, ctxt->EFlags); #endif - DWORD j; + DWORD dw; - for (i = 0, j = 1; (size_t)i < sizeof(eflagsBits)/sizeof(eflagsBits[0]); j <<= 1, ++i) + 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 & j ? '+' : '-'); + ctxt->EFlags & dw ? '+' : '-'); } } Writef (file, "\r\n"); @@ -1580,7 +1546,7 @@ static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, sho 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); diff --git a/src/common/platform/win32/i_dijoy.cpp b/src/common/platform/win32/i_dijoy.cpp index 79b6fcf8f..11f60a35f 100644 --- a/src/common/platform/win32/i_dijoy.cpp +++ b/src/common/platform/win32/i_dijoy.cpp @@ -45,7 +45,7 @@ #include "i_input.h" #include "d_eventbase.h" -#include "templates.h" + #include "gameconfigfile.h" #include "cmdlib.h" #include "v_text.h" @@ -53,6 +53,8 @@ #include "keydef.h" #include "printf.h" +#include "i_mainwindow.h" + #define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } } // WBEMIDL BITS -- because w32api doesn't have this, either ----------------- @@ -266,7 +268,6 @@ protected: // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern LPDIRECTINPUT8 g_pdi; -extern HWND Window; // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -281,14 +282,6 @@ CUSTOM_CVAR(Bool, joy_dinput, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCA static const uint8_t POVButtons[9] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09, 0x00 }; -//("dc12a687-737f-11cf-884d-00aa004b2e24") -static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf, - { 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; - -//("4590f811-1d3a-11d0-891f-00aa004b2e24") -static const CLSID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0, - { 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; - // CODE -------------------------------------------------------------------- //=========================================================================== @@ -380,7 +373,7 @@ bool FDInputJoystick::GetDevice() Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars()); return false; } - hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); + hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); if (FAILED(hr)) { Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars()); diff --git a/src/common/platform/win32/i_input.cpp b/src/common/platform/win32/i_input.cpp index 1b49f5680..05988060f 100644 --- a/src/common/platform/win32/i_input.cpp +++ b/src/common/platform/win32/i_input.cpp @@ -50,18 +50,6 @@ #pragma warning(disable:4244) #endif -// Compensate for w32api's lack -#ifndef WM_WTSSESSION_CHANGE -#define WM_WTSSESSION_CHANGE 0x02B1 -#define WTS_CONSOLE_CONNECT 1 -#define WTS_CONSOLE_DISCONNECT 2 -#define WTS_SESSION_LOCK 7 -#define WTS_SESSION_UNLOCK 8 -#endif -#ifndef PBT_APMSUSPEND -// w32api does not #define the PBT_ macros in winuser.h like the PSDK does -#include -#endif #ifndef GET_RAWINPUT_CODE_WPARAM #define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff) #endif @@ -75,7 +63,6 @@ #include "d_gui.h" #include "c_console.h" #include "s_soundinternal.h" -#include "gameconfigfile.h" #include "hardware.h" #include "d_eventbase.h" #include "v_text.h" @@ -86,6 +73,7 @@ #include "printf.h" #include "c_buttons.h" #include "cmdlib.h" +#include "i_mainwindow.h" // Compensate for w32api's lack #ifndef GET_XBUTTON_WPARAM @@ -104,9 +92,6 @@ FJoystickCollection *JoyDevices[NUM_JOYDEVICES]; extern HINSTANCE g_hInst; -extern DWORD SessionID; - -static HMODULE DInputDLL; bool GUICapture; extern FMouse *Mouse; @@ -116,7 +101,6 @@ extern bool ToggleFullscreen; bool VidResizing; extern BOOL vidactive; -extern HWND Window, ConWindow; EXTERN_CVAR (String, language) EXTERN_CVAR (Bool, lookstrafe) @@ -130,21 +114,16 @@ extern BOOL paused; static bool noidle = false; LPDIRECTINPUT8 g_pdi; -LPDIRECTINPUT g_pdi3; extern bool AppActive; -int SessionState = 0; int BlockMouseMove; static bool EventHandlerResultForNativeMouse; -CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -extern int chatmodeon; - static void I_CheckGUICapture () { bool wantCapt = sysCallbacks.WantGuiCapture && sysCallbacks.WantGuiCapture(); @@ -161,7 +140,7 @@ static void I_CheckGUICapture () void I_SetMouseCapture() { - SetCapture(Window); + SetCapture(mainwindow.GetHandle()); } void I_ReleaseMouseCapture() @@ -420,7 +399,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // If regional settings were changed, reget preferred languages if (wParam == 0 && lParam != 0 && strcmp ((const char *)lParam, "intl") == 0) { - language.Callback (); + language->Callback (); } return 0; @@ -445,7 +424,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SIZE: - InvalidateRect (Window, NULL, FALSE); + InvalidateRect (hWnd, NULL, FALSE); break; case WM_KEYDOWN: @@ -508,68 +487,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS); } - S_SetSoundPaused ((!!i_soundinbackground) || wParam); - break; - - case WM_WTSSESSION_CHANGE: - case WM_POWERBROADCAST: - { - int oldstate = SessionState; - - if (message == WM_WTSSESSION_CHANGE && lParam == (LPARAM)SessionID) - { -#ifdef _DEBUG - OutputDebugStringA ("SessionID matched\n"); -#endif - // When using fast user switching, XP will lock a session before - // disconnecting it, and the session will be unlocked before reconnecting it. - // For our purposes, video output will only happen when the session is - // both unlocked and connected (that is, SessionState is 0). - switch (wParam) - { - case WTS_SESSION_LOCK: - SessionState |= 1; - break; - case WTS_SESSION_UNLOCK: - SessionState &= ~1; - break; - case WTS_CONSOLE_DISCONNECT: - SessionState |= 2; - break; - case WTS_CONSOLE_CONNECT: - SessionState &= ~2; - break; - } - } - else if (message == WM_POWERBROADCAST) - { - switch (wParam) - { - case PBT_APMSUSPEND: - SessionState |= 4; - break; - case PBT_APMRESUMESUSPEND: - SessionState &= ~4; - break; - } - } - - if (GSnd != NULL) - { -#if 0 - // Do we actually need this here? - if (!oldstate && SessionState) - { - GSnd->SuspendSound (); - } -#endif - } -#ifdef _DEBUG - char foo[256]; - mysnprintf (foo, countof(foo), "Session Change: %ld %d\n", (long)lParam, (int)wParam); - OutputDebugStringA (foo); -#endif - } + S_SetSoundPaused (wParam); break; case WM_ERASEBKGND: @@ -600,58 +518,12 @@ bool I_InitInput (void *hwnd) noidle = !!Args->CheckParm ("-noidle"); g_pdi = NULL; - g_pdi3 = NULL; - // Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit. - DInputDLL = LoadLibraryA("dinput8.dll"); - if (DInputDLL != NULL) + hr = DirectInput8Create(g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&g_pdi, NULL); + if (FAILED(hr)) { - typedef HRESULT (WINAPI *blah)(HINSTANCE, DWORD, REFIID, LPVOID *, LPUNKNOWN); - blah di8c = (blah)GetProcAddress(DInputDLL, "DirectInput8Create"); - if (di8c != NULL) - { - hr = di8c(g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&g_pdi, NULL); - if (FAILED(hr)) - { - Printf(TEXTCOLOR_ORANGE "DirectInput8Create failed: %08lx\n", hr); - g_pdi = NULL; // Just to be sure DirectInput8Create didn't change it - } - } - else - { - Printf(TEXTCOLOR_ORANGE "Could not find DirectInput8Create in dinput8.dll\n"); - } - } - - if (g_pdi == NULL) - { - if (DInputDLL != NULL) - { - FreeLibrary(DInputDLL); - } - DInputDLL = LoadLibraryA ("dinput.dll"); - if (DInputDLL == NULL) - { - I_FatalError ("Could not load dinput.dll: %08lx", GetLastError()); - } - - typedef HRESULT (WINAPI *blah)(HINSTANCE, DWORD, LPDIRECTINPUT*, LPUNKNOWN); -#ifdef UNICODE - blah dic = (blah)GetProcAddress (DInputDLL, "DirectInputCreateW"); -#else - blah dic = (blah)GetProcAddress(DInputDLL, "DirectInputCreateA"); -#endif - - if (dic == NULL) - { - I_FatalError ("dinput.dll is corrupt"); - } - - hr = dic (g_hInst, 0x0300, &g_pdi3, NULL); - if (FAILED(hr)) - { - I_FatalError ("DirectInputCreate failed: %08lx", hr); - } + Printf(TEXTCOLOR_ORANGE "DirectInput8Create failed: %08lx\n", hr); + g_pdi = NULL; // Just to be sure DirectInput8Create didn't change it } Printf ("I_StartupMouse\n"); @@ -699,16 +571,6 @@ void I_ShutdownInput () g_pdi->Release (); g_pdi = NULL; } - if (g_pdi3) - { - g_pdi3->Release (); - g_pdi3 = NULL; - } - if (DInputDLL != NULL) - { - FreeLibrary (DInputDLL); - DInputDLL = NULL; - } } void I_GetEvent () @@ -823,7 +685,7 @@ IJoystickConfig *I_UpdateDeviceList() void I_PutInClipboard (const char *str) { - if (str == NULL || !OpenClipboard (Window)) + if (str == NULL || !OpenClipboard (mainwindow.GetHandle())) return; EmptyClipboard (); @@ -845,7 +707,7 @@ FString I_GetFromClipboard (bool return_nothing) HGLOBAL cliphandle; wchar_t *clipstr; - if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (Window)) + if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (mainwindow.GetHandle())) return retstr; cliphandle = GetClipboardData (CF_UNICODETEXT); diff --git a/src/common/platform/win32/i_input.h b/src/common/platform/win32/i_input.h index 433c1f2c6..643cc65b3 100644 --- a/src/common/platform/win32/i_input.h +++ b/src/common/platform/win32/i_input.h @@ -82,7 +82,6 @@ protected: void ClearButtonState(); int WheelMove[2]; - int LastX, LastY; // for m_filter int ButtonState; // bit mask of current button states (1=down, 0=up) }; diff --git a/src/common/platform/win32/i_keyboard.cpp b/src/common/platform/win32/i_keyboard.cpp index ce204f71c..33cf6da5b 100644 --- a/src/common/platform/win32/i_keyboard.cpp +++ b/src/common/platform/win32/i_keyboard.cpp @@ -40,6 +40,7 @@ #include "i_input.h" #include "d_eventbase.h" +#include "i_mainwindow.h" // MACROS ------------------------------------------------------------------ @@ -58,7 +59,7 @@ class FDInputKeyboard : public FKeyboard public: FDInputKeyboard(); ~FDInputKeyboard(); - + bool GetDevice(); void ProcessInput(); @@ -87,9 +88,7 @@ protected: // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -extern HWND Window; extern LPDIRECTINPUT8 g_pdi; -extern LPDIRECTINPUT g_pdi3; extern bool GUICapture; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -320,17 +319,13 @@ bool FDInputKeyboard::GetDevice() { HRESULT hr; - if (g_pdi3 != NULL) - { // DirectInput3 interface - hr = g_pdi3->CreateDevice(GUID_SysKeyboard, (LPDIRECTINPUTDEVICE*)&Device, NULL); - } - else if (g_pdi != NULL) + if (g_pdi != NULL) { // DirectInput8 interface hr = g_pdi->CreateDevice(GUID_SysKeyboard, &Device, NULL); } else { - hr = -1; + hr = E_FAIL; } if (FAILED(hr)) { @@ -347,7 +342,7 @@ ufailit: return false; } - hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); if (FAILED(hr)) { goto ufailit; @@ -379,11 +374,11 @@ void FDInputKeyboard::ProcessInput() DIDEVICEOBJECTDATA od; DWORD dwElements; HRESULT hr; - bool foreground = (GetForegroundWindow() == Window); + bool foreground = (GetForegroundWindow() == mainwindow.GetHandle()); for (;;) { - DWORD cbObjectData = g_pdi3 ? sizeof(DIDEVICEOBJECTDATA_DX3) : sizeof(DIDEVICEOBJECTDATA); + DWORD cbObjectData = sizeof(DIDEVICEOBJECTDATA); dwElements = 1; hr = Device->GetDeviceData(cbObjectData, &od, &dwElements, 0); if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) @@ -448,7 +443,7 @@ bool FRawKeyboard::GetDevice() rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE; rid.usUsage = HID_GDP_KEYBOARD; rid.dwFlags = RIDEV_INPUTSINK; - rid.hwndTarget = Window; + rid.hwndTarget = mainwindow.GetHandle(); if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { return false; diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index acdfd2eb5..c28a3ff4b 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -43,14 +43,12 @@ #include #include +#include #ifdef _MSC_VER #pragma warning(disable:4244) #endif -//#include -#define NOTIFY_FOR_THIS_SESSION 0 - #ifdef _MSC_VER #include #include @@ -80,11 +78,15 @@ #include "startupinfo.h" #include "printf.h" +#include "i_mainwindow.h" + // MACROS ------------------------------------------------------------------ // The main window's title. #ifdef _M_X64 #define X64 " 64-bit" +#elif _M_ARM64 +#define X64 " ARM-64" #else #define X64 "" #endif @@ -94,9 +96,8 @@ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); -void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richedit); +void CreateCrashLog (const char *custominfo, DWORD customsize); void DisplayCrashLog (); -void I_FlushBufferedConsoleStuff(); void DestroyCustomCursor(); int GameMain(); @@ -115,213 +116,13 @@ extern UINT TimerPeriod; FArgs *Args; HINSTANCE g_hInst; -DWORD SessionID; HANDLE MainThread; DWORD MainThreadID; HANDLE StdOut; bool FancyStdOut, AttachedStdOut; -bool ConWindowHidden; - -// The main window -HWND Window; - -// The subwindows used for startup and error output -HWND ConWindow, GameTitleWindow; -HWND ErrorPane, ProgressBar, NetStartPane, StartupScreen, ErrorIcon; - -HFONT GameTitleFont; -LONG GameTitleFontHeight; -LONG DefaultGUIFontHeight; -LONG ErrorIconChar; - -FModule Kernel32Module{"Kernel32"}; -FModule Shell32Module{"Shell32"}; -FModule User32Module{"User32"}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static const WCHAR WinClassName[] = WGAMENAME "MainWindow"; -static HMODULE hwtsapi32; // handle to wtsapi32.dll // CODE -------------------------------------------------------------------- -//========================================================================== -// -// UnCOM -// -// Called by atexit if CoInitialize() succeeded. -// -//========================================================================== - -static void UnCOM (void) -{ - CoUninitialize (); -} - -//========================================================================== -// -// UnWTS -// -// Called by atexit if RegisterSessionNotification() succeeded. -// -//========================================================================== - -static void UnWTS (void) -{ - if (hwtsapi32 != 0) - { - typedef BOOL (WINAPI *ursn)(HWND); - ursn unreg = (ursn)GetProcAddress (hwtsapi32, "WTSUnRegisterSessionNotification"); - if (unreg != 0) - { - unreg (Window); - } - FreeLibrary (hwtsapi32); - hwtsapi32 = 0; - } -} - -//========================================================================== -// -// LayoutErrorPane -// -// Lays out the error pane to the desired width, returning the required -// height. -// -//========================================================================== - -static int 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; -} - -//========================================================================== -// -// LayoutNetStartPane -// -// Lays out the network startup pane to the specified width, returning -// its required height. -// -//========================================================================== - -int 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; -} - -//========================================================================== -// -// LayoutMainWindow -// -// Lays out the main window with the game title and log controls and -// possibly the error pane and progress bar. -// -//========================================================================== - -void 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); - } - // If there is a startup screen, it covers the log window - if (StartupScreen != NULL) - { - SetWindowPos (StartupScreen, HWND_TOP, leftside, bannerheight, w - leftside, - h - bannerheight - errorpaneheight - progressheight - netpaneheight, SWP_SHOWWINDOW); - InvalidateRect (StartupScreen, NULL, FALSE); - MoveWindow (ConWindow, 0, 0, 0, 0, TRUE); - } - else - { - // The log window uses whatever space is left. - MoveWindow (ConWindow, leftside, bannerheight, w - leftside, - h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE); - } -} - //========================================================================== // @@ -332,436 +133,7 @@ void LayoutMainWindow (HWND hWnd, HWND pane) void I_SetIWADInfo() { // Make the startup banner show itself - LayoutMainWindow(Window, NULL); -} - -//========================================================================== -// -// LConProc -// -// The main window's WndProc during startup. During gameplay, the WndProc -// in i_input.cpp is used instead. -// -//========================================================================== - -LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND view; - HDC hdc; - HBRUSH hbr; - HGDIOBJ oldfont; - RECT rect; - SIZE size; - LOGFONT lf; - TEXTMETRIC tm; - HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); - DRAWITEMSTRUCT *drawitem; - CHARFORMAT2W format; - - switch (msg) - { - case WM_CREATE: - // 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; - - case WM_SIZE: - if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW) - { - LayoutMainWindow (hWnd, ErrorPane); - } - return 0; - - case WM_DRAWITEM: - // 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 startup screen - else if (wParam == IDC_STATIC_STARTUP) - { - if (StartupScreen != NULL) - { - drawitem = (LPDRAWITEMSTRUCT)lParam; - - rect = drawitem->rcItem; - // Windows expects DIBs to be bottom-up but ours is top-down, - // so flip it vertically while drawing it. - StretchDIBits (drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom, - 0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight, - ST_Util_BitsForBitmap(StartupBitmap), reinterpret_cast(StartupBitmap), DIB_RGB_COLORS, SRCCOPY); - - // If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt - // where the command prompt would have been in DOS. - if (GameTitleWindow == NULL) - { - auto quitmsg = WideString(GStrings("TXT_QUITENDOOM")); - - SetTextColor (drawitem->hDC, RGB(240,240,240)); - SetBkMode (drawitem->hDC, TRANSPARENT); - oldfont = SelectObject (drawitem->hDC, (HFONT)GetStockObject (DEFAULT_GUI_FONT)); - TextOutW (drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, quitmsg.c_str(), (int)quitmsg.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; - - case WM_COMMAND: - 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; - } - break; - - case WM_CLOSE: - PostQuitMessage (0); - break; - - case WM_DESTROY: - if (GameTitleFont != NULL) - { - DeleteObject (GameTitleFont); - } - break; - } - return DefWindowProc (hWnd, msg, wParam, lParam); -} - -//========================================================================== -// -// ErrorPaneProc -// -// DialogProc for the error pane. -// -//========================================================================== - -bool restartrequest; - -void 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); - } - restartrequest = false; -} - -INT_PTR CALLBACK ErrorPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - // Appear in the main window. - 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 - { - restartrequest = true; - } - PostQuitMessage (0); - return TRUE; - } - break; - } - return FALSE; -} - -//========================================================================== -// -// I_SetWndProc -// -// Sets the main WndProc, hides all the child windows, and starts up -// in-game input. -// -//========================================================================== - -void I_SetWndProc() -{ - if (GetWindowLongPtr (Window, GWLP_USERDATA) == 0) - { - SetWindowLongPtr (Window, GWLP_USERDATA, 1); - SetWindowLongPtr (Window, GWLP_WNDPROC, (WLONG_PTR)WndProc); - ShowWindow (ConWindow, SW_HIDE); - ShowWindow(ProgressBar, SW_HIDE); - ConWindowHidden = true; - ShowWindow (GameTitleWindow, SW_HIDE); - I_InitInput (Window); - } -} - -//========================================================================== -// -// RestoreConView -// -// Returns the main window to its startup state. -// -//========================================================================== - -void 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, (WLONG_PTR)LConProc); - ShowWindow (ConWindow, SW_SHOW); - ConWindowHidden = false; - ShowWindow (GameTitleWindow, SW_SHOW); - I_ShutdownInput (); // Make sure the mouse pointer is available. - // Make sure the progress bar isn't visible. - DeleteStartupScreen(); -} - -//========================================================================== -// -// ShowErrorPane -// -// Shows an error message, preferably in the main window, but it can -// use a normal message box too. -// -//========================================================================== - -void ShowErrorPane(const char *text) -{ - auto widetext = WideString(text); - if (Window == nullptr || ConWindow == nullptr) - { - if (text != NULL) - { - MessageBoxW (Window, widetext.c_str(), - WGAMENAME " Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL); - } - return; - } - - if (StartScreen != NULL) // Ensure that the network pane is hidden. - { - StartScreen->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, g_hInst, NULL); - if (ErrorIcon != NULL) - { - SetWindowLong (ErrorIcon, GWL_ID, IDC_ICONPIC); - } - } - ErrorPane = CreateDialogParam (g_hInst, 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 PeekThreadedErrorPane() -{ - // Allow SendMessage from another thread to call its message handler so that it can display the crash dialog - MSG msg; - PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); -} - -static void UnTbp() -{ - timeEndPeriod(TimerPeriod); + mainwindow.UpdateLayout(); } //========================================================================== @@ -777,7 +149,7 @@ int DoMain (HINSTANCE hInstance) RECT cRect; TIMECAPS tc; DEVMODE displaysettings; - + // Do not use the multibyte __argv here because we want UTF-8 arguments // and those can only be done by converting the Unicode variants. Args = new FArgs(); @@ -787,17 +159,7 @@ int DoMain (HINSTANCE hInstance) { Args->AppendArg(FString(wargv[i])); } - - // Load Win32 modules - Kernel32Module.Load({"kernel32.dll"}); - Shell32Module.Load({"shell32.dll"}); - User32Module.Load({"user32.dll"}); - - // Under XP, get our session ID so we can know when the user changes/locks sessions. - // Since we need to remain binary compatible with older versions of Windows, we - // need to extract the ProcessIdToSessionId function from kernel32.dll manually. - HMODULE kernel = GetModuleHandleA ("kernel32.dll"); - + if (Args->CheckParm("-stdout")) { // As a GUI application, we don't normally get a console when we start. @@ -805,7 +167,7 @@ int DoMain (HINSTANCE hInstance) // console. Otherwise, we can create a new one. If we already have a // stdout handle, then we have been redirected and should just use that // handle instead of creating a console window. - + StdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (StdOut != NULL) { @@ -820,7 +182,7 @@ int DoMain (HINSTANCE hInstance) StdOut = NULL; } } - if (StdOut == NULL) + if (StdOut == nullptr) { if (AttachConsole(ATTACH_PARENT_PROCESS)) { @@ -828,46 +190,33 @@ int DoMain (HINSTANCE hInstance) DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL); AttachedStdOut = true; } - if (StdOut == NULL && AllocConsole()) + if (StdOut == nullptr && AllocConsole()) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); } - - // These two functions do not exist in Windows XP. - BOOL (WINAPI* p_GetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx); - BOOL (WINAPI* p_SetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx); - - p_SetCurrentConsoleFontEx = (decltype(p_SetCurrentConsoleFontEx))GetProcAddress(kernel, "SetCurrentConsoleFontEx"); - p_GetCurrentConsoleFontEx = (decltype(p_GetCurrentConsoleFontEx))GetProcAddress(kernel, "GetCurrentConsoleFontEx"); - if (p_SetCurrentConsoleFontEx && p_GetCurrentConsoleFontEx) + if (StdOut != nullptr) { - CONSOLE_FONT_INFOEX cfi; - cfi.cbSize = sizeof(cfi); - - if (p_GetCurrentConsoleFontEx(StdOut, false, &cfi)) + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + DWORD mode; + if (GetConsoleMode(StdOut, &mode)) { - if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive. - { - //cfi.dwFontSize = { 8, 14 }; - wcscpy(cfi.FaceName, L"Lucida Console"); - cfi.FontFamily = FF_DONTCARE; - p_SetCurrentConsoleFontEx(StdOut, false, &cfi); - } + if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. } } - FancyStdOut = true; } } - + // Set the timer to be as accurate as possible if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR) TimerPeriod = 1; // Assume minimum resolution of 1 ms else TimerPeriod = tc.wPeriodMin; - + timeBeginPeriod (TimerPeriod); - atexit(UnTbp); - + atexit([](){ timeEndPeriod(TimerPeriod); }); + // Figure out what directory the program resides in. WCHAR progbuff[1024]; if (GetModuleFileNameW(nullptr, progbuff, sizeof progbuff) == 0) @@ -875,22 +224,22 @@ int DoMain (HINSTANCE hInstance) MessageBoxA(nullptr, "Fatal", "Could not determine program location.", MB_ICONEXCLAMATION|MB_OK); exit(-1); } - + progbuff[1023] = '\0'; if (auto lastsep = wcsrchr(progbuff, '\\')) { lastsep[1] = '\0'; } - + progdir = progbuff; FixPathSeperator(progdir); - + HDC screenDC = GetDC(0); int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); ReleaseDC(0, screenDC); width = (512 * dpi + 96 / 2) / 96; height = (384 * dpi + 96 / 2) / 96; - + // Many Windows structures that specify their size do so with the first // element. DEVMODE is not one of those structures. memset (&displaysettings, 0, sizeof(displaysettings)); @@ -898,88 +247,26 @@ int DoMain (HINSTANCE hInstance) EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); x = (displaysettings.dmPelsWidth - width) / 2; y = (displaysettings.dmPelsHeight - height) / 2; - + if (Args->CheckParm ("-0")) { x = y = 0; } - - WNDCLASS WndClass; - WndClass.style = 0; - WndClass.lpfnWndProc = LConProc; - WndClass.cbClsExtra = 0; - WndClass.cbWndExtra = 0; - WndClass.hInstance = hInstance; - WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1)); - WndClass.hCursor = LoadCursor (NULL, IDC_ARROW); - WndClass.hbrBackground = NULL; - WndClass.lpszMenuName = NULL; - WndClass.lpszClassName = WinClassName; - - /* register this new class with Windows */ - if (!RegisterClass((LPWNDCLASS)&WndClass)) - { - MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION|MB_OK); - exit(-1); - } - + /* create window */ FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); - std::wstring wcaption = caption.WideString(); - Window = CreateWindowExW( - WS_EX_APPWINDOW, - WinClassName, - wcaption.c_str(), - WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, - x, y, width, height, - (HWND) NULL, - (HMENU) NULL, - hInstance, - NULL); - - if (!Window) - { - MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK); - exit(-1); - } - - if (kernel != NULL) - { - typedef BOOL (WINAPI *pts)(DWORD, DWORD *); - pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId"); - if (pidsid != 0) - { - if (!pidsid (GetCurrentProcessId(), &SessionID)) - { - SessionID = 0; - } - hwtsapi32 = LoadLibraryA ("wtsapi32.dll"); - if (hwtsapi32 != 0) - { - FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification"); - if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION)) - { - FreeLibrary (hwtsapi32); - hwtsapi32 = 0; - } - else - { - atexit (UnWTS); - } - } - } - } - - GetClientRect (Window, &cRect); - + mainwindow.Create(caption, x, y, width, height); + + GetClientRect (mainwindow.GetHandle(), &cRect); + WinWidth = cRect.right; WinHeight = cRect.bottom; - + CoInitialize (NULL); - atexit (UnCOM); - + atexit ([](){ CoUninitialize(); }); // beware of calling convention. + int ret = GameMain (); - CheckForRestart(); + mainwindow.CheckForRestart(); DestroyCustomCursor(); if (ret == 1337) // special exit code for 'norun'. @@ -990,8 +277,8 @@ int DoMain (HINSTANCE hInstance) { // Outputting to a new console window: Wait for a keypress before quitting. DWORD bytes; HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE); - - ShowWindow(Window, SW_HIDE); + + ShowWindow(mainwindow.GetHandle(), SW_HIDE); WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL); FlushConsoleInputBuffer(stdinput); SetConsoleMode(stdinput, 0); @@ -999,7 +286,7 @@ int DoMain (HINSTANCE hInstance) } else if (StdOut == NULL) { - ShowErrorPane(NULL); + mainwindow.ShowErrorPane(nullptr); } } } @@ -1009,18 +296,17 @@ int DoMain (HINSTANCE hInstance) void I_ShowFatalError(const char *msg) { I_ShutdownGraphics (); - RestoreConView (); + mainwindow.RestoreConView(); S_StopMusic(true); - I_FlushBufferedConsoleStuff(); if (CVMAbortException::stacktrace.IsNotEmpty()) { Printf("%s", CVMAbortException::stacktrace.GetChars()); } - + if (!batchrun) { - ShowErrorPane(msg); + mainwindow.ShowErrorPane(msg); } else { @@ -1087,7 +373,7 @@ void CALLBACK ExitFatally (ULONG_PTR dummy) { SetUnhandledExceptionFilter (ExitMessedUp); I_ShutdownGraphics (); - RestoreConView (); + mainwindow.RestoreConView (); DisplayCrashLog (); exit(-1); } @@ -1122,7 +408,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) CrashPointers = *info; if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n"); - CreateCrashLog (custominfo, (DWORD)strlen(custominfo), ConWindow); + 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. @@ -1208,7 +494,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int *(int *)0 = 0; } __except(CrashPointers = *GetExceptionInformation(), - CreateCrashLog ("TestCrash", 9, NULL), EXCEPTION_EXECUTE_HANDLER) + CreateCrashLog ("TestCrash", 9), EXCEPTION_EXECUTE_HANDLER) { } DisplayCrashLog (); @@ -1221,7 +507,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int infiniterecursion(1); } __except(CrashPointers = *GetExceptionInformation(), - CreateCrashLog ("TestStackCrash", 14, NULL), EXCEPTION_EXECUTE_HANDLER) + CreateCrashLog ("TestStackCrash", 14), EXCEPTION_EXECUTE_HANDLER) { } DisplayCrashLog (); @@ -1277,15 +563,5 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int // each platform has its own specific version of this function. void I_SetWindowTitle(const char* caption) { - std::wstring widecaption; - if (!caption) - { - FStringf default_caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); - widecaption = default_caption.WideString(); - } - else - { - widecaption = WideString(caption); - } - SetWindowText(Window, widecaption.c_str()); + mainwindow.SetWindowTitle(caption); } diff --git a/src/common/platform/win32/i_mainwindow.cpp b/src/common/platform/win32/i_mainwindow.cpp new file mode 100644 index 000000000..5b246e457 --- /dev/null +++ b/src/common/platform/win32/i_mainwindow.cpp @@ -0,0 +1,889 @@ + +#include "i_mainwindow.h" +#include "resource.h" +#include "startupinfo.h" +#include "gstrings.h" +#include "palentry.h" +#include "st_start.h" +#include "i_input.h" +#include "version.h" +#include "utf8.h" +#include "v_font.h" +#include "i_net.h" +#include "engineerrors.h" +#include +#include +#include + +#ifdef _M_X64 +#define X64 " 64-bit" +#elif _M_ARM64 +#define X64 " ARM-64" +#else +#define X64 "" +#endif + +MainWindow mainwindow; + +void MainWindow::Create(const FString& caption, int x, int y, int width, int height) +{ + static const WCHAR WinClassName[] = L"MainWindow"; + + HINSTANCE hInstance = GetModuleHandle(0); + + WNDCLASS WndClass; + WndClass.style = 0; + WndClass.lpfnWndProc = LConProc; + WndClass.cbClsExtra = 0; + WndClass.cbWndExtra = 0; + WndClass.hInstance = hInstance; + WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); + WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + WndClass.hbrBackground = NULL; + WndClass.lpszMenuName = NULL; + WndClass.lpszClassName = WinClassName; + + /* register this new class with Windows */ + if (!RegisterClass((LPWNDCLASS)&WndClass)) + { + MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION | MB_OK); + exit(-1); + } + + std::wstring wcaption = caption.WideString(); + Window = CreateWindowExW( + WS_EX_APPWINDOW, + WinClassName, + wcaption.c_str(), + WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, + x, y, width, height, + (HWND)NULL, + (HMENU)NULL, + hInstance, + NULL); + + if (!Window) + { + MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION | MB_OK); + exit(-1); + } +} + +void MainWindow::HideGameTitleWindow() +{ + if (GameTitleWindow != 0) + { + DestroyWindow(GameTitleWindow); + GameTitleWindow = 0; + } +} + +int MainWindow::GetGameTitleWindowHeight() +{ + if (GameTitleWindow != 0) + { + RECT rect; + GetClientRect(GameTitleWindow, &rect); + return rect.bottom; + } + else + { + return 0; + } +} + +// Sets the main WndProc, hides all the child windows, and starts up in-game input. +void MainWindow::ShowGameView() +{ + if (GetWindowLongPtr(Window, GWLP_USERDATA) == 0) + { + 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); + } +} + +// 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. + // 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. + { + 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); +} + +void MainWindow::HideProgressBar() +{ + if (ProgressBar != 0) + { + DestroyWindow(ProgressBar); + ProgressBar = 0; + LayoutMainWindow(Window, 0); + } +} + +void MainWindow::SetProgressPos(int pos) +{ + if (ProgressBar != 0) + SendMessage(ProgressBar, PBM_SETPOS, pos, 0); +} + +// 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; +} + +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""); + } + } +} + +void MainWindow::HideNetStartPane() +{ + if (NetStartPane != 0) + { + DestroyWindow(NetStartPane); + NetStartPane = 0; + LayoutMainWindow(Window, 0); + } +} + +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); + } +} + +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; +} + +void 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); + } + restartrequest = false; +} + +// 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(); +} + +static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG* pcb) +{ + 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) + { + 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 + { + pp = 0; + } + } + + 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. +void MainWindow::SetWindowTitle(const char* caption) +{ + std::wstring widecaption; + if (!caption) + { + FStringf default_caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); + widecaption = default_caption.WideString(); + } + else + { + widecaption = WideString(caption); + } + SetWindowText(Window, widecaption.c_str()); +} diff --git a/src/common/platform/win32/i_mainwindow.h b/src/common/platform/win32/i_mainwindow.h new file mode 100644 index 000000000..2adea7bfa --- /dev/null +++ b/src/common/platform/win32/i_mainwindow.h @@ -0,0 +1,90 @@ +#pragma once + +#include "zstring.h" +#include "printf.h" + +#include + +#define WIN32_LEAN_AND_MEAN +#include + +// The WndProc used when the game view is active +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +class MainWindow +{ +public: + void Create(const FString& title, int x, int y, int width, int height); + + void ShowGameView(); + void RestoreConView(); + + void ShowErrorPane(const char* text); + void CheckForRestart(); + + void HideGameTitleWindow(); + int GetGameTitleWindowHeight(); + + 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); + void HideNetStartPane(); + + void SetWindowTitle(const char* caption); + + 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 7da7e1c4b..f9fb1b8ab 100644 --- a/src/common/platform/win32/i_mouse.cpp +++ b/src/common/platform/win32/i_mouse.cpp @@ -46,6 +46,7 @@ #include "menustate.h" #include "keydef.h" #include "i_interface.h" +#include "i_mainwindow.h" // MACROS ------------------------------------------------------------------ @@ -86,7 +87,7 @@ class FDInputMouse : public FMouse public: FDInputMouse(); ~FDInputMouse(); - + bool GetDevice(); void ProcessInput(); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); @@ -103,7 +104,7 @@ class FWin32Mouse : public FMouse public: FWin32Mouse(); ~FWin32Mouse(); - + bool GetDevice(); void ProcessInput(); bool WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); @@ -138,9 +139,7 @@ static void CenterMouse(int x, int y, LONG *centx, LONG *centy); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -extern HWND Window; extern LPDIRECTINPUT8 g_pdi; -extern LPDIRECTINPUT g_pdi3; extern bool GUICapture; extern int BlockMouseMove; @@ -193,11 +192,11 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) static void SetCursorState(bool visible) { CursorState = visible || !m_hidepointer; - if (GetForegroundWindow() == Window) + if (GetForegroundWindow() == mainwindow.GetHandle()) { if (CursorState) { - SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(Window, GCLP_HCURSOR)); + SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR)); } else { @@ -219,7 +218,7 @@ static void CenterMouse(int curx, int cury, LONG *centxp, LONG *centyp) { RECT rect; - GetWindowRect(Window, &rect); + GetWindowRect(mainwindow.GetHandle(), &rect); int centx = (rect.left + rect.right) >> 1; int centy = (rect.top + rect.bottom) >> 1; @@ -258,7 +257,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) } else { - if ((GetForegroundWindow() != Window) || preferNative || !use_mouse) + if ((GetForegroundWindow() != mainwindow.GetHandle()) || preferNative || !use_mouse) { want_native = true; } @@ -268,7 +267,6 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) } else { - bool pauseState = false; bool captureModeInGame = sysCallbacks.CaptureModeInGame && sysCallbacks.CaptureModeInGame(); want_native = ((!m_use_mouse || menuactive != MENU_WaitKey) && (!captureModeInGame || GUICapture)); @@ -306,7 +304,6 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) FMouse::FMouse() { - LastX = LastY = 0; ButtonState = 0; WheelMove[0] = 0; WheelMove[1] = 0; @@ -491,7 +488,7 @@ bool FRawMouse::GetDevice() rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE; rid.usUsage = HID_GDP_MOUSE; rid.dwFlags = 0; - rid.hwndTarget = Window; + rid.hwndTarget = mainwindow.GetHandle(); if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { return false; @@ -517,7 +514,7 @@ void FRawMouse::Grab() rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE; rid.usUsage = HID_GDP_MOUSE; rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY; - rid.hwndTarget = Window; + rid.hwndTarget = mainwindow.GetHandle(); if (RegisterRawInputDevices(&rid, 1, sizeof(rid))) { GetCursorPos(&UngrabbedPointerPos); @@ -682,23 +679,19 @@ bool FDInputMouse::GetDevice() { HRESULT hr; - if (g_pdi3 != NULL) - { // DirectInput3 interface - hr = g_pdi3->CreateDevice(GUID_SysMouse, (LPDIRECTINPUTDEVICE*)&Device, NULL); - } - else if (g_pdi != NULL) + if (g_pdi != NULL) { // DirectInput8 interface hr = g_pdi->CreateDevice(GUID_SysMouse, &Device, NULL); } else { - hr = -1; + hr = E_FAIL; } if (FAILED(hr)) { return false; } - + // How many buttons does this mouse have? DIDEVCAPS_DX3 caps = { sizeof(caps) }; hr = Device->GetCapabilities((DIDEVCAPS *)&caps); @@ -719,7 +712,7 @@ ufailit: return false; } - hr = Device->SetCooperativeLevel(Window, DISCL_EXCLUSIVE | DISCL_FOREGROUND); + hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_EXCLUSIVE | DISCL_FOREGROUND); if (FAILED(hr)) { goto ufailit; @@ -785,7 +778,7 @@ void FDInputMouse::ProcessInput() event_t ev = { 0 }; for (;;) { - DWORD cbObjectData = g_pdi3 ? sizeof(DIDEVICEOBJECTDATA_DX3) : sizeof(DIDEVICEOBJECTDATA); + DWORD cbObjectData = sizeof(DIDEVICEOBJECTDATA); dwElements = 1; hr = Device->GetDeviceData(cbObjectData, &od, &dwElements, 0); if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) @@ -1067,11 +1060,11 @@ void FWin32Mouse::Grab() GetCursorPos(&UngrabbedPointerPos); ClipCursor(NULL); // helps with Win95? - GetClientRect(Window, &rect); + GetClientRect(mainwindow.GetHandle(), &rect); // Reposition the rect so that it only covers the client area. - ClientToScreen(Window, (LPPOINT)&rect.left); - ClientToScreen(Window, (LPPOINT)&rect.right); + ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.left); + ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.right); ClipCursor(&rect); SetCursorState(false); diff --git a/src/common/platform/win32/i_rawps2.cpp b/src/common/platform/win32/i_rawps2.cpp index 2a7547f3e..f06378803 100644 --- a/src/common/platform/win32/i_rawps2.cpp +++ b/src/common/platform/win32/i_rawps2.cpp @@ -38,12 +38,14 @@ #include "i_input.h" #include "d_eventbase.h" -#include "templates.h" + #include "gameconfigfile.h" #include "m_argv.h" #include "cmdlib.h" #include "keydef.h" +#include "i_mainwindow.h" + // MACROS ------------------------------------------------------------------ #define DEFAULT_DEADZONE 0.25f @@ -214,8 +216,6 @@ struct PS2Descriptor // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -extern HWND Window; - // PUBLIC DATA DEFINITIONS ------------------------------------------------- CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL) @@ -503,7 +503,7 @@ bool FRawPS2Controller::ProcessInput(RAWHID *raw, int code) // Generate events for buttons that have changed. int buttons = 0; - + // If we know we are digital, ignore the D-Pad. if (!digital) { @@ -538,7 +538,7 @@ void FRawPS2Controller::ProcessThumbstick(int value1, AxisInfo *axis1, int value { uint8_t buttonstate; double axisval1, axisval2; - + axisval1 = value1 * (2.0 / 255) - 1.0; axisval2 = value2 * (2.0 / 255) - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); @@ -905,7 +905,7 @@ bool FRawPS2Manager::GetDevice() rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE; rid.usUsage = HID_GDP_JOYSTICK; rid.dwFlags = RIDEV_INPUTSINK; - rid.hwndTarget = Window; + rid.hwndTarget = mainwindow.GetHandle(); if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { return false; @@ -1273,7 +1273,7 @@ void FRawPS2Manager::DoRegister() if (!Registered) { rid.dwFlags = RIDEV_INPUTSINK; - rid.hwndTarget = Window; + rid.hwndTarget = mainwindow.GetHandle(); if (RegisterRawInputDevices(&rid, 1, sizeof(rid))) { Registered = true; diff --git a/src/common/platform/win32/i_specialpaths.cpp b/src/common/platform/win32/i_specialpaths.cpp index bbd3c4976..3bfee00ea 100644 --- a/src/common/platform/win32/i_specialpaths.cpp +++ b/src/common/platform/win32/i_specialpaths.cpp @@ -37,21 +37,19 @@ #include #include #include +#include #include "i_specialpaths.h" #include "printf.h" #include "cmdlib.h" #include "findfile.h" #include "version.h" // for GAMENAME +#include "gstrings.h" +#include "i_mainwindow.h" +#include "engineerrors.h" -// Vanilla MinGW does not have folder ids -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -static const GUID FOLDERID_LocalAppData = { 0xf1b32785, 0x6fba, 0x4fcf, 0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91 }; -static const GUID FOLDERID_RoamingAppData = { 0x3eb685db, 0x65f9, 0x4cf6, 0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d }; -static const GUID FOLDERID_SavedGames = { 0x4c5c32ff, 0xbb9d, 0x43b0, 0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4 }; -static const GUID FOLDERID_Documents = { 0xfdd39ad0, 0x238f, 0x46af, 0xad, 0xb4, 0x6c, 0x85, 0x48, 0x03, 0x69, 0xc7 }; -static const GUID FOLDERID_Pictures = { 0x33e28130, 0x4e1e, 0x4676, 0x83, 0x5a, 0x98, 0x39, 0x5c, 0x3b, 0xc3, 0xbb }; -#endif + +static int isportable = -1; //=========================================================================== // @@ -62,18 +60,18 @@ static const GUID FOLDERID_Pictures = { 0x33e28130, 0x4e1e, 0x4676, 0x83, 0x5a, // //=========================================================================== -bool UseKnownFolders() +bool IsPortable() { // Cache this value so the semantics don't change during a single run // of the program. (e.g. Somebody could add write access while the // program is running.) - static int iswritable = -1; HANDLE file; - if (iswritable >= 0) + if (isportable >= 0) { - return !iswritable; + return !!isportable; } + // Consider 'Program Files' read only without actually checking. bool found = false; for (auto p : { L"ProgramFiles", L"ProgramFiles(x86)" }) @@ -85,50 +83,51 @@ bool UseKnownFolders() FixPathSeperator(envpath); if (progdir.MakeLower().IndexOf(envpath.MakeLower()) == 0) { - found = true; - break; + isportable = false; + return false; } } } - if (!found) + // A portable INI means that this storage location should also be portable if the file can be written to. + FStringf path("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars()); + if (FileExists(path)) { - std::wstring testpath = progdir.WideString() + L"writest"; - file = CreateFile(testpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); + file = CreateFile(path.WideString().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file != INVALID_HANDLE_VALUE) { CloseHandle(file); - if (!batchrun) Printf("Using program directory for storage\n"); - iswritable = true; - return false; + if (!batchrun) Printf("Using portable configuration\n"); + isportable = true; + return true; } } - if (!batchrun) Printf("Using known folders for storage\n"); - iswritable = false; - return true; + + isportable = false; + return false; } //=========================================================================== // // GetKnownFolder // -// Returns the known_folder if SHGetKnownFolderPath is available, otherwise -// returns the shell_folder using SHGetFolderPath. +// Returns the known_folder from SHGetKnownFolderPath // //=========================================================================== -bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path) +FString GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create) { PWSTR wpath; if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath))) { - return false; + // This should never be triggered unless the OS was compromised + I_FatalError("Unable to retrieve known folder."); } - path = wpath; + FString path = FString(wpath); + FixPathSeperator(path); CoTaskMemFree(wpath); - return true; + return path; } //=========================================================================== @@ -141,14 +140,9 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create FString M_GetAppDataPath(bool create) { - FString path; + FString path = GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create); - if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) - { // Failed (e.g. On Win9x): use program directory - path = progdir; - } path += "/" GAMENAMELOWERCASE; - path.Substitute("//", "/"); // needed because progdir ends with a slash. if (create) { CreatePath(path); @@ -166,16 +160,11 @@ FString M_GetAppDataPath(bool create) FString M_GetCachePath(bool create) { - FString path; + FString path = GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create); - if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) - { // Failed (e.g. On Win9x): use program directory - path = progdir; - } // Don't use GAME_DIR and such so that ZDoom and its child ports can // share the node cache. path += "/zdoom/cache"; - path.Substitute("//", "/"); // needed because progdir ends with a slash. if (create) { CreatePath(path); @@ -196,6 +185,84 @@ FString M_GetAutoexecPath() return "$PROGDIR/autoexec.cfg"; } +//=========================================================================== +// +// M_GetOldConfigPath +// +// Check if we have a config in a place that's no longer used. +// +//=========================================================================== + +FString M_GetOldConfigPath(int& type) +{ + FString path; + HRESULT hr; + + // construct "$PROGDIR/-$USER.ini" + WCHAR uname[UNLEN + 1]; + DWORD unamelen = UNLEN; + + path = progdir; + hr = GetUserNameW(uname, &unamelen); + if (SUCCEEDED(hr) && uname[0] != 0) + { + // Is it valid for a user name to have slashes? + // Check for them and substitute just in case. + auto probe = uname; + while (*probe != 0) + { + if (*probe == '\\' || *probe == '/') + *probe = '_'; + ++probe; + } + path << GAMENAMELOWERCASE "-" << FString(uname) << ".ini"; + type = 0; + if (FileExists(path)) + return path; + } + + // Check in app data where this was previously stored. + // We actually prefer to store the config in a more visible place so this is no longer used. + path = GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true); + path += "/" GAME_DIR "/" GAMENAMELOWERCASE ".ini"; + type = 1; + if (FileExists(path)) + return path; + + return ""; +} + +//=========================================================================== +// +// M_MigrateOldConfig +// +// Ask the user what to do with their old config. +// +//=========================================================================== + +int M_MigrateOldConfig() +{ + int selection = IDCANCEL; + auto globalstr = L"Move to Users/ folder"; + auto portablestr = L"Convert to portable installation"; + auto cancelstr = L"Cancel"; + auto titlestr = L"Migrate existing configuration"; + auto infostr = L"" GAMENAME " found a user specific config in the game folder"; + const TASKDIALOG_BUTTON buttons[] = { {IDYES, globalstr}, {IDNO, portablestr}, {IDCANCEL, cancelstr} }; + TASKDIALOGCONFIG taskDialogConfig = {}; + taskDialogConfig.cbSize = sizeof(TASKDIALOGCONFIG); + taskDialogConfig.pszMainIcon = TD_WARNING_ICON; + taskDialogConfig.pButtons = buttons; + taskDialogConfig.cButtons = countof(buttons); + taskDialogConfig.pszWindowTitle = titlestr; + taskDialogConfig.pszContent = infostr; + taskDialogConfig.hwndParent = mainwindow.GetHandle(); + taskDialogConfig.dwFlags = TDF_USE_COMMAND_LINKS; + TaskDialogIndirect(&taskDialogConfig, &selection, NULL, NULL); + if (selection == IDYES || selection == IDNO) return selection; + throw CExitEvent(3); +} + //=========================================================================== // // M_GetConfigPath Windows @@ -208,51 +275,43 @@ FString M_GetAutoexecPath() FString M_GetConfigPath(bool for_reading) { - FString path; - HRESULT hr; - - path.Format("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars()); - if (FileExists(path)) + if (IsPortable()) { - return path; + return FStringf("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars()); } - path = ""; // Construct a user-specific config name - if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path)) + FString path = GetKnownFolder(CSIDL_APPDATA, FOLDERID_Documents, true); + path += "/My Games/" GAME_DIR; + CreatePath(path); + path += "/" GAMENAMELOWERCASE ".ini"; + if (!for_reading || FileExists(path)) + return path; + + // No config was found in the accepted locations. + // Look in previously valid places to see if we have something we can migrate + + int type = 0; + FString oldpath = M_GetOldConfigPath(type); + if (!oldpath.IsEmpty()) { - path += "/" GAME_DIR; - CreatePath(path); - path += "/" GAMENAMELOWERCASE ".ini"; - } - else - { // construct "$PROGDIR/-$USER.ini" - WCHAR uname[UNLEN+1]; - DWORD unamelen = UNLEN; - - path = progdir; - hr = GetUserNameW(uname, &unamelen); - if (SUCCEEDED(hr) && uname[0] != 0) + if (type == 0) { - // Is it valid for a user name to have slashes? - // Check for them and substitute just in case. - auto probe = uname; - while (*probe != 0) + // If we find a local per-user config, ask the user what to do with it. + int action = M_MigrateOldConfig(); + if (action == IDNO) { - if (*probe == '\\' || *probe == '/') - *probe = '_'; - ++probe; + path.Format("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars()); + isportable = true; } - path << GAMENAMELOWERCASE "-" << FString(uname) << ".ini"; - } - else - { // Couldn't get user name, so just use base version. - path += GAMENAMELOWERCASE ".ini"; } + bool res = MoveFileExW(WideString(oldpath).c_str(), WideString(path).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. } - // If we are reading the config file, check if it exists. If not, fallback - // to base version. + // Fall back to the global template if nothing was found. + // If we are reading the config file, check if it exists. If not, fallback to base version. if (for_reading) { if (!FileExists(path)) @@ -273,30 +332,25 @@ FString M_GetConfigPath(bool for_reading) // //=========================================================================== -// I'm not sure when FOLDERID_Screenshots was added, but it was probably -// for Windows 8, since it's not in the v7.0 Windows SDK. -static const GUID MyFOLDERID_Screenshots = { 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f }; - FString M_GetScreenshotsPath() { FString path; - if (!UseKnownFolders()) + if (IsPortable()) { - path << progdir << "/Screenshots/"; + path << progdir << "Screenshots/"; } - else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path)) + else if (IsWindows8OrGreater()) { + path = GetKnownFolder(-1, FOLDERID_Screenshots, true); + path << "/" GAMENAME "/"; } - else if (GetKnownFolder(CSIDL_MYPICTURES, FOLDERID_Pictures, true, path)) + else { + path = GetKnownFolder(CSIDL_MYPICTURES, FOLDERID_Pictures, true); path << "/Screenshots/" GAMENAME "/"; } - else - { - path << progdir << "/Screenshots/"; - } CreatePath(path); return path; } @@ -313,27 +367,16 @@ FString M_GetSavegamesPath() { FString path; - if (!UseKnownFolders()) + if (IsPortable()) { path << progdir << "Save/"; } // Try standard Saved Games folder - else if (GetKnownFolder(-1, FOLDERID_SavedGames, true, path)) - { - path << "/" GAMENAME "/"; - } - // Try defacto My Documents/My Games folder - else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) - { - // I assume since this isn't a standard folder, it doesn't have - // a localized name either. - path << "/My Games/" GAMENAME "/"; - } else { - path << progdir << "Save/"; + path = GetKnownFolder(-1, FOLDERID_SavedGames, true); + path << "/" GAMENAME "/"; } - return path; } @@ -349,29 +392,18 @@ FString M_GetDocumentsPath() { FString path; - // A portable INI means that this storage location should also be portable. - path.Format("%s" GAMENAME "_portable.ini", progdir.GetChars()); - if (FileExists(path)) - { - return progdir; - } - - if (!UseKnownFolders()) + if (IsPortable()) { return progdir; } // Try defacto My Documents/My Games folder - else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) + else { - // I assume since this isn't a standard folder, it doesn't have - // a localized name either. + // 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); } - else - { - path = progdir; - } return path; } @@ -388,23 +420,17 @@ FString M_GetDemoPath() FString path; // A portable INI means that this storage location should also be portable. - FStringf inipath("%s" GAMENAME "_portable.ini", progdir.GetChars()); - if (FileExists(inipath) || !UseKnownFolders()) + if (IsPortable()) { path << progdir << "Demos/"; } else // Try defacto My Documents/My Games folder - if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) { - // I assume since this isn't a standard folder, it doesn't have - // a localized name either. + // 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 "/"; } - else - { - path << progdir << "Demos/"; - } return path; } diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 103b26f31..bd1d0dbbe 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -6,6 +6,7 @@ ** Copyright 1998-2009 Randy Heit ** Copyright (C) 2007-2012 Skulltag Development Team ** Copyright (C) 2007-2016 Zandronum Development Team +** Copyright (C) 2017-2022 GZDoom Development Team ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -45,12 +46,15 @@ // HEADER FILES ------------------------------------------------------------ +#pragma warning(disable:4996) #include #include #include +#include #include #include #include +#include #include @@ -61,6 +65,8 @@ #include #include +#include + #include "hardware.h" #include "printf.h" @@ -73,13 +79,13 @@ #include "i_input.h" #include "c_dispatch.h" -#include "templates.h" -#include "gameconfigfile.h" + #include "v_font.h" #include "i_system.h" #include "bitmap.h" #include "cmdlib.h" #include "i_interface.h" +#include "i_mainwindow.h" // MACROS ------------------------------------------------------------------ @@ -91,10 +97,6 @@ // TYPES ------------------------------------------------------------------- -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -extern void LayoutMainWindow(HWND hWnd, HWND pane); - // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void DestroyCustomCursor(); @@ -109,19 +111,13 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP EXTERN_CVAR (Bool, queryiwad); // Used on welcome/IWAD screen. -EXTERN_CVAR (Bool, disableautoload) -EXTERN_CVAR (Bool, autoloadlights) -EXTERN_CVAR (Bool, autoloadbrightmaps) -EXTERN_CVAR (Bool, autoloadwidescreen) EXTERN_CVAR (Int, vid_preferbackend) -extern HWND Window, ConWindow, GameTitleWindow; extern HANDLE StdOut; extern bool FancyStdOut; extern HINSTANCE g_hInst; extern FILE *Logfile; extern bool NativeMouse; -extern bool ConWindowHidden; // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -280,175 +276,46 @@ void CalculateCPUSpeed() // //========================================================================== -static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut) +static void PrintToStdOut(const char *cpt, HANDLE StdOut) { - if (edit == nullptr && StdOut == nullptr && !con_debugoutput) - return; + const char* srcp = cpt; + FString printData = ""; + bool terminal = FancyStdOut; - wchar_t wbuf[256]; - int bpos = 0; - CHARRANGE selection; - CHARRANGE endselection; - LONG lines_before = 0, lines_after; - CHARFORMAT format; - - if (edit != NULL) + while (*srcp != 0) { - // Store the current selection and set it to the end so we can append text. - SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&selection); - endselection.cpMax = endselection.cpMin = GetWindowTextLength(edit); - SendMessage(edit, 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(edit, EM_EXGETSEL, 0, (LPARAM)&endselection); - - // Remember how many lines there were before we added text. - lines_before = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0); - } - - const uint8_t *cptr = (const uint8_t*)cpt; - - auto outputIt = [&]() - { - wbuf[bpos] = 0; - if (edit != nullptr) + if (*srcp == 0x1c && terminal) { - SendMessageW(edit, EM_REPLACESEL, FALSE, (LPARAM)wbuf); - } - if (con_debugoutput) - { - OutputDebugStringW(wbuf); - } - if (StdOut != nullptr) - { - // Convert back to UTF-8. - DWORD bytes_written; - if (!FancyStdOut) + srcp += 1; + const uint8_t* scratch = (const uint8_t*)srcp; // GCC does not like direct casting of the parameter. + EColorRange range = V_ParseFontColor(scratch, CR_UNTRANSLATED, CR_YELLOW); + srcp = (char*)scratch; + if (range != CR_UNDEFINED) { - FString conout(wbuf); - WriteFile(StdOut, conout.GetChars(), (DWORD)conout.Len(), &bytes_written, NULL); - } - else - { - WriteConsoleW(StdOut, wbuf, bpos, &bytes_written, nullptr); + PalEntry color = V_LogColorFromColorRange(range); + printData.AppendFormat("\033[38;2;%u;%u;%um", color.r, color.g, color.b); } } - bpos = 0; - }; - - while (int chr = GetCharFromString(cptr)) - { - if ((chr == TEXTCOLOR_ESCAPE && bpos != 0) || bpos == 255) + else if (*srcp != 0x1c && *srcp != 0x1d && *srcp != 0x1e && *srcp != 0x1f) { - 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; + printData += *srcp++; } 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); - if (StdOut != NULL && FancyStdOut) - { - // Unfortunately, we are pretty limited here: There are only - // eight basic colors, and each comes in a dark and a bright - // variety. - float h, s, v, r, g, b; - int attrib = 0; - - RGBtoHSV(color.r / 255.f, color.g / 255.f, color.b / 255.f, &h, &s, &v); - if (s != 0) - { // color - HSVtoRGB(&r, &g, &b, h, 1, 1); - if (r == 1) attrib = FOREGROUND_RED; - if (g == 1) attrib |= FOREGROUND_GREEN; - if (b == 1) attrib |= FOREGROUND_BLUE; - if (v > 0.6) attrib |= FOREGROUND_INTENSITY; - } - else - { // gray - if (v < 0.33) attrib = FOREGROUND_INTENSITY; - else if (v < 0.90) attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - else attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; - } - SetConsoleTextAttribute(StdOut, (WORD)attrib); - } - if (edit != NULL) - { - // GDI uses BGR colors, but color is RGB, so swap the R and the B. - std::swap(color.r, color.b); - // Change the color. - format.cbSize = sizeof(format); - format.dwMask = CFM_COLOR; - format.dwEffects = 0; - format.crTextColor = color; - SendMessage(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format); - } - } + if (srcp[1] != 0) srcp += 2; + else break; } } - if (bpos != 0) - { - outputIt(); - } - - if (edit != NULL) - { - // 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 (edit); - lines_after = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0); - if (lines_after > lines_before) - { - SendMessage(edit, EM_LINESCROLL, 0, lines_after - lines_before); - } - } - // Restore the previous selection. - SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&selection); - // Give the edit control a chance to redraw itself. - I_GetEvent(); - } - if (StdOut != NULL && FancyStdOut) - { // Set text back to gray, in case it was changed. - SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - } + DWORD bytes_written; + WriteFile(StdOut, printData.GetChars(), (DWORD)printData.Len(), &bytes_written, NULL); + if (terminal) + WriteFile(StdOut, "\033[0m", 4, &bytes_written, NULL); } -static TArray bufferedConsoleStuff; - void I_PrintStr(const char *cp) { - if (ConWindowHidden) - { - bufferedConsoleStuff.Push(cp); - DoPrintStr(cp, NULL, StdOut); - } - else - { - DoPrintStr(cp, ConWindow, StdOut); - } -} - -void I_FlushBufferedConsoleStuff() -{ - for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++) - { - DoPrintStr(bufferedConsoleStuff[i], ConWindow, NULL); - } - bufferedConsoleStuff.Clear(); + mainwindow.PrintStr(cp); + PrintToStdOut(cp, StdOut); } //========================================================================== @@ -485,9 +352,12 @@ static void SetQueryIWad(HWND dialog) // 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; @@ -516,10 +386,8 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa case 1: SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN2, BM_SETCHECK, BST_CHECKED, 0 ); break; - case 2: - SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN3, BM_SETCHECK, BST_CHECKED, 0 ); - break; #ifdef HAVE_GLES2 + case 2: case 3: SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN4, BM_SETCHECK, BST_CHECKED, 0 ); break; @@ -531,10 +399,10 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // [SP] This is our's - SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, disableautoload ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, autoloadlights ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, autoloadbrightmaps ? BST_CHECKED : BST_UNCHECKED, 0 ); - SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_SETCHECK, autoloadwidescreen ? BST_CHECKED : BST_UNCHECKED, 0 ); + 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. sprintf(szString, "Version %s.", GetVersionString()); @@ -580,21 +448,20 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa vid_fullscreen = SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; #ifdef HAVE_GLES2 if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN4, BM_GETCHECK, 0, 0) == BST_CHECKED) - vid_preferbackend = 3; + vid_preferbackend = 2; else #endif - if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN3, BM_GETCHECK, 0, 0) == BST_CHECKED) - vid_preferbackend = 2; - else if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN2, BM_GETCHECK, 0, 0) == BST_CHECKED) + if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN2, BM_GETCHECK, 0, 0) == BST_CHECKED) vid_preferbackend = 1; else if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN1, BM_GETCHECK, 0, 0) == BST_CHECKED) vid_preferbackend = 0; // [SP] This is our's. - disableautoload = SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - autoloadlights = SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - autoloadbrightmaps = SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - autoloadwidescreen = SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; + 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)); } @@ -611,10 +478,10 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // //========================================================================== -int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad) +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; @@ -634,7 +501,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad) DefaultWad = defaultiwad; return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG), - (HWND)Window, (DLGPROC)IWADBoxCallback); + (HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback); } return defaultiwad; } @@ -681,16 +548,16 @@ bool I_SetCursor(FGameTexture *cursorpic) DestroyCustomCursor(); cursor = LoadCursor(NULL, IDC_ARROW); } - SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)cursor); + SetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR, (LONG_PTR)cursor); if (NativeMouse) { POINT pt; RECT client; // If the mouse pointer is within the window's client rect, set it now. - if (GetCursorPos(&pt) && GetClientRect(Window, &client) && - ClientToScreen(Window, (LPPOINT)&client.left) && - ClientToScreen(Window, (LPPOINT)&client.right)) + if (GetCursorPos(&pt) && GetClientRect(mainwindow.GetHandle(), &client) && + ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.left) && + ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.right)) { if (pt.x >= client.left && pt.x < client.right && pt.y >= client.top && pt.y < client.bottom) @@ -778,7 +645,7 @@ static HCURSOR CreateAlphaCursor(FBitmap &source, int leftofs, int topofs) // Find closest integer scale factor for the monitor DPI HDC screenDC = GetDC(0); int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); - int scale = std::max((dpi + 96 / 2 - 1) / 96, 1); + int scale = max((dpi + 96 / 2 - 1) / 96, 1); ReleaseDC(0, screenDC); memset(&bi, 0, sizeof(bi)); @@ -867,7 +734,7 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP // Delete the bitmaps. DeleteObject(and_mask); DeleteObject(color_mask); - + return cursor; } @@ -894,7 +761,7 @@ void DestroyCustomCursor() // //========================================================================== -bool I_WriteIniFailed() +bool I_WriteIniFailed(const char* filename) { char *lpMsgBuf; FString errortext; @@ -909,9 +776,9 @@ bool I_WriteIniFailed() 0, NULL ); - errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf); + errortext.Format ("The config file %s could not be written:\n%s", filename, lpMsgBuf); LocalFree (lpMsgBuf); - return MessageBoxA(Window, errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY; + return MessageBoxA(mainwindow.GetHandle(), errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY; } @@ -1090,3 +957,43 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode) SetThreadAffinityMask(handle, (DWORD_PTR)numaNodes[numaNode].affinityMask); } } + +FString I_GetCWD() +{ + auto len = GetCurrentDirectoryW(0, nullptr); + TArray curdir(len + 1, true); + if (!GetCurrentDirectoryW(len + 1, curdir.Data())) + { + return ""; + } + FString returnv(curdir.Data()); + FixPathSeperator(returnv); + return returnv; +} + +bool I_ChDir(const char* path) +{ + return SetCurrentDirectoryW(WideString(path).c_str()); +} + + +void I_OpenShellFolder(const char* infolder) +{ + auto len = GetCurrentDirectoryW(0, nullptr); + TArray curdir(len + 1, true); + if (!GetCurrentDirectoryW(len + 1, curdir.Data())) + { + Printf("Unable to retrieve current directory\n"); + } + else if (SetCurrentDirectoryW(WideString(infolder).c_str())) + { + 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); + } +} + diff --git a/src/common/platform/win32/i_system.h b/src/common/platform/win32/i_system.h index f7b2f239b..9d360b55a 100644 --- a/src/common/platform/win32/i_system.h +++ b/src/common/platform/win32/i_system.h @@ -38,13 +38,10 @@ void I_PrintStr (const char *cp); void I_SetIWADInfo (); // Pick from multiple IWADs to use -int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad); +int I_PickIWad(WadStuff* wads, int numwads, bool queryiwad, int defaultiwad, int& autoloadflags); // The ini could not be saved at exit -bool I_WriteIniFailed (); - -// [RH] Used by the display code to set the normal window procedure -void I_SetWndProc(); +bool I_WriteIniFailed (const char* filename); // [RH] Checks the registry for Steam's install path, so we can scan its // directories for IWADs if the user purchased any through Steam. @@ -82,4 +79,8 @@ int I_GetNumaNodeCount(); int I_GetNumaNodeThreadCount(int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode); +void I_OpenShellFolder(const char*); +FString I_GetCWD(); +bool I_ChDir(const char* path); + #endif diff --git a/src/common/platform/win32/i_xinput.cpp b/src/common/platform/win32/i_xinput.cpp index 7085de82f..ba4605dd0 100644 --- a/src/common/platform/win32/i_xinput.cpp +++ b/src/common/platform/win32/i_xinput.cpp @@ -40,7 +40,7 @@ #include "i_input.h" #include "d_eventbase.h" -#include "templates.h" + #include "gameconfigfile.h" #include "m_argv.h" #include "cmdlib.h" @@ -310,7 +310,7 @@ void FXInputController::ProcessThumbstick(int value1, AxisInfo *axis1, { uint8_t buttonstate; double axisval1, axisval2; - + axisval1 = (value1 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval2 = (value2 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); @@ -337,7 +337,7 @@ void FXInputController::ProcessTrigger(int value, AxisInfo *axis, int base) { uint8_t buttonstate; double axisval; - + axisval = Joy_RemoveDeadZone(value / 256.0, axis->DeadZone, &buttonstate); Joy_GenerateButtonEvents(axis->ButtonValue, buttonstate, 1, base); axis->ButtonValue = buttonstate; diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index f36371a9b..07039add2 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -41,7 +41,7 @@ #include "st_start.h" #include "cmdlib.h" -#include "templates.h" + #include "i_system.h" #include "i_input.h" #include "hardware.h" @@ -53,49 +53,15 @@ #include "startupinfo.h" #include "i_interface.h" #include "texturemanager.h" - -// MACROS ------------------------------------------------------------------ - -// How many ms elapse between blinking text flips. On a standard VGA -// adapter, the characters are on for 16 frames and then off for another 16. -// The number here therefore corresponds roughly to the blink rate on a -// 60 Hz display. -#define BLINK_PERIOD 267 -#define TEXT_FONT_NAME "vga-rom-font.16" - - -// TYPES ------------------------------------------------------------------- +#include "i_mainwindow.h" // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -void RestoreConView(); -void LayoutMainWindow (HWND hWnd, HWND pane); -int LayoutNetStartPane (HWND pane, int w); - -bool ST_Util_CreateStartupWindow (); void ST_Util_SizeWindowForBitmap (int scale); -void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern HINSTANCE g_hInst; -extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTitleWindow; - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -FStartupScreen *StartScreen; - -CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < 0) self = 0; - else if (self > 2) self=2; -} // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -110,36 +76,9 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //========================================================================== -FStartupScreen *FStartupScreen::CreateInstance(int max_progress) +FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool showprogress) { - FStartupScreen *scr = NULL; - HRESULT hr; - - if (!Args->CheckParm("-nostartup")) - { - if (GameStartupInfo.Type == FStartupInfo::HexenStartup) - { - scr = new FHexenStartupScreen(max_progress, hr); - } - else if (GameStartupInfo.Type == FStartupInfo::HereticStartup) - { - scr = new FHereticStartupScreen(max_progress, hr); - } - else if (GameStartupInfo.Type == FStartupInfo::StrifeStartup) - { - scr = new FStrifeStartupScreen(max_progress, hr); - } - if (scr != NULL && FAILED(hr)) - { - delete scr; - scr = NULL; - } - } - if (scr == NULL) - { - scr = new FBasicStartupScreen(max_progress, true); - } - return scr; + return new FBasicStartupScreen(max_progress, showprogress); } //========================================================================== @@ -155,12 +94,7 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) { if (show_bar) { - ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, - NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, - 0, 0, 0, 0, - Window, 0, g_hInst, NULL); - SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos)); - LayoutMainWindow (Window, NULL); + mainwindow.ShowProgressBar(MaxPos); } NetMaxPos = 0; NetCurPos = 0; @@ -177,13 +111,8 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) FBasicStartupScreen::~FBasicStartupScreen() { - if (ProgressBar != NULL) - { - DestroyWindow (ProgressBar); - ProgressBar = NULL; - LayoutMainWindow (Window, NULL); - } - KillTimer(Window, 1337); + mainwindow.HideProgressBar(); + KillTimer(mainwindow.GetHandle(), 1337); } //========================================================================== @@ -199,7 +128,7 @@ void FBasicStartupScreen::Progress() if (CurPos < MaxPos) { CurPos++; - SendMessage (ProgressBar, PBM_SETPOS, CurPos, 0); + mainwindow.SetProgressPos(CurPos); } } @@ -218,61 +147,8 @@ void FBasicStartupScreen::Progress() void FBasicStartupScreen::NetInit(const char *message, int numplayers) { NetMaxPos = numplayers; - if (NetStartPane == NULL) - { - NetStartPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0); - // We don't need two progress bars. - if (ProgressBar != NULL) - { - DestroyWindow (ProgressBar); - ProgressBar = NULL; - } - 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); - } - if (NetStartPane != NULL) - { - HWND ctl; + mainwindow.ShowNetStartPane(message, numplayers); - std::wstring wmessage = WideString(message); - SetDlgItemTextW (NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str()); - ctl = GetDlgItem (NetStartPane, IDC_NETSTARTPROGRESS); - - if (numplayers == 0) - { - // PBM_SETMARQUEE is only available under XP and above, so this might fail. - NetMarqueeMode = SendMessage (ctl, PBM_SETMARQUEE, TRUE, 100); - if (NetMarqueeMode == FALSE) - { - SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,16)); - } - else - { - // If we don't set the PBS_MARQUEE style, then the marquee will never show up. - SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) | PBS_MARQUEE); - } - SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L""); - } - else - { - NetMarqueeMode = FALSE; - SendMessage (ctl, PBM_SETMARQUEE, FALSE, 0); - // Make sure the marquee really is turned off. - SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) & (~PBS_MARQUEE)); - - SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,numplayers)); - if (numplayers == 1) - { - SendMessage (ctl, PBM_SETPOS, 1, 0); - SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L""); - } - } - } NetMaxPos = numplayers; NetCurPos = 0; NetProgress(1); // You always know about yourself @@ -288,33 +164,7 @@ void FBasicStartupScreen::NetInit(const char *message, int numplayers) void FBasicStartupScreen::NetDone() { - if (NetStartPane != NULL) - { - DestroyWindow (NetStartPane); - NetStartPane = NULL; - LayoutMainWindow (Window, NULL); - } -} - -//========================================================================== -// -// FBasicStartupScreen :: NetMessage -// -// Call this between NetInit() and NetDone() instead of Printf() to -// display messages, in case the progress meter is mixed in the same output -// stream as normal messages. -// -//========================================================================== - -void FBasicStartupScreen::NetMessage(const char *format, ...) -{ - FString str; - va_list argptr; - - va_start (argptr, format); - str.VFormat (format, argptr); - va_end (argptr); - Printf ("%s\n", str.GetChars()); + mainwindow.HideNetStartPane(); } //========================================================================== @@ -326,7 +176,7 @@ void FBasicStartupScreen::NetMessage(const char *format, ...) // //========================================================================== -void FBasicStartupScreen :: NetProgress(int count) +void FBasicStartupScreen::NetProgress(int count) { if (count == 0) { @@ -336,23 +186,8 @@ void FBasicStartupScreen :: NetProgress(int count) { NetCurPos = count; } - if (NetStartPane == NULL) - { - return; - } - if (NetMaxPos == 0 && !NetMarqueeMode) - { - // PBM_SETMARQUEE didn't work, so just increment the progress bar endlessly. - SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, NetCurPos & 15, 0); - } - else if (NetMaxPos > 1) - { - char buf[16]; - mysnprintf (buf, countof(buf), "%d/%d", NetCurPos, NetMaxPos); - SetDlgItemTextA (NetStartPane, IDC_NETSTARTCOUNT, buf); - SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, std::min(NetCurPos, NetMaxPos), 0); - } + mainwindow.SetNetStartProgress(count); } //========================================================================== @@ -371,350 +206,5 @@ void FBasicStartupScreen :: NetProgress(int count) bool FBasicStartupScreen::NetLoop(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 - { - if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337) - { - if (timer_callback (userdata)) - { - KillTimer (NetStartPane, 1); - return true; - } - } - if (!IsDialogMessage (NetStartPane, &msg)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - } - } - KillTimer (Window, 1337); - return false; -} - -//========================================================================== -// -// NetStartPaneProc -// -// 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) - { - PostQuitMessage (0); - return TRUE; - } - return FALSE; -} - -//========================================================================== -// -// FGraphicalStartupScreen Constructor -// -// This doesn't really do anything. The subclass is responsible for -// creating the resources that will be freed by this class's destructor. -// -//========================================================================== - -FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress) -: FBasicStartupScreen(max_progress, false) -{ -} - -//========================================================================== -// -// FGraphicalStartupScreen Destructor -// -//========================================================================== - -FGraphicalStartupScreen::~FGraphicalStartupScreen() -{ - if (StartupScreen != NULL) - { - DestroyWindow (StartupScreen); - StartupScreen = NULL; - } - if (StartupBitmap != NULL) - { - ST_Util_FreeBitmap (StartupBitmap); - StartupBitmap = NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FHexenStartupScreen::SetWindowSize() -{ - ST_Util_SizeWindowForBitmap(1); - LayoutMainWindow(Window, NULL); - InvalidateRect(StartupScreen, NULL, TRUE); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FHereticStartupScreen::SetWindowSize() -{ - ST_Util_SizeWindowForBitmap(1); - LayoutMainWindow(Window, NULL); - InvalidateRect(StartupScreen, NULL, TRUE); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FStrifeStartupScreen::SetWindowSize() -{ - ST_Util_SizeWindowForBitmap(2); - LayoutMainWindow(Window, NULL); - InvalidateRect(StartupScreen, NULL, TRUE); -} - -//========================================================================== -// -// ST_Endoom -// -// Shows an ENDOOM text screen -// -//========================================================================== - -int RunEndoom() -{ - if (showendoom == 0 || endoomName.Len() == 0) - { - return 0; - } - - int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true); - - uint8_t endoom_screen[4000]; - uint8_t *font; - MSG mess; - BOOL bRet; - bool blinking = false, blinkstate = false; - int i; - - if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) - { - return 0; - } - - if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2) - { - // showendoom==2 means to show only lumps from PWADs. - return 0; - } - - font = ST_Util_LoadFont (TEXT_FONT_NAME); - if (font == NULL) - { - return 0; - } - - if (!ST_Util_CreateStartupWindow()) - { - ST_Util_FreeFont (font); - return 0; - } - - I_ShutdownGraphics (); - RestoreConView (); - S_StopMusic(true); - - fileSystem.ReadFile (endoom_lump, endoom_screen); - - // Draw the loading screen to a bitmap. - StartupBitmap = ST_Util_AllocTextBitmap (font); - ST_Util_DrawTextScreen (StartupBitmap, endoom_screen, font); - - // Make the title banner go away. - if (GameTitleWindow != NULL) - { - DestroyWindow (GameTitleWindow); - GameTitleWindow = NULL; - } - - ST_Util_SizeWindowForBitmap (1); - LayoutMainWindow (Window, NULL); - InvalidateRect (StartupScreen, NULL, TRUE); - - // Does this screen need blinking? - for (i = 0; i < 80*25; ++i) - { - if (endoom_screen[1+i*2] & 0x80) - { - blinking = true; - break; - } - } - if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0) - { - blinking = false; - } - - // Wait until any key has been pressed or a quit message has been received - for (;;) - { - bRet = GetMessage (&mess, NULL, 0, 0); - if (bRet == 0 || bRet == -1 || // bRet == 0 means we received WM_QUIT - mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) - { - if (blinking) - { - KillTimer (Window, 0x5A15A); - } - ST_Util_FreeBitmap (StartupBitmap); - ST_Util_FreeFont (font); - return int(bRet == 0 ? mess.wParam : 0); - } - else if (blinking && mess.message == WM_TIMER && mess.hwnd == Window && mess.wParam == 0x5A15A) - { - ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, font, blinkstate); - blinkstate = !blinkstate; - } - TranslateMessage (&mess); - DispatchMessage (&mess); - } -} - -void ST_Endoom() -{ - TexMan.DeleteAll(); - int code = RunEndoom(); - throw CExitEvent(code); - -} - -//========================================================================== -// -// ST_Util_CreateStartupWindow -// -// Creates the static control that will draw the startup screen. -// -//========================================================================== - -bool ST_Util_CreateStartupWindow () -{ - StartupScreen = CreateWindowEx (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, - WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, - 0, 0, 0, 0, Window, NULL, g_hInst, NULL); - if (StartupScreen == NULL) - { - return false; - } - SetWindowLong (StartupScreen, GWL_ID, IDC_STATIC_STARTUP); - return true; -} - -//========================================================================== -// -// ST_Util_SizeWindowForBitmap -// -// Resizes the main window so that the startup bitmap will be drawn -// at the desired scale. -// -//========================================================================== - -void ST_Util_SizeWindowForBitmap (int scale) -{ - DEVMODE displaysettings; - int w, h, cx, cy, x, y; - RECT rect; - - if (GameTitleWindow != NULL) - { - GetClientRect (GameTitleWindow, &rect); - } - else - { - rect.bottom = 0; - } - RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale, - StartupBitmap->bmiHeader.biHeight * scale + rect.bottom }; - AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); - w = sizerect.right - sizerect.left; - h = sizerect.bottom - sizerect.top; - - // Resize the window, but keep its center point the same, unless that - // puts it partially offscreen. - memset (&displaysettings, 0, sizeof(displaysettings)); - displaysettings.dmSize = sizeof(displaysettings); - EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); - GetWindowRect (Window, &rect); - cx = (rect.left + rect.right) / 2; - cy = (rect.top + rect.bottom) / 2; - x = cx - w / 2; - y = cy - h / 2; - if (x + w > (int)displaysettings.dmPelsWidth) - { - x = displaysettings.dmPelsWidth - w; - } - if (x < 0) - { - x = 0; - } - if (y + h > (int)displaysettings.dmPelsHeight) - { - y = displaysettings.dmPelsHeight - h; - } - if (y < 0) - { - y = 0; - } - MoveWindow (Window, x, y, w, h, TRUE); -} - -//========================================================================== -// -// ST_Util_InvalidateRect -// -// Invalidates the portion of the window that the specified rect of the -// bitmap appears in. -// -//========================================================================== - -void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom) -{ - RECT rect; - - GetClientRect (hwnd, &rect); - rect.left = left * rect.right / bitmap_info->bmiHeader.biWidth - 1; - rect.top = top * rect.bottom / bitmap_info->bmiHeader.biHeight - 1; - rect.right = right * rect.right / bitmap_info->bmiHeader.biWidth + 1; - rect.bottom = bottom * rect.bottom / bitmap_info->bmiHeader.biHeight + 1; - InvalidateRect (hwnd, &rect, FALSE); -} - -void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom) -{ - ST_Util_InvalidateRect(StartupScreen , bitmap_info, left, top, right, bottom); + return mainwindow.RunMessageLoop(timer_callback, userdata); } diff --git a/src/common/platform/win32/st_start_util.cpp b/src/common/platform/win32/st_start_util.cpp deleted file mode 100644 index 8c6074863..000000000 --- a/src/common/platform/win32/st_start_util.cpp +++ /dev/null @@ -1,1192 +0,0 @@ -/* -** st_start.cpp -** Handles the startup screen. -** -**--------------------------------------------------------------------------- -** Copyright 2006-2007 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. -**--------------------------------------------------------------------------- -** -*/ - - -#include -#include -#include "st_start.h" -#include "m_alloc.h" -#include "filesystem.h" -#include "s_soundinternal.h" -#include "s_music.h" -#include "startupinfo.h" -#include "palutil.h" -#include "i_interface.h" - -void I_GetEvent(); // i_input.h pulls in too much garbage. - -void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom); -bool ST_Util_CreateStartupWindow(); - -static const uint16_t IBM437ToUnicode[] = { - 0x0000, //#NULL - 0x0001, //#START OF HEADING - 0x0002, //#START OF TEXT - 0x0003, //#END OF TEXT - 0x0004, //#END OF TRANSMISSION - 0x0005, //#ENQUIRY - 0x0006, //#ACKNOWLEDGE - 0x0007, //#BELL - 0x0008, //#BACKSPACE - 0x0009, //#HORIZONTAL TABULATION - 0x000a, //#LINE FEED - 0x000b, //#VERTICAL TABULATION - 0x000c, //#FORM FEED - 0x000d, //#CARRIAGE RETURN - 0x000e, //#SHIFT OUT - 0x000f, //#SHIFT IN - 0x0010, //#DATA LINK ESCAPE - 0x0011, //#DEVICE CONTROL ONE - 0x0012, //#DEVICE CONTROL TWO - 0x0013, //#DEVICE CONTROL THREE - 0x0014, //#DEVICE CONTROL FOUR - 0x0015, //#NEGATIVE ACKNOWLEDGE - 0x0016, //#SYNCHRONOUS IDLE - 0x0017, //#END OF TRANSMISSION BLOCK - 0x0018, //#CANCEL - 0x0019, //#END OF MEDIUM - 0x001a, //#SUBSTITUTE - 0x001b, //#ESCAPE - 0x001c, //#FILE SEPARATOR - 0x001d, //#GROUP SEPARATOR - 0x001e, //#RECORD SEPARATOR - 0x001f, //#UNIT SEPARATOR - 0x0020, //#SPACE - 0x0021, //#EXCLAMATION MARK - 0x0022, //#QUOTATION MARK - 0x0023, //#NUMBER SIGN - 0x0024, //#DOLLAR SIGN - 0x0025, //#PERCENT SIGN - 0x0026, //#AMPERSAND - 0x0027, //#APOSTROPHE - 0x0028, //#LEFT PARENTHESIS - 0x0029, //#RIGHT PARENTHESIS - 0x002a, //#ASTERISK - 0x002b, //#PLUS SIGN - 0x002c, //#COMMA - 0x002d, //#HYPHEN-MINUS - 0x002e, //#FULL STOP - 0x002f, //#SOLIDUS - 0x0030, //#DIGIT ZERO - 0x0031, //#DIGIT ONE - 0x0032, //#DIGIT TWO - 0x0033, //#DIGIT THREE - 0x0034, //#DIGIT FOUR - 0x0035, //#DIGIT FIVE - 0x0036, //#DIGIT SIX - 0x0037, //#DIGIT SEVEN - 0x0038, //#DIGIT EIGHT - 0x0039, //#DIGIT NINE - 0x003a, //#COLON - 0x003b, //#SEMICOLON - 0x003c, //#LESS-THAN SIGN - 0x003d, //#EQUALS SIGN - 0x003e, //#GREATER-THAN SIGN - 0x003f, //#QUESTION MARK - 0x0040, //#COMMERCIAL AT - 0x0041, //#LATIN CAPITAL LETTER A - 0x0042, //#LATIN CAPITAL LETTER B - 0x0043, //#LATIN CAPITAL LETTER C - 0x0044, //#LATIN CAPITAL LETTER D - 0x0045, //#LATIN CAPITAL LETTER E - 0x0046, //#LATIN CAPITAL LETTER F - 0x0047, //#LATIN CAPITAL LETTER G - 0x0048, //#LATIN CAPITAL LETTER H - 0x0049, //#LATIN CAPITAL LETTER I - 0x004a, //#LATIN CAPITAL LETTER J - 0x004b, //#LATIN CAPITAL LETTER K - 0x004c, //#LATIN CAPITAL LETTER L - 0x004d, //#LATIN CAPITAL LETTER M - 0x004e, //#LATIN CAPITAL LETTER N - 0x004f, //#LATIN CAPITAL LETTER O - 0x0050, //#LATIN CAPITAL LETTER P - 0x0051, //#LATIN CAPITAL LETTER Q - 0x0052, //#LATIN CAPITAL LETTER R - 0x0053, //#LATIN CAPITAL LETTER S - 0x0054, //#LATIN CAPITAL LETTER T - 0x0055, //#LATIN CAPITAL LETTER U - 0x0056, //#LATIN CAPITAL LETTER V - 0x0057, //#LATIN CAPITAL LETTER W - 0x0058, //#LATIN CAPITAL LETTER X - 0x0059, //#LATIN CAPITAL LETTER Y - 0x005a, //#LATIN CAPITAL LETTER Z - 0x005b, //#LEFT SQUARE BRACKET - 0x005c, //#REVERSE SOLIDUS - 0x005d, //#RIGHT SQUARE BRACKET - 0x005e, //#CIRCUMFLEX ACCENT - 0x005f, //#LOW LINE - 0x0060, //#GRAVE ACCENT - 0x0061, //#LATIN SMALL LETTER A - 0x0062, //#LATIN SMALL LETTER B - 0x0063, //#LATIN SMALL LETTER C - 0x0064, //#LATIN SMALL LETTER D - 0x0065, //#LATIN SMALL LETTER E - 0x0066, //#LATIN SMALL LETTER F - 0x0067, //#LATIN SMALL LETTER G - 0x0068, //#LATIN SMALL LETTER H - 0x0069, //#LATIN SMALL LETTER I - 0x006a, //#LATIN SMALL LETTER J - 0x006b, //#LATIN SMALL LETTER K - 0x006c, //#LATIN SMALL LETTER L - 0x006d, //#LATIN SMALL LETTER M - 0x006e, //#LATIN SMALL LETTER N - 0x006f, //#LATIN SMALL LETTER O - 0x0070, //#LATIN SMALL LETTER P - 0x0071, //#LATIN SMALL LETTER Q - 0x0072, //#LATIN SMALL LETTER R - 0x0073, //#LATIN SMALL LETTER S - 0x0074, //#LATIN SMALL LETTER T - 0x0075, //#LATIN SMALL LETTER U - 0x0076, //#LATIN SMALL LETTER V - 0x0077, //#LATIN SMALL LETTER W - 0x0078, //#LATIN SMALL LETTER X - 0x0079, //#LATIN SMALL LETTER Y - 0x007a, //#LATIN SMALL LETTER Z - 0x007b, //#LEFT CURLY BRACKET - 0x007c, //#VERTICAL LINE - 0x007d, //#RIGHT CURLY BRACKET - 0x007e, //#TILDE - 0x007f, //#DELETE - 0x00c7, //#LATIN CAPITAL LETTER C WITH CEDILLA - 0x00fc, //#LATIN SMALL LETTER U WITH DIAERESIS - 0x00e9, //#LATIN SMALL LETTER E WITH ACUTE - 0x00e2, //#LATIN SMALL LETTER A WITH CIRCUMFLEX - 0x00e4, //#LATIN SMALL LETTER A WITH DIAERESIS - 0x00e0, //#LATIN SMALL LETTER A WITH GRAVE - 0x00e5, //#LATIN SMALL LETTER A WITH RING ABOVE - 0x00e7, //#LATIN SMALL LETTER C WITH CEDILLA - 0x00ea, //#LATIN SMALL LETTER E WITH CIRCUMFLEX - 0x00eb, //#LATIN SMALL LETTER E WITH DIAERESIS - 0x00e8, //#LATIN SMALL LETTER E WITH GRAVE - 0x00ef, //#LATIN SMALL LETTER I WITH DIAERESIS - 0x00ee, //#LATIN SMALL LETTER I WITH CIRCUMFLEX - 0x00ec, //#LATIN SMALL LETTER I WITH GRAVE - 0x00c4, //#LATIN CAPITAL LETTER A WITH DIAERESIS - 0x00c5, //#LATIN CAPITAL LETTER A WITH RING ABOVE - 0x00c9, //#LATIN CAPITAL LETTER E WITH ACUTE - 0x00e6, //#LATIN SMALL LIGATURE AE - 0x00c6, //#LATIN CAPITAL LIGATURE AE - 0x00f4, //#LATIN SMALL LETTER O WITH CIRCUMFLEX - 0x00f6, //#LATIN SMALL LETTER O WITH DIAERESIS - 0x00f2, //#LATIN SMALL LETTER O WITH GRAVE - 0x00fb, //#LATIN SMALL LETTER U WITH CIRCUMFLEX - 0x00f9, //#LATIN SMALL LETTER U WITH GRAVE - 0x00ff, //#LATIN SMALL LETTER Y WITH DIAERESIS - 0x00d6, //#LATIN CAPITAL LETTER O WITH DIAERESIS - 0x00dc, //#LATIN CAPITAL LETTER U WITH DIAERESIS - 0x00a2, //#CENT SIGN - 0x00a3, //#POUND SIGN - 0x00a5, //#YEN SIGN - 0x20a7, //#PESETA SIGN - 0x0192, //#LATIN SMALL LETTER F WITH HOOK - 0x00e1, //#LATIN SMALL LETTER A WITH ACUTE - 0x00ed, //#LATIN SMALL LETTER I WITH ACUTE - 0x00f3, //#LATIN SMALL LETTER O WITH ACUTE - 0x00fa, //#LATIN SMALL LETTER U WITH ACUTE - 0x00f1, //#LATIN SMALL LETTER N WITH TILDE - 0x00d1, //#LATIN CAPITAL LETTER N WITH TILDE - 0x00aa, //#FEMININE ORDINAL INDICATOR - 0x00ba, //#MASCULINE ORDINAL INDICATOR - 0x00bf, //#INVERTED QUESTION MARK - 0x2310, //#REVERSED NOT SIGN - 0x00ac, //#NOT SIGN - 0x00bd, //#VULGAR FRACTION ONE HALF - 0x00bc, //#VULGAR FRACTION ONE QUARTER - 0x00a1, //#INVERTED EXCLAMATION MARK - 0x00ab, //#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x00bb, //#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x2591, //#LIGHT SHADE - 0x2592, //#MEDIUM SHADE - 0x2593, //#DARK SHADE - 0x2502, //#BOX DRAWINGS LIGHT VERTICAL - 0x2524, //#BOX DRAWINGS LIGHT VERTICAL AND LEFT - 0x2561, //#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - 0x2562, //#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - 0x2556, //#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - 0x2555, //#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - 0x2563, //#BOX DRAWINGS DOUBLE VERTICAL AND LEFT - 0x2551, //#BOX DRAWINGS DOUBLE VERTICAL - 0x2557, //#BOX DRAWINGS DOUBLE DOWN AND LEFT - 0x255d, //#BOX DRAWINGS DOUBLE UP AND LEFT - 0x255c, //#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - 0x255b, //#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - 0x2510, //#BOX DRAWINGS LIGHT DOWN AND LEFT - 0x2514, //#BOX DRAWINGS LIGHT UP AND RIGHT - 0x2534, //#BOX DRAWINGS LIGHT UP AND HORIZONTAL - 0x252c, //#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - 0x251c, //#BOX DRAWINGS LIGHT VERTICAL AND RIGHT - 0x2500, //#BOX DRAWINGS LIGHT HORIZONTAL - 0x253c, //#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - 0x255e, //#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - 0x255f, //#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - 0x255a, //#BOX DRAWINGS DOUBLE UP AND RIGHT - 0x2554, //#BOX DRAWINGS DOUBLE DOWN AND RIGHT - 0x2569, //#BOX DRAWINGS DOUBLE UP AND HORIZONTAL - 0x2566, //#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - 0x2560, //#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - 0x2550, //#BOX DRAWINGS DOUBLE HORIZONTAL - 0x256c, //#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - 0x2567, //#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - 0x2568, //#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - 0x2564, //#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - 0x2565, //#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - 0x2559, //#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - 0x2558, //#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - 0x2552, //#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE - 0x2553, //#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - 0x256b, //#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - 0x256a, //#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - 0x2518, //#BOX DRAWINGS LIGHT UP AND LEFT - 0x250c, //#BOX DRAWINGS LIGHT DOWN AND RIGHT - 0x2588, //#FULL BLOCK - 0x2584, //#LOWER HALF BLOCK - 0x258c, //#LEFT HALF BLOCK - 0x2590, //#RIGHT HALF BLOCK - 0x2580, //#UPPER HALF BLOCK - 0x03b1, //#GREEK SMALL LETTER ALPHA - 0x00df, //#LATIN SMALL LETTER SHARP S - 0x0393, //#GREEK CAPITAL LETTER GAMMA - 0x03c0, //#GREEK SMALL LETTER PI - 0x03a3, //#GREEK CAPITAL LETTER SIGMA - 0x03c3, //#GREEK SMALL LETTER SIGMA - 0x00b5, //#MICRO SIGN - 0x03c4, //#GREEK SMALL LETTER TAU - 0x03a6, //#GREEK CAPITAL LETTER PHI - 0x0398, //#GREEK CAPITAL LETTER THETA - 0x03a9, //#GREEK CAPITAL LETTER OMEGA - 0x03b4, //#GREEK SMALL LETTER DELTA - 0x221e, //#INFINITY - 0x03c6, //#GREEK SMALL LETTER PHI - 0x03b5, //#GREEK SMALL LETTER EPSILON - 0x2229, //#INTERSECTION - 0x2261, //#IDENTICAL TO - 0x00b1, //#PLUS-MINUS SIGN - 0x2265, //#GREATER-THAN OR EQUAL TO - 0x2264, //#LESS-THAN OR EQUAL TO - 0x2320, //#TOP HALF INTEGRAL - 0x2321, //#BOTTOM HALF INTEGRAL - 0x00f7, //#DIVISION SIGN - 0x2248, //#ALMOST EQUAL TO - 0x00b0, //#DEGREE SIGN - 0x2219, //#BULLET OPERATOR - 0x00b7, //#MIDDLE DOT - 0x221a, //#SQUARE ROOT - 0x207f, //#SUPERSCRIPT LATIN SMALL LETTER N - 0x00b2, //#SUPERSCRIPT TWO - 0x25a0, //#BLACK SQUARE - 0x00a0, //#NO-BREAK SPACE -}; - -BitmapInfo* StartupBitmap; - -// Hexen startup screen -#define ST_MAX_NOTCHES 32 -#define ST_NOTCH_WIDTH 16 -#define ST_NOTCH_HEIGHT 23 -#define ST_PROGRESS_X 64 // Start of notches x screen pos. -#define ST_PROGRESS_Y 441 // Start of notches y screen pos. - -#define ST_NETPROGRESS_X 288 -#define ST_NETPROGRESS_Y 32 -#define ST_NETNOTCH_WIDTH 4 -#define ST_NETNOTCH_HEIGHT 16 -#define ST_MAX_NETNOTCHES 8 - -// Heretic startup screen -#define HERETIC_MINOR_VERSION '3' // Since we're based on Heretic 1.3 - -#define THERM_X 14 -#define THERM_Y 14 -#define THERM_LEN 51 -#define THERM_COLOR 0xAA // light green - -#define TEXT_FONT_NAME "vga-rom-font.16" - -// Strife startup screen -#define PEASANT_INDEX 0 -#define LASER_INDEX 4 -#define BOT_INDEX 6 - -#define ST_LASERSPACE_X 60 -#define ST_LASERSPACE_Y 156 -#define ST_LASERSPACE_WIDTH 200 -#define ST_LASER_WIDTH 16 -#define ST_LASER_HEIGHT 16 - -#define ST_BOT_X 14 -#define ST_BOT_Y 138 -#define ST_BOT_WIDTH 48 -#define ST_BOT_HEIGHT 48 - -#define ST_PEASANT_X 262 -#define ST_PEASANT_Y 136 -#define ST_PEASANT_WIDTH 32 -#define ST_PEASANT_HEIGHT 64 - -// Text mode color values -#define LO 85 -#define MD 170 -#define HI 255 - -static const RgbQuad TextModePalette[16] = -{ - { 0, 0, 0, 0 }, // 0 black - { MD, 0, 0, 0 }, // 1 blue - { 0, MD, 0, 0 }, // 2 green - { MD, MD, 0, 0 }, // 3 cyan - { 0, 0, MD, 0 }, // 4 red - { MD, 0, MD, 0 }, // 5 magenta - { 0, LO, MD, 0 }, // 6 brown - { MD, MD, MD, 0 }, // 7 light gray - - { LO, LO, LO, 0 }, // 8 dark gray - { HI, LO, LO, 0 }, // 9 light blue - { LO, HI, LO, 0 }, // A light green - { HI, HI, LO, 0 }, // B light cyan - { LO, LO, HI, 0 }, // C light red - { HI, LO, HI, 0 }, // D light magenta - { LO, HI, HI, 0 }, // E yellow - { HI, HI, HI, 0 }, // F white -}; - -static const char* StrifeStartupPicNames[4 + 2 + 1] = -{ - "STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1", - "STRTLZ1", "STRTLZ2", - "STRTBOT" -}; -static const int StrifeStartupPicSizes[4 + 2 + 1] = -{ - 2048, 2048, 2048, 2048, - 256, 256, - 2304 -}; - - -static void ST_Sound(const char* sndname) -{ - if (sysCallbacks.PlayStartupSound) - sysCallbacks.PlayStartupSound(sndname); -} - -//========================================================================== -// -// FHexenStartupScreen Constructor -// -// Shows the Hexen startup screen. If the screen doesn't appear to be -// valid, it sets hr for a failure. -// -// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a -// 16 entry (48 byte) VGA palette. -// -//========================================================================== - -FHexenStartupScreen::FHexenStartupScreen(int max_progress, long& hr) - : FGraphicalStartupScreen(max_progress) -{ - int startup_lump = fileSystem.CheckNumForName("STARTUP"); - int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH"); - int notch_lump = fileSystem.CheckNumForName("NOTCH"); - hr = -1; - - if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 153648 || !ST_Util_CreateStartupWindow() || - netnotch_lump < 0 || fileSystem.FileLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT || - notch_lump < 0 || fileSystem.FileLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT) - { - NetNotchBits = NotchBits = NULL; - return; - } - - NetNotchBits = new uint8_t[ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT]; - fileSystem.ReadFile(netnotch_lump, NetNotchBits); - NotchBits = new uint8_t[ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT]; - fileSystem.ReadFile(notch_lump, NotchBits); - - uint8_t startup_screen[153648]; - union - { - RgbQuad color; - uint32_t quad; - } c; - - fileSystem.ReadFile(startup_lump, startup_screen); - - c.color.rgbReserved = 0; - - StartupBitmap = ST_Util_CreateBitmap(640, 480, 4); - - // Initialize the bitmap palette. - for (int i = 0; i < 16; ++i) - { - c.color.rgbRed = startup_screen[i * 3 + 0]; - c.color.rgbGreen = startup_screen[i * 3 + 1]; - c.color.rgbBlue = startup_screen[i * 3 + 2]; - // Convert from 6-bit per component to 8-bit per component. - c.quad = (c.quad << 2) | ((c.quad >> 4) & 0x03030303); - StartupBitmap->bmiColors[i] = c.color; - } - - // Fill in the bitmap data. Convert to chunky, because I can't figure out - // if Windows actually supports planar images or not, despite the presence - // of biPlanes in the BITMAPINFOHEADER. - ST_Util_PlanarToChunky4(ST_Util_BitsForBitmap(StartupBitmap), startup_screen + 48, 640, 480); - - - if (!batchrun) - { - if (GameStartupInfo.Song.IsNotEmpty()) - { - S_ChangeMusic(GameStartupInfo.Song.GetChars(), true, true); - } - else - { - S_ChangeMusic("orb", true, true); - } - } - SetWindowSize(); - hr = 0; -} - -//========================================================================== -// -// FHexenStartupScreen Deconstructor -// -// Frees the notch pictures. -// -//========================================================================== - -FHexenStartupScreen::~FHexenStartupScreen() -{ - if (NotchBits) - delete[] NotchBits; - if (NetNotchBits) - delete[] NetNotchBits; -} - -//========================================================================== -// -// FHexenStartupScreen :: Progress -// -// Bumps the progress meter one notch. -// -//========================================================================== - -void FHexenStartupScreen::Progress() -{ - int notch_pos, x, y; - - if (CurPos < MaxPos) - { - CurPos++; - notch_pos = (CurPos * ST_MAX_NOTCHES) / MaxPos; - if (notch_pos != NotchPos) - { // Time to draw another notch. - for (; NotchPos < notch_pos; NotchPos++) - { - x = ST_PROGRESS_X + ST_NOTCH_WIDTH * NotchPos; - y = ST_PROGRESS_Y; - ST_Util_DrawBlock(StartupBitmap, NotchBits, x, y, ST_NOTCH_WIDTH / 2, ST_NOTCH_HEIGHT); - } - ST_Sound("StartupTick"); - } - } - I_GetEvent(); -} - -//========================================================================== -// -// FHexenStartupScreen :: NetProgress -// -// Draws the red net noches in addition to the normal progress bar. -// -//========================================================================== - -void FHexenStartupScreen::NetProgress(int count) -{ - int oldpos = NetCurPos; - int x, y; - - FGraphicalStartupScreen::NetProgress(count); - if (NetMaxPos != 0 && NetCurPos > oldpos) - { - for (; oldpos < NetCurPos && oldpos < ST_MAX_NETNOTCHES; ++oldpos) - { - x = ST_NETPROGRESS_X + ST_NETNOTCH_WIDTH * oldpos; - y = ST_NETPROGRESS_Y; - ST_Util_DrawBlock(StartupBitmap, NetNotchBits, x, y, ST_NETNOTCH_WIDTH / 2, ST_NETNOTCH_HEIGHT); - } - ST_Sound("misc/netnotch"); - I_GetEvent(); - } -} - -//========================================================================== -// -// FHexenStartupScreen :: NetDone -// -// Aside from the standard processing, also plays a sound. -// -//========================================================================== - -void FHexenStartupScreen::NetDone() -{ - ST_Sound("PickupWeapon"); - FGraphicalStartupScreen::NetDone(); -} - - -//========================================================================== -// -// FHereticStartupScreen Constructor -// -// Shows the Heretic startup screen. If the screen doesn't appear to be -// valid, it returns a failure code in hr. -// -// The loading screen is an 80x25 text screen with character data and -// attributes intermixed, which means it must be exactly 4000 bytes long. -// -//========================================================================== - -FHereticStartupScreen::FHereticStartupScreen(int max_progress, long& hr) - : FGraphicalStartupScreen(max_progress) -{ - int loading_lump = fileSystem.CheckNumForName("LOADING"); - uint8_t loading_screen[4000]; - uint8_t* font; - - hr = -1; - if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) - { - return; - } - - font = ST_Util_LoadFont(TEXT_FONT_NAME); - if (font == NULL) - { - return; - } - - fileSystem.ReadFile(loading_lump, loading_screen); - - // Slap the Heretic minor version on the loading screen. Heretic - // did this inside the executable rather than coming with modified - // LOADING screens, so we need to do the same. - loading_screen[2 * 160 + 49 * 2] = HERETIC_MINOR_VERSION; - - // Draw the loading screen to a bitmap. - StartupBitmap = ST_Util_AllocTextBitmap(font); - ST_Util_DrawTextScreen(StartupBitmap, loading_screen, font); - - ThermX = THERM_X * 8; - ThermY = THERM_Y * font[0]; - ThermWidth = THERM_LEN * 8 - 4; - ThermHeight = font[0]; - HMsgY = 7; - SMsgX = 1; - - ST_Util_FreeFont(font); - SetWindowSize(); - hr = 0; -} - -//========================================================================== -// -// FHereticStartupScreen::Progress -// -// Bumps the progress meter one notch. -// -//========================================================================== - -void FHereticStartupScreen::Progress() -{ - int notch_pos; - - if (CurPos < MaxPos) - { - CurPos++; - notch_pos = (CurPos * ThermWidth) / MaxPos; - if (notch_pos != NotchPos && !(notch_pos & 3)) - { // Time to draw another notch. - int left = NotchPos + ThermX; - int top = ThermY; - int right = notch_pos + ThermX; - int bottom = top + ThermHeight; - ST_Util_ClearBlock(StartupBitmap, THERM_COLOR, left, top, right - left, bottom - top); - NotchPos = notch_pos; - } - } - I_GetEvent(); -} - -//========================================================================== -// -// FHereticStartupScreen :: LoadingStatus -// -// Prints text in the center box of the startup screen. -// -//========================================================================== - -void FHereticStartupScreen::LoadingStatus(const char* message, int colors) -{ - uint8_t* font = ST_Util_LoadFont(TEXT_FONT_NAME); - if (font != NULL) - { - int x; - - for (x = 0; message[x] != '\0'; ++x) - { - ST_Util_DrawChar(StartupBitmap, font, 17 + x, HMsgY, message[x], colors); - } - ST_Util_InvalidateRect(StartupBitmap, 17 * 8, HMsgY * font[0], (17 + x) * 8, HMsgY * font[0] + font[0]); - ST_Util_FreeFont(font); - HMsgY++; - I_GetEvent(); - } -} - -//========================================================================== -// -// FHereticStartupScreen :: AppendStatusLine -// -// Appends text to Heretic's status line. -// -//========================================================================== - -void FHereticStartupScreen::AppendStatusLine(const char* status) -{ - uint8_t* font = ST_Util_LoadFont(TEXT_FONT_NAME); - if (font != NULL) - { - int x; - - for (x = 0; status[x] != '\0'; ++x) - { - ST_Util_DrawChar(StartupBitmap, font, SMsgX + x, 24, status[x], 0x1f); - } - ST_Util_InvalidateRect(StartupBitmap, SMsgX * 8, 24 * font[0], (SMsgX + x) * 8, 25 * font[0]); - ST_Util_FreeFont(font); - SMsgX += x; - I_GetEvent(); - } -} - -//========================================================================== -// -// FStrifeStartupScreen Constructor -// -// Shows the Strife startup screen. If the screen doesn't appear to be -// valid, it returns a failure code in hr. -// -// The startup background is a raw 320x200 image, however Strife only -// actually uses 95 rows from it, starting at row 57. The rest of the image -// is discarded. (What a shame.) -// -// The peasants are raw 32x64 images. The laser dots are raw 16x16 images. -// The bot is a raw 48x48 image. All use the standard PLAYPAL. -// -//========================================================================== - -FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr) - : FGraphicalStartupScreen(max_progress) -{ - int startup_lump = fileSystem.CheckNumForName("STARTUP0"); - int i; - - hr = -1; - for (i = 0; i < 4 + 2 + 1; ++i) - { - StartupPics[i] = NULL; - } - - if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 64000 || !ST_Util_CreateStartupWindow()) - { - return; - } - - StartupBitmap = ST_Util_CreateBitmap(320, 200, 8); - ST_Util_BitmapColorsFromPlaypal(StartupBitmap); - - // Fill bitmap with the startup image. - memset(ST_Util_BitsForBitmap(StartupBitmap), 0xF0, 64000); - auto lumpr = fileSystem.OpenFileReader(startup_lump); - lumpr.Seek(57 * 320, FileReader::SeekSet); - lumpr.Read(ST_Util_BitsForBitmap(StartupBitmap) + 41 * 320, 95 * 320); - - // Load the animated overlays. - for (i = 0; i < 4 + 2 + 1; ++i) - { - int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); - int lumplen; - - if (lumpnum >= 0 && (lumplen = fileSystem.FileLength(lumpnum)) == StrifeStartupPicSizes[i]) - { - auto lumpr = fileSystem.OpenFileReader(lumpnum); - StartupPics[i] = new uint8_t[lumplen]; - lumpr.Read(StartupPics[i], lumplen); - } - } - - // Make the startup image appear. - DrawStuff(0, 0); - SetWindowSize(); - hr = 0; -} - -//========================================================================== -// -// FStrifeStartupScreen Destructor -// -// Frees the strife pictures. -// -//========================================================================== - -FStrifeStartupScreen::~FStrifeStartupScreen() -{ - for (int i = 0; i < 4 + 2 + 1; ++i) - { - if (StartupPics[i] != NULL) - { - delete[] StartupPics[i]; - } - StartupPics[i] = NULL; - } -} - -//========================================================================== -// -// FStrifeStartupScreen :: Progress -// -// Bumps the progress meter one notch. -// -//========================================================================== - -void FStrifeStartupScreen::Progress() -{ - int notch_pos; - - if (CurPos < MaxPos) - { - CurPos++; - notch_pos = (CurPos * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos; - if (notch_pos != NotchPos && !(notch_pos & 1)) - { // Time to update. - DrawStuff(NotchPos, notch_pos); - NotchPos = notch_pos; - } - } - I_GetEvent(); -} - -//========================================================================== -// -// FStrifeStartupScreen :: DrawStuff -// -// Draws all the moving parts of Strife's startup screen. If you're -// running off a slow drive, it can look kind of good. Otherwise, it -// borders on crazy insane fast. -// -//========================================================================== - -void FStrifeStartupScreen::DrawStuff(int old_laser, int new_laser) -{ - int y; - auto bitmap_info = StartupBitmap; - - // Clear old laser - ST_Util_ClearBlock(bitmap_info, 0xF0, ST_LASERSPACE_X + old_laser, - ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); - // Draw new laser - ST_Util_DrawBlock(bitmap_info, StartupPics[LASER_INDEX + (new_laser & 1)], - ST_LASERSPACE_X + new_laser, ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); - - // The bot jumps up and down like crazy. - y = std::max(0, (new_laser >> 1) % 5 - 2); - if (y > 0) - { - ST_Util_ClearBlock(bitmap_info, 0xF0, ST_BOT_X, ST_BOT_Y, ST_BOT_WIDTH, y); - } - ST_Util_DrawBlock(bitmap_info, StartupPics[BOT_INDEX], ST_BOT_X, ST_BOT_Y + y, ST_BOT_WIDTH, ST_BOT_HEIGHT); - if (y < (5 - 1) - 2) - { - ST_Util_ClearBlock(bitmap_info, 0xF0, ST_BOT_X, ST_BOT_Y + ST_BOT_HEIGHT + y, ST_BOT_WIDTH, 2 - y); - } - - // The peasant desperately runs in place, trying to get away from the laser. - // Yet, despite all his limb flailing, he never manages to get anywhere. - ST_Util_DrawBlock(bitmap_info, StartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)], - ST_PEASANT_X, ST_PEASANT_Y, ST_PEASANT_WIDTH, ST_PEASANT_HEIGHT); -} - - -//========================================================================== -// -// ST_Util_PlanarToChunky4 -// -// Convert a 4-bpp planar image to chunky pixels. -// -//========================================================================== - -void ST_Util_PlanarToChunky4(uint8_t* dest, const uint8_t* src, int width, int height) -{ - int y, x; - const uint8_t* src1, * src2, * src3, * src4; - size_t plane_size = width / 8 * height; - - src1 = src; - src2 = src1 + plane_size; - src3 = src2 + plane_size; - src4 = src3 + plane_size; - - for (y = height; y > 0; --y) - { - for (x = width; x > 0; x -= 8) - { - // Pixels 0 and 1 - dest[0] = (*src4 & 0x80) | ((*src3 & 0x80) >> 1) | ((*src2 & 0x80) >> 2) | ((*src1 & 0x80) >> 3) | - ((*src4 & 0x40) >> 3) | ((*src3 & 0x40) >> 4) | ((*src2 & 0x40) >> 5) | ((*src1 & 0x40) >> 6); - // Pixels 2 and 3 - dest[1] = ((*src4 & 0x20) << 2) | ((*src3 & 0x20) << 1) | ((*src2 & 0x20)) | ((*src1 & 0x20) >> 1) | - ((*src4 & 0x10) >> 1) | ((*src3 & 0x10) >> 2) | ((*src2 & 0x10) >> 3) | ((*src1 & 0x10) >> 4); - // Pixels 4 and 5 - dest[2] = ((*src4 & 0x08) << 4) | ((*src3 & 0x08) << 3) | ((*src2 & 0x08) << 2) | ((*src1 & 0x08) << 1) | - ((*src4 & 0x04) << 1) | ((*src3 & 0x04)) | ((*src2 & 0x04) >> 1) | ((*src1 & 0x04) >> 2); - // Pixels 6 and 7 - dest[3] = ((*src4 & 0x02) << 6) | ((*src3 & 0x02) << 5) | ((*src2 & 0x02) << 4) | ((*src1 & 0x02) << 3) | - ((*src4 & 0x01) << 3) | ((*src3 & 0x01) << 2) | ((*src2 & 0x01) << 1) | ((*src1 & 0x01)); - dest += 4; - src1 += 1; - src2 += 1; - src3 += 1; - src4 += 1; - } - } -} - -//========================================================================== -// -// ST_Util_DrawBlock -// -//========================================================================== - -void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y, int bytewidth, int height) -{ - if (src == NULL) - { - return; - } - - int pitchshift = int(bitmap_info->bmiHeader.biBitCount == 4); - int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift; - uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch; - - ST_Util_InvalidateRect(bitmap_info, x, y, x + (bytewidth << pitchshift), y + height); - - if (bytewidth == 8) - { // progress notches - for (; height > 0; --height) - { - ((uint32_t*)dest)[0] = ((const uint32_t*)src)[0]; - ((uint32_t*)dest)[1] = ((const uint32_t*)src)[1]; - dest += destpitch; - src += 8; - } - } - else if (bytewidth == 2) - { // net progress notches - for (; height > 0; --height) - { - *((uint16_t*)dest) = *((const uint16_t*)src); - dest += destpitch; - src += 2; - } - } - else - { - for (; height > 0; --height) - { - memcpy(dest, src, bytewidth); - dest += destpitch; - src += bytewidth; - } - } -} - -//========================================================================== -// -// ST_Util_ClearBlock -// -//========================================================================== - -void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int bytewidth, int height) -{ - int pitchshift = int(bitmap_info->bmiHeader.biBitCount == 4); - int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift; - uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch; - - ST_Util_InvalidateRect(bitmap_info, x, y, x + (bytewidth << pitchshift), y + height); - - while (height > 0) - { - memset(dest, fill, bytewidth); - dest += destpitch; - height--; - } -} - -//========================================================================== -// -// ST_Util_CreateBitmap -// -// Creates a BitmapInfoHeader, RgbQuad, and pixel data arranged -// consecutively in memory (in other words, a normal Windows BMP file). -// The BitmapInfoHeader will be filled in, and the caller must fill -// in the color and pixel data. -// -// You must pass 4 or 8 for color_bits. -// -//========================================================================== - -BitmapInfo* ST_Util_CreateBitmap(int width, int height, int color_bits) -{ - uint32_t size_image = (width * height) >> int(color_bits == 4); - BitmapInfo* bitmap_info = (BitmapInfo*)M_Malloc(sizeof(BitmapInfoHeader) + - (sizeof(RgbQuad) << color_bits) + size_image); - - // Initialize the header. - bitmap_info->bmiHeader.biSize = sizeof(BitmapInfoHeader); - bitmap_info->bmiHeader.biWidth = width; - bitmap_info->bmiHeader.biHeight = height; - bitmap_info->bmiHeader.biPlanes = 1; - bitmap_info->bmiHeader.biBitCount = color_bits; - bitmap_info->bmiHeader.biCompression = 0; - bitmap_info->bmiHeader.biSizeImage = size_image; - bitmap_info->bmiHeader.biXPelsPerMeter = 0; - bitmap_info->bmiHeader.biYPelsPerMeter = 0; - bitmap_info->bmiHeader.biClrUsed = 1 << color_bits; - bitmap_info->bmiHeader.biClrImportant = 0; - - return bitmap_info; -} - -//========================================================================== -// -// ST_Util_BitsForBitmap -// -// Given a bitmap created by ST_Util_CreateBitmap, returns the start -// address for the pixel data for the bitmap. -// -//========================================================================== - -uint8_t* ST_Util_BitsForBitmap(BitmapInfo* bitmap_info) -{ - return (uint8_t*)bitmap_info + sizeof(BitmapInfoHeader) + (sizeof(RgbQuad) << bitmap_info->bmiHeader.biBitCount); -} - -//========================================================================== -// -// ST_Util_FreeBitmap -// -// Frees all the data for a bitmap created by ST_Util_CreateBitmap. -// -//========================================================================== - -void ST_Util_FreeBitmap(BitmapInfo* bitmap_info) -{ - M_Free(bitmap_info); -} - -//========================================================================== -// -// ST_Util_BitmapColorsFromPlaypal -// -// Fills the bitmap palette from the PLAYPAL lump. -// -//========================================================================== - -void ST_Util_BitmapColorsFromPlaypal(BitmapInfo* bitmap_info) -{ - uint8_t playpal[768]; - - ReadPalette(fileSystem.GetNumForName("PLAYPAL"), playpal); - for (int i = 0; i < 256; ++i) - { - bitmap_info->bmiColors[i].rgbBlue = playpal[i * 3 + 2]; - bitmap_info->bmiColors[i].rgbGreen = playpal[i * 3 + 1]; - bitmap_info->bmiColors[i].rgbRed = playpal[i * 3]; - bitmap_info->bmiColors[i].rgbReserved = 0; - } -} - -//========================================================================== -// -// ST_Util_LoadFont -// -// Loads a monochrome fixed-width font. Every character is one byte -// (eight pixels) wide, so we can deduce the height of each character -// by looking at the size of the font data. -// -//========================================================================== - -uint8_t* ST_Util_LoadFont(const char* filename) -{ - int lumpnum, lumplen, height; - uint8_t* font; - - lumpnum = fileSystem.CheckNumForFullName(filename); - if (lumpnum < 0) - { // font not found - return NULL; - } - lumplen = fileSystem.FileLength(lumpnum); - height = lumplen / 256; - if (height * 256 != lumplen) - { // font is a bad size - return NULL; - } - if (height < 6 || height > 36) - { // let's be reasonable here - return NULL; - } - font = new uint8_t[lumplen + 1]; - font[0] = height; // Store font height in the first byte. - fileSystem.ReadFile(lumpnum, font + 1); - return font; -} - -void ST_Util_FreeFont(uint8_t* font) -{ - delete[] font; -} - -//========================================================================== -// -// ST_Util_AllocTextBitmap -// -// Returns a bitmap properly sized to hold an 80x25 display of characters -// using the specified font. -// -//========================================================================== - -BitmapInfo* ST_Util_AllocTextBitmap(const uint8_t* font) -{ - BitmapInfo* bitmap = ST_Util_CreateBitmap(80 * 8, 25 * font[0], 4); - memcpy(bitmap->bmiColors, TextModePalette, sizeof(TextModePalette)); - return bitmap; -} - -//========================================================================== -// -// ST_Util_DrawTextScreen -// -// Draws the text screen to the bitmap. The bitmap must be the proper size -// for the font. -// -//========================================================================== - -void ST_Util_DrawTextScreen(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font) -{ - int x, y; - - for (y = 0; y < 25; ++y) - { - for (x = 0; x < 80; ++x) - { - ST_Util_DrawChar(bitmap_info, font, x, y, text_screen[0], text_screen[1]); - text_screen += 2; - } - } -} - -//========================================================================== -// -// ST_Util_DrawChar -// -// Draws a character on the bitmap. X and Y specify the character cell, -// and fg and bg are 4-bit colors. -// -//========================================================================== - -void ST_Util_DrawChar(BitmapInfo* screen, const uint8_t* font, int x, int y, uint8_t charnum, uint8_t attrib) -{ - const uint8_t bg_left = attrib & 0x70; - const uint8_t fg = attrib & 0x0F; - const uint8_t fg_left = fg << 4; - const uint8_t bg = bg_left >> 4; - const uint8_t color_array[4] = { (uint8_t)(bg_left | bg), (uint8_t)(attrib & 0x7F), (uint8_t)(fg_left | bg), (uint8_t)(fg_left | fg) }; - const uint8_t* src = font + 1 + charnum * font[0]; - int pitch = screen->bmiHeader.biWidth >> 1; - uint8_t* dest = ST_Util_BitsForBitmap(screen) + x * 4 + y * font[0] * pitch; - - for (y = font[0]; y > 0; --y) - { - uint8_t srcbyte = *src++; - - // Pixels 0 and 1 - dest[0] = color_array[(srcbyte >> 6) & 3]; - // Pixels 2 and 3 - dest[1] = color_array[(srcbyte >> 4) & 3]; - // Pixels 4 and 5 - dest[2] = color_array[(srcbyte >> 2) & 3]; - // Pixels 6 and 7 - dest[3] = color_array[(srcbyte) & 3]; - dest += pitch; - } -} - -//========================================================================== -// -// ST_Util_UpdateTextBlink -// -// Draws the parts of the text screen that blink to the bitmap. The bitmap -// must be the proper size for the font. -// -//========================================================================== - -void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font, bool on) -{ - int x, y; - - for (y = 0; y < 25; ++y) - { - for (x = 0; x < 80; ++x) - { - if (text_screen[1] & 0x80) - { - ST_Util_DrawChar(bitmap_info, font, x, y, on ? text_screen[0] : ' ', text_screen[1]); - ST_Util_InvalidateRect(bitmap_info, x * 8, y * font[0], x * 8 + 8, y * font[0] + font[0]); - } - text_screen += 2; - } - } -} diff --git a/src/common/platform/win32/win32basevideo.cpp b/src/common/platform/win32/win32basevideo.cpp index fc2ae67c4..b67af93d7 100644 --- a/src/common/platform/win32/win32basevideo.cpp +++ b/src/common/platform/win32/win32basevideo.cpp @@ -35,7 +35,7 @@ #include #include "hardware.h" -#include "templates.h" + #include "version.h" #include "c_console.h" #include "v_video.h" @@ -47,6 +47,7 @@ #include "printf.h" #include "win32basevideo.h" #include "cmdlib.h" +#include "i_mainwindow.h" CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -58,7 +59,7 @@ CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) Win32BaseVideo::Win32BaseVideo() { - I_SetWndProc(); + mainwindow.ShowGameView(); GetDisplayDeviceName(); } diff --git a/src/common/platform/win32/win32glvideo.cpp b/src/common/platform/win32/win32glvideo.cpp index abc9768cc..ebeb13cc9 100644 --- a/src/common/platform/win32/win32glvideo.cpp +++ b/src/common/platform/win32/win32glvideo.cpp @@ -40,7 +40,7 @@ #include "gl_sysfb.h" #include "hardware.h" -#include "templates.h" + #include "version.h" #include "c_console.h" #include "v_video.h" @@ -65,7 +65,6 @@ PROC zd_wglGetProcAddress(LPCSTR name); } EXTERN_CVAR(Int, vid_adapter) -EXTERN_CVAR(Int, vid_preferbackend) EXTERN_CVAR(Bool, vid_hdr) CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -110,7 +109,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer() SystemGLFrameBuffer *fb; #ifdef HAVE_GLES2 - if ((Args->CheckParm("-gles2_renderer")) || (vid_preferbackend == 3) ) + if (V_GetBackend() == 2) fb = new OpenGLESRenderer::OpenGLFrameBuffer(m_hMonitor, vid_fullscreen); else #endif @@ -423,8 +422,6 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) } int prof = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - const char *version = Args->CheckValue("-glversion"); - for (; prof <= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; prof++) { diff --git a/src/common/platform/win32/win32polyvideo.cpp b/src/common/platform/win32/win32polyvideo.cpp deleted file mode 100644 index 9a4538d29..000000000 --- a/src/common/platform/win32/win32polyvideo.cpp +++ /dev/null @@ -1,199 +0,0 @@ - -#include -#include "hardware.h" -#include "engineerrors.h" -#include - -#ifdef HAVE_SOFTPOLY - -EXTERN_CVAR(Bool, vid_vsync) - -bool ViewportLinearScale(); - -extern HWND Window; - -#include -#pragma comment(lib, "d3d9.lib") - -#ifndef D3DPRESENT_FORCEIMMEDIATE -#define D3DPRESENT_FORCEIMMEDIATE 0x00000100L // MinGW -#endif - -namespace -{ - int SrcWidth = 0; - int SrcHeight = 0; - int ClientWidth = 0; - int ClientHeight = 0; - bool CurrentVSync = false; - - IDirect3D9Ex *d3d9 = nullptr; - IDirect3DDevice9Ex *device = nullptr; - IDirect3DSurface9* surface = nullptr; -} - -void I_PolyPresentInit() -{ - Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9); - if (!d3d9) - { - I_FatalError("Direct3DCreate9 failed"); - } - - RECT rect = {}; - GetClientRect(Window, &rect); - - ClientWidth = rect.right; - ClientHeight = rect.bottom; - - D3DPRESENT_PARAMETERS pp = {}; - pp.Windowed = true; - pp.SwapEffect = D3DSWAPEFFECT_FLIPEX; - pp.BackBufferWidth = ClientWidth; - pp.BackBufferHeight = ClientHeight; - pp.BackBufferCount = 1; - pp.hDeviceWindow = Window; - pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; - - HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device); - if (FAILED(result)) - { - I_FatalError("IDirect3D9.CreateDevice failed"); - } -} - -uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch) -{ - HRESULT result; - - RECT rect = {}; - GetClientRect(Window, &rect); - if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync) - { - if (surface) - { - surface->Release(); - surface = nullptr; - } - - CurrentVSync = vsync; - ClientWidth = rect.right; - ClientHeight = rect.bottom; - - D3DPRESENT_PARAMETERS pp = {}; - pp.Windowed = true; - pp.SwapEffect = D3DSWAPEFFECT_FLIPEX; - pp.BackBufferWidth = ClientWidth; - pp.BackBufferHeight = ClientHeight; - pp.BackBufferCount = 1; - pp.hDeviceWindow = Window; - pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; - device->Reset(&pp); - } - - if (SrcWidth != w || SrcHeight != h || !surface) - { - if (surface) - { - surface->Release(); - surface = nullptr; - } - - SrcWidth = w; - SrcHeight = h; - result = device->CreateOffscreenPlainSurface(SrcWidth, SrcHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, 0); - if (FAILED(result)) - { - I_FatalError("IDirect3DDevice9.CreateOffscreenPlainSurface failed"); - } - } - - D3DLOCKED_RECT lockrect = {}; - result = surface->LockRect(&lockrect, nullptr, D3DLOCK_DISCARD); - if (FAILED(result)) - { - pitch = 0; - return nullptr; - } - - pitch = lockrect.Pitch; - return (uint8_t*)lockrect.pBits; -} - -void I_PolyPresentUnlock(int x, int y, int width, int height) -{ - surface->UnlockRect(); - - IDirect3DSurface9 *backbuffer = nullptr; - HRESULT result = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); - if (FAILED(result)) - return; - - result = device->BeginScene(); - if (SUCCEEDED(result)) - { - int count = 0; - D3DRECT clearrects[4]; - if (y > 0) - { - clearrects[count].x1 = 0; - clearrects[count].y1 = 0; - clearrects[count].x2 = ClientWidth; - clearrects[count].y2 = y; - count++; - } - if (y + height < ClientHeight) - { - clearrects[count].x1 = 0; - clearrects[count].y1 = y + height; - clearrects[count].x2 = ClientWidth; - clearrects[count].y2 = ClientHeight; - count++; - } - if (x > 0) - { - clearrects[count].x1 = 0; - clearrects[count].y1 = y; - clearrects[count].x2 = x; - clearrects[count].y2 = y + height; - count++; - } - if (x + width < ClientWidth) - { - clearrects[count].x1 = x + width; - clearrects[count].y1 = y; - clearrects[count].x2 = ClientWidth; - clearrects[count].y2 = y + height; - count++; - } - if (count > 0) - device->Clear(count, clearrects, D3DCLEAR_TARGET, 0, 0.0f, 0); - - RECT srcrect = {}, dstrect = {}; - srcrect.right = SrcWidth; - srcrect.bottom = SrcHeight; - dstrect.left = x; - dstrect.top = y; - dstrect.right = x + width; - dstrect.bottom = y + height; - if (ViewportLinearScale()) - device->StretchRect(surface, &srcrect, backbuffer, &dstrect, D3DTEXF_LINEAR); - else - device->StretchRect(surface, &srcrect, backbuffer, &dstrect, D3DTEXF_POINT); - - result = device->EndScene(); - if (SUCCEEDED(result)) - device->PresentEx(nullptr, nullptr, 0, nullptr, CurrentVSync ? 0 : D3DPRESENT_FORCEIMMEDIATE); - } - - backbuffer->Release(); -} - -void I_PolyPresentDeinit() -{ - if (surface) surface->Release(); - if (device) device->Release(); - if (d3d9) d3d9->Release(); -} - -#endif \ No newline at end of file diff --git a/src/common/platform/win32/win32polyvideo.h b/src/common/platform/win32/win32polyvideo.h deleted file mode 100644 index 3a1c36242..000000000 --- a/src/common/platform/win32/win32polyvideo.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "win32basevideo.h" -#include "c_cvars.h" -#include "poly_framebuffer.h" - -EXTERN_CVAR(Bool, vid_fullscreen) - -class Win32PolyVideo : public Win32BaseVideo -{ -public: - void Shutdown() override - { - } - - DFrameBuffer *CreateFrameBuffer() override - { - auto fb = new PolyFrameBuffer(m_hMonitor, vid_fullscreen); - return fb; - } -}; diff --git a/src/common/platform/win32/win32vulkanvideo.cpp b/src/common/platform/win32/win32vulkanvideo.cpp index d2c2e7b40..25cf661ca 100644 --- a/src/common/platform/win32/win32vulkanvideo.cpp +++ b/src/common/platform/win32/win32vulkanvideo.cpp @@ -6,18 +6,16 @@ #define VK_USE_PLATFORM_WIN32_KHR #endif -#include "volk/volk.h" - - -extern HWND Window; +#include +#include "i_mainwindow.h" void I_GetVulkanDrawableSize(int *width, int *height) { - assert(Window); + assert(mainwindow.GetHandle()); RECT clientRect = { 0 }; - GetClientRect(Window, &clientRect); - + GetClientRect(mainwindow.GetHandle(), &clientRect); + if (width != nullptr) { *width = clientRect.right; @@ -67,7 +65,7 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; windowCreateInfo.pNext = nullptr; windowCreateInfo.flags = 0; - windowCreateInfo.hwnd = Window; + windowCreateInfo.hwnd = mainwindow.GetHandle(); windowCreateInfo.hinstance = GetModuleHandle(nullptr); const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface); diff --git a/src/common/platform/win32/win32vulkanvideo.h b/src/common/platform/win32/win32vulkanvideo.h index 2654597c7..1cd070f2a 100644 --- a/src/common/platform/win32/win32vulkanvideo.h +++ b/src/common/platform/win32/win32vulkanvideo.h @@ -2,10 +2,17 @@ #include "win32basevideo.h" #include "c_cvars.h" -#include "vulkan/system/vk_framebuffer.h" +#include "vulkan/system/vk_renderdevice.h" +#include +#include +void I_GetVulkanDrawableSize(int* width, int* height); +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR* surface); +bool I_GetVulkanPlatformExtensions(unsigned int* count, const char** names); EXTERN_CVAR(Bool, vid_fullscreen) +EXTERN_CVAR(Bool, vk_debug) +EXTERN_CVAR(Int, vk_device) //========================================================================== // @@ -15,27 +22,40 @@ EXTERN_CVAR(Bool, vid_fullscreen) class Win32VulkanVideo : public Win32BaseVideo { - VulkanDevice *device = nullptr; + std::shared_ptr surface; public: Win32VulkanVideo() { - device = new VulkanDevice(); + unsigned int count = 64; + const char* names[64]; + if (!I_GetVulkanPlatformExtensions(&count, names)) + VulkanError("I_GetVulkanPlatformExtensions failed"); + + VulkanInstanceBuilder builder; + builder.DebugLayer(vk_debug); + for (unsigned int i = 0; i < count; i++) + builder.RequireExtension(names[i]); + auto instance = builder.Create(); + + VkSurfaceKHR surfacehandle = nullptr; + if (!I_CreateVulkanSurface(instance->Instance, &surfacehandle)) + VulkanError("I_CreateVulkanSurface failed"); + + surface = std::make_shared(instance, surfacehandle); } - + ~Win32VulkanVideo() { - delete device; } void Shutdown() override { - delete device; - device = nullptr; + surface.reset(); } DFrameBuffer *CreateFrameBuffer() override { - auto fb = new VulkanFrameBuffer(m_hMonitor, vid_fullscreen, device); + auto fb = new VulkanRenderDevice(m_hMonitor, vid_fullscreen, surface); return fb; } diff --git a/src/common/platform/win32/zutil.natvis b/src/common/platform/win32/zutil.natvis index 156594329..9a257a7cf 100644 --- a/src/common/platform/win32/zutil.natvis +++ b/src/common/platform/win32/zutil.natvis @@ -25,6 +25,17 @@ + + Size = {Count} + + Count + + Count + (value_type*)Array + + + + Size = {Count} diff --git a/src/common/rendering/gl/gl_buffers.cpp b/src/common/rendering/gl/gl_buffers.cpp index 9338fee98..a576b6431 100644 --- a/src/common/rendering/gl/gl_buffers.cpp +++ b/src/common/rendering/gl/gl_buffers.cpp @@ -192,12 +192,12 @@ void GLBuffer::GPUDropSync() void GLBuffer::GPUWaitSync() { GLenum status = glClientWaitSync(mGLSync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 50); // Wait for a max of 50ms... - + if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED) { //Printf("Error on glClientWaitSync: %d\n", status); } - + glDeleteSync(mGLSync); mGLSync = NULL; @@ -211,12 +211,14 @@ void GLBuffer::GPUWaitSync() void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) { - static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT_2_10_10_10_REV }; - static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4}; - + static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE }; + static uint8_t VFmtToSize[] = { 4, 3, 2, 1, 4, 4, 4 }; + static bool VFmtToNormalize[] = { false, false, false, false, true, true, false }; + static bool VFmtToIntegerType[] = { false, false, false, false, false, false, true }; + mStride = stride; mNumBindingPoints = numBindingPoints; - + for(int i = 0; i < numAttributes; i++) { if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX) @@ -226,6 +228,8 @@ void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s attrinf.size = VFmtToSize[attrs[i].format]; attrinf.offset = attrs[i].offset; attrinf.bindingpoint = attrs[i].binding; + attrinf.normalize = VFmtToNormalize[attrs[i].format]; + attrinf.integerType = VFmtToIntegerType[attrs[i].format]; } } } @@ -246,7 +250,10 @@ void GLVertexBuffer::Bind(int *offsets) { glEnableVertexAttribArray(i); size_t ofs = offsets == nullptr ? attrinf.offset : attrinf.offset + mStride * offsets[attrinf.bindingpoint]; - glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.format != GL_FLOAT, (GLsizei)mStride, (void*)(intptr_t)ofs); + if (!attrinf.integerType) + glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.normalize, (GLsizei)mStride, (void*)(intptr_t)ofs); + else + glVertexAttribIPointer(i, attrinf.size, attrinf.format, (GLsizei)mStride, (void*)(intptr_t)ofs); } i++; } diff --git a/src/common/rendering/gl/gl_buffers.h b/src/common/rendering/gl/gl_buffers.h index d0c2b62c8..9bca819a1 100644 --- a/src/common/rendering/gl/gl_buffers.h +++ b/src/common/rendering/gl/gl_buffers.h @@ -46,6 +46,8 @@ class GLVertexBuffer : public IVertexBuffer, public GLBuffer { int bindingpoint; int format; + bool normalize; + bool integerType; int size; int offset; }; diff --git a/src/common/rendering/gl/gl_debug.cpp b/src/common/rendering/gl/gl_debug.cpp index c6c3adbfc..38625e73d 100644 --- a/src/common/rendering/gl/gl_debug.cpp +++ b/src/common/rendering/gl/gl_debug.cpp @@ -19,7 +19,7 @@ ** 3. This notice may not be removed or altered from any source distribution. */ -#include "templates.h" + #include "gl_system.h" #include "gl_debug.h" #include "stats.h" diff --git a/src/common/rendering/gl/gl_framebuffer.cpp b/src/common/rendering/gl/gl_framebuffer.cpp index 668965a11..6ea31e5bd 100644 --- a/src/common/rendering/gl/gl_framebuffer.cpp +++ b/src/common/rendering/gl/gl_framebuffer.cpp @@ -36,7 +36,7 @@ #include "gl_system.h" #include "v_video.h" #include "m_png.h" -#include "templates.h" + #include "i_time.h" #include "gl_interface.h" @@ -49,6 +49,7 @@ #include "hw_skydome.h" #include "hw_viewpointbuffer.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "gl_shaderprogram.h" #include "gl_debug.h" #include "r_videoscale.h" @@ -69,7 +70,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); void gl_LoadExtensions(); void gl_PrintStartupLog(); -void Draw2D(F2DDrawer *drawer, FRenderState &state); extern bool vid_hdr_active; @@ -105,6 +105,7 @@ OpenGLFrameBuffer::~OpenGLFrameBuffer() if (mSkyData != nullptr) delete mSkyData; if (mViewpoints != nullptr) delete mViewpoints; if (mLights != nullptr) delete mLights; + if (mBones != nullptr) delete mBones; mShadowMap.Reset(); if (GLRenderer) @@ -172,11 +173,13 @@ void OpenGLFrameBuffer::InitializeState() mSkyData = new FSkyVertexBuffer; mViewpoints = new HWViewpointBuffer(screen->mPipelineNbr); mLights = new FLightBuffer(screen->mPipelineNbr); + mBones = new BoneBuffer(screen->mPipelineNbr); GLRenderer = new FGLRenderer(this); GLRenderer->Initialize(GetWidth(), GetHeight()); static_cast(mLights->GetBuffer())->BindBase(); + static_cast(mBones->GetBuffer())->BindBase(); - mDebug = std::make_shared(); + mDebug = std::make_unique(); mDebug->Update(); } @@ -326,7 +329,6 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - int flags = mat->GetScaleFlags(); int numLayers = mat->NumLayers(); MaterialLayerInfo* layer; auto base = static_cast(mat->GetLayer(0, translation, &layer)); @@ -364,6 +366,29 @@ void OpenGLFrameBuffer::BlurScene(float amount) GLRenderer->BlurScene(amount); } +void OpenGLFrameBuffer::InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) +{ + if (LMTextureData.Size() > 0) + { + GLint activeTex = 0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); + glActiveTexture(GL_TEXTURE0 + 17); + + if (GLRenderer->mLightMapID == 0) + glGenTextures(1, (GLuint*)&GLRenderer->mLightMapID); + + glBindTexture(GL_TEXTURE_2D_ARRAY, GLRenderer->mLightMapID); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB16F, LMTextureSize, LMTextureSize, LMTextureCount, 0, GL_RGB, GL_HALF_FLOAT, &LMTextureData[0]); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + + glActiveTexture(activeTex); + + LMTextureData.Reset(); // We no longer need this, release the memory + } +} + void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds) { Super::SetViewportRects(bounds); @@ -463,6 +488,7 @@ void OpenGLFrameBuffer::SetSaveBuffers(bool yes) void OpenGLFrameBuffer::BeginFrame() { SetViewportRects(nullptr); + mViewpoints->Clear(); if (GLRenderer != nullptr) GLRenderer->BeginFrame(); } @@ -540,6 +566,11 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); } +bool OpenGLFrameBuffer::CompileNextShader() +{ + return GLRenderer->mShaderManager->CompileNextShader(); +} + //========================================================================== // // OpenGLFrameBuffer :: WipeStartScreen diff --git a/src/common/rendering/gl/gl_framebuffer.h b/src/common/rendering/gl/gl_framebuffer.h index 8f8a139b6..7b659db0a 100644 --- a/src/common/rendering/gl/gl_framebuffer.h +++ b/src/common/rendering/gl/gl_framebuffer.h @@ -20,10 +20,10 @@ class OpenGLFrameBuffer : public SystemGLFrameBuffer public: - explicit OpenGLFrameBuffer() {} OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; ~OpenGLFrameBuffer(); - + int Backend() override { return 2; } + bool CompileNextShader() override; void InitializeState() override; void Update() override; @@ -50,6 +50,8 @@ public: IIndexBuffer *CreateIndexBuffer() override; IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; + void InitLightmap(int LMTextureSize, int LMTextureCount, TArray& LMTextureData) override; + // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer // points to the last row in the buffer, which will be the first row output. @@ -64,8 +66,8 @@ public: void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; bool HWGammaActive = false; // Are we using hardware or software gamma? - std::shared_ptr mDebug; // Debug API - + std::unique_ptr mDebug; // Debug API + FTexture *WipeStartScreen() override; FTexture *WipeEndScreen() override; diff --git a/src/common/rendering/gl/gl_hwtexture.cpp b/src/common/rendering/gl/gl_hwtexture.cpp index 0043a67b8..37b066155 100644 --- a/src/common/rendering/gl/gl_hwtexture.cpp +++ b/src/common/rendering/gl/gl_hwtexture.cpp @@ -34,7 +34,7 @@ */ #include "gl_system.h" -#include "templates.h" + #include "c_cvars.h" #include "hw_material.h" @@ -148,7 +148,7 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int { sourcetype = GL_BGRA; } - + if (!firstCall && glBufferID > 0) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rw, rh, sourcetype, GL_UNSIGNED_BYTE, buffer); else @@ -301,8 +301,6 @@ void FHardwareTexture::BindToFrameBuffer(int width, int height) bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) { - int usebright = false; - bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; // Bind it to the system. @@ -317,7 +315,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i int w = 0, h = 0; // Create this texture - + FTextureBuffer texbuffer; if (!tex->isHardwareCanvas()) diff --git a/src/common/rendering/gl/gl_postprocess.cpp b/src/common/rendering/gl/gl_postprocess.cpp index 949fee4b0..f5ec0bfae 100644 --- a/src/common/rendering/gl/gl_postprocess.cpp +++ b/src/common/rendering/gl/gl_postprocess.cpp @@ -33,7 +33,7 @@ #include "flatvertices.h" #include "r_videoscale.h" #include "v_video.h" -#include "templates.h" + #include "hw_vrmodes.h" #include "v_draw.h" diff --git a/src/common/rendering/gl/gl_postprocessstate.cpp b/src/common/rendering/gl/gl_postprocessstate.cpp index 2e6a04f05..e490e8708 100644 --- a/src/common/rendering/gl/gl_postprocessstate.cpp +++ b/src/common/rendering/gl/gl_postprocessstate.cpp @@ -19,7 +19,7 @@ ** 3. This notice may not be removed or altered from any source distribution. */ -#include "templates.h" + #include "gl_system.h" #include "gl_interface.h" #include "gl_postprocessstate.h" diff --git a/src/common/rendering/gl/gl_renderbuffers.cpp b/src/common/rendering/gl/gl_renderbuffers.cpp index 134009fc4..4f49cdce3 100644 --- a/src/common/rendering/gl/gl_renderbuffers.cpp +++ b/src/common/rendering/gl/gl_renderbuffers.cpp @@ -30,7 +30,7 @@ #include "gl_postprocessstate.h" #include "gl_shaderprogram.h" #include "gl_buffers.h" -#include "templates.h" + #include EXTERN_CVAR(Int, gl_debug_level) @@ -87,6 +87,7 @@ void FGLRenderBuffers::ClearScene() void FGLRenderBuffers::ClearPipeline() { + DeleteRenderBuffer(mPipelineDepthStencilBuf); for (int i = 0; i < NumPipelineTextures; i++) { DeleteFrameBuffer(mPipelineFB[i]); @@ -239,10 +240,11 @@ void FGLRenderBuffers::CreatePipeline(int width, int height) ClearPipeline(); ClearEyeBuffers(); + mPipelineDepthStencilBuf = CreateRenderBuffer("PipelineDepthStencil", GL_DEPTH24_STENCIL8, width, height); for (int i = 0; i < NumPipelineTextures; i++) { mPipelineTexture[i] = Create2DTexture("PipelineTexture", GL_RGBA16F, width, height); - mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i]); + mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i], mPipelineDepthStencilBuf); } } @@ -444,8 +446,6 @@ bool FGLRenderBuffers::CheckFrameBufferCompleteness() if (result == GL_FRAMEBUFFER_COMPLETE) return true; - bool FailedCreate = true; - if (gl_debug_level > 0) { FString error = "glCheckFramebufferStatus failed: "; @@ -992,4 +992,4 @@ int FGLRenderBuffers::NextEye(int eyeCount) return mCurrentEye; } -} // namespace OpenGLRenderer \ No newline at end of file +} // namespace OpenGLRenderer diff --git a/src/common/rendering/gl/gl_renderbuffers.h b/src/common/rendering/gl/gl_renderbuffers.h index da967f021..bb652e495 100644 --- a/src/common/rendering/gl/gl_renderbuffers.h +++ b/src/common/rendering/gl/gl_renderbuffers.h @@ -173,6 +173,7 @@ private: static const int NumPipelineTextures = 2; int mCurrentPipelineTexture = 0; + PPGLRenderBuffer mPipelineDepthStencilBuf; // Buffers for the scene PPGLTexture mSceneMultisampleTex; @@ -208,4 +209,4 @@ private: friend class GLPPRenderState; }; -} \ No newline at end of file +} diff --git a/src/common/rendering/gl/gl_renderer.h b/src/common/rendering/gl/gl_renderer.h index 3a4c55a70..cb276d8bc 100644 --- a/src/common/rendering/gl/gl_renderer.h +++ b/src/common/rendering/gl/gl_renderer.h @@ -61,6 +61,8 @@ public: FPresent3DRowShader *mPresent3dRowShader = nullptr; FShadowMapShader *mShadowMapShader = nullptr; + int mLightMapID = 0; + //FRotator mAngles; FGLRenderer(OpenGLFrameBuffer *fb); @@ -80,7 +82,7 @@ public: void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void BeginFrame(); - + bool StartOffscreen(); void EndOffscreen(); diff --git a/src/common/rendering/gl/gl_renderstate.cpp b/src/common/rendering/gl/gl_renderstate.cpp index c660fb98e..10baa3e66 100644 --- a/src/common/rendering/gl/gl_renderstate.cpp +++ b/src/common/rendering/gl/gl_renderstate.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -25,7 +25,7 @@ ** */ -#include "templates.h" + #include "gl_system.h" #include "gl_interface.h" #include "hw_cvars.h" @@ -33,6 +33,7 @@ #include "gl_shader.h" #include "gl_renderer.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "gl_renderbuffers.h" #include "gl_hwtexture.h" #include "gl_buffers.h" @@ -133,6 +134,7 @@ bool FGLRenderState::ApplyShader() activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.); activeShader->muAlphaThreshold.Set(mAlphaThreshold); activeShader->muLightIndex.Set(-1); + activeShader->muBoneIndexBase.Set(-1); activeShader->muClipSplit.Set(mClipSplit); activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel); activeShader->muAddColor.Set(mStreamData.uAddColor); @@ -210,6 +212,21 @@ bool FGLRenderState::ApplyShader() } activeShader->muLightIndex.Set(index); + + index = mBoneIndexBase; + if (!screen->mBones->GetBufferType() && index >= 0) // Uniform buffer fallback support + { + size_t start, size; + index = screen->mBones->GetBinding(index, &start, &size); + + if (start != mLastMappedBoneIndexBase || screen->mPipelineNbr > 1) // If multiple buffers always bind + { + mLastMappedBoneIndexBase = start; + static_cast(screen->mBones->GetBuffer())->BindRange(nullptr, start, size); + } + } + activeShader->muBoneIndexBase.Set(index); + return true; } @@ -311,14 +328,13 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio if (tex->isHardwareCanvas()) static_cast(tex->GetTexture())->NeedUpdate(); clampmode = tex->GetClampMode(clampmode); - + // avoid rebinding the same texture multiple times. if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; lastMaterial = mat; lastClamp = clampmode; lastTranslation = translation; - int usebright = false; int maxbound = 0; int numLayers = mat->NumLayers(); diff --git a/src/common/rendering/gl/gl_renderstate.h b/src/common/rendering/gl/gl_renderstate.h index 948255d71..b89a02ad8 100644 --- a/src/common/rendering/gl/gl_renderstate.h +++ b/src/common/rendering/gl/gl_renderstate.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -66,6 +66,7 @@ class FGLRenderState final : public FRenderState int lastTranslation = 0; int maxBoundMaterial = -1; size_t mLastMappedLightIndex = SIZE_MAX; + size_t mLastMappedBoneIndexBase = SIZE_MAX; IVertexBuffer *mCurrentVertexBuffer; int mCurrentVertexOffsets[2]; // one per binding point @@ -107,7 +108,7 @@ public: void EnableDrawBuffers(int count, bool apply = false) override { - count = std::min(count, 3); + count = min(count, 3); if (mNumDrawBuffers != count) { static GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; diff --git a/src/common/rendering/gl/gl_samplers.cpp b/src/common/rendering/gl/gl_samplers.cpp index 3f1f53110..5ed7cbc19 100644 --- a/src/common/rendering/gl/gl_samplers.cpp +++ b/src/common/rendering/gl/gl_samplers.cpp @@ -98,7 +98,7 @@ void FSamplerManager::UnbindAll() glBindSampler(i, 0); } } - + uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { unsigned int samp = mSamplers[num]; @@ -106,11 +106,11 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) return 255; } - + void FSamplerManager::SetTextureFilterMode() { GLint bounds[IHardwareTexture::MAX_TEXTURES]; - + // Unbind all for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--) { @@ -138,4 +138,4 @@ void FSamplerManager::SetTextureFilterMode() } -} \ No newline at end of file +} diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index 60c5677a6..2e4951f1a 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -38,6 +38,7 @@ #include "shaderuniforms.h" #include "hw_viewpointuniforms.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "i_specialpaths.h" #include "printf.h" #include "version.h" @@ -234,6 +235,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * float uClipHeight; float uClipHeightDirection; int uShadowmapFilter; + + int uLightBlendMode; }; uniform int uTextureMode; @@ -276,6 +279,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * // dynamic lights uniform int uLightIndex; + // bone animation + uniform int uBoneIndexBase; + // Blinn glossiness and specular level uniform vec2 uSpecularMaterial; @@ -297,9 +303,23 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * }; #endif + // bone matrix buffers + #ifdef SHADER_STORAGE_BONES + layout(std430, binding = 7) buffer BoneBufferSSO + { + mat4 bones[]; + }; + #elif defined NUM_UBO_BONES + uniform BoneBufferUBO + { + mat4 bones[NUM_UBO_BONES]; + }; + #endif + // textures uniform sampler2D tex; uniform sampler2D ShadowMap; + uniform sampler2DArray LightMap; uniform sampler2D texture2; uniform sampler2D texture3; uniform sampler2D texture4; @@ -310,6 +330,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * uniform sampler2D texture9; uniform sampler2D texture10; uniform sampler2D texture11; + uniform sampler2D texture12; // timer data uniform float timer; @@ -336,7 +357,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * #endif )"; - + #ifdef __APPLE__ // The noise functions are completely broken in macOS OpenGL drivers @@ -368,20 +389,21 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * FString vp_comb; assert(screen->mLights != NULL); + assert(screen->mBones != NULL); bool lightbuffertype = screen->mLights->GetBufferType(); unsigned int lightbuffersize = screen->mLights->GetBlockSize(); if (!lightbuffertype) { - vp_comb.Format("#version 330 core\n#define NUM_UBO_LIGHTS %d\n", lightbuffersize); + vp_comb.Format("#version 330 core\n#define NUM_UBO_LIGHTS %d\n#define NUM_UBO_BONES %d\n", lightbuffersize, screen->mBones->GetBlockSize()); } else { // This differentiation is for Intel which do not seem to expose the full extension, even if marked as required. if (gl.glslversion < 4.3f) - vp_comb = "#version 400 core\n#extension GL_ARB_shader_storage_buffer_object : require\n#define SHADER_STORAGE_LIGHTS\n"; + vp_comb = "#version 400 core\n#extension GL_ARB_shader_storage_buffer_object : require\n#define SHADER_STORAGE_LIGHTS\n#define SHADER_STORAGE_BONES\n"; else - vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n"; + vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n#define SHADER_STORAGE_BONES\n"; } if ((gl.flags & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO()) @@ -575,6 +597,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muLightParms.Init(hShader, "uLightAttr"); muClipSplit.Init(hShader, "uClipSplit"); muLightIndex.Init(hShader, "uLightIndex"); + muBoneIndexBase.Init(hShader, "uBoneIndexBase"); muFogColor.Init(hShader, "uFogColor"); muDynLightColor.Init(hShader, "uDynLightColor"); muObjectColor.Init(hShader, "uObjectColor"); @@ -609,6 +632,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { int tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO"); if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, LIGHTBUF_BINDINGPOINT); + + tempindex = glGetUniformBlockIndex(hShader, "BoneBufferUBO"); + if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, BONEBUF_BINDINGPOINT); } int tempindex = glGetUniformBlockIndex(hShader, "ViewpointUBO"); if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, VIEWPOINT_BINDINGPOINT); @@ -620,12 +646,15 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { char stringbuf[20]; mysnprintf(stringbuf, 20, "texture%d", i); - int tempindex = glGetUniformLocation(hShader, stringbuf); - if (tempindex > 0) glUniform1i(tempindex, i - 1); + tempindex = glGetUniformLocation(hShader, stringbuf); + if (tempindex != -1) glUniform1i(tempindex, i - 1); } int shadowmapindex = glGetUniformLocation(hShader, "ShadowMap"); - if (shadowmapindex > 0) glUniform1i(shadowmapindex, 16); + if (shadowmapindex != -1) glUniform1i(shadowmapindex, 16); + + int lightmapindex = glGetUniformLocation(hShader, "LightMap"); + if (lightmapindex != -1) glUniform1i(lightmapindex, 17); glUseProgram(0); return linked; @@ -668,7 +697,7 @@ bool FShader::Bind() FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType) { FString defines; - defines += shaderdefines; + if (shaderdefines) defines += shaderdefines; // this can't be in the shader code due to ATI strangeness. if (!usediscard) defines += "#define NO_ALPHATEST\n"; if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n"; @@ -703,6 +732,20 @@ FShaderManager::FShaderManager() mPassShaders.Push(new FShaderCollection((EPassType)passType)); } +bool FShaderManager::CompileNextShader() +{ + if (mPassShaders[mCompilePass]->CompileNextShader()) + { + mCompilePass++; + if (mCompilePass >= MAX_PASS_TYPES) + { + mCompilePass = -1; + return true; + } + } + return false; +} + FShaderManager::~FShaderManager() { glUseProgram(0); @@ -723,7 +766,7 @@ void FShaderManager::SetActiveShader(FShader *sh) FShader *FShaderManager::BindEffect(int effect, EPassType passType) { - if (passType < mPassShaders.Size()) + if (passType < mPassShaders.Size() && mCompilePass == -1) return mPassShaders[passType]->BindEffect(effect); else return nullptr; @@ -731,7 +774,11 @@ FShader *FShaderManager::BindEffect(int effect, EPassType passType) FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) { - if (r_skipmats && eff >= 3 && eff <= 4) + if (mCompilePass > -1) + { + return mPassShaders[0]->Get(0, false); + } + if ((r_skipmats && eff >= 3 && eff <= 4)) eff = 0; if (passType < mPassShaders.Size()) @@ -748,7 +795,14 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT FShaderCollection::FShaderCollection(EPassType passType) { - CompileShaders(passType); + mPassType = passType; + mMaterialShaders.Clear(); + mMaterialShadersNAT.Clear(); + for (int i = 0; i < MAX_EFFECTS; i++) + { + mEffectShaders[i] = NULL; + } + CompileNextShader(); } //========================================================================== @@ -768,35 +822,47 @@ FShaderCollection::~FShaderCollection() // //========================================================================== -void FShaderCollection::CompileShaders(EPassType passType) +bool FShaderCollection::CompileNextShader() { - mMaterialShaders.Clear(); - mMaterialShadersNAT.Clear(); - for (int i = 0; i < MAX_EFFECTS; i++) + int i = mCompileIndex; + if (mCompileState == 0) { - mEffectShaders[i] = NULL; - } - - for(int i=0;defaultshaders[i].ShaderName != NULL;i++) - { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType); + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, mPassType); mMaterialShaders.Push(shc); - if (i < SHADER_NoTexture) + mCompileIndex++; + if (defaultshaders[mCompileIndex].ShaderName == nullptr) { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); - mMaterialShadersNAT.Push(shc); + mCompileIndex = 0; + mCompileState++; + } } - - for(unsigned i = 0; i < usershaders.Size(); i++) + else if (mCompileState == 1) + { + FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, mPassType); + mMaterialShadersNAT.Push(shc1); + mCompileIndex++; + if (mCompileIndex >= SHADER_NoTexture) + { + mCompileIndex = 0; + mCompileState++; + if (usershaders.Size() == 0) mCompileState++; + } + } + else if (mCompileState == 2) { FString name = ExtractFileBase(usershaders[i].shader); FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; - FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType); + FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, mPassType); mMaterialShaders.Push(shc); + mCompileIndex++; + if (mCompileIndex >= (int)usershaders.Size()) + { + mCompileIndex = 0; + mCompileState++; + } } - - for(int i=0;iLoad(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, @@ -805,7 +871,13 @@ void FShaderCollection::CompileShaders(EPassType passType) delete eff; } else mEffectShaders[i] = eff; + mCompileIndex++; + if (mCompileIndex >= MAX_EFFECTS) + { + return true; + } } + return false; } //========================================================================== diff --git a/src/common/rendering/gl/gl_shader.h b/src/common/rendering/gl/gl_shader.h index b42e144ef..b93299e08 100644 --- a/src/common/rendering/gl/gl_shader.h +++ b/src/common/rendering/gl/gl_shader.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -241,6 +241,7 @@ class FShader FBufferedUniform4f muLightParms; FBufferedUniform2f muClipSplit; FBufferedUniform1i muLightIndex; + FBufferedUniform1i muBoneIndexBase; FBufferedUniformPE muFogColor; FBufferedUniform4f muDynLightColor; FBufferedUniformPE muObjectColor; @@ -309,10 +310,12 @@ public: FShader *Get(unsigned int eff, bool alphateston, EPassType passType); void SetActiveShader(FShader *sh); + bool CompileNextShader(); private: FShader *mActiveShader = nullptr; TArray mPassShaders; + int mCompilePass = 0; friend class FShader; }; @@ -322,21 +325,23 @@ class FShaderCollection TArray mMaterialShaders; TArray mMaterialShadersNAT; FShader *mEffectShaders[MAX_EFFECTS]; + int mCompileState = 0, mCompileIndex = 0; + EPassType mPassType; void Clean(); - void CompileShaders(EPassType passType); - + public: FShaderCollection(EPassType passType); ~FShaderCollection(); FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType); int Find(const char *mame); + bool CompileNextShader(); FShader *BindEffect(int effect); FShader *Get(unsigned int eff, bool alphateston) { // indices 0-2 match the warping modes, 3 no texture, the following are custom - if (!alphateston && eff <= 2) + if (!alphateston && eff < SHADER_NoTexture && mCompileState == -1) { return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway } diff --git a/src/common/rendering/gl/gl_shaderprogram.cpp b/src/common/rendering/gl/gl_shaderprogram.cpp index eb322fb94..2b6df3254 100644 --- a/src/common/rendering/gl/gl_shaderprogram.cpp +++ b/src/common/rendering/gl/gl_shaderprogram.cpp @@ -263,7 +263,7 @@ FString FShaderProgram::PatchShader(ShaderType type, const FString &code, const // If we have 4.2, always use it because it adds important new syntax. if (maxGlslVersion < 420 && gl.glslversion >= 4.2f) maxGlslVersion = 420; - int shaderVersion = std::min((int)round(gl.glslversion * 10) * 10, maxGlslVersion); + int shaderVersion = min((int)round(gl.glslversion * 10) * 10, maxGlslVersion); patchedCode.AppendFormat("#version %d\n", shaderVersion); // TODO: Find some way to add extension requirements to the patching diff --git a/src/common/rendering/gl/gl_stereo3d.cpp b/src/common/rendering/gl/gl_stereo3d.cpp index c81a8e66a..c13914e22 100644 --- a/src/common/rendering/gl/gl_stereo3d.cpp +++ b/src/common/rendering/gl/gl_stereo3d.cpp @@ -1,28 +1,38 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2015 Christopher Bruns -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// /* -** gl_stereo3d.cpp +** gl_stereo.cpp ** Stereoscopic 3D API ** +**--------------------------------------------------------------------------- +** Copyright 2015 Christopher Bruns +** Copyright 2016-2021 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 "gl_system.h" @@ -34,7 +44,8 @@ #include "gl_framebuffer.h" #include "gl_shaderprogram.h" #include "gl_buffers.h" -#include "templates.h" +#include "menu.h" + EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Float, vid_saturation) @@ -43,7 +54,32 @@ EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Int, gl_satformula) EXTERN_CVAR(Int, gl_dither_bpc) -void UpdateVRModes(bool considerQuadBuffered = true); +#ifdef _WIN32 +EXTERN_CVAR(Bool, vr_enable_quadbuffered) +#endif + +void UpdateVRModes(bool considerQuadBuffered) +{ + 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); + } + vals = filteredValues; +} namespace OpenGLRenderer { @@ -420,4 +456,4 @@ void FGLRenderer::PresentStereo() } } -} +} \ No newline at end of file diff --git a/src/common/rendering/gl_load/gl_interface.cpp b/src/common/rendering/gl_load/gl_interface.cpp index 3b5309e8c..ea011819b 100644 --- a/src/common/rendering/gl_load/gl_interface.cpp +++ b/src/common/rendering/gl_load/gl_interface.cpp @@ -44,7 +44,8 @@ static TArray m_Extensions; RenderContext gl; -static double realglversion; // this is public so the statistics code can access it. +static double realglversion; +static bool bindless; //========================================================================== // @@ -156,7 +157,7 @@ void gl_LoadExtensions() #ifdef _WIN32 if (strstr(gl.vendorstring, "ATI Tech")) { - gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. (TBD: Relegate to vintage build? Maybe after the next survey.) + gl.flags |= RFL_NO_CLIP_PLANES; // gl_ClipDistance is horribly broken on ATI GL3 drivers for Windows. } #endif gl.glslversion = 3.31f; // Force GLSL down to 3.3. @@ -201,6 +202,8 @@ void gl_LoadExtensions() glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl.max_texturesize); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + bindless = CheckExtension("GL_ARB_bindless_texture"); } //========================================================================== @@ -230,7 +233,7 @@ void gl_PrintStartupLog() Printf ("Max. texture units: %d\n", v); glGetIntegerv(GL_MAX_VARYING_FLOATS, &v); Printf ("Max. varying: %d\n", v); - + if (gl.flags & RFL_SHADER_STORAGE_BUFFER) { glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &v); @@ -247,9 +250,14 @@ void gl_PrintStartupLog() } } +void setGlVersion(double glv) +{ + realglversion = glv; +} + std::pair gl_getInfo() { // gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL. // This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support. - return std::make_pair(realglversion, CheckExtension("GL_ARB_bindless_texture")); + return std::make_pair(realglversion, bindless); } diff --git a/src/common/rendering/gl_load/gl_load.c b/src/common/rendering/gl_load/gl_load.c index bf563afe0..e29207f4a 100644 --- a/src/common/rendering/gl_load/gl_load.c +++ b/src/common/rendering/gl_load/gl_load.c @@ -9,7 +9,7 @@ static void* AppleGLGetProcAddress (const char *name) { static void* image = NULL; - + if (NULL == image) image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); @@ -61,9 +61,9 @@ static int TestPointer(const PROC pTest) ptrdiff_t iTest; if(!pTest) return 0; iTest = (ptrdiff_t)pTest; - + if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; - + return 1; } @@ -119,7 +119,7 @@ static PROC WinGetProcAddress(const char *name) glMod = GetModuleHandleA("OpenGL32.dll"); return (PROC)GetProcAddress(glMod, (LPCSTR)name); } - + #define IntGetProcAddress(name) WinGetProcAddress(name) #else #if defined(__APPLE__) @@ -3363,7 +3363,7 @@ static ogl_StrToExtMap *FindExtEntry(const char *extensionName) if(strcmp(extensionName, currLoc->extensionName) == 0) return currLoc; } - + return NULL; } @@ -3465,7 +3465,7 @@ int ogl_LoadFunctions() { int numFailed = 0; ClearExtensionVars(); - + _ptrc_glGetIntegerv = (void (CODEGEN_FUNCPTR *)(GLenum, GLint *))IntGetProcAddress("glGetIntegerv"); if(!_ptrc_glGetIntegerv) return ogl_LOAD_FAILED; _ptrc_glGetStringi = (const GLubyte * (CODEGEN_FUNCPTR *)(GLenum, GLuint))IntGetProcAddress("glGetStringi"); @@ -3479,7 +3479,7 @@ int ogl_LoadFunctions() } numFailed = Load_Version_4_5(); - + if(numFailed == 0) return ogl_LOAD_SUCCEEDED; else @@ -3515,7 +3515,7 @@ int ogl_IsVersionGEQ(int majorVersion, int minorVersion) { if(g_major_version == 0) GetGLVersion(); - + if(majorVersion < g_major_version) return 1; if(majorVersion > g_major_version) return 0; if(minorVersion <= g_minor_version) return 1; diff --git a/src/common/rendering/gles/glad/include/glad/glad.h b/src/common/rendering/gles/glad/include/glad/glad.h index 5a7c1505e..212864bc1 100644 --- a/src/common/rendering/gles/glad/include/glad/glad.h +++ b/src/common/rendering/gles/glad/include/glad/glad.h @@ -7,7 +7,7 @@ APIs: gles2=2.0 Profile: compatibility Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/include/glad/glad_egl.h b/src/common/rendering/gles/glad/include/glad/glad_egl.h index fbc5b8630..1c47f7ced 100644 --- a/src/common/rendering/gles/glad/include/glad/glad_egl.h +++ b/src/common/rendering/gles/glad/include/glad/glad_egl.h @@ -7,7 +7,7 @@ APIs: egl=1.4 Profile: - Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/src/glad.c b/src/common/rendering/gles/glad/src/glad.c index 9da9f0ed1..6653cc3f6 100644 --- a/src/common/rendering/gles/glad/src/glad.c +++ b/src/common/rendering/gles/glad/src/glad.c @@ -7,7 +7,7 @@ APIs: gles2=2.0 Profile: compatibility Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/glad/src/glad_egl.c b/src/common/rendering/gles/glad/src/glad_egl.c index 3c939401c..8d0744041 100644 --- a/src/common/rendering/gles/glad/src/glad_egl.c +++ b/src/common/rendering/gles/glad/src/glad_egl.c @@ -7,7 +7,7 @@ APIs: egl=1.4 Profile: - Extensions: - + Loader: True Local files: False Omit khrplatform: False diff --git a/src/common/rendering/gles/gles_buffers.cpp b/src/common/rendering/gles/gles_buffers.cpp index de815ea34..cf7b8ae97 100644 --- a/src/common/rendering/gles/gles_buffers.cpp +++ b/src/common/rendering/gles/gles_buffers.cpp @@ -79,7 +79,7 @@ GLBuffer::~GLBuffer() glBindBuffer(mUseType, 0); glDeleteBuffers(1, &mBufferId); } - + if (memory) delete[] memory; } @@ -129,9 +129,9 @@ void GLBuffer::SetData(size_t size, const void* data, BufferUsageType usage) void GLBuffer::SetSubData(size_t offset, size_t size, const void *data) { Bind(); - + memcpy(memory + offset, data, size); - + if (!isData) { glBufferSubData(mUseType, offset, size, data); @@ -143,7 +143,7 @@ void GLBuffer::Upload(size_t start, size_t size) if (!gles.useMappedBuffers) { Bind(); - + if(size) glBufferSubData(mUseType, start, size, memory + start); } @@ -207,29 +207,28 @@ void GLBuffer::Unlock() } void GLBuffer::Resize(size_t newsize) -{ - assert(!nomap); // only mappable buffers can be resized. - if (newsize > buffersize && !nomap) +{ + if (newsize > buffersize) { - /* - // reallocate the buffer with twice the size - unsigned int oldbuffer = mBufferId; + if (isData) + { + // Create new bigger memory + char* memoryNew = (char*)(new uint64_t[newsize / 8 + 16]); - // first unmap the old buffer - Bind(); - glUnmapBuffer(mUseType); + // Copy old data + memcpy(memoryNew, memory, buffersize); - glGenBuffers(1, &mBufferId); - SetData(newsize, nullptr, false); - glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer); + // Delete old memory + delete[] memory; - // copy contents and delete the old buffer. - glCopyBufferSubData(GL_COPY_READ_BUFFER, mUseType, 0, 0, buffersize); - glBindBuffer(GL_COPY_READ_BUFFER, 0); - glDeleteBuffers(1, &oldbuffer); - buffersize = newsize; - InvalidateBufferState(); - */ + memory = memoryNew; + + buffersize = newsize; + } + else + { + // TODO + } } } @@ -276,12 +275,14 @@ void GLBuffer::GPUWaitSync() void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) { - static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_FLOAT }; // TODO Fix last entry GL_INT_2_10_10_10_REV, normals for models will be broken - static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4}; - + static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE }; // TODO Fix last entry GL_INT_2_10_10_10_REV, normals for models will be broken + static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4, 4}; + static bool VFmtToNormalize[] = { false, false, false, false, true, true, false }; + static bool VFmtToIntegerType[] = { false, false, false, false, false, false, true }; + mStride = stride; mNumBindingPoints = numBindingPoints; - + for(int i = 0; i < numAttributes; i++) { if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX) @@ -291,6 +292,8 @@ void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s attrinf.size = VFmtToSize[attrs[i].format]; attrinf.offset = attrs[i].offset; attrinf.bindingpoint = attrs[i].binding; + attrinf.normalize = VFmtToNormalize[attrs[i].format]; + attrinf.integerType = VFmtToIntegerType[attrs[i].format]; } } } @@ -311,7 +314,13 @@ void GLVertexBuffer::Bind(int *offsets) { glEnableVertexAttribArray(i); size_t ofs = offsets == nullptr ? attrinf.offset : attrinf.offset + mStride * offsets[attrinf.bindingpoint]; - glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.format != GL_FLOAT, (GLsizei)mStride, (void*)(intptr_t)ofs); + if (!attrinf.integerType) + glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.normalize, (GLsizei)mStride, (void*)(intptr_t)ofs); + else + { + if (gles.gles3Features) + glVertexAttribIPointer(i, attrinf.size, attrinf.format, (GLsizei)mStride, (void*)(intptr_t)ofs); + } } i++; } diff --git a/src/common/rendering/gles/gles_buffers.h b/src/common/rendering/gles/gles_buffers.h index d9e01ece6..50156ef7e 100644 --- a/src/common/rendering/gles/gles_buffers.h +++ b/src/common/rendering/gles/gles_buffers.h @@ -49,6 +49,8 @@ class GLVertexBuffer : public IVertexBuffer, public GLBuffer { int bindingpoint; int format; + bool normalize; + bool integerType; int size; int offset; }; diff --git a/src/common/rendering/gles/gles_framebuffer.cpp b/src/common/rendering/gles/gles_framebuffer.cpp index 3a74ee6bc..0d0a459c0 100644 --- a/src/common/rendering/gles/gles_framebuffer.cpp +++ b/src/common/rendering/gles/gles_framebuffer.cpp @@ -36,7 +36,7 @@ #include "gles_system.h" #include "v_video.h" #include "m_png.h" -#include "templates.h" + #include "i_time.h" #include "gles_framebuffer.h" @@ -48,6 +48,7 @@ #include "hw_skydome.h" #include "hw_viewpointbuffer.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "gles_shaderprogram.h" #include "r_videoscale.h" #include "gles_buffers.h" @@ -67,8 +68,6 @@ EXTERN_CVAR(Int, gl_pipeline_depth); EXTERN_CVAR(Bool, gl_sort_textures); -void Draw2D(F2DDrawer *drawer, FRenderState &state); - extern bool vid_hdr_active; namespace OpenGLESRenderer @@ -103,6 +102,7 @@ OpenGLFrameBuffer::~OpenGLFrameBuffer() if (mSkyData != nullptr) delete mSkyData; if (mViewpoints != nullptr) delete mViewpoints; if (mLights != nullptr) delete mLights; + if (mBones != nullptr) delete mBones; mShadowMap.Reset(); if (GLRenderer) @@ -122,7 +122,7 @@ void OpenGLFrameBuffer::InitializeState() { static bool first=true; - mPipelineNbr = gl_pipeline_depth == 0? std::min(4, HW_MAX_PIPELINE_BUFFERS) : clamp(*gl_pipeline_depth, 1, HW_MAX_PIPELINE_BUFFERS); + mPipelineNbr = gl_pipeline_depth == 0? min(4, HW_MAX_PIPELINE_BUFFERS) : clamp(*gl_pipeline_depth, 1, HW_MAX_PIPELINE_BUFFERS); mPipelineType = 1; InitGLES(); @@ -136,8 +136,9 @@ void OpenGLFrameBuffer::InitializeState() glEnable(GL_DITHER); glDisable(GL_CULL_FACE); glDisable(GL_POLYGON_OFFSET_FILL); - + glEnable(GL_BLEND); + if (gles.depthClampAvailable) glEnable(GL_DEPTH_CLAMP); glDisable(GL_DEPTH_TEST); @@ -155,9 +156,11 @@ void OpenGLFrameBuffer::InitializeState() mSkyData = new FSkyVertexBuffer; mViewpoints = new HWViewpointBuffer(mPipelineNbr); mLights = new FLightBuffer(mPipelineNbr); + mBones = new BoneBuffer(mPipelineNbr); GLRenderer = new FGLRenderer(this); GLRenderer->Initialize(GetWidth(), GetHeight()); static_cast(mLights->GetBuffer())->BindBase(); + static_cast(mBones->GetBuffer())->BindBase(); } //========================================================================== @@ -236,7 +239,7 @@ const char* OpenGLFrameBuffer::DeviceName() const void OpenGLFrameBuffer::Swap() { - + Finish.Reset(); Finish.Clock(); @@ -244,7 +247,7 @@ void OpenGLFrameBuffer::Swap() FPSLimit(); SwapBuffers(); - + mVertexData->NextPipelineBuffer(); mVertexData->WaitSync(); @@ -286,7 +289,6 @@ void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - int flags = mat->GetScaleFlags(); int numLayers = mat->NumLayers(); MaterialLayerInfo* layer; auto base = static_cast(mat->GetLayer(0, translation, &layer)); @@ -371,6 +373,7 @@ void OpenGLFrameBuffer::WaitForCommands(bool finish) void OpenGLFrameBuffer::BeginFrame() { SetViewportRects(nullptr); + mViewpoints->Clear(); if (GLRenderer != nullptr) GLRenderer->BeginFrame(); } diff --git a/src/common/rendering/gles/gles_framebuffer.h b/src/common/rendering/gles/gles_framebuffer.h index 25626c659..3cf32f179 100644 --- a/src/common/rendering/gles/gles_framebuffer.h +++ b/src/common/rendering/gles/gles_framebuffer.h @@ -10,7 +10,6 @@ namespace OpenGLESRenderer { class FHardwareTexture; -class FGLDebug; class OpenGLFrameBuffer : public SystemGLFrameBuffer { @@ -23,9 +22,11 @@ public: explicit OpenGLFrameBuffer() {} OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; ~OpenGLFrameBuffer(); + int Backend() override { return 0; } void InitializeState() override; void Update() override; + int GetShaderCount() override { return 0; } void FirstEye() override; void NextEye(int eyecount) override; @@ -60,8 +61,7 @@ public: void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; bool HWGammaActive = false; // Are we using hardware or software gamma? - std::shared_ptr mDebug; // Debug API - + FTexture *WipeStartScreen() override; FTexture *WipeEndScreen() override; diff --git a/src/common/rendering/gles/gles_hwtexture.cpp b/src/common/rendering/gles/gles_hwtexture.cpp index 00370481b..43425ce7d 100644 --- a/src/common/rendering/gles/gles_hwtexture.cpp +++ b/src/common/rendering/gles/gles_hwtexture.cpp @@ -34,7 +34,7 @@ */ #include "gles_system.h" -#include "templates.h" + #include "c_cvars.h" #include "hw_material.h" @@ -132,14 +132,23 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int #if USE_GLES2 - sourcetype = GL_BGRA; - texformat = GL_BGRA; + if (glTextureBytes == 1) + { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + sourcetype = GL_ALPHA; + texformat = GL_ALPHA; + } + else + { + sourcetype = GL_BGRA; + texformat = GL_BGRA; + } #else if (glTextureBytes == 1) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); sourcetype = GL_RED; - texformat = GL_R8; + texformat = GL_RED; } else { @@ -150,6 +159,16 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); +#if !(USE_GLES2) + // The shader is using the alpha channel instead of red, this work on GLES but not on GL + // So the texture uses GL_RED and this swizzels the red channel into the alpha channel + if (glTextureBytes == 1) + { + GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } +#endif + if (deletebuffer && buffer) free(buffer); if (mipmap && TexFilter[gl_texture_filter].mipmapping) @@ -157,7 +176,7 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int glGenerateMipmap(GL_TEXTURE_2D); mipmapped = true; } - + if (texunit > 0) glActiveTexture(GL_TEXTURE0); else if (texunit == -1) glBindTexture(GL_TEXTURE_2D, textureBinding); return glTexID; @@ -166,9 +185,6 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { - int rw = GetTexDimension(w); - int rh = GetTexDimension(h); - if (texelsize < 1 || texelsize > 4) texelsize = 4; glTextureBytes = texelsize; bufferpitch = w; @@ -287,8 +303,6 @@ void FHardwareTexture::BindToFrameBuffer(int width, int height) bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) { - int usebright = false; - bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; // Bind it to the system. @@ -303,7 +317,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i int w = 0, h = 0; // Create this texture - + FTextureBuffer texbuffer; if (!tex->isHardwareCanvas()) diff --git a/src/common/rendering/gles/gles_postprocess.cpp b/src/common/rendering/gles/gles_postprocess.cpp index a618c3b2e..1bedaf9cc 100644 --- a/src/common/rendering/gles/gles_postprocess.cpp +++ b/src/common/rendering/gles/gles_postprocess.cpp @@ -32,7 +32,7 @@ #include "flatvertices.h" #include "r_videoscale.h" #include "v_video.h" -#include "templates.h" + #include "hw_vrmodes.h" #include "v_draw.h" @@ -158,10 +158,9 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) mPresentShader->Uniforms->Offset = { 0.0f, 0.0f }; mPresentShader->Uniforms.SetData(); - - for (int n = 0; n < mPresentShader->Uniforms.mFields.size(); n++) + + for (size_t n = 0; n < mPresentShader->Uniforms.mFields.size(); n++) { - int index = -1; UniformFieldDesc desc = mPresentShader->Uniforms.mFields[n]; int loc = mPresentShader->Uniforms.UniformLocation[n]; switch (desc.Type) @@ -175,9 +174,11 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) case UniformType::Vec2: glUniform2fv(loc,1 , ((GLfloat*)(((char*)(&mPresentShader->Uniforms)) + desc.Offset))); break; + default: + break; } } - + RenderScreenQuad(); } @@ -222,4 +223,4 @@ void FGLRenderer::ClearBorders() glDisable(GL_SCISSOR_TEST); } -} \ No newline at end of file +} diff --git a/src/common/rendering/gles/gles_postprocessstate.cpp b/src/common/rendering/gles/gles_postprocessstate.cpp index 216406125..ea8921837 100644 --- a/src/common/rendering/gles/gles_postprocessstate.cpp +++ b/src/common/rendering/gles/gles_postprocessstate.cpp @@ -19,7 +19,7 @@ ** 3. This notice may not be removed or altered from any source distribution. */ -#include "templates.h" + #include "gles_system.h" #include "gles_postprocessstate.h" diff --git a/src/common/rendering/gles/gles_renderbuffers.cpp b/src/common/rendering/gles/gles_renderbuffers.cpp index 91f8ce462..002734b99 100644 --- a/src/common/rendering/gles/gles_renderbuffers.cpp +++ b/src/common/rendering/gles/gles_renderbuffers.cpp @@ -28,7 +28,7 @@ #include "gles_postprocessstate.h" #include "gles_shaderprogram.h" #include "gles_buffers.h" -#include "templates.h" + #include EXTERN_CVAR(Int, gl_debug_level) @@ -44,7 +44,7 @@ namespace OpenGLESRenderer FGLRenderBuffers::FGLRenderBuffers() { - + } //========================================================================== @@ -56,7 +56,7 @@ namespace OpenGLESRenderer FGLRenderBuffers::~FGLRenderBuffers() { ClearScene(); - + DeleteTexture(mDitherTexture); } @@ -163,7 +163,7 @@ namespace OpenGLESRenderer mSceneTex = Create2DTexture("PipelineTexture", GL_RGBA, width, height); } - + //========================================================================== // @@ -178,7 +178,7 @@ namespace OpenGLESRenderer tex.Height = height; glGenTextures(1, &tex.handle); glBindTexture(GL_TEXTURE_2D, tex.handle); - + GLenum dataformat = 0, datatype = 0; /* switch (format) @@ -224,7 +224,7 @@ namespace OpenGLESRenderer PPGLRenderBuffer buf; glGenRenderbuffers(1, &buf.handle); glBindRenderbuffer(GL_RENDERBUFFER, buf.handle); - + glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); return buf; } @@ -240,7 +240,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); if (CheckFrameBufferCompleteness()) ClearFrameBuffer(false, false); @@ -252,7 +252,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); @@ -266,7 +266,7 @@ namespace OpenGLESRenderer PPGLFrameBuffer fb; glGenFramebuffers(1, &fb.handle); glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); - + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); @@ -284,7 +284,7 @@ namespace OpenGLESRenderer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0.handle, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); - + if (CheckFrameBufferCompleteness()) ClearFrameBuffer(true, true); return fb; @@ -302,9 +302,6 @@ namespace OpenGLESRenderer if (result == GL_FRAMEBUFFER_COMPLETE) return true; - bool FailedCreate = true; - - FString error = "glCheckFramebufferStatus failed: "; switch (result) { @@ -314,7 +311,7 @@ namespace OpenGLESRenderer case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break; } Printf("%s\n", error.GetChars()); - + return false; } @@ -372,7 +369,7 @@ namespace OpenGLESRenderer mDitherTexture.Bind(1, GL_NEAREST, GL_REPEAT); } - + //========================================================================== // // Makes the scene frame buffer active (multisample, depth, stecil, etc.) diff --git a/src/common/rendering/gles/gles_renderbuffers.h b/src/common/rendering/gles/gles_renderbuffers.h index ce052e26f..3369a864f 100644 --- a/src/common/rendering/gles/gles_renderbuffers.h +++ b/src/common/rendering/gles/gles_renderbuffers.h @@ -113,7 +113,7 @@ public: private: void ClearScene(); - + void CreateScene(int width, int height); void CreatePipeline(int width, int height); diff --git a/src/common/rendering/gles/gles_renderer.cpp b/src/common/rendering/gles/gles_renderer.cpp index b3b79ddae..1a33b3bd7 100644 --- a/src/common/rendering/gles/gles_renderer.cpp +++ b/src/common/rendering/gles/gles_renderer.cpp @@ -83,7 +83,7 @@ void FGLRenderer::Initialize(int width, int height) mScreenBuffers = new FGLRenderBuffers(); mBuffers = mScreenBuffers; mPresentShader = new FPresentShader(); - + mFBID = 0; mOldFBID = 0; @@ -97,7 +97,7 @@ FGLRenderer::~FGLRenderer() TexMan.FlushAll(); if (mShaderManager != nullptr) delete mShaderManager; if (mFBID != 0) glDeleteFramebuffers(1, &mFBID); - + if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; } @@ -110,7 +110,6 @@ FGLRenderer::~FGLRenderer() bool FGLRenderer::StartOffscreen() { - bool firstBind = (mFBID == 0); if (mFBID == 0) glGenFramebuffers(1, &mFBID); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mOldFBID); diff --git a/src/common/rendering/gles/gles_renderer.h b/src/common/rendering/gles/gles_renderer.h index a19690029..b1e7d2346 100644 --- a/src/common/rendering/gles/gles_renderer.h +++ b/src/common/rendering/gles/gles_renderer.h @@ -17,6 +17,7 @@ class FFlatVertexBuffer; class FSkyVertexBuffer; class HWPortal; class FLightBuffer; +class BoneBuffer; class DPSprite; class FGLRenderBuffers; class FGL2DDrawer; @@ -67,12 +68,12 @@ public: void PresentStereo(); void RenderScreenQuad(); void PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D); - + void CopyToBackbuffer(const IntRect *bounds, bool applyGamma); void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void BeginFrame(); - + bool StartOffscreen(); void EndOffscreen(); diff --git a/src/common/rendering/gles/gles_renderstate.cpp b/src/common/rendering/gles/gles_renderstate.cpp index 78bfc23de..87cf2681e 100644 --- a/src/common/rendering/gles/gles_renderstate.cpp +++ b/src/common/rendering/gles/gles_renderstate.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -25,16 +25,20 @@ ** */ -#include "templates.h" + #include "gles_system.h" #include "hw_cvars.h" #include "flatvertices.h" #include "gles_shader.h" #include "gles_renderer.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "gles_renderbuffers.h" #include "gles_hwtexture.h" #include "gles_buffers.h" +#include "gles_renderer.h" +#include "gles_samplers.h" + #include "hw_clock.h" #include "printf.h" @@ -91,7 +95,7 @@ void FGLRenderState::Reset() bool FGLRenderState::ApplyShader() { static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; - + ShaderFlavourData flavour; // Need to calc light data now in order to select correct shader @@ -107,24 +111,22 @@ bool FGLRenderState::ApplyShader() { lightPtr = ((float*)screen->mLights->GetBuffer()->Memory()); lightPtr += ((int64_t)mLightIndex * 4); - //float array[64]; - //memcpy(array, ptr, 4 * 64); // Calculate how much light data there is to upload, this is stored in the first 4 floats modLights = int(lightPtr[1]) / LIGHT_VEC4_NUM; subLights = (int(lightPtr[2]) - int(lightPtr[1])) / LIGHT_VEC4_NUM; addLights = (int(lightPtr[3]) - int(lightPtr[2])) / LIGHT_VEC4_NUM; - // Here we limit the number of lights, but dont' change the light data so priority has to be mod, sub then add - if (modLights > gles.maxlights) + // Here we limit the number of lights, but don't change the light data so priority has to be mod, sub then add + if (modLights > (int)gles.maxlights) modLights = gles.maxlights; - if (modLights + subLights > gles.maxlights) + if (modLights + subLights > (int)gles.maxlights) subLights = gles.maxlights - modLights; - if (modLights + subLights + addLights > gles.maxlights) + if (modLights + subLights + addLights > (int)gles.maxlights) addLights = gles.maxlights - modLights - subLights; - + totalLights = modLights + subLights + addLights; // Skip passed the first 4 floats so the upload below only contains light data @@ -149,12 +151,13 @@ bool FGLRenderState::ApplyShader() flavour.texFlags = tm >> 16; //Move flags to start of word if (mTextureClamp && flavour.textureMode == TM_NORMAL) flavour.textureMode = TM_CLAMPY; // fixme. Clamp can now be combined with all modes. - + if (flavour.textureMode == -1) flavour.textureMode = 0; flavour.blendFlags = (int)(mStreamData.uTextureAddColor.a + 0.01); + flavour.paletteInterpolate = !!(flavour.blendFlags & 0x4000); flavour.twoDFog = false; flavour.fogEnabled = false; @@ -162,7 +165,7 @@ bool FGLRenderState::ApplyShader() flavour.colouredFog = false; flavour.fogEquationRadial = (gl_fogmode == 2); - + flavour.twoDFog = false; flavour.fogEnabled = false; flavour.colouredFog = false; @@ -193,7 +196,7 @@ bool FGLRenderState::ApplyShader() flavour.useObjectColor2 = (mStreamData.uObjectColor2.a > 0); flavour.useGlowTopColor = mGlowEnabled && (mStreamData.uGlowTopColor[3] > 0); flavour.useGlowBottomColor = mGlowEnabled && (mStreamData.uGlowBottomColor[3] > 0); - + flavour.useColorMap = (mColorMapSpecial >= CM_FIRSTSPECIALCOLORMAP) || (mColorMapFlash != 1); flavour.buildLighting = (mHwUniforms->mPalLightLevels >> 16) == 5; // Build engine mode @@ -214,18 +217,15 @@ bool FGLRenderState::ApplyShader() activeShader->Bind(flavour); } - + if (mHwUniforms) { activeShader->cur->muProjectionMatrix.Set(&mHwUniforms->mProjectionMatrix); activeShader->cur->muViewMatrix.Set(&mHwUniforms->mViewMatrix); activeShader->cur->muNormalViewMatrix.Set(&mHwUniforms->mNormalViewMatrix); - activeShader->cur->muCameraPos.Set(&mHwUniforms->mCameraPos.X); activeShader->cur->muClipLine.Set(&mHwUniforms->mClipLine.X); - activeShader->cur->muGlobVis.Set(mHwUniforms->mGlobVis); - activeShader->cur->muPalLightLevels.Set(mHwUniforms->mPalLightLevels & 0xFF); // JUST pass the pal levels, clear the top bits activeShader->cur->muViewHeight.Set(mHwUniforms->mViewHeight); activeShader->cur->muClipHeight.Set(mHwUniforms->mClipHeight); @@ -246,6 +246,7 @@ bool FGLRenderState::ApplyShader() activeShader->cur->muInterpolationFactor.Set(mStreamData.uInterpolationFactor); activeShader->cur->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.); activeShader->cur->muAlphaThreshold.Set(mAlphaThreshold); + activeShader->cur->muBoneIndexBase.Set(-1); activeShader->cur->muClipSplit.Set(mClipSplit); activeShader->cur->muSpecularMaterial.Set(mGlossiness, mSpecularLevel); activeShader->cur->muAddColor.Set(mStreamData.uAddColor); @@ -331,8 +332,8 @@ bool FGLRenderState::ApplyShader() { // Calculate the total number of vec4s we need int totalVectors = totalLights * LIGHT_VEC4_NUM; - - if (totalVectors > gles.numlightvectors) + + if (totalVectors > (int)gles.numlightvectors) totalVectors = gles.numlightvectors; glUniform4fv(activeShader->cur->lights_index, totalVectors, lightPtr); @@ -344,7 +345,24 @@ bool FGLRenderState::ApplyShader() activeShader->cur->muLightRange.Set(range); } - + + if (gles.gles3Features) + { + // Upload bone data + // NOTE, this is pretty inefficient, it will be reloading the same data over and over in a single frame + // Need to add something to detect a start of new frame then only update the data when it's been changed + if ((mBoneIndexBase >= 0)) + { + float* bonesPtr = ((float*)screen->mBones->GetBuffer()->Memory()); + + int number = screen->mBones->GetCurrentIndex(); + + glUniformMatrix4fv(activeShader->cur->bones_index, number, false, bonesPtr); + + activeShader->cur->muBoneIndexBase.Set(mBoneIndexBase); + } + } + return true; } @@ -365,18 +383,6 @@ void FGLRenderState::ApplyState() if (mSplitEnabled != stSplitEnabled) { - /* - if (mSplitEnabled) - { - glEnable(GL_CLIP_DISTANCE3); - glEnable(GL_CLIP_DISTANCE4); - } - else - { - glDisable(GL_CLIP_DISTANCE3); - glDisable(GL_CLIP_DISTANCE4); - } - */ stSplitEnabled = mSplitEnabled; } @@ -386,19 +392,17 @@ void FGLRenderState::ApplyState() mMaterial.mChanged = false; } - if (mBias.mChanged) + + if (mBias.mFactor == 0 && mBias.mUnits == 0) { - if (mBias.mFactor == 0 && mBias.mUnits == 0) - { - glDisable(GL_POLYGON_OFFSET_FILL); - } - else - { - glEnable(GL_POLYGON_OFFSET_FILL); - } - glPolygonOffset(mBias.mFactor, mBias.mUnits); - mBias.mChanged = false; + glDisable(GL_POLYGON_OFFSET_FILL); } + else + { + glEnable(GL_POLYGON_OFFSET_FILL); + } + glPolygonOffset(mBias.mFactor, mBias.mUnits); + mBias.mChanged = false; } void FGLRenderState::ApplyBuffers() @@ -448,14 +452,13 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio if (tex->isHardwareCanvas()) static_cast(tex->GetTexture())->NeedUpdate(); clampmode = tex->GetClampMode(clampmode); - + // avoid rebinding the same texture multiple times. if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; lastMaterial = mat; lastClamp = clampmode; lastTranslation = translation; - int usebright = false; int maxbound = 0; int numLayers = mat->NumLayers(); @@ -479,6 +482,7 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio for (int i = 1; i < 3; i++) { auto systex = static_cast(mat->GetLayer(i, translation, &layer)); + GLRenderer->mSamplerManager->Bind(i, CLAMP_NONE, 255); systex->Bind(i, false); maxbound = i; } @@ -720,10 +724,13 @@ void FGLRenderState::ClearScreen() bool FGLRenderState::SetDepthClamp(bool on) { bool res = mLastDepthClamp; - /* - if (!on) glDisable(GL_DEPTH_CLAMP); - else glEnable(GL_DEPTH_CLAMP); - */ + + if (gles.depthClampAvailable) + { + if (!on) glDisable(GL_DEPTH_CLAMP); + else glEnable(GL_DEPTH_CLAMP); + } + mLastDepthClamp = on; return res; } diff --git a/src/common/rendering/gles/gles_renderstate.h b/src/common/rendering/gles/gles_renderstate.h index 7b7768541..c0bee73c0 100644 --- a/src/common/rendering/gles/gles_renderstate.h +++ b/src/common/rendering/gles/gles_renderstate.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -66,6 +66,7 @@ class FGLRenderState final : public FRenderState int lastTranslation = 0; int maxBoundMaterial = -1; size_t mLastMappedLightIndex = SIZE_MAX; + size_t mLastMappedBoneIndexBase = SIZE_MAX; IVertexBuffer *mCurrentVertexBuffer; int mCurrentVertexOffsets[2]; // one per binding point @@ -108,16 +109,7 @@ public: void EnableDrawBuffers(int count, bool apply = false) override { - /* - count = std::min(count, 3); - if (mNumDrawBuffers != count) - { - static GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; - glDrawBuffers(count, buffers); - mNumDrawBuffers = count; - } - if (apply) Apply(); - */ + } void ToggleState(int state, bool on); diff --git a/src/common/rendering/gles/gles_samplers.cpp b/src/common/rendering/gles/gles_samplers.cpp index 1e3b16d2d..17efe78ca 100644 --- a/src/common/rendering/gles/gles_samplers.cpp +++ b/src/common/rendering/gles/gles_samplers.cpp @@ -60,13 +60,14 @@ FSamplerManager::~FSamplerManager() void FSamplerManager::UnbindAll() { - + } - + uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter; + bool anisoAvailable = gles.anistropicFilterAvailable && (!sysCallbacks.DisableTextureFilter || !sysCallbacks.DisableTextureFilter()); glActiveTexture(GL_TEXTURE0 + texunit); switch (num) @@ -78,6 +79,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); } break; @@ -88,6 +91,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); } break; @@ -98,6 +103,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); } break; @@ -108,6 +115,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); } break; @@ -116,16 +125,44 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); break; case CLAMP_NOFILTER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); + break; + case CLAMP_NOFILTER_X: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); + break; + case CLAMP_NOFILTER_Y: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); + break; + case CLAMP_NOFILTER_XY: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); break; case CLAMP_CAMTEX: @@ -133,20 +170,22 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + if (anisoAvailable) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0); break; } glActiveTexture(GL_TEXTURE0); return 255; } - + void FSamplerManager::SetTextureFilterMode() { /* GLRenderer->FlushTextures(); GLint bounds[IHardwareTexture::MAX_TEXTURES]; - + // Unbind all for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--) { diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp index 37a9fd7ed..61c1a720e 100644 --- a/src/common/rendering/gles/gles_shader.cpp +++ b/src/common/rendering/gles/gles_shader.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -266,7 +266,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * // light buffers uniform vec4 lights[MAXIMUM_LIGHT_VECTORS]; - + + // bone matrix buffers + uniform mat4 bones[MAXIMUM_LIGHT_VECTORS]; + uniform mat4 ProjectionMatrix; uniform mat4 ViewMatrix; uniform mat4 NormalViewMatrix; @@ -321,6 +324,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * // dynamic lights uniform ivec4 uLightRange; + // bone animation + uniform int uBoneIndexBase; + // Blinn glossiness and specular level uniform vec2 uSpecularMaterial; @@ -370,7 +376,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * #define glowtexture texture4 #endif )"; - + #ifdef NPOT_EMULATION i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif @@ -391,11 +397,11 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * FString vp_comb; assert(screen->mLights != NULL); + assert(screen->mBones != NULL); - bool lightbuffertype = screen->mLights->GetBufferType(); unsigned int lightbuffersize = screen->mLights->GetBlockSize(); - vp_comb.Format("#version 100\n#define NUM_UBO_LIGHTS %d\n#define NO_CLIPDISTANCE_SUPPORT\n", lightbuffersize); + vp_comb.Format("#version %s\n\n#define NO_CLIPDISTANCE_SUPPORT\n", gles.shaderVersionString); FString fp_comb = vp_comb; vp_comb << defines << i_data.GetChars(); @@ -495,7 +501,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * } shaderData->hShader = glCreateProgram(); - + uint32_t binaryFormat = 0; TArray binary; if (IsShaderCacheActive()) @@ -530,6 +536,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * glBindAttribLocation(shaderData->hShader, VATTR_VERTEX2, "aVertex2"); glBindAttribLocation(shaderData->hShader, VATTR_NORMAL, "aNormal"); glBindAttribLocation(shaderData->hShader, VATTR_NORMAL2, "aNormal2"); + glBindAttribLocation(shaderData->hShader, VATTR_BONEWEIGHT, "aBoneWeight"); + glBindAttribLocation(shaderData->hShader, VATTR_BONESELECTOR, "aBoneSelector"); glLinkProgram(shaderData->hShader); @@ -570,10 +578,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * shaderData->muViewMatrix.Init(shaderData->hShader, "ViewMatrix"); shaderData->muNormalViewMatrix.Init(shaderData->hShader, "NormalViewMatrix"); - //shaderData->ProjectionMatrix_index = glGetUniformLocation(shaderData->hShader, "ProjectionMatrix"); - //shaderData->ViewMatrix_index = glGetUniformLocation(shaderData->hShader, "ViewMatrix"); - //shaderData->NormalViewMatrix_index = glGetUniformLocation(shaderData->hShader, "NormalViewMatrix"); - shaderData->muCameraPos.Init(shaderData->hShader, "uCameraPos"); shaderData->muClipLine.Init(shaderData->hShader, "uClipLine"); @@ -592,6 +596,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * shaderData->muLightParms.Init(shaderData->hShader, "uLightAttr"); shaderData->muClipSplit.Init(shaderData->hShader, "uClipSplit"); shaderData->muLightRange.Init(shaderData->hShader, "uLightRange"); + shaderData->muBoneIndexBase.Init(shaderData->hShader, "uBoneIndexBase"); shaderData->muFogColor.Init(shaderData->hShader, "uFogColor"); shaderData->muDynLightColor.Init(shaderData->hShader, "uDynLightColor"); shaderData->muObjectColor.Init(shaderData->hShader, "uObjectColor"); @@ -620,6 +625,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * shaderData->muFixedColormapRange.Init(shaderData->hShader, "uFixedColormapRange"); shaderData->lights_index = glGetUniformLocation(shaderData->hShader, "lights"); + shaderData->bones_index = glGetUniformLocation(shaderData->hShader, "bones"); shaderData->modelmatrix_index = glGetUniformLocation(shaderData->hShader, "ModelMatrix"); shaderData->texturematrix_index = glGetUniformLocation(shaderData->hShader, "TextureMatrix"); shaderData->normalmodelmatrix_index = glGetUniformLocation(shaderData->hShader, "NormalModelMatrix"); @@ -687,7 +693,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define MAXIMUM_LIGHT_VECTORS %d\n", gles.numlightvectors); variantConfig.AppendFormat("#define DEF_TEXTURE_MODE %d\n", flavour.textureMode); variantConfig.AppendFormat("#define DEF_TEXTURE_FLAGS %d\n", flavour.texFlags); - variantConfig.AppendFormat("#define DEF_BLEND_FLAGS %d\n", flavour.blendFlags); + variantConfig.AppendFormat("#define DEF_BLEND_FLAGS %d\n", flavour.blendFlags & 0x7); variantConfig.AppendFormat("#define DEF_FOG_2D %d\n", flavour.twoDFog); variantConfig.AppendFormat("#define DEF_FOG_ENABLED %d\n", flavour.fogEnabled); variantConfig.AppendFormat("#define DEF_FOG_RADIAL %d\n", flavour.fogEquationRadial); @@ -695,7 +701,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define DEF_USE_U_LIGHT_LEVEL %d\n", flavour.useULightLevel); variantConfig.AppendFormat("#define DEF_DO_DESATURATE %d\n", flavour.doDesaturate); - + variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_MOD %d\n", flavour.dynLightsMod); variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_SUB %d\n", flavour.dynLightsSub); variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_ADD %d\n", flavour.dynLightsAdd); @@ -703,7 +709,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) variantConfig.AppendFormat("#define DEF_USE_OBJECT_COLOR_2 %d\n", flavour.useObjectColor2); variantConfig.AppendFormat("#define DEF_USE_GLOW_TOP_COLOR %d\n", flavour.useGlowTopColor); variantConfig.AppendFormat("#define DEF_USE_GLOW_BOTTOM_COLOR %d\n", flavour.useGlowBottomColor); - + variantConfig.AppendFormat("#define DEF_USE_COLOR_MAP %d\n", flavour.useColorMap); variantConfig.AppendFormat("#define DEF_BUILD_LIGHTING %d\n", flavour.buildLighting); variantConfig.AppendFormat("#define DEF_BANDED_SW_LIGHTING %d\n", flavour.bandedSwLight); @@ -715,6 +721,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) #endif variantConfig.AppendFormat("#define DEF_HAS_SPOTLIGHT %d\n", flavour.hasSpotLight); + variantConfig.AppendFormat("#define DEF_PALETTE_INTERPOLATE %d\n", flavour.paletteInterpolate); //Printf("Shader: %s, %08x %s", mFragProg2.GetChars(), tag, variantConfig.GetChars()); @@ -733,7 +740,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) //========================================================================== // -// Since all shaders are REQUIRED, any error here needs to be fatal +// // //========================================================================== @@ -744,21 +751,8 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP // this can't be in the shader code due to ATI strangeness. if (!usediscard) defines += "#define NO_ALPHATEST\n"; - FShader *shader = NULL; - try - { - shader = new FShader(ShaderName); - if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars())) - { - I_FatalError("Unable to load shader %s\n", ShaderName); - } - } - catch(CRecoverableError &err) - { - if (shader != NULL) delete shader; - shader = NULL; - I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage()); - } + FShader *shader = new FShader(ShaderName); + shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()); return shader; } @@ -851,7 +845,7 @@ void FShaderCollection::CompileShaders(EPassType passType) mMaterialShaders.Push(shc); if (i < SHADER_NoTexture) { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); + shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); mMaterialShadersNAT.Push(shc); } } diff --git a/src/common/rendering/gles/gles_shader.h b/src/common/rendering/gles/gles_shader.h index 66fcb1ebd..31ebffa39 100644 --- a/src/common/rendering/gles/gles_shader.h +++ b/src/common/rendering/gles/gles_shader.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -277,13 +277,14 @@ public: #endif bool hasSpotLight; + bool paletteInterpolate; }; class FShader { friend class FShaderCollection; friend class FGLRenderState; - + FName mName; FString mVertProg; @@ -325,6 +326,7 @@ public: class ShaderVariantData FBufferedUniform1i muTextureMode; FBufferedUniform4f muLightParms; FBufferedUniform2f muClipSplit; + FBufferedUniform1i muBoneIndexBase; FBufferedUniform4i muLightRange; FBufferedUniformPE muFogColor; FBufferedUniform4f muDynLightColor; @@ -355,6 +357,7 @@ public: class ShaderVariantData int lights_index = 0; + int bones_index = 0; int modelmatrix_index = 0; int normalmodelmatrix_index = 0; int texturematrix_index = 0; @@ -378,7 +381,7 @@ public: FShader(const char *name) : mName(name) { - + } ~FShader(); @@ -393,9 +396,9 @@ public: { uint32_t tag = 0; tag |= (flavour.textureMode & 0x7); - + tag |= (flavour.texFlags & 7) << 3; - + tag |= (flavour.blendFlags & 7) << 6; tag |= (flavour.twoDFog & 1) << 7; @@ -419,15 +422,15 @@ public: #ifdef NPOT_EMULATION tag |= (flavour.npotEmulation & 1) << 22; #endif - tag |= (flavour.hasSpotLight & 1) << 23; + tag |= (flavour.paletteInterpolate & 1) << 24; return tag; } bool Bind(ShaderFlavourData& flavour); - + }; //========================================================================== @@ -461,7 +464,7 @@ class FShaderCollection void Clean(); void CompileShaders(EPassType passType); - + public: FShaderCollection(EPassType passType); ~FShaderCollection(); @@ -480,7 +483,10 @@ public: { return mMaterialShaders[eff]; } - return NULL; + else // This can happen if we try and active a user shader which is not loaded, so return default shader so it does not crash + { + return mMaterialShaders[0]; + } } }; diff --git a/src/common/rendering/gles/gles_shaderprogram.cpp b/src/common/rendering/gles/gles_shaderprogram.cpp index 26906f57a..16bd1ebe9 100644 --- a/src/common/rendering/gles/gles_shaderprogram.cpp +++ b/src/common/rendering/gles/gles_shaderprogram.cpp @@ -104,7 +104,7 @@ void FShaderProgram::CompileShader(ShaderType type) const auto &handle = mShaders[type]; - + const FString &patchedCode = mShaderSources[type]; int lengths[1] = { (int)patchedCode.Len() }; const char *sources[1] = { patchedCode.GetChars() }; @@ -236,7 +236,7 @@ FString FShaderProgram::PatchShader(ShaderType type, const FString &code, const { FString patchedCode; - patchedCode.AppendFormat("#version %d\n", 100); // Set to GLES2 + patchedCode.AppendFormat("#version %s\n", gles.shaderVersionString); patchedCode += GetGLSLPrecision(); @@ -272,7 +272,7 @@ void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program Uniforms.UniformLocation.resize(Uniforms.mFields.size()); - for (int n = 0; n < Uniforms.mFields.size(); n++) + for (size_t n = 0; n < Uniforms.mFields.size(); n++) { int index = -1; UniformFieldDesc desc = Uniforms.mFields[n]; @@ -290,4 +290,4 @@ void FPresentShader::Bind() mShader->Bind(); } -} \ No newline at end of file +} diff --git a/src/common/rendering/gles/gles_system.cpp b/src/common/rendering/gles/gles_system.cpp index a01b8b92c..22ba8cad6 100644 --- a/src/common/rendering/gles/gles_system.cpp +++ b/src/common/rendering/gles/gles_system.cpp @@ -9,12 +9,14 @@ CVAR(Bool, gles_use_mapped_buffer, false, 0); CVAR(Bool, gles_force_glsl_v100, false, 0); CVAR(Int, gles_max_lights_per_surface, 32, 0); EXTERN_CVAR(Bool, gl_customshader); +void setGlVersion(double glv); #if USE_GLES2 PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange = NULL; PFNGLUNMAPBUFFEROESPROC glUnmapBuffer = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL; #ifdef __ANDROID__ #include @@ -62,15 +64,15 @@ static PROC(WINAPI* getprocaddress)(LPCSTR name); static void* LoadGLES2Proc(const char* name) { - HINSTANCE hGetProcIDDLL = LoadLibraryA("libGLESv2.dll"); - + int error = GetLastError(); void* addr = GetProcAddress(hGetProcIDDLL, name); if (!addr) { //exit(1); + return nullptr; } else { @@ -133,7 +135,7 @@ namespace OpenGLESRenderer glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)LoadGLES2Proc("glMapBufferRange"); glUnmapBuffer = (PFNGLUNMAPBUFFEROESPROC)LoadGLES2Proc("glUnmapBuffer"); - + glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)LoadGLES2Proc("glVertexAttribIPointer"); #else static bool first = true; @@ -169,25 +171,38 @@ namespace OpenGLESRenderer gles.modelstring = (char*)glGetString(GL_RENDERER); gles.vendorstring = (char*)glGetString(GL_VENDOR); - + gl_customshader = false; GLint maxTextureSize[1]; glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); gles.max_texturesize = maxTextureSize[0]; - + Printf("GL_MAX_TEXTURE_SIZE: %d\n", gles.max_texturesize); #if USE_GLES2 + gles.gles3Features = false; // Enales IQM bones + gles.shaderVersionString = "100"; + gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil"); gles.npotAvailable = CheckExtension("GL_OES_texture_npot"); + gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp"); + gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic"); #else + gles.gles3Features = true; + gles.shaderVersionString = "330"; gles.depthStencilAvailable = true; gles.npotAvailable = true; gles.useMappedBuffers = true; + gles.depthClampAvailable = true; + gles.anistropicFilterAvailable = true; #endif - + gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); + + const char* glversion = (const char*)glGetString(GL_VERSION); + setGlVersion( strtod(glversion, NULL)); + } } diff --git a/src/common/rendering/gles/gles_system.h b/src/common/rendering/gles/gles_system.h index 021499362..481c132d0 100644 --- a/src/common/rendering/gles/gles_system.h +++ b/src/common/rendering/gles/gles_system.h @@ -23,7 +23,8 @@ #include #include -#define USE_GLES2 0 +#define USE_GLES2 0 // For Desktop PC leave as 0, it will use the exisiting OpenGL context creationg code but run with the GLES2 renderer + // Set to 1 for when comipling for a real GLES device #if (USE_GLES2) #include "glad/glad.h" @@ -35,6 +36,9 @@ GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange; typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target); GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer; +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; + #define GL_DEPTH24_STENCIL8 0x88F0 #define GL_MAP_PERSISTENT_BIT 0x0040 #define GL_MAP_READ_BIT 0x0001 @@ -42,7 +46,9 @@ GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer; #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 #define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 #define GL_BGRA 0x80E1 - +#define GL_DEPTH_CLAMP 0x864F +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_INT_2_10_10_10_REV 0x8D9F #else #include "gl_load/gl_load.h" #endif @@ -69,6 +75,10 @@ namespace OpenGLESRenderer bool depthStencilAvailable; bool npotAvailable; bool forceGLSLv100; + bool depthClampAvailable; + bool anistropicFilterAvailable; + bool gles3Features; + const char* shaderVersionString; int max_texturesize; char* vendorstring; char* modelstring; diff --git a/src/common/rendering/hwrenderer/data/buffers.h b/src/common/rendering/hwrenderer/data/buffers.h index 980adde5e..5e2c02728 100644 --- a/src/common/rendering/hwrenderer/data/buffers.h +++ b/src/common/rendering/hwrenderer/data/buffers.h @@ -24,7 +24,9 @@ enum VATTR_VERTEX2, VATTR_NORMAL, VATTR_NORMAL2, - + VATTR_LIGHTMAP, + VATTR_BONEWEIGHT, + VATTR_BONESELECTOR, VATTR_MAX }; @@ -36,6 +38,7 @@ enum EVertexAttributeFormat VFmt_Float, VFmt_Byte4, VFmt_Packed_A2R10G10B10, + VFmt_Byte4_UInt }; struct FVertexBufferAttribute diff --git a/src/common/rendering/hwrenderer/data/flatvertices.cpp b/src/common/rendering/hwrenderer/data/flatvertices.cpp index 6fe258b26..cfbfea080 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/src/common/rendering/hwrenderer/data/flatvertices.cpp @@ -93,10 +93,11 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr): static const FVertexBufferAttribute format[] = { { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) } + { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) }, + { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FFlatVertex, lu) }, }; - mVertexBufferPipeline[n]->SetFormat(1, 2, sizeof(FFlatVertex), format); + mVertexBufferPipeline[n]->SetFormat(1, 3, sizeof(FFlatVertex), format); } mVertexBuffer = mVertexBufferPipeline[mPipelinePos]; @@ -149,7 +150,6 @@ std::pair FFlatVertexBuffer::AllocVertices(unsigned { FFlatVertex *p = GetBuffer(); auto index = mCurIndex.fetch_add(count); - auto offset = index; if (index + count >= BUFFER_SIZE_TO_USE) { // If a single scene needs 2'000'000 vertices there must be something very wrong. diff --git a/src/common/rendering/hwrenderer/data/flatvertices.h b/src/common/rendering/hwrenderer/data/flatvertices.h index 619128a33..1056560a1 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.h +++ b/src/common/rendering/hwrenderer/data/flatvertices.h @@ -14,6 +14,8 @@ struct FFlatVertex { float x, z, y; // world position 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,6 +24,19 @@ struct FFlatVertex y = yy; u = uu; v = vv; + lindex = -1.0f; + } + + void Set(float xx, float zz, float yy, float uu, float vv, float llu, float llv, float llindex) + { + x = xx; + z = zz; + y = yy; + u = uu; + v = vv; + lu = llu; + lv = llv; + lindex = llindex; } void SetVertex(float _x, float _y, float _z = 0) @@ -52,7 +67,7 @@ public: IVertexBuffer *mVertexBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; IIndexBuffer *mIndexBuffer; - + unsigned int mIndex; std::atomic mCurIndex; diff --git a/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp b/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp index 0a8c81900..20a1d39a1 100644 --- a/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp +++ b/src/common/rendering/hwrenderer/data/hw_aabbtree.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, diff --git a/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp b/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp new file mode 100644 index 000000000..6335c3fc4 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_bonebuffer.cpp @@ -0,0 +1,112 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2014-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// + +#include "hw_bonebuffer.h" +#include "hw_dynlightdata.h" +#include "shaderuniforms.h" + +static const int BONE_SIZE = (16*sizeof(float)); + +BoneBuffer::BoneBuffer(int pipelineNbr) : mPipelineNbr(pipelineNbr) +{ + int maxNumberOfBones = 80000; + + mBufferSize = maxNumberOfBones; + mByteSize = mBufferSize * BONE_SIZE; + + // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. + // We only want to disable using SSBOs for bones but not disable the feature entirely. + // Note that using an uniform buffer here will limit the number of bones per model so it isn't done for NVidia and AMD. + if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO() && !strstr(screen->vendorstring, "Intel"))) + { + mBufferType = true; + mBlockAlign = 0; + mBlockSize = mBufferSize; + mMaxUploadSize = mBlockSize; + } + else + { + mBufferType = false; + mBlockSize = screen->maxuniformblock / BONE_SIZE; + mBlockAlign = screen->uniformblockalignment < 64 ? 1 : screen->uniformblockalignment / BONE_SIZE; + mMaxUploadSize = (mBlockSize - mBlockAlign); + } + + for (int n = 0; n < mPipelineNbr; n++) + { + mBufferPipeline[n] = screen->CreateDataBuffer(BONEBUF_BINDINGPOINT, mBufferType, false); + mBufferPipeline[n]->SetData(mByteSize, nullptr, BufferUsageType::Persistent); + } + + Clear(); +} + +BoneBuffer::~BoneBuffer() +{ + delete mBuffer; +} + +void BoneBuffer::Clear() +{ + mIndex = 0; + + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + + mBuffer = mBufferPipeline[mPipelinePos]; +} + +int BoneBuffer::UploadBones(const TArray& bones) +{ + int totalsize = bones.Size(); + if (totalsize > (int)mMaxUploadSize) + { + totalsize = mMaxUploadSize; + } + + uint8_t *mBufferPointer = (uint8_t*)mBuffer->Memory(); + assert(mBufferPointer != nullptr); + if (mBufferPointer == nullptr) return -1; + if (totalsize <= 0) return -1; // there are no bones + + unsigned int thisindex = mIndex.fetch_add(totalsize); + + if (thisindex + totalsize <= mBufferSize) + { + memcpy(mBufferPointer + thisindex * BONE_SIZE, bones.Data(), totalsize * BONE_SIZE); + return thisindex; + } + else + { + return -1; // Buffer is full. Since it is being used live at the point of the upload we cannot do much here but to abort. + } +} + +int BoneBuffer::GetBinding(unsigned int index, size_t* pOffset, size_t* pSize) +{ + // this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start. + unsigned int offset = (index / mBlockAlign) * mBlockAlign; + + *pOffset = offset * BONE_SIZE; + *pSize = mBlockSize * BONE_SIZE; + return (index - offset); +} diff --git a/src/common/rendering/hwrenderer/data/hw_bonebuffer.h b/src/common/rendering/hwrenderer/data/hw_bonebuffer.h new file mode 100644 index 000000000..44e74ffcf --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_bonebuffer.h @@ -0,0 +1,46 @@ +#pragma once + +#include "tarray.h" +#include "hwrenderer/data/buffers.h" +#include "common/utility/matrix.h" +#include +#include + +class FRenderState; + +class BoneBuffer +{ + IDataBuffer *mBuffer; + IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; + int mPipelineNbr; + int mPipelinePos = 0; + + bool mBufferType; + std::atomic mIndex; + unsigned int mBlockAlign; + unsigned int mBlockSize; + unsigned int mBufferSize; + unsigned int mByteSize; + unsigned int mMaxUploadSize; + +public: + BoneBuffer(int pipelineNbr = 1); + ~BoneBuffer(); + + void Clear(); + int UploadBones(const TArray &bones); + void Map() { mBuffer->Map(); } + void Unmap() { mBuffer->Unmap(); } + unsigned int GetBlockSize() const { return mBlockSize; } + bool GetBufferType() const { return mBufferType; } + int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize); + + // Only for GLES to determin how much data is in the buffer + int GetCurrentIndex() { return mIndex; }; + + // OpenGL needs the buffer to mess around with the binding. + IDataBuffer* GetBuffer() const + { + return mBuffer; + } +}; diff --git a/src/common/rendering/hwrenderer/data/hw_clock.cpp b/src/common/rendering/hwrenderer/data/hw_clock.cpp index e9affdbe6..ec2847944 100644 --- a/src/common/rendering/hwrenderer/data/hw_clock.cpp +++ b/src/common/rendering/hwrenderer/data/hw_clock.cpp @@ -153,7 +153,6 @@ ADD_STAT(lightstats) static int printstats; static bool switchfps; static uint64_t waitstart; -extern uint64_t LastCount; EXTERN_CVAR(Bool, vid_fps) void CheckBench() @@ -167,7 +166,7 @@ void CheckBench() FString compose; if (sysCallbacks.GetLocationDescription) compose = sysCallbacks.GetLocationDescription(); - + AppendRenderStats(compose); AppendRenderTimes(compose); AppendLightStats(compose); diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.cpp b/src/common/rendering/hwrenderer/data/hw_cvars.cpp index 5c1b64359..a7967b92e 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.cpp +++ b/src/common/rendering/hwrenderer/data/hw_cvars.cpp @@ -44,7 +44,7 @@ #include "printf.h" -CUSTOM_CVAR(Int, gl_fogmode, 1, CVAR_ARCHIVE | CVAR_NOINITCALL) +CUSTOM_CVAR(Int, gl_fogmode, 2, CVAR_ARCHIVE | CVAR_NOINITCALL) { if (self > 2) self = 2; if (self < 0) self = 0; @@ -115,7 +115,7 @@ CVAR(Int, gl_satformula, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); // Texture CVARs // //========================================================================== -CUSTOM_CVARD(Float, gl_texture_filter_anisotropic, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL, "changes the OpenGL texture anisotropy setting") +CUSTOM_CVARD(Float, gl_texture_filter_anisotropic, 8.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL, "changes the OpenGL texture anisotropy setting") { screen->SetTextureFilterMode(); } diff --git a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h index e24e49bed..7da1c1b5a 100644 --- a/src/common/rendering/hwrenderer/data/hw_dynlightdata.h +++ b/src/common/rendering/hwrenderer/data/hw_dynlightdata.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -23,6 +23,8 @@ #ifndef __GLC_DYNLIGHT_H #define __GLC_DYNLIGHT_H +#include "tarray.h" + struct FDynLightData { TArray arrays[3]; @@ -49,7 +51,7 @@ struct FDynLightData if (siz[1] > max) siz[1] = max; if (siz[2] > max) siz[2] = max; } - + }; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h new file mode 100644 index 000000000..c385f8738 --- /dev/null +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "tarray.h" +#include "vectors.h" + +namespace hwrenderer +{ + +class LevelMesh +{ +public: + virtual ~LevelMesh() = default; + + TArray MeshVertices; + TArray MeshUVIndex; + TArray MeshElements; + TArray MeshSurfaces; +}; + +} // namespace diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp index 9f7bb66c2..622626056 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -37,10 +37,10 @@ FLightBuffer::FLightBuffer(int pipelineNbr): mPipelineNbr(pipelineNbr) { int maxNumberOfLights = 80000; - + mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT; mByteSize = mBufferSize * ELEMENT_SIZE; - + // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. // We only want to disable using SSBOs for lights but not disable the feature entirely. // Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD. @@ -57,7 +57,7 @@ FLightBuffer::FLightBuffer(int pipelineNbr): mBlockSize = screen->maxuniformblock / ELEMENT_SIZE; mBlockAlign = screen->uniformblockalignment / ELEMENT_SIZE; mMaxUploadSize = (mBlockSize - mBlockAlign); - + //mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. REMOVED this...This can try to allocate 100's of MB.. } @@ -96,7 +96,7 @@ int FLightBuffer::UploadLights(FDynLightData &data) if (totalsize > (int)mMaxUploadSize) { int diff = totalsize - (int)mMaxUploadSize; - + size2 -= diff; if (size2 < 0) { @@ -115,14 +115,14 @@ int FLightBuffer::UploadLights(FDynLightData &data) assert(mBufferPointer != nullptr); if (mBufferPointer == nullptr) return -1; if (totalsize <= 1) return -1; // there are no lights - + unsigned thisindex = mIndex.fetch_add(totalsize); float parmcnt[] = { 0, float(size0), float(size0 + size1), float(size0 + size1 + size2) }; if (thisindex + totalsize <= mBufferSize) { float *copyptr = mBufferPointer + thisindex*4; - + memcpy(©ptr[0], parmcnt, ELEMENT_SIZE); memcpy(©ptr[4], &data.arrays[0][0], size0 * ELEMENT_SIZE); memcpy(©ptr[4 + 4*size0], &data.arrays[1][0], size1 * ELEMENT_SIZE); diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h index 441dc55ff..ad266bd94 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h @@ -23,7 +23,7 @@ class FLightBuffer unsigned int mBufferSize; unsigned int mByteSize; unsigned int mMaxUploadSize; - + void CheckSize(); public: diff --git a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp index e4d5ba030..9dff499f9 100644 --- a/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_modelvertexbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -46,10 +46,13 @@ FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe) { 0, VATTR_VERTEX, VFmt_Float3, (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_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) }, { 1, VATTR_NORMAL2, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) } }; - mVertexBuffer->SetFormat(2, 5, sizeof(FModelVertex), format); + mVertexBuffer->SetFormat(2, 8, sizeof(FModelVertex), format); } //=========================================================================== diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 5b4af5681..1f5e08d4c 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -217,6 +217,7 @@ protected: uint8_t mBrightmapEnabled : 1; int mLightIndex; + int mBoneIndexBase; int mSpecialEffect; int mTextureMode; int mTextureClamp; @@ -278,6 +279,7 @@ public: mLightParms[3] = -1.f; mSpecialEffect = EFF_NONE; mLightIndex = -1; + mBoneIndexBase = -1; mStreamData.uInterpolationFactor = 0; mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); @@ -568,6 +570,11 @@ public: mLightIndex = index; } + void SetBoneIndexBase(int index) + { + mBoneIndexBase = index; + } + void SetRenderStyle(FRenderStyle rs) { mRenderStyle = rs; @@ -585,7 +592,7 @@ public: void SetDepthBias(float a, float b) { - mBias.mChanged = mBias.mFactor != a || mBias.mUnits != b; + mBias.mChanged |= mBias.mFactor != a || mBias.mUnits != b; mBias.mFactor = a; mBias.mUnits = b; } @@ -597,7 +604,7 @@ public: void ClearDepthBias() { - mBias.mChanged = mBias.mFactor != 0 || mBias.mUnits != 0; + mBias.mChanged |= mBias.mFactor != 0 || mBias.mUnits != 0; mBias.mFactor = 0; mBias.mUnits = 0; } @@ -618,6 +625,7 @@ private: public: void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader) { + tex->setSeen(); if (!sysCallbacks.PreBindTexture || !sysCallbacks.PreBindTexture(this, tex, upscalemask, scaleflags, clampmode, translation, overrideshader)) { if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale; diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp index 97420e0c2..50fed5a94 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp @@ -34,7 +34,11 @@ */ +#include "cmdlib.h" #include "hw_shaderpatcher.h" +#include "textures.h" +#include "hw_renderstate.h" +#include "v_video.h" static bool IsGlslWhitespace(char c) @@ -152,7 +156,7 @@ FString RemoveSamplerBindings(FString code, TArray> &sam char *chars = code.LockBuffer(); ptrdiff_t startIndex = 0; - ptrdiff_t startpos, endpos; + ptrdiff_t startpos, endpos = 0; while (true) { ptrdiff_t matchIndex = code.IndexOf("layout(binding", startIndex); @@ -188,10 +192,10 @@ FString RemoveSamplerBindings(FString code, TArray> &sam if (isSamplerUniformName) { samplerstobind.Push(std::make_pair(identifier, val)); - for (auto pos = startpos; pos < endpos; pos++) + for (auto posi = startpos; posi < endpos; posi++) { - if (!IsGlslWhitespace(chars[pos])) - chars[pos] = ' '; + if (!IsGlslWhitespace(chars[posi])) + chars[posi] = ' '; } } } @@ -216,7 +220,6 @@ FString RemoveSamplerBindings(FString code, TArray> &sam FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword) { - ptrdiff_t len = code.Len(); char *chars = code.LockBuffer(); ptrdiff_t startIndex = 0; @@ -255,8 +258,8 @@ FString RemoveLayoutLocationDecl(FString code, const char *inoutkeyword) if (keywordFound && IsGlslWhitespace(chars[endIndex + i])) { // yes - replace declaration with spaces - for (auto i = matchIndex; i < endIndex; i++) - chars[i] = ' '; + for (auto ii = matchIndex; ii < endIndex; ii++) + chars[ii] = ' '; } startIndex = endIndex; @@ -297,3 +300,12 @@ const FEffectShader effectshaders[] = { "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, { "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, }; + +int DFrameBuffer::GetShaderCount() +{ + int i; + for (i = 0; defaultshaders[i].ShaderName != nullptr; i++); + + return MAX_PASS_TYPES * (countof(defaultshaders) - 1 + usershaders.Size() + MAX_EFFECTS + SHADER_NoTexture); +} + diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h index 7133441a2..4a3a1c39f 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h @@ -28,3 +28,4 @@ struct FEffectShader extern const FDefaultShader defaultshaders[]; extern const FEffectShader effectshaders[]; + diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp index 26eaa2d2c..e53609840 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -38,13 +38,13 @@ but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map it first decides in which direction the fragment is (relative to the light), like cubemap sampling does for 3D, but once again just for the 2D case. - + Texels 0-255 is Y positive, 256-511 is X positive, 512-767 is Y negative and 768-1023 is X negative. Generating the shadow map itself is done by FShadowMap::Update(). The shadow map texture's FBO is bound and then a screen quad is drawn to make a fragment shader cover all texels. For each fragment it shoots a ray and collects the distance to what it hit. - + The shadowmap.fp shader knows which light and texel it is processing by mapping gl_FragCoord.y back to the light index, and it knows which direction to ray trace by looking at gl_FragCoord.x. For example, if gl_FragCoord.y is 20.5, then it knows its processing light 20, and if gl_FragCoord.x is diff --git a/src/common/rendering/hwrenderer/data/hw_shadowmap.h b/src/common/rendering/hwrenderer/data/hw_shadowmap.h index e755c0f59..3bc2eb98f 100644 --- a/src/common/rendering/hwrenderer/data/hw_shadowmap.h +++ b/src/common/rendering/hwrenderer/data/hw_shadowmap.h @@ -4,6 +4,7 @@ #include "hw_aabbtree.h" #include "stats.h" #include +#include class IDataBuffer; diff --git a/src/common/rendering/hwrenderer/data/hw_skydome.cpp b/src/common/rendering/hwrenderer/data/hw_skydome.cpp index e9e1bc364..43e56adec 100644 --- a/src/common/rendering/hwrenderer/data/hw_skydome.cpp +++ b/src/common/rendering/hwrenderer/data/hw_skydome.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -70,7 +70,7 @@ // also shamelessly lifted from ZDoomGL! ;) // //----------------------------------------------------------------------------- -CVAR(Float, skyoffset, 0, 0) // for testing +CVAR(Float, skyoffset, 0.f, 0) // for testing struct SkyColor @@ -98,7 +98,7 @@ std::pair& R_GetSkyCapColor(FGameTexture* tex) const uint32_t* buffer = (const uint32_t*)bitmap.GetPixels(); if (buffer) { - sky.Colors.first = averageColor((uint32_t*)buffer, w * MIN(30, h), 0); + sky.Colors.first = averageColor((uint32_t*)buffer, w * min(30, h), 0); if (h > 30) { sky.Colors.second = averageColor(((uint32_t*)buffer) + (h - 30) * w, w * 30, 0); @@ -127,9 +127,10 @@ FSkyVertexBuffer::FSkyVertexBuffer() static const FVertexBufferAttribute format[] = { { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FSkyVertex, x) }, { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FSkyVertex, u) }, - { 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(FSkyVertex, color) } + { 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(FSkyVertex, color) }, + { 0, VATTR_LIGHTMAP, VFmt_Float3, (int)myoffsetof(FSkyVertex, lu) }, }; - mVertexBuffer->SetFormat(1, 3, sizeof(FSkyVertex), format); + mVertexBuffer->SetFormat(1, 4, sizeof(FSkyVertex), format); mVertexBuffer->SetData(mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], BufferUsageType::Static); } @@ -146,10 +147,10 @@ FSkyVertexBuffer::~FSkyVertexBuffer() void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip) { - static const FAngle maxSideAngle = 60.f; + static const FAngle maxSideAngle = FAngle::fromDeg(60.f); static const float scale = 10000.; - FAngle topAngle = (c / (float)mColumns * 360.f); + FAngle topAngle = FAngle::fromDeg((c / (float)mColumns * 360.f)); FAngle sideAngle = maxSideAngle * float(mRows - r) / float(mRows); float height = sideAngle.Sin(); float realRadius = scale * sideAngle.Cos(); @@ -189,10 +190,10 @@ void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip) void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip) { - static const FAngle maxSideAngle = 60.f; + static const FAngle maxSideAngle = FAngle::fromDeg(60.f); static const float scale = 10000.; - FAngle topAngle = (c / (float)mColumns * 360.f); + FAngle topAngle = FAngle::fromDeg((c / (float)mColumns * 360.f)); FVector2 pos = topAngle.ToVector(scale); float z = (!zflip) ? (mRows - r) * 4000.f : -(mRows - r) * 4000.f; @@ -455,7 +456,7 @@ void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, T // //----------------------------------------------------------------------------- -void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which) +void FSkyVertexBuffer::DoRenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which, PalEntry color) { auto& primStart = which ? mPrimStartBuild : mPrimStartDoom; if (tex && tex->isValid()) @@ -470,7 +471,15 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mo // The caps only get drawn for the main layer but not for the overlay. if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != nullptr) { - auto& col = R_GetSkyCapColor(tex); + auto col = R_GetSkyCapColor(tex); + + col.first.r = col.first.r * color.r / 255; + col.first.g = col.first.g * color.g / 255; + col.first.b = col.first.b * color.b / 255; + col.second.r = col.second.r * color.r / 255; + col.second.g = col.second.g * color.g / 255; + col.second.b = col.second.b * color.b / 255; + state.SetObjectColor(col.first); state.EnableTexture(false); RenderRow(state, DT_TriangleFan, 0, primStart); @@ -497,13 +506,13 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mo // //----------------------------------------------------------------------------- -void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale, float yscale) +void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale, float yscale, PalEntry color) { if (tex) { SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled, xscale, yscale); } - RenderDome(state, tex, mode, false); + DoRenderDome(state, tex, mode, false, color); } @@ -513,10 +522,11 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float // //----------------------------------------------------------------------------- -void FSkyVertexBuffer::RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2) +void FSkyVertexBuffer::RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2, PalEntry color) { int faces; + state.SetObjectColor(color); state.EnableModelMatrix(true); state.mModelMatrix.loadIdentity(); state.mModelMatrix.scale(1, 1 / stretch, 1); // Undo the map's vertical scaling as skyboxes are true cubes. @@ -562,5 +572,6 @@ void FSkyVertexBuffer::RenderBox(FRenderState& state, FSkyBox* tex, float x_offs state.Draw(DT_TriangleStrip, FaceStart(4), 4); state.EnableModelMatrix(false); + state.SetObjectColor(0xffffffff); } diff --git a/src/common/rendering/hwrenderer/data/hw_skydome.h b/src/common/rendering/hwrenderer/data/hw_skydome.h index 2e10869bb..f794e96bb 100644 --- a/src/common/rendering/hwrenderer/data/hw_skydome.h +++ b/src/common/rendering/hwrenderer/data/hw_skydome.h @@ -12,14 +12,11 @@ struct HWSkyPortal; struct HWDrawInfo; // 57 world units roughly represent one sky texel for the glTranslate call. -enum -{ - skyoffsetfactor = 57 -}; +const int skyoffsetfactor = 57; struct FSkyVertex { - float x, y, z, u, v; + float x, y, z, u, v, lu, lv, lindex; PalEntry color; void Set(float xx, float zz, float yy, float uu=0, float vv=0, PalEntry col=0xffffffff) @@ -29,6 +26,9 @@ struct FSkyVertex y = yy; u = uu; v = vv; + lu = 0.0f; + lv = 0.0f; + lindex = -1.0f; color = col; } @@ -39,6 +39,9 @@ struct FSkyVertex z = zz; u = uu; v = vv; + lu = 0.0f; + lv = 0.0f; + lindex = -1.0f; color = col; } @@ -93,8 +96,8 @@ public: } void RenderRow(FRenderState& state, EDrawType prim, int row, TArray& mPrimStart, bool apply = true); - void RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which); - void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float yscale = 0); - void RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2); + void DoRenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which, PalEntry color = 0xffffffff); + void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float yscale = 0, PalEntry color = 0xffffffff); + void RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2, PalEntry color = 0xffffffff); }; diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index 89a5a8436..3d67b46be 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -48,7 +48,6 @@ HWViewpointBuffer::HWViewpointBuffer(int pipelineNbr): Clear(); mLastMappedIndex = UINT_MAX; - mClipPlaneInfo.Push(0); } HWViewpointBuffer::~HWViewpointBuffer() @@ -67,7 +66,6 @@ void HWViewpointBuffer::CheckSize() { mBufferPipeline[n]->Resize(mByteSize); } - m2DHeight = m2DWidth = -1; } } @@ -84,33 +82,27 @@ int HWViewpointBuffer::Bind(FRenderState &di, unsigned int index) void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height, int pll) { - if (width != m2DWidth || height != m2DHeight) - { - HWViewpointUniforms matrices; + HWViewpointUniforms matrices; - matrices.mViewMatrix.loadIdentity(); - matrices.mNormalViewMatrix.loadIdentity(); - matrices.mViewHeight = 0; - matrices.mGlobVis = 1.f; - matrices.mPalLightLevels = pll; - matrices.mClipLine.X = -10000000.0f; - matrices.mShadowmapFilter = gl_shadowmap_filter; + matrices.mViewMatrix.loadIdentity(); + matrices.mNormalViewMatrix.loadIdentity(); + matrices.mViewHeight = 0; + matrices.mGlobVis = 1.f; + matrices.mPalLightLevels = pll; + matrices.mClipLine.X = -10000000.0f; + matrices.mShadowmapFilter = gl_shadowmap_filter; + matrices.mLightBlendMode = 0; - matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f); - matrices.CalcDependencies(); - - for (int n = 0; n < mPipelineNbr; n++) - { - mBufferPipeline[n]->Map(); - memcpy(mBufferPipeline[n]->Memory(), &matrices, sizeof(matrices)); - mBufferPipeline[n]->Unmap(); - } + matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f); + matrices.CalcDependencies(); - m2DWidth = width; - m2DHeight = height; - mLastMappedIndex = -1; - } - Bind(di, 0); + mBuffer->Map(); + memcpy(((char*)mBuffer->Memory()) + mUploadIndex * mBlockAlign, &matrices, sizeof(matrices)); + mBuffer->Unmap(); + + mClipPlaneInfo.Push(0); + + Bind(di, mUploadIndex++); } int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp) @@ -126,12 +118,16 @@ int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp) void HWViewpointBuffer::Clear() { - // Index 0 is reserved for the 2D projection. - mUploadIndex = 1; - mClipPlaneInfo.Resize(1); + bool needNewPipeline = mUploadIndex > 0; // Clear might be called multiple times before any actual rendering - mPipelinePos++; - mPipelinePos %= mPipelineNbr; + mUploadIndex = 0; + mClipPlaneInfo.Clear(); + + if (needNewPipeline) + { + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + } mBuffer = mBufferPipeline[mPipelinePos]; } diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h index 0fbd46dfa..f52af7ebc 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h @@ -18,8 +18,6 @@ class HWViewpointBuffer unsigned int mLastMappedIndex; unsigned int mByteSize; TArray mClipPlaneInfo; - - int m2DWidth = -1, m2DHeight = -1; unsigned int mBlockSize; diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h index 3d28f5c4a..def3b4808 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h @@ -4,6 +4,15 @@ struct HWDrawInfo; +enum class ELightBlendMode : uint8_t +{ + CLAMP = 0, + CLAMP_COLOR = 1, + NOCLAMP = 2, + + DEFAULT = CLAMP, +}; + struct HWViewpointUniforms { VSMatrix mProjectionMatrix; @@ -19,6 +28,8 @@ struct HWViewpointUniforms float mClipHeightDirection = 0.f; int mShadowmapFilter = 1; + int mLightBlendMode = 0; + void CalcDependencies() { mNormalViewMatrix.computeNormalMatrix(mViewMatrix); diff --git a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp index 35b5eea06..ac80eec54 100644 --- a/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp +++ b/src/common/rendering/hwrenderer/data/hw_vrmodes.cpp @@ -1,27 +1,36 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2015 Christopher Bruns -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// /* -** gl_stereo_leftright.cpp -** Offsets for left and right eye views +** hw_vrmodes.cpp +** Matrix handling for stereo 3D rendering +** +**--------------------------------------------------------------------------- +** Copyright 2015 Christopher Bruns +** Copyright 2016-2021 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. +**--------------------------------------------------------------------------- +** ** */ @@ -154,9 +163,9 @@ VSMatrix VREyeInfo::GetProjection(float fov, float aspectRatio, float fovRatio) double bottom = -fH; double top = fH; - VSMatrix result(1); - result.frustum((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); - return result; + VSMatrix fmat(1); + fmat.frustum((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); + return fmat; } } diff --git a/src/common/rendering/hwrenderer/data/shaderuniforms.h b/src/common/rendering/hwrenderer/data/shaderuniforms.h index 92995fcaa..4b11a3755 100644 --- a/src/common/rendering/hwrenderer/data/shaderuniforms.h +++ b/src/common/rendering/hwrenderer/data/shaderuniforms.h @@ -11,7 +11,8 @@ enum VIEWPOINT_BINDINGPOINT = 3, LIGHTNODES_BINDINGPOINT = 4, LIGHTLINES_BINDINGPOINT = 5, - LIGHTLIST_BINDINGPOINT = 6 + LIGHTLIST_BINDINGPOINT = 6, + BONEBUF_BINDINGPOINT = 7 }; enum class UniformType diff --git a/src/common/rendering/hwrenderer/hw_draw2d.cpp b/src/common/rendering/hwrenderer/hw_draw2d.cpp index af10a7bf2..5c7100b34 100644 --- a/src/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/src/common/rendering/hwrenderer/hw_draw2d.cpp @@ -51,14 +51,22 @@ CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE) -void Draw2D(F2DDrawer *drawer, FRenderState &state) +void Draw2D(F2DDrawer* drawer, FRenderState& state) +{ + const auto& mScreenViewport = screen->mScreenViewport; + Draw2D(drawer, state, mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); +} + +void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int height) { twoD.Clock(); - const auto &mScreenViewport = screen->mScreenViewport; - state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); - screen->mViewpoints->Set2D(state, twod->GetWidth(), twod->GetHeight()); + state.SetViewport(x, y, width, height); + screen->mViewpoints->Set2D(state, drawer->GetWidth(), drawer->GetHeight()); + state.EnableStencil(false); + state.SetStencil(0, SOP_Keep, SF_AllOn); + state.Clear(CT_Stencil); state.EnableDepthTest(false); state.EnableMultisampling(false); state.EnableLineSmooth(gl_aalines); @@ -88,8 +96,23 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) for(auto &cmd : commands) { + if (cmd.isSpecial != SpecialDrawCommand::NotSpecial) + { + if (cmd.isSpecial == SpecialDrawCommand::EnableStencil) + { + state.EnableStencil(cmd.stencilOn); + } + else if (cmd.isSpecial == SpecialDrawCommand::SetStencil) + { + state.SetStencil(cmd.stencilOffs, cmd.stencilOp, cmd.stencilFlags); + } + else if (cmd.isSpecial == SpecialDrawCommand::ClearStencil) + { + state.Clear(CT_Stencil); + } + continue; + } - int gltrans = -1; state.SetRenderStyle(cmd.mRenderStyle); state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed)); state.EnableFog(2); // Special 2D mode 'fog'. @@ -127,7 +150,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) if (cmd.mFlags & F2DDrawer::DTF_Indexed) state.SetSoftLightLevel(cmd.mLightLevel); state.SetLightParms(0, 0); - state.AlphaFunc(Alpha_GEqual, 0.f); + state.AlphaFunc(Alpha_Greater, 0.f); if (cmd.useTransform) { @@ -226,6 +249,8 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) state.SetRenderStyle(STYLE_Translucent); state.SetVertexBuffer(screen->mVertexData); + state.EnableStencil(false); + state.SetStencil(0, SOP_Keep, SF_AllOn); state.EnableTexture(true); state.EnableBrightmap(true); state.SetTextureMode(TM_NORMAL); diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 219bb9bd6..9cf1badb7 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -26,7 +26,7 @@ #include "hwrenderer/postprocessing/hw_postprocessshader.h" #include #include "texturemanager.h" -#include "templates.h" + #include "stats.h" Postprocess hw_postprocess; @@ -326,9 +326,9 @@ void PPLensDistort::Render(PPRenderState *renderstate) // Scale factor to keep sampling within the input texture float r2 = aspect * aspect * 0.25f + 0.25f; float sqrt_r2 = sqrt(r2); - float f0 = 1.0f + MAX(r2 * (k[0] + kcube[0] * sqrt_r2), 0.0f); - float f2 = 1.0f + MAX(r2 * (k[2] + kcube[2] * sqrt_r2), 0.0f); - float f = MAX(f0, f2); + float f0 = 1.0f + max(r2 * (k[0] + kcube[0] * sqrt_r2), 0.0f); + float f2 = 1.0f + max(r2 * (k[2] + kcube[2] * sqrt_r2), 0.0f); + float f = max(f0, f2); float scale = 1.0f / f; LensUniforms uniforms; @@ -498,8 +498,8 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc void PPCameraExposure::UpdateTextures(int width, int height) { - int firstwidth = MAX(width / 2, 1); - int firstheight = MAX(height / 2, 1); + int firstwidth = max(width / 2, 1); + int firstheight = max(height / 2, 1); if (ExposureLevels.size() > 0 && ExposureLevels[0].Viewport.width == firstwidth && ExposureLevels[0].Viewport.height == firstheight) { @@ -511,8 +511,8 @@ void PPCameraExposure::UpdateTextures(int width, int height) int i = 0; do { - width = MAX(width / 2, 1); - height = MAX(height / 2, 1); + width = max(width / 2, 1); + height = max(height / 2, 1); PPExposureLevel blevel; blevel.Viewport.left = 0; @@ -570,7 +570,8 @@ void PPColormap::Render(PPRenderState *renderstate, int fixedcm, float flash) void PPTonemap::UpdateTextures() { - if (gl_tonemap == Palette && !PaletteTexture.Data) + // level.info->tonemap cannot be ETonemapMode::Palette, so it's fine to only check gl_tonemap here + if (ETonemapMode((int)gl_tonemap) == ETonemapMode::Palette && !PaletteTexture.Data) { std::shared_ptr data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; }); @@ -598,7 +599,9 @@ void PPTonemap::UpdateTextures() void PPTonemap::Render(PPRenderState *renderstate) { - if (gl_tonemap == 0) + ETonemapMode current_tonemap = (level_tonemap != ETonemapMode::None) ? level_tonemap : ETonemapMode((int)gl_tonemap); + + if (current_tonemap == ETonemapMode::None) { return; } @@ -606,14 +609,14 @@ void PPTonemap::Render(PPRenderState *renderstate) UpdateTextures(); PPShader *shader = nullptr; - switch (gl_tonemap) + switch (current_tonemap) { default: - case Linear: shader = &LinearShader; break; - case Reinhard: shader = &ReinhardShader; break; - case HejlDawson: shader = &HejlDawsonShader; break; - case Uncharted2: shader = &Uncharted2Shader; break; - case Palette: shader = &PaletteShader; break; + case ETonemapMode::Linear: shader = &LinearShader; break; + case ETonemapMode::Reinhard: shader = &ReinhardShader; break; + case ETonemapMode::HejlDawson: shader = &HejlDawsonShader; break; + case ETonemapMode::Uncharted2: shader = &Uncharted2Shader; break; + case ETonemapMode::Palette: shader = &PaletteShader; break; } renderstate->PushGroup("tonemap"); @@ -622,7 +625,7 @@ void PPTonemap::Render(PPRenderState *renderstate) renderstate->Shader = shader; renderstate->Viewport = screen->mScreenViewport; renderstate->SetInputCurrent(0); - if (gl_tonemap == Palette) + if (current_tonemap == ETonemapMode::Palette) renderstate->SetInputTexture(1, &PaletteTexture); renderstate->SetOutputNext(); renderstate->SetNoBlend(); @@ -746,7 +749,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW LinearDepthUniforms linearUniforms; linearUniforms.SampleIndex = 0; linearUniforms.LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear(); - linearUniforms.LinearizeDepthB = MAX(1.0f / screen->GetZNear(), 1.e-8f); + linearUniforms.LinearizeDepthB = max(1.0f / screen->GetZNear(), 1.e-8f); linearUniforms.InverseDepthRangeA = 1.0f; linearUniforms.InverseDepthRangeB = 0.0f; linearUniforms.Scale = sceneScale; @@ -894,7 +897,7 @@ void PPShadowMap::Update(PPRenderState* renderstate) ///////////////////////////////////////////////////////////////////////////// -CVAR(Bool, gl_custompost, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +CVAR(Bool, gl_custompost, true, 0) void PPCustomShaders::Run(PPRenderState *renderstate, FString target) { diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h index 71defdcae..357396da7 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -13,6 +13,19 @@ typedef IntRect PPViewport; class PPTexture; class PPShader; +enum class ETonemapMode : uint8_t +{ + None, + Uncharted2, + HejlDawson, + Reinhard, + Linear, + Palette, + NumTonemapModes +}; + + + enum class PPFilterMode { Nearest, Linear }; enum class PPWrapMode { Clamp, Repeat }; enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap }; @@ -541,6 +554,7 @@ private: class PPTonemap { public: + void SetTonemapMode(ETonemapMode tm) { level_tonemap = tm; } void Render(PPRenderState *renderstate); void ClearTonemapPalette() { PaletteTexture = {}; } @@ -554,17 +568,7 @@ private: PPShader HejlDawsonShader = { "shaders/pp/tonemap.fp", "#define HEJLDAWSON\n", {} }; PPShader Uncharted2Shader = { "shaders/pp/tonemap.fp", "#define UNCHARTED2\n", {} }; PPShader PaletteShader = { "shaders/pp/tonemap.fp", "#define PALETTE\n", {} }; - - enum TonemapMode - { - None, - Uncharted2, - HejlDawson, - Reinhard, - Linear, - Palette, - NumTonemapModes - }; + ETonemapMode level_tonemap = ETonemapMode::None; }; ///////////////////////////////////////////////////////////////////////////// @@ -840,8 +844,11 @@ public: PPCustomShaders customShaders; + void SetTonemapMode(ETonemapMode tm) { tonemap.SetTonemapMode(tm); } void Pass1(PPRenderState *state, int fixedcm, int sceneWidth, int sceneHeight); void Pass2(PPRenderState* state, int fixedcm, float flash, int sceneWidth, int sceneHeight); }; + extern Postprocess hw_postprocess; + diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp new file mode 100644 index 000000000..f23d4497f --- /dev/null +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp @@ -0,0 +1,139 @@ +/* +** Postprocessing framework +** 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 "vm.h" +#include "hwrenderer/postprocessing/hw_postprocessshader.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" + +static void ShaderSetEnabled(const FString &shaderName, bool value) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + shader.Enabled = value; + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetEnabled, ShaderSetEnabled) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_BOOL(value); + ShaderSetEnabled(shaderName, value); + + return 0; +} + +static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double value) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = value; + vec4[1] = 0.0; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetUniform1f, ShaderSetUniform1f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(value); + ShaderSetUniform1f(shaderName, uniformName, value); + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform2f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = x; + vec4[1] = y; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = x; + vec4[1] = y; + vec4[2] = z; + vec4[3] = 1.0; + } + } + return 0; +} + +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_INT(value); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = (double)value; + vec4[1] = 0.0; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + } + return 0; +} diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp new file mode 100644 index 000000000..4608b9ce9 --- /dev/null +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp @@ -0,0 +1,136 @@ +/* +** Debug ccmds for post-process shaders +** Copyright (c) 2022 Rachael Alexanderson +** +** 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 "hwrenderer/postprocessing/hw_postprocessshader.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include "printf.h" +#include "c_dispatch.h" + +CCMD (shaderenable) +{ + if (argv.argc() < 3) + { + Printf("Usage: shaderenable [name] [1/0/-1]\nState '-1' toggles the active shader state\n"); + return; + } + auto shaderName = argv[1]; + + int value = atoi(argv[2]); + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + if (value != -1) + shader.Enabled = value; + else + shader.Enabled = !shader.Enabled; //toggle + found = 1; + } + } + if (found && value != -1) + Printf("Changed active state of all instances of %s to %s\n", shaderName, value?"On":"Off"); + else if (found) + Printf("Toggled active state of all instances of %s\n", shaderName); + else + Printf("No shader named '%s' found\n", shaderName); +} + +CCMD (shaderuniform) +{ + if (argv.argc() < 3) + { + Printf("Usage: shaderuniform [shader name] [uniform name] [[value1 ..]]\n"); + return; + } + auto shaderName = argv[1]; + auto uniformName = argv[2]; + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + if (argv.argc() > 3) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; + vec4[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; + vec4[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0; + vec4[3] = 1.0; + } + else + { + double *vec4 = shader.Uniforms[uniformName].Values; + Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, vec4[0], vec4[1], vec4[2]); + } + found = 1; + } + } + if (found && argv.argc() > 3) + Printf("Changed uniforms of %s named %s\n", shaderName, uniformName); + else if (!found) + Printf("No shader named '%s' found\n", shaderName); +} + +CCMD(listshaders) +{ + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + Printf("Shader (%i): %s\n", i, shader.Name.GetChars()); + } +} + +CCMD(listuniforms) +{ + if (argv.argc() < 2) + { + Printf("Usage: listuniforms [name]\n"); + return; + } + auto shaderName = argv[1]; + + bool found = 0; + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (strcmp(shader.Name, shaderName) == 0) + { + Printf("Shader '%s' uniforms:\n", shaderName); + + decltype(shader.Uniforms)::Iterator it(shader.Uniforms); + decltype(shader.Uniforms)::Pair* pair; + + while (it.NextPair(pair)) + { + double *vec4 = shader.Uniforms[pair->Key].Values; + Printf(" %s : %f %f %f\n", pair->Key.GetChars(), vec4[0], vec4[1], vec4[2]); + } + found = 1; + } + } + if (!found) + Printf("No shader named '%s' found\n", shaderName); +} diff --git a/src/common/rendering/i_modelvertexbuffer.h b/src/common/rendering/i_modelvertexbuffer.h index febec3c71..f68d4e117 100644 --- a/src/common/rendering/i_modelvertexbuffer.h +++ b/src/common/rendering/i_modelvertexbuffer.h @@ -1,12 +1,16 @@ #pragma once -#include "templates.h" + struct FModelVertex { float x, y, z; // world position 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]; void Set(float xx, float yy, float zz, float uu, float vv) { @@ -15,6 +19,9 @@ struct FModelVertex z = zz; u = uu; v = vv; + lu = 0.0f; + lv = 0.0f; + lindex = -1.0f; } void SetNormal(float nx, float ny, float nz) @@ -25,6 +32,22 @@ struct FModelVertex int inw = 0; packedNormal = (inw << 30) | ((inz & 1023) << 20) | ((iny & 1023) << 10) | (inx & 1023); } + + void SetBoneSelector(int x, int y, int z, int w) + { + boneselector[0] = x; + boneselector[1] = y; + boneselector[2] = z; + boneselector[3] = w; + } + + void SetBoneWeight(int x, int y, int z, int w) + { + boneweight[0] = x; + boneweight[1] = y; + boneweight[2] = z; + boneweight[3] = w; + } }; #define VMO ((FModelVertex*)nullptr) diff --git a/src/common/rendering/i_video.h b/src/common/rendering/i_video.h index d9a9b9701..f33d35caf 100644 --- a/src/common/rendering/i_video.h +++ b/src/common/rendering/i_video.h @@ -29,10 +29,4 @@ void I_PolyPresentUnlock(int x, int y, int w, int h); void I_PolyPresentDeinit(); -// Pause a bit. -// [RH] Despite the name, it apparently never waited for the VBL, even in -// the original DOS version (if the Heretic/Hexen source is any indicator). -void I_WaitVBL(int count); - - #endif // __I_VIDEO_H__ diff --git a/src/common/rendering/polyrenderer/backend/poly_buffers.cpp b/src/common/rendering/polyrenderer/backend/poly_buffers.cpp deleted file mode 100644 index 10ebef0d0..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_buffers.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* -** Softpoly 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 "poly_buffers.h" -#include "poly_framebuffer.h" -#include "poly_renderstate.h" -#include "poly_thread.h" -#include "engineerrors.h" - -PolyBuffer *PolyBuffer::First = nullptr; - -PolyBuffer::PolyBuffer() -{ - Next = First; - First = this; - if (Next) Next->Prev = this; -} - -PolyBuffer::~PolyBuffer() -{ - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - auto fb = GetPolyFrameBuffer(); - if (fb && !mData.empty()) - fb->FrameDeleteList.Buffers.push_back(std::move(mData)); -} - -void PolyBuffer::ResetAll() -{ - for (PolyBuffer *cur = PolyBuffer::First; cur; cur = cur->Next) - cur->Reset(); -} - -void PolyBuffer::Reset() -{ -} - -void PolyBuffer::SetData(size_t size, const void *data, BufferUsageType usage) -{ - mData.resize(size); - map = mData.data(); - if (data) - memcpy(map, data, size); - buffersize = size; -} - -void PolyBuffer::SetSubData(size_t offset, size_t size, const void *data) -{ - memcpy(static_cast(map) + offset, data, size); -} - -void PolyBuffer::Resize(size_t newsize) -{ - mData.resize(newsize); - buffersize = newsize; - map = mData.data(); -} - -void PolyBuffer::Map() -{ -} - -void PolyBuffer::Unmap() -{ -} - -void *PolyBuffer::Lock(unsigned int size) -{ - if (mData.size() < (size_t)size) - Resize(size); - return map; -} - -void PolyBuffer::Unlock() -{ -} - -///////////////////////////////////////////////////////////////////////////// - -void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) -{ - VertexFormat = GetPolyFrameBuffer()->GetRenderState()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs); -} - -///////////////////////////////////////////////////////////////////////////// - -void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *vertices, int frame0, int frame1, int index) -{ - uint8_t* buff = (uint8_t*)vertices; - - // [GEC] finds the right frame. - uint32_t offsets[2] = { static_cast(frame0 * Stride), static_cast(frame1 * Stride) }; - uint8_t* vertexBuffers[2] = { buff + offsets[0], buff + offsets[1] }; - - const uint8_t* vertex = static_cast(vertexBuffers[0]) + mStride * index; - const float* attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); - - const uint8_t* vertex2 = static_cast(vertexBuffers[1]) + mStride * index; - const float* attrVertex2 = reinterpret_cast(vertex2 + mOffsets[VATTR_VERTEX]); - - const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); - const uint8_t *attrColor = reinterpret_cast(vertex + mOffsets[VATTR_COLOR]); - const uint32_t* attrNormal = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL]); - const uint32_t* attrNormal2 = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL2]); - - // [GEC] Apply the formula for model interpolation - - float newVertex[3]; - - float t = thread->mainVertexShader.Data.uInterpolationFactor; - float invt = 1.0f - t; - - newVertex[0] = (invt * attrVertex[0]) + (t * attrVertex2[0]); - newVertex[1] = (invt * attrVertex[1]) + (t * attrVertex2[1]); - newVertex[2] = (invt * attrVertex[2]) + (t * attrVertex2[2]); - - thread->mainVertexShader.aPosition = { newVertex[0], newVertex[1], newVertex[2], 1.0f }; - thread->mainVertexShader.aTexCoord = { attrTexcoord[0], attrTexcoord[1] }; - - if ((UseVertexData & 1) == 0) - { - const auto &c = thread->mainVertexShader.Data.uVertexColor; - thread->mainVertexShader.aColor.X = c.X; - thread->mainVertexShader.aColor.Y = c.Y; - thread->mainVertexShader.aColor.Z = c.Z; - thread->mainVertexShader.aColor.W = c.W; - } - else - { - thread->mainVertexShader.aColor.X = attrColor[0] * (1.0f / 255.0f); - thread->mainVertexShader.aColor.Y = attrColor[1] * (1.0f / 255.0f); - thread->mainVertexShader.aColor.Z = attrColor[2] * (1.0f / 255.0f); - thread->mainVertexShader.aColor.W = attrColor[3] * (1.0f / 255.0f); - } - - if ((UseVertexData & 2) == 0) - { - const auto &n = thread->mainVertexShader.Data.uVertexNormal; - thread->mainVertexShader.aNormal = FVector4(n.X, n.Y, n.Z, 1.0); - thread->mainVertexShader.aNormal2 = thread->mainVertexShader.aNormal; - } - else - { - int n = *attrNormal; - int n2 = *attrNormal2; - float x = ((n << 22) >> 22) / 512.0f; - float y = ((n << 12) >> 22) / 512.0f; - float z = ((n << 2) >> 22) / 512.0f; - float x2 = ((n2 << 22) >> 22) / 512.0f; - float y2 = ((n2 << 12) >> 22) / 512.0f; - float z2 = ((n2 << 2) >> 22) / 512.0f; - thread->mainVertexShader.aNormal = FVector4(x, y, z, 0.0f); - thread->mainVertexShader.aNormal2 = FVector4(x2, y2, z2, 0.0f); - } -} - -///////////////////////////////////////////////////////////////////////////// - -void PolyDataBuffer::BindRange(FRenderState *state, size_t start, size_t length) -{ - static_cast(state)->Bind(this, (uint32_t)start, (uint32_t)length); -} diff --git a/src/common/rendering/polyrenderer/backend/poly_buffers.h b/src/common/rendering/polyrenderer/backend/poly_buffers.h deleted file mode 100644 index c364586fa..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_buffers.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "hwrenderer/data/buffers.h" -#include "polyrenderer/drawers/poly_triangle.h" -#include "tarray.h" -#include - -#ifdef _MSC_VER -// silence bogus warning C4250: 'PolyVertexBuffer': inherits 'PolyBuffer::PolyBuffer::SetData' via dominance -// According to internet infos, the warning is erroneously emitted in this case. -#pragma warning(disable:4250) -#endif - -class PolyBuffer : virtual public IBuffer -{ -public: - PolyBuffer(); - ~PolyBuffer(); - - static void ResetAll(); - void Reset(); - - void SetData(size_t size, const void *data, BufferUsageType usage) override; - void SetSubData(size_t offset, size_t size, const void *data) override; - void Resize(size_t newsize) override; - - void Map() override; - void Unmap() override; - - void *Lock(unsigned int size) override; - void Unlock() override; - -private: - static PolyBuffer *First; - PolyBuffer *Prev = nullptr; - PolyBuffer *Next = nullptr; - std::vector mData; -}; - -class PolyVertexInputAssembly final : public PolyInputAssembly -{ -public: - size_t mOffsets[VATTR_MAX] = {}; - size_t mStride = 0; - - int NumBindingPoints; - size_t Stride; - std::vector Attrs; - int UseVertexData; - - void Load(PolyTriangleThreadData *thread, const void *vertices, int frame0, int frame1, int index) override; -}; - -class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer -{ -public: - PolyVertexBuffer() { } - void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; - - PolyVertexInputAssembly *VertexFormat = nullptr; -}; - -class PolyIndexBuffer : public IIndexBuffer, public PolyBuffer -{ -public: - PolyIndexBuffer() { } -}; - -class PolyDataBuffer : public IDataBuffer, public PolyBuffer -{ -public: - PolyDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint) - { - } - - void BindRange(FRenderState *state, size_t start, size_t length) override; - - int bindingpoint; -}; diff --git a/src/common/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/common/rendering/polyrenderer/backend/poly_framebuffer.cpp deleted file mode 100644 index 6f8ead0c5..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* -** Softpoly 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 "v_video.h" -#include "m_png.h" -#include "templates.h" -#include "r_videoscale.h" -#include "i_time.h" -#include "v_text.h" -#include "i_video.h" -#include "v_draw.h" - -#include "hw_clock.h" -#include "hw_vrmodes.h" -#include "hw_cvars.h" -#include "hw_skydome.h" -#include "hwrenderer/data/hw_viewpointbuffer.h" -#include "flatvertices.h" -#include "hwrenderer/data/shaderuniforms.h" -#include "hw_lightbuffer.h" -#include "hwrenderer/postprocessing/hw_postprocess.h" - -#include "poly_framebuffer.h" -#include "poly_buffers.h" -#include "poly_renderstate.h" -#include "poly_hwtexture.h" -#include "engineerrors.h" - -void Draw2D(F2DDrawer *drawer, FRenderState &state); - -extern int rendered_commandbuffers; -extern int current_rendered_commandbuffers; - -extern bool gpuStatActive; -extern bool keepGpuStatActive; -extern FString gpuStatOutput; - -PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen) -{ - I_PolyPresentInit(); -} - -PolyFrameBuffer::~PolyFrameBuffer() -{ - // screen is already null at this point, but PolyHardwareTexture::ResetAll needs it during clean up. Is there a better way we can do this? - auto tmp = screen; - screen = this; - - PolyHardwareTexture::ResetAll(); - PolyBuffer::ResetAll(); - PPResource::ResetAll(); - - delete mScreenQuad.VertexBuffer; - delete mScreenQuad.IndexBuffer; - - delete mVertexData; - delete mSkyData; - delete mViewpoints; - delete mLights; - mShadowMap.Reset(); - - screen = tmp; - - I_PolyPresentDeinit(); -} - -void PolyFrameBuffer::InitializeState() -{ - vendorstring = "Poly"; - hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; - glslversion = 4.50f; - uniformblockalignment = 1; - maxuniformblock = 0x7fffffff; - - mRenderState.reset(new PolyRenderState()); - - mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); - mSkyData = new FSkyVertexBuffer; - mViewpoints = new HWViewpointBuffer; - mLights = new FLightBuffer(); - - static const FVertexBufferAttribute format[] = - { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(ScreenQuadVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(ScreenQuadVertex, u) }, - { 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(ScreenQuadVertex, color0) } - }; - - uint32_t indices[6] = { 0, 1, 2, 1, 3, 2 }; - - mScreenQuad.VertexBuffer = screen->CreateVertexBuffer(); - mScreenQuad.VertexBuffer->SetFormat(1, 3, sizeof(ScreenQuadVertex), format); - - mScreenQuad.IndexBuffer = screen->CreateIndexBuffer(); - mScreenQuad.IndexBuffer->SetData(6 * sizeof(uint32_t), indices, BufferUsageType::Stream); - - CheckCanvas(); -} - -void PolyFrameBuffer::CheckCanvas() -{ - if (!mCanvas || mCanvas->GetWidth() != GetWidth() || mCanvas->GetHeight() != GetHeight()) - { - FlushDrawCommands(); - DrawerThreads::WaitForWorkers(); - - mCanvas.reset(new DCanvas(0, 0, true)); - mCanvas->Resize(GetWidth(), GetHeight(), false); - mDepthStencil.reset(); - mDepthStencil.reset(new PolyDepthStencil(GetWidth(), GetHeight())); - - mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil(), true); - } -} - -PolyCommandBuffer *PolyFrameBuffer::GetDrawCommands() -{ - if (!mDrawCommands) - { - mDrawCommands.reset(new PolyCommandBuffer(&mFrameMemory)); - mDrawCommands->SetLightBuffer(mLightBuffer->Memory()); - } - return mDrawCommands.get(); -} - -void PolyFrameBuffer::FlushDrawCommands() -{ - mRenderState->EndRenderPass(); - if (mDrawCommands) - { - mDrawCommands->Submit(); - mDrawCommands.reset(); - } -} - -EXTERN_CVAR(Float, vid_brightness) -EXTERN_CVAR(Float, vid_contrast) -EXTERN_CVAR(Float, vid_saturation) - -void PolyFrameBuffer::Update() -{ - twoD.Reset(); - Flush3D.Reset(); - - Flush3D.Clock(); - - Draw2D(); - twod->Clear(); - - Flush3D.Unclock(); - - FlushDrawCommands(); - - if (mCanvas) - { - int w = mCanvas->GetWidth(); - int h = mCanvas->GetHeight(); - int pixelsize = 4; - const uint8_t *src = (const uint8_t*)mCanvas->GetPixels(); - int pitch = 0; - uint8_t *dst = I_PolyPresentLock(w, h, cur_vsync, pitch); - if (dst) - { -#if 1 - // [GEC] with the help of dpJudas a new system of copying and applying gamma in the video buffer - auto copyqueue = std::make_shared(&mFrameMemory); - copyqueue->Push(dst, pitch / pixelsize, src, w, h, w, vid_gamma, vid_contrast, vid_brightness, vid_saturation); - DrawerThreads::Execute(copyqueue); -#else - for (int y = 0; y < h; y++) - { - memcpy(dst + y * pitch, src + y * w * pixelsize, w * pixelsize); - } -#endif - - DrawerThreads::WaitForWorkers(); - I_PolyPresentUnlock(mOutputLetterbox.left, mOutputLetterbox.top, mOutputLetterbox.width, mOutputLetterbox.height); - } - FPSLimit(); - } - - DrawerThreads::WaitForWorkers(); - mFrameMemory.Clear(); - FrameDeleteList.Buffers.clear(); - FrameDeleteList.Images.clear(); - - CheckCanvas(); - - Super::Update(); -} - - -void PolyFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function renderFunc) -{ - auto BaseLayer = static_cast(tex->GetHardwareTexture(0, 0)); - - DCanvas *image = BaseLayer->GetImage(tex, 0, 0); - PolyDepthStencil *depthStencil = BaseLayer->GetDepthStencil(tex); - mRenderState->SetRenderTarget(image, depthStencil, false); - - IntRect bounds; - bounds.left = bounds.top = 0; - bounds.width = std::min(tex->GetWidth(), image->GetWidth()); - bounds.height = std::min(tex->GetHeight(), image->GetHeight()); - - renderFunc(bounds); - - FlushDrawCommands(); - DrawerThreads::WaitForWorkers(); - mRenderState->SetRenderTarget(GetCanvas(), GetDepthStencil(), true); - - tex->SetUpdated(true); -} - -static uint8_t ToIntColorComponent(float v) -{ - return clamp((int)(v * 255.0f + 0.5f), 0, 255); -} - -void PolyFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) -{ - afterBloomDrawEndScene2D(); - - if (fixedcm >= CM_FIRSTSPECIALCOLORMAP && fixedcm < CM_MAXCOLORMAP) - { - FSpecialColormap* scm = &SpecialColormaps[fixedcm - CM_FIRSTSPECIALCOLORMAP]; - - mRenderState->SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); - screen->mViewpoints->Set2D(*mRenderState, screen->GetWidth(), screen->GetHeight()); - - ScreenQuadVertex vertices[4] = - { - { 0.0f, 0.0f, 0.0f, 0.0f }, - { (float)mScreenViewport.width, 0.0f, 1.0f, 0.0f }, - { 0.0f, (float)mScreenViewport.height, 0.0f, 1.0f }, - { (float)mScreenViewport.width, (float)mScreenViewport.height, 1.0f, 1.0f } - }; - mScreenQuad.VertexBuffer->SetData(4 * sizeof(ScreenQuadVertex), vertices, BufferUsageType::Stream); - - mRenderState->SetVertexBuffer(mScreenQuad.VertexBuffer, 0, 0); - mRenderState->SetIndexBuffer(mScreenQuad.IndexBuffer); - - mRenderState->SetObjectColor(PalEntry(255, int(scm->ColorizeStart[0] * 127.5f), int(scm->ColorizeStart[1] * 127.5f), int(scm->ColorizeStart[2] * 127.5f))); - mRenderState->SetAddColor(PalEntry(255, int(scm->ColorizeEnd[0] * 127.5f), int(scm->ColorizeEnd[1] * 127.5f), int(scm->ColorizeEnd[2] * 127.5f))); - - mRenderState->EnableDepthTest(false); - mRenderState->EnableMultisampling(false); - mRenderState->SetCulling(Cull_None); - - mRenderState->SetScissor(-1, -1, -1, -1); - mRenderState->SetColor(1, 1, 1, 1); - mRenderState->AlphaFunc(Alpha_GEqual, 0.f); - mRenderState->EnableTexture(false); - mRenderState->SetColormapShader(true); - mRenderState->DrawIndexed(DT_Triangles, 0, 6); - mRenderState->SetColormapShader(false); - mRenderState->SetObjectColor(0xffffffff); - mRenderState->SetAddColor(0); - mRenderState->SetVertexBuffer(screen->mVertexData); - mRenderState->EnableTexture(true); - mRenderState->ResetColor(); - } -} - - -void PolyFrameBuffer::SetVSync(bool vsync) -{ - cur_vsync = vsync; -} - -FRenderState* PolyFrameBuffer::RenderState() -{ - return mRenderState.get(); -} - - -void PolyFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) -{ - if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - - MaterialLayerInfo* layer; - auto systex = static_cast(mat->GetLayer(0, translation, &layer)); - systex->GetImage(layer->layerTexture, translation, layer->scaleFlags); - - int numLayers = mat->NumLayers(); - for (int i = 1; i < numLayers; i++) - { - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); // fixme: Upscale flags must be disabled for certain layers. - } -} - -IHardwareTexture *PolyFrameBuffer::CreateHardwareTexture(int numchannels) -{ - return new PolyHardwareTexture(); -} - -IVertexBuffer *PolyFrameBuffer::CreateVertexBuffer() -{ - return new PolyVertexBuffer(); -} - -IIndexBuffer *PolyFrameBuffer::CreateIndexBuffer() -{ - return new PolyIndexBuffer(); -} - -IDataBuffer *PolyFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) -{ - IDataBuffer *buffer = new PolyDataBuffer(bindingpoint, ssbo, needsresize); - if (bindingpoint == LIGHTBUF_BINDINGPOINT) - mLightBuffer = buffer; - return buffer; -} - -void PolyFrameBuffer::SetTextureFilterMode() -{ -} - -void PolyFrameBuffer::BlurScene(float amount) -{ -} - -void PolyFrameBuffer::UpdatePalette() -{ -} - -FTexture *PolyFrameBuffer::WipeStartScreen() -{ - SetViewportRects(nullptr); - - auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); - auto systex = static_cast(tex->GetSystemTexture()); - - systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen"); - - return tex; -} - -FTexture *PolyFrameBuffer::WipeEndScreen() -{ - Draw2D(); - twod->Clear(); - - auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); - auto systex = static_cast(tex->GetSystemTexture()); - - systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen"); - - return tex; -} - -TArray PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) -{ - // [GEC] Really necessary to apply gamma, brightness, contrast and saturation for screenshot - - std::vector gammatablebuf(256); - uint8_t* gammatable = gammatablebuf.data(); - - float InvGamma = 1.0f / clamp(vid_gamma, 0.1f, 4.f); - float Brightness = clamp(vid_brightness, -0.8f, 0.8f); - float Contrast = clamp(vid_contrast, 0.1f, 3.f); - float Saturation = clamp(vid_saturation, -15.0f, 15.f); - - for (int x = 0; x < 256; x++) - { - float ramp = (float)(x / 255.f); - // Apply Contrast - // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); - if(vid_contrast != 1.0f) - ramp = (((ramp - 0.5f) * Contrast) + 0.5f); - - // Apply Brightness - // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); - if (vid_brightness != 0.0f) - ramp += (Brightness / 2.0f); - - // Apply Gamma - // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); - if (vid_gamma != 1.0f) - ramp = pow(ramp, InvGamma); - - // Clamp ramp - ramp = clamp(ramp, 0.0f, 1.f); - - gammatable[x] = (uint8_t)(ramp * 255); - } - - int w = SCREENWIDTH; - int h = SCREENHEIGHT; - - TArray ScreenshotBuffer(w * h * 3, true); - const uint8_t* pixels = GetCanvas()->GetPixels(); - int dindex = 0; - - // Convert to RGB - for (int y = 0; y < h; y++) - { - int sindex = y * w * 4; - - for (int x = 0; x < w; x++) - { - uint32_t red = pixels[sindex + 2]; - uint32_t green = pixels[sindex + 1]; - uint32_t blue = pixels[sindex]; - - if (vid_saturation != 1.0f) - { - float NewR = (float)(red / 255.f); - float NewG = (float)(green / 255.f); - float NewB = (float)(blue / 255.f); - - // Apply Saturation - // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); - // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); - //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 - float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 - NewR = luma + (Saturation * (NewR - luma)); - NewG = luma + (Saturation * (NewG - luma)); - NewB = luma + (Saturation * (NewB - luma)); - - // Clamp All - NewR = clamp(NewR, 0.0f, 1.f); - NewG = clamp(NewG, 0.0f, 1.f); - NewB = clamp(NewB, 0.0f, 1.f); - - red = (uint32_t)(NewR * 255.f); - green = (uint32_t)(NewG * 255.f); - blue = (uint32_t)(NewB * 255.f); - } - - // Apply Contrast / Brightness / Gamma - red = gammatable[red]; - green = gammatable[green]; - blue = gammatable[blue]; - - ScreenshotBuffer[dindex ] = red; - ScreenshotBuffer[dindex + 1] = green; - ScreenshotBuffer[dindex + 2] = blue; - - dindex += 3; - sindex += 4; - } - } - - pitch = w * 3; - color_type = SS_RGB; - gamma = 1.0f; - return ScreenshotBuffer; -} - -void PolyFrameBuffer::BeginFrame() -{ - SetViewportRects(nullptr); - CheckCanvas(); - -#if 0 - swrenderer::R_InitFuzzTable(GetCanvas()->GetPitch()); - static int next_random = 0; - swrenderer::fuzzpos = (swrenderer::fuzzpos + swrenderer::fuzz_random_x_offset[next_random] * FUZZTABLE / 100) % FUZZTABLE; - next_random++; - if (next_random == FUZZ_RANDOM_X_SIZE) - next_random = 0; -#endif -} - -void PolyFrameBuffer::Draw2D() -{ - ::Draw2D(twod, *mRenderState); -} - -unsigned int PolyFrameBuffer::GetLightBufferBlockSize() const -{ - return mLights->GetBlockSize(); -} - -void PolyFrameBuffer::UpdateShadowMap() -{ -} - -void PolyFrameBuffer::AmbientOccludeScene(float m5) -{ - //mPostprocess->AmbientOccludeScene(m5); -} diff --git a/src/common/rendering/polyrenderer/backend/poly_framebuffer.h b/src/common/rendering/polyrenderer/backend/poly_framebuffer.h deleted file mode 100644 index 76eae0ced..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_framebuffer.h +++ /dev/null @@ -1,214 +0,0 @@ -#pragma once - -#include "gl_sysfb.h" -#include "r_memory.h" -#include "r_thread.h" -#include "poly_triangle.h" - -struct FRenderViewpoint; -class PolyDataBuffer; -class PolyRenderState; -class SWSceneDrawer; - -class PolyFrameBuffer : public SystemBaseFrameBuffer -{ - typedef SystemBaseFrameBuffer Super; - -public: - RenderMemory *GetFrameMemory() { return &mFrameMemory; } - PolyRenderState *GetRenderState() { return mRenderState.get(); } - DCanvas *GetCanvas() override { return mCanvas.get(); } - PolyDepthStencil *GetDepthStencil() { return mDepthStencil.get(); } - PolyCommandBuffer *GetDrawCommands(); - void FlushDrawCommands(); - - unsigned int GetLightBufferBlockSize() const; - - PolyFrameBuffer(void *hMonitor, bool fullscreen); - ~PolyFrameBuffer(); - - void Update() override; - - bool IsPoly() override { return true; } - - void InitializeState() override; - - FRenderState* RenderState() override; - void PrecacheMaterial(FMaterial *mat, int translation) override; - void UpdatePalette() override; - void SetTextureFilterMode() override; - void BeginFrame() 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; - - IHardwareTexture *CreateHardwareTexture(int numchannels) override; - IVertexBuffer *CreateVertexBuffer() override; - IIndexBuffer *CreateIndexBuffer() override; - IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; - - FTexture *WipeStartScreen() override; - FTexture *WipeEndScreen() override; - - TArray GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override; - - void SetVSync(bool vsync) override; - void Draw2D() override; - - struct DeleteList - { - std::vector> Buffers; - std::vector> Images; - } FrameDeleteList; - -private: - void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; - void UpdateShadowMap() override; - - void CheckCanvas(); - - IDataBuffer *mLightBuffer = nullptr; - - std::unique_ptr mRenderState; - std::unique_ptr mCanvas; - std::unique_ptr mDepthStencil; - std::unique_ptr mDrawCommands; - RenderMemory mFrameMemory; - - struct ScreenQuadVertex - { - float x, y, z; - float u, v; - PalEntry color0; - - ScreenQuadVertex() = default; - ScreenQuadVertex(float x, float y, float u, float v) : x(x), y(y), z(1.0f), u(u), v(v), color0(0xffffffff) { } - }; - - struct ScreenQuad - { - IVertexBuffer* VertexBuffer = nullptr; - IIndexBuffer* IndexBuffer = nullptr; - } mScreenQuad; - - bool cur_vsync = false; -}; - -inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast(screen); } - -// [GEC] Original code of dpJudas, I add the formulas of gamma, brightness, contrast and saturation. -class CopyAndApplyGammaCommand : public DrawerCommand -{ -public: - CopyAndApplyGammaCommand(void* dest, int destpitch, const void* src, int width, int height, int srcpitch, - float gamma, float contrast, float brightness, float saturation) : dest(dest), src(src), destpitch(destpitch), width(width), height(height), srcpitch(srcpitch), - gamma(gamma), contrast(contrast), brightness(brightness), saturation(saturation) - { - } - - void Execute(DrawerThread* thread) - { - float Saturation = clamp(saturation, -15.0f, 15.f); - - std::vector gammatablebuf(256); - uint8_t* gammatable = gammatablebuf.data(); - InitGammaTable(gammatable); - - int w = width; - int start = thread->skipped_by_thread(0); - int count = thread->count_for_thread(0, height); - int sstep = thread->num_cores * srcpitch; - int dstep = thread->num_cores * destpitch; - uint32_t* d = (uint32_t*)dest + start * destpitch; - const uint32_t* s = (const uint32_t*)src + start * srcpitch; - for (int y = 0; y < count; y++) - { - for (int x = 0; x < w; x++) - { - uint32_t red = RPART(s[x]); - uint32_t green = GPART(s[x]); - uint32_t blue = BPART(s[x]); - uint32_t alpha = APART(s[x]); - - if (saturation != 1.0f) - { - float NewR = (float)(red / 255.f); - float NewG = (float)(green / 255.f); - float NewB = (float)(blue / 255.f); - - // Apply Saturation - // float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750)); - // Out = luma.xxx + Saturation.xxx * (In - luma.xxx); - //float luma = (NewR * 0.2126729f) + (NewG * 0.7151522f) + (NewB * 0.0721750f); // Rec. 709 - float luma = (NewR * 0.299f) + (NewG * 0.587f) + (NewB * 0.114f); //Rec. 601 - NewR = luma + (Saturation * (NewR - luma)); - NewG = luma + (Saturation * (NewG - luma)); - NewB = luma + (Saturation * (NewB - luma)); - - // Clamp All - NewR = clamp(NewR, 0.0f, 1.f); - NewG = clamp(NewG, 0.0f, 1.f); - NewB = clamp(NewB, 0.0f, 1.f); - - red = (uint32_t)(NewR * 255.f); - green = (uint32_t)(NewG * 255.f); - blue = (uint32_t)(NewB * 255.f); - } - - // Apply Contrast / Brightness / Gamma - red = gammatable[red]; - green = gammatable[green]; - blue = gammatable[blue]; - - d[x] = MAKEARGB(alpha, (uint8_t)red, (uint8_t)green, (uint8_t)blue); - } - d += dstep; - s += sstep; - } - } - -private: - void InitGammaTable(uint8_t *gammatable) - { - float InvGamma = 1.0f / clamp(gamma, 0.1f, 4.f); - float Brightness = clamp(brightness, -0.8f, 0.8f); - float Contrast = clamp(contrast, 0.1f, 3.f); - - for (int x = 0; x < 256; x++) - { - float ramp = (float)(x / 255.f); - - // Apply Contrast - // vec4 finalColor = vec4((((originalColor.rgb - vec3(0.5)) * Contrast) + vec3(0.5)), 1.0); - if (contrast != 1.0f) - ramp = (((ramp - 0.5f) * Contrast) + 0.5f); - - // Apply Brightness - // vec4 finalColor = vec4(originalColor.rgb + Brightness, 1.0); - if (brightness != 0.0f) - ramp += (Brightness / 2.0f); - - // Apply Gamma - // FragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma)); - if (gamma != 1.0f) - ramp = pow(ramp, InvGamma); - - // Clamp ramp - ramp = clamp(ramp, 0.0f, 1.f); - - gammatable[x] = (uint8_t)(ramp * 255); - } - } - - void* dest; - const void* src; - int destpitch; - int width; - int height; - int srcpitch; - float gamma; - float contrast; - float brightness; - float saturation; -}; diff --git a/src/common/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/common/rendering/polyrenderer/backend/poly_hwtexture.cpp deleted file mode 100644 index 0e56303fe..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -** Softpoly 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 "templates.h" -#include "c_cvars.h" -#include "hw_material.h" -#include "hw_cvars.h" -#include "hw_renderstate.h" -#include "poly_framebuffer.h" -#include "poly_hwtexture.h" - -PolyHardwareTexture *PolyHardwareTexture::First = nullptr; - -PolyHardwareTexture::PolyHardwareTexture() -{ - Next = First; - First = this; - if (Next) Next->Prev = this; -} - -PolyHardwareTexture::~PolyHardwareTexture() -{ - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - Reset(); -} - -void PolyHardwareTexture::ResetAll() -{ - for (PolyHardwareTexture *cur = PolyHardwareTexture::First; cur; cur = cur->Next) - cur->Reset(); -} - -void PolyHardwareTexture::Reset() -{ - if (auto fb = GetPolyFrameBuffer()) - { - auto &deleteList = fb->FrameDeleteList; - if (mCanvas) deleteList.Images.push_back(std::move(mCanvas)); - } -} - -DCanvas *PolyHardwareTexture::GetImage(FTexture *tex, int translation, int flags) -{ - if (!mCanvas) - CreateImage(tex, translation, flags); - return mCanvas.get(); -} - -PolyDepthStencil *PolyHardwareTexture::GetDepthStencil(FTexture *tex) -{ - if (!mDepthStencil) - { - int w = tex->GetWidth(); - int h = tex->GetHeight(); - mDepthStencil.reset(new PolyDepthStencil(w, h)); - } - return mDepthStencil.get(); -} - -void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize) -{ - if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) - { - mCanvas.reset(new DCanvas(0, 0, texelsize == 4)); - mCanvas->Resize(w, h, false); - bufferpitch = mCanvas->GetPitch(); - } -} - -uint8_t *PolyHardwareTexture::MapBuffer() -{ - return mCanvas->GetPixels(); -} - -unsigned int PolyHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) -{ - return 0; -} - -void PolyHardwareTexture::CreateWipeTexture(int w, int h, const char *name) -{ - if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h) - { - mCanvas.reset(new DCanvas(0, 0, true)); - mCanvas->Resize(w, h, false); - } - - auto fb = static_cast(screen); - - fb->FlushDrawCommands(); - DrawerThreads::WaitForWorkers(); - - uint32_t* dest = (uint32_t*)mCanvas->GetPixels(); - uint32_t* src = (uint32_t*)fb->GetCanvas()->GetPixels(); - int dpitch = mCanvas->GetPitch(); - int spitch = fb->GetCanvas()->GetPitch(); - int pixelsize = 4; - - for (int y = 0; y < h; y++) - { - memcpy(dest + dpitch * (h - 1 - y), src + spitch * y, w * pixelsize); - } -} - -void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) -{ - mCanvas.reset(new DCanvas(0, 0, true)); - - if (!tex->isHardwareCanvas()) - { - FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); - mCanvas->Resize(texbuffer.mWidth, texbuffer.mHeight, false); - memcpy(mCanvas->GetPixels(), texbuffer.mBuffer, texbuffer.mWidth * texbuffer.mHeight * 4); - } - else - { - int w = tex->GetWidth(); - int h = tex->GetHeight(); - mCanvas->Resize(w, h, false); - } -} diff --git a/src/common/rendering/polyrenderer/backend/poly_hwtexture.h b/src/common/rendering/polyrenderer/backend/poly_hwtexture.h deleted file mode 100644 index c93f2339d..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_hwtexture.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#ifdef LoadImage -#undef LoadImage -#endif - -#define SHADED_TEXTURE -1 -#define DIRECT_PALETTE -2 - -#include "tarray.h" -#include "hw_ihwtexture.h" -#include "volk/volk.h" - -struct FMaterialState; -class PolyBuffer; - -class PolyHardwareTexture : public IHardwareTexture -{ -public: - PolyHardwareTexture(); - ~PolyHardwareTexture(); - - static void ResetAll(); - void Reset(); - - DCanvas *GetImage(FTexture *tex, int translation, int flags); - PolyDepthStencil *GetDepthStencil(FTexture *tex); - - // Software renderer stuff - void AllocateBuffer(int w, int h, int texelsize) override; - uint8_t *MapBuffer() override; - unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) override; - - // Wipe screen - void CreateWipeTexture(int w, int h, const char *name); - -private: - void CreateImage(FTexture *tex, int translation, int flags); - - static PolyHardwareTexture *First; - PolyHardwareTexture *Prev = nullptr; - PolyHardwareTexture *Next = nullptr; - std::unique_ptr mCanvas; - std::unique_ptr mDepthStencil; -}; diff --git a/src/common/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/common/rendering/polyrenderer/backend/poly_renderstate.cpp deleted file mode 100644 index 14077e489..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_renderstate.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* -** Softpoly 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 "polyrenderer/backend/poly_renderstate.h" -#include "polyrenderer/backend/poly_framebuffer.h" -#include "polyrenderer/backend/poly_hwtexture.h" -#include "templates.h" -#include "hw_skydome.h" -#include "hw_viewpointuniforms.h" -#include "hw_lightbuffer.h" -#include "hw_cvars.h" -#include "hw_clock.h" -#include "flatvertices.h" -#include "hwrenderer/data/hw_viewpointbuffer.h" -#include "hwrenderer/data/shaderuniforms.h" - -static PolyDrawMode dtToDrawMode[] = -{ - PolyDrawMode::Points, - PolyDrawMode::Lines, - PolyDrawMode::Triangles, - PolyDrawMode::TriangleFan, - PolyDrawMode::TriangleStrip, -}; - -PolyRenderState::PolyRenderState() -{ - mIdentityMatrix.loadIdentity(); - Reset(); -} - -void PolyRenderState::ClearScreen() -{ - screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT); - SetColor(0, 0, 0); - Draw(DT_TriangleStrip, FFlatVertexBuffer::FULLSCREEN_INDEX, 4, true); -} - -void PolyRenderState::Draw(int dt, int index, int count, bool apply) -{ - if (apply || mNeedApply) - Apply(); - - mDrawCommands->Draw(index, count, dtToDrawMode[dt]); -} - -void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) -{ - if (apply || mNeedApply) - Apply(); - - mDrawCommands->DrawIndexed(index, count, dtToDrawMode[dt]); -} - -bool PolyRenderState::SetDepthClamp(bool on) -{ - bool lastValue = mDepthClamp; - mDepthClamp = on; - mNeedApply = true; - return lastValue; -} - -void PolyRenderState::SetDepthMask(bool on) -{ - mDepthMask = on; - mNeedApply = true; -} - -void PolyRenderState::SetDepthFunc(int func) -{ - mDepthFunc = func; - mNeedApply = true; -} - -void PolyRenderState::SetDepthRange(float min, float max) -{ - mDepthRangeMin = min; - mDepthRangeMax = max; - mNeedApply = true; -} - -void PolyRenderState::SetColorMask(bool r, bool g, bool b, bool a) -{ - mColorMask[0] = r; - mColorMask[1] = g; - mColorMask[2] = b; - mColorMask[3] = a; - mNeedApply = true; -} - -void PolyRenderState::SetStencil(int offs, int op, int flags) -{ - mStencilValue = screen->stencilValue + offs; - mStencilOp = op; - mNeedApply = true; - - if (flags != -1) - { - bool cmon = !(flags & SF_ColorMaskOff); - SetColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer - SetDepthMask(!(flags & SF_DepthMaskOff)); - } -} - -void PolyRenderState::SetCulling(int mode) -{ - mCulling = mode; - mNeedApply = true; -} - -void PolyRenderState::EnableClipDistance(int num, bool state) -{ -} - -void PolyRenderState::Clear(int targets) -{ - if (mNeedApply) - Apply(); - - //if (targets & CT_Color) - // mDrawCommands->ClearColor(); - if (targets & CT_Depth) - mDrawCommands->ClearDepth(65535.0f); - if (targets & CT_Stencil) - mDrawCommands->ClearStencil(0); -} - -void PolyRenderState::EnableStencil(bool on) -{ - mStencilEnabled = on; - mNeedApply = true; -} - -void PolyRenderState::SetScissor(int x, int y, int w, int h) -{ - if (w < 0) - { - x = 0; - y = 0; - w = mRenderTarget.Canvas->GetWidth(); - h = mRenderTarget.Canvas->GetHeight(); - } - mScissor.x = x; - mScissor.y = mRenderTarget.Canvas->GetHeight() - y - h; - mScissor.width = w; - mScissor.height = h; - mNeedApply = true; -} - -void PolyRenderState::SetViewport(int x, int y, int w, int h) -{ - auto fb = GetPolyFrameBuffer(); - if (w < 0) - { - x = 0; - y = 0; - w = mRenderTarget.Canvas->GetWidth(); - h = mRenderTarget.Canvas->GetHeight(); - } - mViewport.x = x; - mViewport.y = mRenderTarget.Canvas->GetHeight() - y - h; - mViewport.width = w; - mViewport.height = h; - mNeedApply = true; -} - -void PolyRenderState::EnableDepthTest(bool on) -{ - mDepthTest = on; - mNeedApply = true; -} - -void PolyRenderState::EnableMultisampling(bool on) -{ -} - -void PolyRenderState::EnableLineSmooth(bool on) -{ -} - -void PolyRenderState::EnableDrawBuffers(int count, bool apply) -{ -} - -void PolyRenderState::SetColormapShader(bool enable) -{ - mNeedApply = true; - mColormapShader = enable; -} - -void PolyRenderState::EndRenderPass() -{ - mDrawCommands = nullptr; - mNeedApply = true; - mFirstMatrixApply = true; -} - -void PolyRenderState::Apply() -{ - drawcalls.Clock(); - - if (!mDrawCommands) - { - mDrawCommands = GetPolyFrameBuffer()->GetDrawCommands(); - } - - if (mNeedApply) - { - mDrawCommands->SetViewport(mViewport.x, mViewport.y, mViewport.width, mViewport.height, mRenderTarget.Canvas, mRenderTarget.DepthStencil, mRenderTarget.TopDown); - mDrawCommands->SetScissor(mScissor.x, mScissor.y, mScissor.width, mScissor.height); - mDrawCommands->SetViewpointUniforms(mViewpointUniforms); - mDrawCommands->SetDepthClamp(mDepthClamp); - mDrawCommands->SetDepthMask(mDepthTest && mDepthMask); - mDrawCommands->SetDepthFunc(mDepthTest ? mDepthFunc : DF_Always); - mDrawCommands->SetDepthRange(mDepthRangeMin, mDepthRangeMax); - mDrawCommands->SetStencil(mStencilValue, mStencilOp); - mDrawCommands->EnableStencil(mStencilEnabled); - mDrawCommands->SetCulling(mCulling); - mDrawCommands->SetColorMask(mColorMask[0], mColorMask[1], mColorMask[2], mColorMask[3]); - mNeedApply = false; - } - - int fogset = 0; - if (mFogEnabled) - { - if (mFogEnabled == 2) - { - fogset = -3; // 2D rendering with 'foggy' overlay. - } - else if ((GetFogColor() & 0xffffff) == 0) - { - fogset = gl_fogmode; - } - else - { - fogset = -gl_fogmode; - } - } - - ApplyMaterial(); - - if (mVertexBuffer) - { - mDrawCommands->SetVertexBuffer(mVertexBuffer->Memory(), mVertexOffsets[0], mVertexOffsets[1]); // [GEC] Add offset params - } - if (mIndexBuffer) mDrawCommands->SetIndexBuffer(mIndexBuffer->Memory()); - mDrawCommands->SetInputAssembly(static_cast(mVertexBuffer)->VertexFormat); - mDrawCommands->SetRenderStyle(mRenderStyle); - - if (mColormapShader) - { - mDrawCommands->SetShader(EFF_NONE, 0, false, true); - } - else if (mSpecialEffect > EFF_NONE) - { - mDrawCommands->SetShader(mSpecialEffect, 0, false, false); - } - else - { - int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0); - mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, false); - } - - if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) - mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.); - else - mStreamData.timer = 0.0f; - - PolyPushConstants constants; - constants.uFogEnabled = fogset; - constants.uTextureMode = GetTextureModeAndFlags(mTempTM); - constants.uLightDist = mLightParms[0]; - constants.uLightFactor = mLightParms[1]; - constants.uFogDensity = mLightParms[2]; - constants.uLightLevel = mLightParms[3]; - constants.uAlphaThreshold = mAlphaThreshold; - constants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; - constants.uLightIndex = mLightIndex; - constants.uDynLightColor = mStreamData.uDynLightColor; // [GEC] - - mDrawCommands->PushStreamData(mStreamData, constants); - ApplyMatrices(); - - if (mBias.mChanged) - { - mDrawCommands->SetDepthBias(mBias.mUnits, mBias.mFactor); - mBias.mChanged = false; - } - - drawcalls.Unclock(); -} - -void PolyRenderState::ApplyMaterial() -{ - if (mMaterial.mChanged && mMaterial.mMaterial) - { - mTempTM = mMaterial.mMaterial->Source()->isHardwareCanvas() ? TM_OPAQUE : TM_NORMAL; - - if (mMaterial.mMaterial->Source()->isHardwareCanvas()) static_cast(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate(); - - MaterialLayerInfo* layer; - auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation, &layer)); - if (base) - { - DCanvas *texcanvas = base->GetImage(layer->layerTexture, mMaterial.mTranslation, layer->scaleFlags); - mDrawCommands->SetTexture(0, texcanvas->GetPixels(), texcanvas->GetWidth(), texcanvas->GetHeight(), texcanvas->IsBgra()); - - int numLayers = mMaterial.mMaterial->NumLayers(); - for (int i = 1; i < numLayers; i++) - { - auto systex = static_cast(mMaterial.mMaterial->GetLayer(i, 0, &layer)); - - texcanvas = systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); - mDrawCommands->SetTexture(i, texcanvas->GetPixels(), texcanvas->GetWidth(), texcanvas->GetHeight(), texcanvas->IsBgra()); - } - } - - mMaterial.mChanged = false; - } -} - -template -static void BufferedSet(bool &modified, T &dst, const T &src) -{ - if (dst == src) - return; - dst = src; - modified = true; -} - -static void BufferedSet(bool &modified, VSMatrix &dst, const VSMatrix &src) -{ - if (memcmp(dst.get(), src.get(), sizeof(FLOATTYPE) * 16) == 0) - return; - dst = src; - modified = true; -} - -void PolyRenderState::ApplyMatrices() -{ - bool modified = mFirstMatrixApply; - if (mTextureMatrixEnabled) - { - BufferedSet(modified, mMatrices.TextureMatrix, mTextureMatrix); - } - else - { - BufferedSet(modified, mMatrices.TextureMatrix, mIdentityMatrix); - } - - if (mModelMatrixEnabled) - { - BufferedSet(modified, mMatrices.ModelMatrix, mModelMatrix); - if (modified) - mMatrices.NormalModelMatrix.computeNormalMatrix(mModelMatrix); - } - else - { - BufferedSet(modified, mMatrices.ModelMatrix, mIdentityMatrix); - BufferedSet(modified, mMatrices.NormalModelMatrix, mIdentityMatrix); - } - - if (modified) - { - mFirstMatrixApply = false; - mDrawCommands->PushMatrices(mMatrices.ModelMatrix, mMatrices.NormalModelMatrix, mMatrices.TextureMatrix); - } -} - -void PolyRenderState::SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown) -{ - mRenderTarget.Canvas = canvas; - mRenderTarget.DepthStencil = depthStencil; - mRenderTarget.TopDown = topdown; -} - -void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length) -{ - if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT) - { - mViewpointUniforms = reinterpret_cast(static_cast(buffer->Memory()) + offset); - mNeedApply = true; - } -} - -PolyVertexInputAssembly *PolyRenderState::GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) -{ - for (size_t i = 0; i < mVertexFormats.size(); i++) - { - auto f = mVertexFormats[i].get(); - if (f->Attrs.size() == (size_t)numAttributes && f->NumBindingPoints == numBindingPoints && f->Stride == stride) - { - 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 f; - } - } - - auto fmt = std::make_unique(); - fmt->NumBindingPoints = numBindingPoints; - fmt->Stride = stride; - fmt->UseVertexData = 0; - for (int j = 0; j < numAttributes; j++) - { - if (attrs[j].location == VATTR_COLOR) - fmt->UseVertexData |= 1; - else if (attrs[j].location == VATTR_NORMAL) - fmt->UseVertexData |= 2; - fmt->Attrs.push_back(attrs[j]); - } - - for (int j = 0; j < numAttributes; j++) - { - fmt->mOffsets[attrs[j].location] = attrs[j].offset; - } - fmt->mStride = stride; - - mVertexFormats.push_back(std::move(fmt)); - return mVertexFormats.back().get(); -} diff --git a/src/common/rendering/polyrenderer/backend/poly_renderstate.h b/src/common/rendering/polyrenderer/backend/poly_renderstate.h deleted file mode 100644 index f539bc7c2..000000000 --- a/src/common/rendering/polyrenderer/backend/poly_renderstate.h +++ /dev/null @@ -1,99 +0,0 @@ - -#pragma once - -#include "polyrenderer/backend/poly_buffers.h" -#include "poly_triangle.h" - -#include "name.h" - -#include "hw_renderstate.h" -#include "hw_material.h" - -struct HWViewpointUniforms; - -class PolyRenderState final : public FRenderState -{ -public: - PolyRenderState(); - - // Draw commands - void ClearScreen() override; - void Draw(int dt, int index, int count, bool apply = true) override; - void DrawIndexed(int dt, int index, int count, bool apply = true) override; - - // Immediate render state change commands. These only change infrequently and should not clutter the render state. - bool SetDepthClamp(bool on) override; - void SetDepthMask(bool on) override; - void SetDepthFunc(int func) override; - void SetDepthRange(float min, float max) override; - void SetColorMask(bool r, bool g, bool b, bool a) override; - void SetStencil(int offs, int op, int flags = -1) override; - void SetCulling(int mode) override; - void EnableClipDistance(int num, bool state) override; - void Clear(int targets) override; - void EnableStencil(bool on) override; - void SetScissor(int x, int y, int w, int h) override; - void SetViewport(int x, int y, int w, int h) override; - void EnableDepthTest(bool on) override; - void EnableMultisampling(bool on) override; - void EnableLineSmooth(bool on) override; - void EnableDrawBuffers(int count, bool apply) override; - - void SetRenderTarget(DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown); - void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length); - PolyVertexInputAssembly *GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); - void EndRenderPass(); - - void SetColormapShader(bool enable); - -private: - void Apply(); - void ApplyMaterial(); - void ApplyMatrices(); - - struct Matrices - { - VSMatrix ModelMatrix; - VSMatrix NormalModelMatrix; - VSMatrix TextureMatrix; - } mMatrices; - VSMatrix mIdentityMatrix; - bool mFirstMatrixApply = true; - - HWViewpointUniforms *mViewpointUniforms = nullptr; - std::vector> mVertexFormats; - - bool mDepthClamp = true; - int mTempTM = TM_NORMAL; - - struct RenderTarget - { - DCanvas *Canvas = nullptr; - PolyDepthStencil *DepthStencil = nullptr; - bool TopDown = true; - } mRenderTarget; - - struct Rect - { - int x = 0; - int y = 0; - int width = 0; - int height = 0; - } mScissor, mViewport; - - bool mNeedApply = true; - - bool mDepthTest = false; - bool mDepthMask = false; - int mDepthFunc = DF_Always; - float mDepthRangeMin = 0.0f; - float mDepthRangeMax = 1.0f; - bool mStencilEnabled = false; - int mStencilValue = 0; - int mStencilOp = SOP_Keep; - int mCulling = Cull_None; - bool mColorMask[4] = { true, true, true, true }; - bool mColormapShader = false; - - PolyCommandBuffer* mDrawCommands = nullptr; -}; diff --git a/src/common/rendering/polyrenderer/drawers/poly_thread.cpp b/src/common/rendering/polyrenderer/drawers/poly_thread.cpp deleted file mode 100644 index 338b12139..000000000 --- a/src/common/rendering/polyrenderer/drawers/poly_thread.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" - -#include "filesystem.h" -#include "v_video.h" -#include "model.h" -#include "poly_thread.h" -#include "screen_triangle.h" - -#ifndef NO_SSE -#include -#endif - -PolyTriangleThreadData::PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y) - : core(core), num_cores(num_cores), numa_node(numa_node), num_numa_nodes(num_numa_nodes), numa_start_y(numa_start_y), numa_end_y(numa_end_y) -{ -} - -void PolyTriangleThreadData::ClearDepth(float value) -{ - int width = depthstencil->Width(); - int height = depthstencil->Height(); - float *data = depthstencil->DepthValues(); - - int skip = skipped_by_thread(0); - int count = count_for_thread(0, height); - - data += skip * width; - for (int i = 0; i < count; i++) - { - for (int x = 0; x < width; x++) - data[x] = value; - data += num_cores * width; - } -} - -void PolyTriangleThreadData::ClearStencil(uint8_t value) -{ - int width = depthstencil->Width(); - int height = depthstencil->Height(); - uint8_t *data = depthstencil->StencilValues(); - - int skip = skipped_by_thread(0); - int count = count_for_thread(0, height); - - data += skip * width; - for (int i = 0; i < count; i++) - { - memset(data, value, width); - data += num_cores * width; - } -} - -void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, PolyDepthStencil *new_depthstencil, bool new_topdown) -{ - viewport_x = x; - viewport_y = y; - viewport_width = width; - viewport_height = height; - dest = new_dest; - dest_width = new_dest_width; - dest_height = new_dest_height; - dest_pitch = new_dest_pitch; - dest_bgra = new_dest_bgra; - depthstencil = new_depthstencil; - topdown = new_topdown; - UpdateClip(); -} - -void PolyTriangleThreadData::SetScissor(int x, int y, int w, int h) -{ - scissor.left = x; - scissor.right = x + w; - scissor.top = y; - scissor.bottom = y + h; - UpdateClip(); -} - -void PolyTriangleThreadData::UpdateClip() -{ - clip.left = MAX(MAX(viewport_x, scissor.left), 0); - clip.top = MAX(MAX(viewport_y, scissor.top), 0); - clip.right = MIN(MIN(viewport_x + viewport_width, scissor.right), dest_width); - clip.bottom = MIN(MIN(viewport_y + viewport_height, scissor.bottom), dest_height); -} - -void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPushConstants &constants) -{ - mainVertexShader.Data = data; - mainVertexShader.uClipSplit = constants.uClipSplit; - - PushConstants = &constants; - - AlphaThreshold = clamp((int)(PushConstants->uAlphaThreshold * 255.0f + 0.5f), 0, 255) << 24; - - numPolyLights = 0; - if (constants.uLightIndex >= 0) - { - const FVector4 &lightRange = lights[constants.uLightIndex]; - static_assert(sizeof(FVector4) == 16, "sizeof(FVector4) is not 16 bytes"); - if (lightRange.Y > lightRange.X) - { - int start = constants.uLightIndex + 1; - int modulatedStart = static_cast(lightRange.X) + start; - int modulatedEnd = static_cast(lightRange.Y) + start; - for (int i = modulatedStart; i < modulatedEnd; i += 4) - { - if (numPolyLights == maxPolyLights) - break; - - auto &lightpos = lights[i]; - auto &lightcolor = lights[i + 1]; - //auto &lightspot1 = lights[i + 2]; - //auto &lightspot2 = lights[i + 3]; - uint32_t r = (int)clamp(lightcolor.X * 255.0f, 0.0f, 255.0f); - uint32_t g = (int)clamp(lightcolor.Y * 255.0f, 0.0f, 255.0f); - uint32_t b = (int)clamp(lightcolor.Z * 255.0f, 0.0f, 255.0f); - - auto& polylight = polyLights[numPolyLights++]; - polylight.x = lightpos.X; - polylight.y = lightpos.Y; - polylight.z = lightpos.Z; - polylight.radius = 256.0f / lightpos.W; - polylight.color = (r << 16) | (g << 8) | b; - if (lightcolor.W < 0.0f) - polylight.radius = -polylight.radius; - } - } - } -} - -void PolyTriangleThreadData::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) -{ - mainVertexShader.ModelMatrix = modelMatrix; - mainVertexShader.NormalModelMatrix = normalModelMatrix; - mainVertexShader.TextureMatrix = textureMatrix; -} - -void PolyTriangleThreadData::SetViewpointUniforms(const HWViewpointUniforms *uniforms) -{ - mainVertexShader.Viewpoint = uniforms; -} - -void PolyTriangleThreadData::SetDepthClamp(bool on) -{ - DepthClamp = on; -} - -void PolyTriangleThreadData::SetDepthMask(bool on) -{ - WriteDepth = on; -} - -void PolyTriangleThreadData::SetDepthFunc(int func) -{ - if (func == DF_LEqual || func == DF_Less) - { - DepthTest = true; - } - else // if (func == DF_Always) - { - DepthTest = false; - } -} - -void PolyTriangleThreadData::SetDepthRange(float min, float max) -{ - DepthRangeStart = min; - DepthRangeScale = max - min; -} - -void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor) -{ - depthbias = (float)(depthBiasConstantFactor / 2500.0); -} - -void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a) -{ - WriteColor = r; -} - -void PolyTriangleThreadData::SetStencil(int stencilRef, int op) -{ - StencilTestValue = stencilRef; - if (op == SOP_Increment) - { - StencilWriteValue = MIN(stencilRef + 1, (int)255); - } - else if (op == SOP_Decrement) - { - StencilWriteValue = MAX(stencilRef - 1, (int)0); - } - else // SOP_Keep - { - StencilWriteValue = stencilRef; - } - - WriteStencil = StencilTest && (StencilTestValue != StencilWriteValue); -} - -void PolyTriangleThreadData::SetCulling(int mode) -{ - SetTwoSided(mode == Cull_None); - SetCullCCW(mode == Cull_CCW); -} - -void PolyTriangleThreadData::EnableStencil(bool on) -{ - StencilTest = on; - WriteStencil = on && (StencilTestValue != StencilWriteValue); -} - -void PolyTriangleThreadData::SetRenderStyle(FRenderStyle style) -{ - RenderStyle = style; -} - -void PolyTriangleThreadData::SetShader(int specialEffect, int effectState, bool alphaTest, bool colormapShader) -{ - SpecialEffect = specialEffect; - EffectState = effectState; - AlphaTest = alphaTest; - ColormapShader = colormapShader; -} - -void PolyTriangleThreadData::SetTexture(int unit, const void *pixels, int width, int height, bool bgra) -{ - textures[unit].pixels = pixels; - textures[unit].width = width; - textures[unit].height = height; - textures[unit].bgra = bgra; -} - -void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) -{ - if (vcount < 3) - return; - - elements += index; - - ShadedTriVertex vertbuffer[3]; - ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] }; - if (drawmode == PolyDrawMode::Triangles) - { - for (int i = 0; i < vcount / 3; i++) - { - for (int j = 0; j < 3; j++) - *vert[j] = ShadeVertex(*(elements++)); - DrawShadedTriangle(vert, ccw); - } - } - else if (drawmode == PolyDrawMode::TriangleFan) - { - *vert[0] = ShadeVertex(*(elements++)); - *vert[1] = ShadeVertex(*(elements++)); - for (int i = 2; i < vcount; i++) - { - *vert[2] = ShadeVertex(*(elements++)); - DrawShadedTriangle(vert, ccw); - std::swap(vert[1], vert[2]); - } - } - else if (drawmode == PolyDrawMode::TriangleStrip) - { - bool toggleccw = ccw; - *vert[0] = ShadeVertex(*(elements++)); - *vert[1] = ShadeVertex(*(elements++)); - for (int i = 2; i < vcount; i++) - { - *vert[2] = ShadeVertex(*(elements++)); - DrawShadedTriangle(vert, toggleccw); - ShadedTriVertex *vtmp = vert[0]; - vert[0] = vert[1]; - vert[1] = vert[2]; - vert[2] = vtmp; - toggleccw = !toggleccw; - } - } - else if (drawmode == PolyDrawMode::Lines) - { - for (int i = 0; i < vcount / 2; i++) - { - *vert[0] = ShadeVertex(*(elements++)); - *vert[1] = ShadeVertex(*(elements++)); - DrawShadedLine(vert); - } - } - else if (drawmode == PolyDrawMode::Points) - { - for (int i = 0; i < vcount; i++) - { - *vert[0] = ShadeVertex(*(elements++)); - DrawShadedPoint(vert); - } - } -} - -void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) -{ - if (vcount < 3) - return; - - int vinput = index; - - ShadedTriVertex vertbuffer[3]; - ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] }; - if (drawmode == PolyDrawMode::Triangles) - { - for (int i = 0; i < vcount / 3; i++) - { - for (int j = 0; j < 3; j++) - *vert[j] = ShadeVertex(vinput++); - DrawShadedTriangle(vert, ccw); - } - } - else if (drawmode == PolyDrawMode::TriangleFan) - { - *vert[0] = ShadeVertex(vinput++); - *vert[1] = ShadeVertex(vinput++); - for (int i = 2; i < vcount; i++) - { - *vert[2] = ShadeVertex(vinput++); - DrawShadedTriangle(vert, ccw); - std::swap(vert[1], vert[2]); - } - } - else if (drawmode == PolyDrawMode::TriangleStrip) - { - bool toggleccw = ccw; - *vert[0] = ShadeVertex(vinput++); - *vert[1] = ShadeVertex(vinput++); - for (int i = 2; i < vcount; i++) - { - *vert[2] = ShadeVertex(vinput++); - DrawShadedTriangle(vert, toggleccw); - ShadedTriVertex *vtmp = vert[0]; - vert[0] = vert[1]; - vert[1] = vert[2]; - vert[2] = vtmp; - toggleccw = !toggleccw; - } - } - else if (drawmode == PolyDrawMode::Lines) - { - for (int i = 0; i < vcount / 2; i++) - { - *vert[0] = ShadeVertex(vinput++); - *vert[1] = ShadeVertex(vinput++); - DrawShadedLine(vert); - } - } - else if (drawmode == PolyDrawMode::Points) - { - for (int i = 0; i < vcount; i++) - { - *vert[0] = ShadeVertex(vinput++); - DrawShadedPoint(vert); - } - } -} - -ShadedTriVertex PolyTriangleThreadData::ShadeVertex(int index) -{ - inputAssembly->Load(this, vertices, frame0, frame1, index); - mainVertexShader.SIMPLE = (SpecialEffect == EFF_BURN) || (SpecialEffect == EFF_STENCIL); - mainVertexShader.SPHEREMAP = (SpecialEffect == EFF_SPHEREMAP); - mainVertexShader.main(); - return mainVertexShader; -} - -bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *const* vert) -{ - // A degenerate triangle has a zero cross product for two of its sides. - float ax = vert[1]->gl_Position.X - vert[0]->gl_Position.X; - float ay = vert[1]->gl_Position.Y - vert[0]->gl_Position.Y; - float az = vert[1]->gl_Position.W - vert[0]->gl_Position.W; - float bx = vert[2]->gl_Position.X - vert[0]->gl_Position.X; - float by = vert[2]->gl_Position.Y - vert[0]->gl_Position.Y; - float bz = vert[2]->gl_Position.W - vert[0]->gl_Position.W; - 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-8f; -} - -bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args) -{ - float a = - args->v1->x * args->v2->y - args->v2->x * args->v1->y + - args->v2->x * args->v3->y - args->v3->x * args->v2->y + - args->v3->x * args->v1->y - args->v1->x * args->v3->y; - return a <= 0.0f; -} - -void PolyTriangleThreadData::DrawShadedPoint(const ShadedTriVertex *const* vertex) -{ -} - -void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert) -{ - static const int numclipdistances = 9; - float clipdistance[numclipdistances * 2]; - float *clipd = clipdistance; - for (int i = 0; i < 2; i++) - { - const auto &v = *vert[i]; - clipd[0] = v.gl_Position.X + v.gl_Position.W; - clipd[1] = v.gl_Position.W - v.gl_Position.X; - clipd[2] = v.gl_Position.Y + v.gl_Position.W; - clipd[3] = v.gl_Position.W - v.gl_Position.Y; - if (DepthClamp) - { - clipd[4] = 1.0f; - clipd[5] = 1.0f; - } - else - { - clipd[4] = v.gl_Position.Z + v.gl_Position.W; - clipd[5] = v.gl_Position.W - v.gl_Position.Z; - } - clipd[6] = v.gl_ClipDistance[0]; - clipd[7] = v.gl_ClipDistance[1]; - clipd[8] = v.gl_ClipDistance[2]; - clipd += numclipdistances; - } - - float t1 = 0.0f; - float t2 = 1.0f; - for (int p = 0; p < numclipdistances; p++) - { - float clipdistance1 = clipdistance[0 * numclipdistances + p]; - float clipdistance2 = clipdistance[1 * numclipdistances + p]; - if (clipdistance1 < 0.0f) t1 = MAX(-clipdistance1 / (clipdistance2 - clipdistance1), t1); - if (clipdistance2 < 0.0f) t2 = MIN(1.0f + clipdistance2 / (clipdistance1 - clipdistance2), t2); - if (t1 >= t2) - return; - } - - float weights[] = { 1.0f - t1, t1, 1.0f - t2, t2 }; - - ScreenTriVertex clippedvert[2]; - for (int i = 0; i < 2; i++) - { - auto &v = clippedvert[i]; - memset(&v, 0, sizeof(ScreenTriVertex)); - for (int w = 0; w < 2; w++) - { - float weight = weights[i * 2 + w]; - v.x += vert[w]->gl_Position.X * weight; - v.y += vert[w]->gl_Position.Y * weight; - v.z += vert[w]->gl_Position.Z * weight; - v.w += vert[w]->gl_Position.W * weight; - } - - // Calculate normalized device coordinates: - v.w = 1.0f / v.w; - v.x *= v.w; - v.y *= v.w; - v.z *= v.w; - - // Apply viewport scale to get screen coordinates: - v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; - if (topdown) - v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; - else - v.y = viewport_y + viewport_height * (1.0f + v.y) * 0.5f; - } - - uint32_t vColorA = (int)(vert[0]->vColor.W * 255.0f + 0.5f); - uint32_t vColorR = (int)(vert[0]->vColor.X * 255.0f + 0.5f); - uint32_t vColorG = (int)(vert[0]->vColor.Y * 255.0f + 0.5f); - uint32_t vColorB = (int)(vert[0]->vColor.Z * 255.0f + 0.5f); - uint32_t color = MAKEARGB(vColorA, vColorR, vColorG, vColorB); - - // Slow and naive implementation. Hopefully fast enough.. - - float x1 = clippedvert[0].x; - float y1 = clippedvert[0].y; - float x2 = clippedvert[1].x; - float y2 = clippedvert[1].y; - float dx = x2 - x1; - float dy = y2 - y1; - float step = (abs(dx) >= abs(dy)) ? abs(dx) : abs(dy); - dx /= step; - dy /= step; - float x = x1; - float y = y1; - int istep = (int)step; - int pixelsize = dest_bgra ? 4 : 1; - for (int i = 0; i <= istep; i++) - { - int scrx = (int)x; - int scry = (int)y; - if (scrx >= clip.left && scrx < clip.right && scry >= clip.top && scry < clip.bottom && !line_skipped_by_thread(scry)) - { - uint8_t *destpixel = dest + (scrx + scry * dest_width) * pixelsize; - if (pixelsize == 4) - { - *reinterpret_cast(destpixel) = color; - } - else - { - *destpixel = color; - } - } - x += dx; - y += dy; - } -} - -void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw) -{ - // Reject triangle if degenerate - if (IsDegenerate(vert)) - return; - - // Cull, clip and generate additional vertices as needed - ScreenTriVertex clippedvert[max_additional_vertices]; - int numclipvert = ClipEdge(vert); - - // Convert barycentric weights to actual vertices - for (int i = 0; i < numclipvert; i++) - { - auto &v = clippedvert[i]; - memset(&v, 0, sizeof(ScreenTriVertex)); - for (int w = 0; w < 3; w++) - { - float weight = weights[i * 3 + w]; - v.x += vert[w]->gl_Position.X * weight; - v.y += vert[w]->gl_Position.Y * weight; - v.z += vert[w]->gl_Position.Z * weight; - v.w += vert[w]->gl_Position.W * weight; - v.u += vert[w]->vTexCoord.X * weight; - v.v += vert[w]->vTexCoord.Y * weight; - v.worldX += vert[w]->pixelpos.X * weight; - v.worldY += vert[w]->pixelpos.Y * weight; - v.worldZ += vert[w]->pixelpos.Z * weight; - v.a += vert[w]->vColor.W * weight; - v.r += vert[w]->vColor.X * weight; - v.g += vert[w]->vColor.Y * weight; - v.b += vert[w]->vColor.Z * weight; - v.gradientdistZ += vert[w]->gradientdist.Z * weight; - } - } - -#ifdef NO_SSE - // Map to 2D viewport: - for (int j = 0; j < numclipvert; j++) - { - auto &v = clippedvert[j]; - - // Calculate normalized device coordinates: - v.w = 1.0f / v.w; - v.x *= v.w; - v.y *= v.w; - v.z *= v.w; - - // Apply viewport scale to get screen coordinates: - v.x = viewport_x + viewport_width * (1.0f + v.x) * 0.5f; - if (topdown) - v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f; - else - v.y = viewport_y + viewport_height * (1.0f + v.y) * 0.5f; - } -#else - // Map to 2D viewport: - __m128 mviewport_x = _mm_set1_ps((float)viewport_x); - __m128 mviewport_y = _mm_set1_ps((float)viewport_y); - __m128 mviewport_halfwidth = _mm_set1_ps(viewport_width * 0.5f); - __m128 mviewport_halfheight = _mm_set1_ps(viewport_height * 0.5f); - __m128 mone = _mm_set1_ps(1.0f); - int sse_length = (numclipvert + 3) / 4 * 4; - for (int j = 0; j < sse_length; j += 4) - { - __m128 vx = _mm_loadu_ps(&clippedvert[j].x); - __m128 vy = _mm_loadu_ps(&clippedvert[j + 1].x); - __m128 vz = _mm_loadu_ps(&clippedvert[j + 2].x); - __m128 vw = _mm_loadu_ps(&clippedvert[j + 3].x); - _MM_TRANSPOSE4_PS(vx, vy, vz, vw); - - // Calculate normalized device coordinates: - vw = _mm_div_ps(mone, vw); - vx = _mm_mul_ps(vx, vw); - vy = _mm_mul_ps(vy, vw); - vz = _mm_mul_ps(vz, vw); - - // Apply viewport scale to get screen coordinates: - vx = _mm_add_ps(mviewport_x, _mm_mul_ps(mviewport_halfwidth, _mm_add_ps(mone, vx))); - if (topdown) - vy = _mm_add_ps(mviewport_y, _mm_mul_ps(mviewport_halfheight, _mm_sub_ps(mone, vy))); - else - vy = _mm_add_ps(mviewport_y, _mm_mul_ps(mviewport_halfheight, _mm_add_ps(mone, vy))); - - _MM_TRANSPOSE4_PS(vx, vy, vz, vw); - _mm_storeu_ps(&clippedvert[j].x, vx); - _mm_storeu_ps(&clippedvert[j + 1].x, vy); - _mm_storeu_ps(&clippedvert[j + 2].x, vz); - _mm_storeu_ps(&clippedvert[j + 3].x, vw); - } -#endif - - if (!topdown) ccw = !ccw; - - TriDrawTriangleArgs args; - - if (twosided && numclipvert > 2) - { - args.v1 = &clippedvert[0]; - args.v2 = &clippedvert[1]; - args.v3 = &clippedvert[2]; - ccw = !IsFrontfacing(&args); - } - - // Draw screen triangles - if (ccw) - { - for (int i = numclipvert - 1; i > 1; i--) - { - args.v1 = &clippedvert[numclipvert - 1]; - args.v2 = &clippedvert[i - 1]; - args.v3 = &clippedvert[i - 2]; - if (IsFrontfacing(&args) == ccw && args.CalculateGradients()) - { - ScreenTriangle::Draw(&args, this); - } - } - } - else - { - for (int i = 2; i < numclipvert; i++) - { - args.v1 = &clippedvert[0]; - args.v2 = &clippedvert[i - 1]; - args.v3 = &clippedvert[i]; - if (IsFrontfacing(&args) != ccw && args.CalculateGradients()) - { - ScreenTriangle::Draw(&args, this); - } - } - } -} - -int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts) -{ - // use barycentric weights for clipped vertices - weights = weightsbuffer; - for (int i = 0; i < 3; i++) - { - weights[i * 3 + 0] = 0.0f; - weights[i * 3 + 1] = 0.0f; - weights[i * 3 + 2] = 0.0f; - weights[i * 3 + i] = 1.0f; - } - - // Clip and cull so that the following is true for all vertices: - // -v.w <= v.x <= v.w - // -v.w <= v.y <= v.w - // -v.w <= v.z <= v.w - - // halfspace clip distances - static const int numclipdistances = 9; -#ifdef NO_SSE - float clipdistance[numclipdistances * 3]; - bool needsclipping = false; - float *clipd = clipdistance; - for (int i = 0; i < 3; i++) - { - const auto &v = *verts[i]; - clipd[0] = v.gl_Position.X + v.gl_Position.W; - clipd[1] = v.gl_Position.W - v.gl_Position.X; - clipd[2] = v.gl_Position.Y + v.gl_Position.W; - clipd[3] = v.gl_Position.W - v.gl_Position.Y; - if (DepthClamp) - { - clipd[4] = 1.0f; - clipd[5] = 1.0f; - } - else - { - clipd[4] = v.gl_Position.Z + v.gl_Position.W; - clipd[5] = v.gl_Position.W - v.gl_Position.Z; - } - clipd[6] = v.gl_ClipDistance[0]; - clipd[7] = v.gl_ClipDistance[1]; - clipd[8] = v.gl_ClipDistance[2]; - for (int j = 0; j < 9; j++) - needsclipping = needsclipping || clipd[i]; - clipd += numclipdistances; - } - - // If all halfspace clip distances are positive then the entire triangle is visible. Skip the expensive clipping step. - if (!needsclipping) - { - return 3; - } -#else - __m128 mx = _mm_loadu_ps(&verts[0]->gl_Position.X); - __m128 my = _mm_loadu_ps(&verts[1]->gl_Position.X); - __m128 mz = _mm_loadu_ps(&verts[2]->gl_Position.X); - __m128 mw = _mm_setzero_ps(); - _MM_TRANSPOSE4_PS(mx, my, mz, mw); - __m128 clipd0 = _mm_add_ps(mx, mw); - __m128 clipd1 = _mm_sub_ps(mw, mx); - __m128 clipd2 = _mm_add_ps(my, mw); - __m128 clipd3 = _mm_sub_ps(mw, my); - __m128 clipd4 = DepthClamp ? _mm_set1_ps(1.0f) : _mm_add_ps(mz, mw); - __m128 clipd5 = DepthClamp ? _mm_set1_ps(1.0f) : _mm_sub_ps(mw, mz); - __m128 clipd6 = _mm_setr_ps(verts[0]->gl_ClipDistance[0], verts[1]->gl_ClipDistance[0], verts[2]->gl_ClipDistance[0], 0.0f); - __m128 clipd7 = _mm_setr_ps(verts[0]->gl_ClipDistance[1], verts[1]->gl_ClipDistance[1], verts[2]->gl_ClipDistance[1], 0.0f); - __m128 clipd8 = _mm_setr_ps(verts[0]->gl_ClipDistance[2], verts[1]->gl_ClipDistance[2], verts[2]->gl_ClipDistance[2], 0.0f); - __m128 mneedsclipping = _mm_cmplt_ps(clipd0, _mm_setzero_ps()); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd1, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd2, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd3, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd4, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd5, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd6, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd7, _mm_setzero_ps())); - mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd8, _mm_setzero_ps())); - if (_mm_movemask_ps(mneedsclipping) == 0) - { - return 3; - } - float clipdistance[numclipdistances * 4]; - _mm_storeu_ps(clipdistance, clipd0); - _mm_storeu_ps(clipdistance + 4, clipd1); - _mm_storeu_ps(clipdistance + 8, clipd2); - _mm_storeu_ps(clipdistance + 12, clipd3); - _mm_storeu_ps(clipdistance + 16, clipd4); - _mm_storeu_ps(clipdistance + 20, clipd5); - _mm_storeu_ps(clipdistance + 24, clipd6); - _mm_storeu_ps(clipdistance + 28, clipd7); - _mm_storeu_ps(clipdistance + 32, clipd8); -#endif - - // Clip against each halfspace - float *input = weights; - float *output = weights + max_additional_vertices * 3; - int inputverts = 3; - for (int p = 0; p < numclipdistances; p++) - { - // Clip each edge - int outputverts = 0; - for (int i = 0; i < inputverts; i++) - { - int j = (i + 1) % inputverts; -#ifdef NO_SSE - float clipdistance1 = - clipdistance[0 * numclipdistances + p] * input[i * 3 + 0] + - clipdistance[1 * numclipdistances + p] * input[i * 3 + 1] + - clipdistance[2 * numclipdistances + p] * input[i * 3 + 2]; - - float clipdistance2 = - clipdistance[0 * numclipdistances + p] * input[j * 3 + 0] + - clipdistance[1 * numclipdistances + p] * input[j * 3 + 1] + - clipdistance[2 * numclipdistances + p] * input[j * 3 + 2]; -#else - float clipdistance1 = - clipdistance[0 + p * 4] * input[i * 3 + 0] + - clipdistance[1 + p * 4] * input[i * 3 + 1] + - clipdistance[2 + p * 4] * input[i * 3 + 2]; - - float clipdistance2 = - clipdistance[0 + p * 4] * input[j * 3 + 0] + - clipdistance[1 + p * 4] * input[j * 3 + 1] + - clipdistance[2 + p * 4] * input[j * 3 + 2]; -#endif - - // Clip halfspace - if ((clipdistance1 >= 0.0f || clipdistance2 >= 0.0f) && outputverts + 1 < max_additional_vertices) - { - float t1 = (clipdistance1 < 0.0f) ? MAX(-clipdistance1 / (clipdistance2 - clipdistance1), 0.0f) : 0.0f; - float t2 = (clipdistance2 < 0.0f) ? MIN(1.0f + clipdistance2 / (clipdistance1 - clipdistance2), 1.0f) : 1.0f; - - // add t1 vertex - for (int k = 0; k < 3; k++) - output[outputverts * 3 + k] = input[i * 3 + k] * (1.0f - t1) + input[j * 3 + k] * t1; - outputverts++; - - if (t2 != 1.0f && t2 > t1) - { - // add t2 vertex - for (int k = 0; k < 3; k++) - output[outputverts * 3 + k] = input[i * 3 + k] * (1.0f - t2) + input[j * 3 + k] * t2; - outputverts++; - } - } - } - std::swap(input, output); - inputverts = outputverts; - if (inputverts == 0) - break; - } - - weights = input; - return inputverts; -} - -PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread) -{ - if (!thread->poly) - thread->poly = std::make_shared(thread->core, thread->num_cores, thread->numa_node, thread->num_numa_nodes, thread->numa_start_y, thread->numa_end_y); - return thread->poly.get(); -} diff --git a/src/common/rendering/polyrenderer/drawers/poly_thread.h b/src/common/rendering/polyrenderer/drawers/poly_thread.h deleted file mode 100644 index 8d7b8bce6..000000000 --- a/src/common/rendering/polyrenderer/drawers/poly_thread.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 "poly_triangle.h" - -struct PolyLight -{ - uint32_t color; - float x, y, z; - float radius; -}; - -class PolyTriangleThreadData -{ -public: - PolyTriangleThreadData(int32_t core, int32_t num_cores, int32_t numa_node, int32_t num_numa_nodes, int numa_start_y, int numa_end_y); - - void ClearDepth(float value); - void ClearStencil(uint8_t value); - void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil *depthstencil, bool topdown); - - void SetCullCCW(bool value) { ccw = value; } - void SetTwoSided(bool value) { twosided = value; } - - void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } - void SetVertexBuffer(const void *data, int offset0, int offset1) { vertices = data; frame0 = offset0; frame1 = offset1;} //[GEC] Save frame params - void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } - void SetLightBuffer(const void *data) { lights = (const FVector4 *)data; } - void SetViewpointUniforms(const HWViewpointUniforms *uniforms); - void SetDepthClamp(bool on); - void SetDepthMask(bool on); - void SetDepthFunc(int func); - void SetDepthRange(float min, float max); - void SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor); - void SetColorMask(bool r, bool g, bool b, bool a); - void SetStencil(int stencilRef, int op); - void SetCulling(int mode); - void EnableStencil(bool on); - void SetScissor(int x, int y, int w, int h); - void SetRenderStyle(FRenderStyle style); - void SetTexture(int unit, const void *pixels, int width, int height, bool bgra); - void SetShader(int specialEffect, int effectState, bool alphaTest, bool colormapShader); - - void UpdateClip(); - - void PushStreamData(const StreamData &data, const PolyPushConstants &constants); - void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); - - void DrawIndexed(int index, int count, PolyDrawMode mode); - void Draw(int index, int vcount, PolyDrawMode mode); - - int32_t core; - int32_t num_cores; - int32_t numa_node; - int32_t num_numa_nodes; - - int numa_start_y; - int numa_end_y; - - bool line_skipped_by_thread(int line) - { - return line < numa_start_y || line >= numa_end_y || line % num_cores != core; - } - - int skipped_by_thread(int first_line) - { - int clip_first_line = MAX(first_line, numa_start_y); - int core_skip = (num_cores - (clip_first_line - core) % num_cores) % num_cores; - return clip_first_line + core_skip - first_line; - } - - int count_for_thread(int first_line, int count) - { - count = MIN(count, numa_end_y - first_line); - int c = (count - skipped_by_thread(first_line) + num_cores - 1) / num_cores; - return MAX(c, 0); - } - - struct Scanline - { - float W[MAXWIDTH]; - uint16_t U[MAXWIDTH]; - uint16_t V[MAXWIDTH]; - float WorldX[MAXWIDTH]; - float WorldY[MAXWIDTH]; - float WorldZ[MAXWIDTH]; - uint8_t vColorA[MAXWIDTH]; - uint8_t vColorR[MAXWIDTH]; - uint8_t vColorG[MAXWIDTH]; - uint8_t vColorB[MAXWIDTH]; - float GradientdistZ[MAXWIDTH]; - uint32_t FragColor[MAXWIDTH]; - uint32_t lightarray[MAXWIDTH]; - uint8_t discard[MAXWIDTH]; - } scanline; - - static PolyTriangleThreadData *Get(DrawerThread *thread); - - int dest_pitch = 0; - int dest_width = 0; - int dest_height = 0; - bool dest_bgra = false; - uint8_t *dest = nullptr; - PolyDepthStencil *depthstencil = nullptr; - bool topdown = true; - - float depthbias = 0.0f; - - int viewport_y = 0; - - struct ClipRect - { - int left = 0; - int top = 0; - int right = 0; - int bottom = 0; - } clip, scissor; - - FRenderStyle RenderStyle; - int SpecialEffect = EFF_NONE; - int EffectState = 0; - bool AlphaTest = false; - bool ColormapShader = false; - uint32_t AlphaThreshold = 0x7f000000; - const PolyPushConstants* PushConstants = nullptr; - - // [GEC] Add frame params, necessary to project frames and model interpolation correctly - int frame0 = 0; - int frame1 = 0; - - const void *vertices = nullptr; - const unsigned int *elements = nullptr; - const FVector4 *lights = nullptr; - - enum { maxPolyLights = 16 }; - PolyLight polyLights[maxPolyLights]; - int numPolyLights = 0; - - PolyMainVertexShader mainVertexShader; - - struct TextureUnit - { - const void* pixels = nullptr; - int width = 0; - int height = 0; - bool bgra = true; - } textures[16]; - - bool DepthTest = false; - bool StencilTest = true; - bool WriteStencil = true; - bool WriteColor = true; - bool WriteDepth = true; - uint8_t StencilTestValue = 0; - uint8_t StencilWriteValue = 0; - float DepthRangeStart = 0.0f; - float DepthRangeScale = 1.0f; - bool DepthClamp = true; - - void (*FragmentShader)(int x0, int x1, PolyTriangleThreadData* thread) = nullptr; - void (*WriteColorFunc)(int y, int x0, int x1, PolyTriangleThreadData* thread) = nullptr; - -private: - ShadedTriVertex ShadeVertex(int index); - void DrawShadedPoint(const ShadedTriVertex *const* vertex); - void DrawShadedLine(const ShadedTriVertex *const* vertices); - void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw); - static bool IsDegenerate(const ShadedTriVertex *const* vertices); - static bool IsFrontfacing(TriDrawTriangleArgs *args); - - int ClipEdge(const ShadedTriVertex *const* verts); - - int viewport_x = 0; - int viewport_width = 0; - int viewport_height = 0; - bool ccw = true; - bool twosided = true; - PolyInputAssembly *inputAssembly = nullptr; - - enum { max_additional_vertices = 16 }; - float weightsbuffer[max_additional_vertices * 3 * 2]; - float *weights = nullptr; -}; diff --git a/src/common/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/common/rendering/polyrenderer/drawers/poly_triangle.cpp deleted file mode 100644 index 986ac946a..000000000 --- a/src/common/rendering/polyrenderer/drawers/poly_triangle.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" - -#include "filesystem.h" -#include "v_video.h" -#include "model.h" -#include "poly_triangle.h" -#include "poly_thread.h" -#include "screen_triangle.h" - -///////////////////////////////////////////////////////////////////////////// - -class PolyDrawerCommand : public DrawerCommand -{ -public: -}; - -class PolySetDepthClampCommand : public PolyDrawerCommand -{ -public: - PolySetDepthClampCommand(bool on) : on(on) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetDepthClamp(on); } - -private: - bool on; -}; - -class PolySetDepthMaskCommand : public PolyDrawerCommand -{ -public: - PolySetDepthMaskCommand(bool on) : on(on) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetDepthMask(on); } - -private: - bool on; -}; - -class PolySetDepthFuncCommand : public PolyDrawerCommand -{ -public: - PolySetDepthFuncCommand(int func) : func(func) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetDepthFunc(func); } - -private: - int func; -}; - -class PolySetDepthRangeCommand : public PolyDrawerCommand -{ -public: - PolySetDepthRangeCommand(float min, float max) : min(min), max(max) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetDepthRange(min, max); } - -private: - float min; - float max; -}; - -class PolySetDepthBiasCommand : public PolyDrawerCommand -{ -public: - PolySetDepthBiasCommand(float depthBiasConstantFactor, float depthBiasSlopeFactor) : depthBiasConstantFactor(depthBiasConstantFactor), depthBiasSlopeFactor(depthBiasSlopeFactor) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetDepthBias(depthBiasConstantFactor, depthBiasSlopeFactor); } - -private: - float depthBiasConstantFactor; - float depthBiasSlopeFactor; -}; - -class PolySetColorMaskCommand : public PolyDrawerCommand -{ -public: - PolySetColorMaskCommand(bool r, bool g, bool b, bool a) : r(r), g(g), b(b), a(a) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetColorMask(r, g, b, a); } - -private: - bool r; - bool g; - bool b; - bool a; -}; - -class PolySetStencilCommand : public PolyDrawerCommand -{ -public: - PolySetStencilCommand(int stencilRef, int op) : stencilRef(stencilRef), op(op) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetStencil(stencilRef, op); } - -private: - int stencilRef; - int op; -}; - -class PolySetCullingCommand : public PolyDrawerCommand -{ -public: - PolySetCullingCommand(int mode) : mode(mode) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetCulling(mode); } - -private: - int mode; -}; - -class PolyEnableStencilCommand : public PolyDrawerCommand -{ -public: - PolyEnableStencilCommand(bool on) : on(on) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->EnableStencil(on); } - -private: - bool on; -}; - -class PolySetScissorCommand : public PolyDrawerCommand -{ -public: - PolySetScissorCommand(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetScissor(x, y, w, h); } - -private: - int x; - int y; - int w; - int h; -}; - -class PolySetRenderStyleCommand : public PolyDrawerCommand -{ -public: - PolySetRenderStyleCommand(FRenderStyle style) : style(style) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetRenderStyle(style); } - -private: - FRenderStyle style; -}; - -class PolySetTextureCommand : public PolyDrawerCommand -{ -public: - PolySetTextureCommand(int unit, void* pixels, int width, int height, bool bgra) : unit(unit), pixels(pixels), width(width), height(height), bgra(bgra) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetTexture(unit, pixels, width, height, bgra); } - -private: - int unit; - void* pixels; - int width; - int height; - bool bgra; -}; - -class PolySetShaderCommand : public PolyDrawerCommand -{ -public: - PolySetShaderCommand(int specialEffect, int effectState, bool alphaTest, bool colormapShader) : specialEffect(specialEffect), effectState(effectState), alphaTest(alphaTest), colormapShader(colormapShader) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetShader(specialEffect, effectState, alphaTest, colormapShader); } - -private: - int specialEffect; - int effectState; - bool alphaTest; - bool colormapShader; -}; - -class PolySetVertexBufferCommand : public PolyDrawerCommand -{ -public: - PolySetVertexBufferCommand(const void* vertices, int offset0, int offset1) : vertices(vertices), offset0(offset0), offset1(offset1){ } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetVertexBuffer(vertices, offset0, offset1); } - -private: - const void* vertices; - // [GEC] Add offset params, necessary to project frames and model interpolation correctly - int offset0; - int offset1; -}; - -class PolySetIndexBufferCommand : public PolyDrawerCommand -{ -public: - PolySetIndexBufferCommand(const void* indices) : indices(indices) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetIndexBuffer(indices); } - -private: - const void* indices; -}; - -class PolySetLightBufferCommand : public PolyDrawerCommand -{ -public: - PolySetLightBufferCommand(const void* lights) : lights(lights) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetLightBuffer(lights); } - -private: - const void* lights; -}; - -class PolySetInputAssemblyCommand : public PolyDrawerCommand -{ -public: - PolySetInputAssemblyCommand(PolyInputAssembly* input) : input(input) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetInputAssembly(input); } - -private: - PolyInputAssembly* input; -}; - -class PolyClearDepthCommand : public PolyDrawerCommand -{ -public: - PolyClearDepthCommand(float value) : value(value) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->ClearDepth(value); } - -private: - float value; -}; - -class PolyClearStencilCommand : public PolyDrawerCommand -{ -public: - PolyClearStencilCommand(uint8_t value) : value(value) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->ClearStencil(value); } - -private: - uint8_t value; -}; - -class PolySetViewportCommand : public PolyDrawerCommand -{ -public: - PolySetViewportCommand(int x, int y, int width, int height, uint8_t* dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, PolyDepthStencil* depthstencil, bool topdown) - : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), depthstencil(depthstencil), topdown(topdown) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil, topdown); } - -private: - int x; - int y; - int width; - int height; - uint8_t* dest; - int dest_width; - int dest_height; - int dest_pitch; - bool dest_bgra; - PolyDepthStencil* depthstencil; - bool topdown; -}; - -class PolySetViewpointUniformsCommand : public PolyDrawerCommand -{ -public: - PolySetViewpointUniformsCommand(const HWViewpointUniforms* uniforms) : uniforms(uniforms) {} - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->SetViewpointUniforms(uniforms); } - -private: - const HWViewpointUniforms* uniforms; -}; - -class PolyPushMatricesCommand : public PolyDrawerCommand -{ -public: - PolyPushMatricesCommand(const VSMatrix& modelMatrix, const VSMatrix& normalModelMatrix, const VSMatrix& textureMatrix) - : modelMatrix(modelMatrix), normalModelMatrix(normalModelMatrix), textureMatrix(textureMatrix) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->PushMatrices(modelMatrix, normalModelMatrix, textureMatrix); } - -private: - VSMatrix modelMatrix; - VSMatrix normalModelMatrix; - VSMatrix textureMatrix; -}; - -class PolyPushStreamDataCommand : public PolyDrawerCommand -{ -public: - PolyPushStreamDataCommand(const StreamData& data, const PolyPushConstants& constants) : data(data), constants(constants) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->PushStreamData(data, constants); } - -private: - StreamData data; - PolyPushConstants constants; -}; - -class PolyDrawCommand : public PolyDrawerCommand -{ -public: - PolyDrawCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->Draw(index, count, mode); } - -private: - int index; - int count; - PolyDrawMode mode; -}; - -class PolyDrawIndexedCommand : public PolyDrawerCommand -{ -public: - PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->DrawIndexed(index, count, mode); } - -private: - int index; - int count; - PolyDrawMode mode; -}; - -///////////////////////////////////////////////////////////////////////////// - -PolyCommandBuffer::PolyCommandBuffer(RenderMemory* frameMemory) -{ - mQueue = std::make_shared(frameMemory); -} - -void PolyCommandBuffer::SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthstencil, bool topdown) -{ - uint8_t *dest = (uint8_t*)canvas->GetPixels(); - int dest_width = canvas->GetWidth(); - int dest_height = canvas->GetHeight(); - int dest_pitch = canvas->GetPitch(); - bool dest_bgra = canvas->IsBgra(); - - mQueue->Push(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, depthstencil, topdown); -} - -void PolyCommandBuffer::SetInputAssembly(PolyInputAssembly *input) -{ - mQueue->Push(input); -} - -void PolyCommandBuffer::SetVertexBuffer(const void *vertices, int offset0, int offset1) -{ - mQueue->Push(vertices, offset0, offset1); -} - -void PolyCommandBuffer::SetIndexBuffer(const void *elements) -{ - mQueue->Push(elements); -} - -void PolyCommandBuffer::SetLightBuffer(const void *lights) -{ - mQueue->Push(lights); -} - -void PolyCommandBuffer::SetDepthClamp(bool on) -{ - mQueue->Push(on); -} - -void PolyCommandBuffer::SetDepthMask(bool on) -{ - mQueue->Push(on); -} - -void PolyCommandBuffer::SetDepthFunc(int func) -{ - mQueue->Push(func); -} - -void PolyCommandBuffer::SetDepthRange(float min, float max) -{ - mQueue->Push(min, max); -} - -void PolyCommandBuffer::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor) -{ - mQueue->Push(depthBiasConstantFactor, depthBiasSlopeFactor); -} - -void PolyCommandBuffer::SetColorMask(bool r, bool g, bool b, bool a) -{ - mQueue->Push(r, g, b, a); -} - -void PolyCommandBuffer::SetStencil(int stencilRef, int op) -{ - mQueue->Push(stencilRef, op); -} - -void PolyCommandBuffer::SetCulling(int mode) -{ - mQueue->Push(mode); -} - -void PolyCommandBuffer::EnableStencil(bool on) -{ - mQueue->Push(on); -} - -void PolyCommandBuffer::SetScissor(int x, int y, int w, int h) -{ - mQueue->Push(x, y, w, h); -} - -void PolyCommandBuffer::SetRenderStyle(FRenderStyle style) -{ - mQueue->Push(style); -} - -void PolyCommandBuffer::SetTexture(int unit, void *pixels, int width, int height, bool bgra) -{ - mQueue->Push(unit, pixels, width, height, bgra); -} - -void PolyCommandBuffer::SetShader(int specialEffect, int effectState, bool alphaTest, bool colormapShader) -{ - mQueue->Push(specialEffect, effectState, alphaTest, colormapShader); -} - -void PolyCommandBuffer::PushStreamData(const StreamData &data, const PolyPushConstants &constants) -{ - mQueue->Push(data, constants); -} - -void PolyCommandBuffer::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) -{ - mQueue->Push(modelMatrix, normalModelMatrix, textureMatrix); -} - -void PolyCommandBuffer::SetViewpointUniforms(const HWViewpointUniforms *uniforms) -{ - mQueue->Push(uniforms); -} - -void PolyCommandBuffer::ClearDepth(float value) -{ - mQueue->Push(value); -} - -void PolyCommandBuffer::ClearStencil(uint8_t value) -{ - mQueue->Push(value); -} - -void PolyCommandBuffer::Draw(int index, int vcount, PolyDrawMode mode) -{ - mQueue->Push(index, vcount, mode); -} - -void PolyCommandBuffer::DrawIndexed(int index, int count, PolyDrawMode mode) -{ - mQueue->Push(index, count, mode); -} - -void PolyCommandBuffer::Submit() -{ - DrawerThreads::Execute(mQueue); -} diff --git a/src/common/rendering/polyrenderer/drawers/poly_triangle.h b/src/common/rendering/polyrenderer/drawers/poly_triangle.h deleted file mode 100644 index d29b10ba3..000000000 --- a/src/common/rendering/polyrenderer/drawers/poly_triangle.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 "swrenderer/drawers/r_draw.h" -#include "r_thread.h" -#include "polyrenderer/drawers/screen_triangle.h" -#include "polyrenderer/drawers/poly_vertex_shader.h" - -class DCanvas; -class RenderMemory; -class PolyDrawerCommand; -class PolyInputAssembly; -class PolyDepthStencil; -struct PolyPushConstants; - -enum class PolyDrawMode -{ - Points, - Lines, - Triangles, - TriangleFan, - TriangleStrip -}; - -class PolyCommandBuffer -{ -public: - PolyCommandBuffer(RenderMemory* frameMemory); - - void SetViewport(int x, int y, int width, int height, DCanvas *canvas, PolyDepthStencil *depthStencil, bool topdown); - void SetInputAssembly(PolyInputAssembly *input); - void SetVertexBuffer(const void *vertices, int offset0, int offset1); // [GEC] Add offset params - void SetIndexBuffer(const void *elements); - void SetLightBuffer(const void *lights); - void SetViewpointUniforms(const HWViewpointUniforms *uniforms); - void SetDepthClamp(bool on); - void SetDepthMask(bool on); - void SetDepthFunc(int func); - void SetDepthRange(float min, float max); - void SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor); - void SetColorMask(bool r, bool g, bool b, bool a); - void SetStencil(int stencilRef, int op); - void SetCulling(int mode); - void EnableStencil(bool on); - void SetScissor(int x, int y, int w, int h); - void SetRenderStyle(FRenderStyle style); - void SetTexture(int unit, void *pixels, int width, int height, bool bgra); - void SetShader(int specialEffect, int effectState, bool alphaTest, bool colormapShader); - void PushStreamData(const StreamData &data, const PolyPushConstants &constants); - void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); - void ClearDepth(float value); - void ClearStencil(uint8_t value); - void Draw(int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - void DrawIndexed(int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); - void Submit(); - -private: - std::shared_ptr mQueue; -}; - -class PolyDepthStencil -{ -public: - PolyDepthStencil(int width, int height) : width(width), height(height), depthbuffer(width * height), stencilbuffer(width * height) { } - - int Width() const { return width; } - int Height() const { return height; } - float *DepthValues() { return depthbuffer.data(); } - uint8_t *StencilValues() { return stencilbuffer.data(); } - -private: - int width; - int height; - std::vector depthbuffer; - std::vector stencilbuffer; -}; - -struct PolyPushConstants -{ - int uTextureMode; - float uAlphaThreshold; - FVector2 uClipSplit; - - // Lighting + Fog - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; - int uFogEnabled; - - // dynamic lights - int uLightIndex; - FVector4 uDynLightColor; // [GEC] -}; - -class PolyInputAssembly -{ -public: - virtual void Load(PolyTriangleThreadData *thread, const void *vertices, int frame0, int frame1, int index) = 0; // [GEC] Add frame params -}; diff --git a/src/common/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/common/rendering/polyrenderer/drawers/poly_vertex_shader.h deleted file mode 100644 index aaf613d98..000000000 --- a/src/common/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ /dev/null @@ -1,194 +0,0 @@ - -#pragma once - -#include "hw_viewpointuniforms.h" -#include "hw_renderstate.h" - -#ifndef NO_SSE -#include -#endif - -class ShadedTriVertex -{ -public: - FVector4 gl_Position; - float gl_ClipDistance[5]; - FVector4 vTexCoord; - FVector4 vColor; - FVector4 pixelpos; - //FVector3 glowdist; - FVector3 gradientdist; - //FVector4 vEyeNormal; - FVector4 vWorldNormal; -}; - -class PolyMainVertexShader : public ShadedTriVertex -{ -public: - // Input - FVector4 aPosition; - FVector2 aTexCoord; - FVector4 aColor; - FVector4 aVertex2; - FVector4 aNormal; - FVector4 aNormal2; - - // Defines - bool SIMPLE = false; - bool SPHEREMAP = false; - - // Uniforms - VSMatrix ModelMatrix; - VSMatrix NormalModelMatrix; - VSMatrix TextureMatrix; - StreamData Data; - FVector2 uClipSplit; - const HWViewpointUniforms *Viewpoint = nullptr; - - void main() - { - FVector2 parmTexCoord = aTexCoord; - FVector4 parmPosition = aPosition; - - FVector4 worldcoord; - if (SIMPLE) - worldcoord = mul(ModelMatrix, mix(parmPosition, aVertex2, Data.uInterpolationFactor)); - else - worldcoord = mul(ModelMatrix, parmPosition); - - FVector4 eyeCoordPos = mul(Viewpoint->mViewMatrix, worldcoord); - - vColor = aColor; - - if (!SIMPLE) - { - pixelpos.X = worldcoord.X; - pixelpos.Y = worldcoord.Y; - pixelpos.Z = worldcoord.Z; - pixelpos.W = -eyeCoordPos.Z / eyeCoordPos.W; - - /*if (Data.uGlowTopColor.W > 0 || Data.uGlowBottomColor.W > 0) - { - float topatpoint = (Data.uGlowTopPlane.W + Data.uGlowTopPlane.X * worldcoord.X + Data.uGlowTopPlane.Y * worldcoord.Z) * Data.uGlowTopPlane.Z; - float bottomatpoint = (Data.uGlowBottomPlane.W + Data.uGlowBottomPlane.X * worldcoord.X + Data.uGlowBottomPlane.Y * worldcoord.Z) * Data.uGlowBottomPlane.Z; - glowdist.X = topatpoint - worldcoord.Y; - glowdist.Y = worldcoord.Y - bottomatpoint; - glowdist.Z = clamp(glowdist.X / (topatpoint - bottomatpoint), 0.0f, 1.0f); - }*/ - - if (Data.uObjectColor2.a != 0) - { - float topatpoint = (Data.uGradientTopPlane.W + Data.uGradientTopPlane.X * worldcoord.X + Data.uGradientTopPlane.Y * worldcoord.Z) * Data.uGradientTopPlane.Z; - float bottomatpoint = (Data.uGradientBottomPlane.W + Data.uGradientBottomPlane.X * worldcoord.X + Data.uGradientBottomPlane.Y * worldcoord.Z) * Data.uGradientBottomPlane.Z; - gradientdist.X = topatpoint - worldcoord.Y; - gradientdist.Y = worldcoord.Y - bottomatpoint; - gradientdist.Z = clamp(gradientdist.X / (topatpoint - bottomatpoint), 0.0f, 1.0f); - } - - if (Data.uSplitBottomPlane.Z != 0.0f) - { - gl_ClipDistance[3] = ((Data.uSplitTopPlane.W + Data.uSplitTopPlane.X * worldcoord.X + Data.uSplitTopPlane.Y * worldcoord.Z) * Data.uSplitTopPlane.Z) - worldcoord.Y; - gl_ClipDistance[4] = worldcoord.Y - ((Data.uSplitBottomPlane.W + Data.uSplitBottomPlane.X * worldcoord.X + Data.uSplitBottomPlane.Y * worldcoord.Z) * Data.uSplitBottomPlane.Z); - } - - vWorldNormal = mul(NormalModelMatrix, FVector4(normalize(mix3(aNormal, aNormal2, Data.uInterpolationFactor)), 1.0f)); - //vEyeNormal = mul(Viewpoint->mNormalViewMatrix, vWorldNormal); - } - - if (!SPHEREMAP) - { - vTexCoord = mul(TextureMatrix, FVector4(parmTexCoord.X, parmTexCoord.Y, 0.0f, 1.0f)); - } - else - { - FVector3 u = normalize3(eyeCoordPos); - FVector3 n = normalize3(mul(Viewpoint->mNormalViewMatrix, FVector4(parmTexCoord.X, 0.0f, parmTexCoord.Y, 0.0f))); - FVector3 r = reflect(u, n); - float m = 2.0f * sqrtf(r.X*r.X + r.Y*r.Y + (r.Z + 1.0f)*(r.Z + 1.0f)); - vTexCoord.X = r.X / m + 0.5f; - vTexCoord.Y = r.Y / m + 0.5f; - } - - gl_Position = mul(Viewpoint->mProjectionMatrix, eyeCoordPos); - - if (Viewpoint->mClipHeightDirection != 0.0f) // clip planes used for reflective flats - { - gl_ClipDistance[0] = (worldcoord.Y - Viewpoint->mClipHeight) * Viewpoint->mClipHeightDirection; - } - else if (Viewpoint->mClipLine.X > -1000000.0f) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. - { - gl_ClipDistance[0] = -((worldcoord.Z - Viewpoint->mClipLine.Y) * Viewpoint->mClipLine.Z + (Viewpoint->mClipLine.X - worldcoord.X) * Viewpoint->mClipLine.W) + 1.0f / 32768.0f; // allow a tiny bit of imprecisions for colinear linedefs. - } - else - { - gl_ClipDistance[0] = 1.0f; - } - - // clip planes used for translucency splitting - gl_ClipDistance[1] = worldcoord.Y - uClipSplit.X; - gl_ClipDistance[2] = uClipSplit.Y - worldcoord.Y; - - if (Data.uSplitTopPlane == FVector4(0.0f, 0.0f, 0.0f, 0.0f)) - { - gl_ClipDistance[3] = 1.0f; - gl_ClipDistance[4] = 1.0f; - } - } - -private: - static FVector3 normalize(const FVector3 &a) - { - float rcplen = 1.0f / sqrtf(a.X * a.X + a.Y * a.Y + a.Z * a.Z); - return FVector3(a.X * rcplen, a.Y * rcplen, a.Z * rcplen); - } - - static FVector3 normalize3(const FVector4 &a) - { - float rcplen = 1.0f / sqrtf(a.X * a.X + a.Y * a.Y + a.Z * a.Z); - return FVector3(a.X * rcplen, a.Y * rcplen, a.Z * rcplen); - } - - static FVector4 mix(const FVector4 &a, const FVector4 &b, float t) - { - float invt = 1.0f - t; - return FVector4(a.X * invt + b.X * t, a.Y * invt + b.Y * t, a.Z * invt + b.Z * t, a.W * invt + b.W * t); - } - - static FVector3 mix3(const FVector4 &a, const FVector4 &b, float t) - { - float invt = 1.0f - t; - return FVector3(a.X * invt + b.X * t, a.Y * invt + b.Y * t, a.Z * invt + b.Z * t); - } - - static FVector3 reflect(const FVector3 &u, const FVector3 &n) - { - float d = 2.0f * (n.X * u.X + n.Y * u.Y + n.Z * u.Z); - return FVector3(u.X - d * n.X, u.Y - d * n.Y, u.Z - d * n.Z); - } - - static FVector4 mul(const VSMatrix &mat, const FVector4 &v) - { - const float *m = mat.get(); - - FVector4 result; -#ifdef NO_SSE - result.X = m[0 * 4 + 0] * v.X + m[1 * 4 + 0] * v.Y + m[2 * 4 + 0] * v.Z + m[3 * 4 + 0] * v.W; - result.Y = m[0 * 4 + 1] * v.X + m[1 * 4 + 1] * v.Y + m[2 * 4 + 1] * v.Z + m[3 * 4 + 1] * v.W; - result.Z = m[0 * 4 + 2] * v.X + m[1 * 4 + 2] * v.Y + m[2 * 4 + 2] * v.Z + m[3 * 4 + 2] * v.W; - result.W = m[0 * 4 + 3] * v.X + m[1 * 4 + 3] * v.Y + m[2 * 4 + 3] * v.Z + m[3 * 4 + 3] * v.W; -#else - __m128 m0 = _mm_loadu_ps(m); - __m128 m1 = _mm_loadu_ps(m + 4); - __m128 m2 = _mm_loadu_ps(m + 8); - __m128 m3 = _mm_loadu_ps(m + 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); - _mm_storeu_ps(&result.X, mv); -#endif - return result; - } -}; diff --git a/src/common/rendering/polyrenderer/drawers/screen_blend.cpp b/src/common/rendering/polyrenderer/drawers/screen_blend.cpp deleted file mode 100644 index afe540289..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_blend.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 "screen_blend.h" - -#ifndef NO_SSE -#include -#endif - -static const int shiftTable[] = { - 0, 0, 0, 0, // STYLEALPHA_Zero - 0, 0, 0, 0, // STYLEALPHA_One - 24, 24, 24, 24, // STYLEALPHA_Src - 24, 24, 24, 24, // STYLEALPHA_InvSrc - 24, 16, 8, 0, // STYLEALPHA_SrcCol - 24, 16, 8, 0, // STYLEALPHA_InvSrcCol - 24, 16, 8, 0, // STYLEALPHA_DstCol - 24, 16, 8, 0 // STYLEALPHA_InvDstCol -}; - -#if 1 //#ifndef USE_AVX2 -template -void BlendColor(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - FRenderStyle style = thread->RenderStyle; - - bool invsrc = style.SrcAlpha & 1; - bool invdst = style.DestAlpha & 1; - - const int* shiftsrc = shiftTable + (style.SrcAlpha << 2); - const int* shiftdst = shiftTable + (style.DestAlpha << 2); - - uint32_t* dest = (uint32_t*)thread->dest; - uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int srcSelect = style.SrcAlpha <= STYLEALPHA_One ? 0 : (style.SrcAlpha >= STYLEALPHA_DstCol ? 1 : 2); - int dstSelect = style.DestAlpha <= STYLEALPHA_One ? 0 : (style.DestAlpha >= STYLEALPHA_DstCol ? 1 : 2); - - uint32_t inputs[3]; - inputs[0] = 0; - - for (int x = x0; x < x1; x++) - { - inputs[1] = line[x]; - inputs[2] = fragcolor[x]; - - uint32_t srcinput = inputs[srcSelect]; - uint32_t dstinput = inputs[dstSelect]; - - uint32_t out[4]; - for (int i = 0; i < 4; i++) - { - // Grab component for scale factors - int32_t src = (srcinput >> shiftsrc[i]) & 0xff; - int32_t dst = (dstinput >> shiftdst[i]) & 0xff; - - // Inverse if needed - if (invsrc) src = 0xff - src; - if (invdst) dst = 0xff - dst; - - // Rescale 0-255 to 0-256 - src = src + (src >> 7); - dst = dst + (dst >> 7); - - // Multiply with input - src = src * ((inputs[2] >> (24 - (i << 3))) & 0xff); - dst = dst * ((inputs[1] >> (24 - (i << 3))) & 0xff); - - // Apply blend operator - int32_t val; - if (OptT::Flags & SWBLEND_Sub) - { - val = src - dst; - } - else if (OptT::Flags & SWBLEND_RevSub) - { - val = dst - src; - } - else - { - val = src + dst; - } - out[i] = clamp((val + 127) >> 8, 0, 255); - } - - line[x] = MAKEARGB(out[0], out[1], out[2], out[3]); - } -} -#else -template -void BlendColor(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - FRenderStyle style = thread->RenderStyle; - - bool invsrc = style.SrcAlpha & 1; - bool invdst = style.DestAlpha & 1; - - __m128i shiftsrc = _mm_loadu_si128((const __m128i*)(shiftTable + (style.SrcAlpha << 2))); - __m128i shiftdst = _mm_loadu_si128((const __m128i*)(shiftTable + (style.DestAlpha << 2))); - - uint32_t* dest = (uint32_t*)thread->dest; - uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int srcSelect = style.SrcAlpha <= STYLEALPHA_One ? 0 : (style.SrcAlpha >= STYLEALPHA_DstCol ? 1 : 2); - int dstSelect = style.DestAlpha <= STYLEALPHA_One ? 0 : (style.DestAlpha >= STYLEALPHA_DstCol ? 1 : 2); - - uint32_t inputs[3]; - inputs[0] = 0; - - __m128i shiftmul = _mm_set_epi32(24, 16, 8, 0); - - for (int x = x0; x < x1; x++) - { - inputs[1] = line[x]; - inputs[2] = fragcolor[x]; - - __m128i srcinput = _mm_set1_epi32(inputs[srcSelect]); - __m128i dstinput = _mm_set1_epi32(inputs[dstSelect]); - - // Grab component for scale factors - __m128i src = _mm_and_si128(_mm_srlv_epi32(srcinput, shiftsrc), _mm_set1_epi32(0xff)); - __m128i dst = _mm_and_si128(_mm_srlv_epi32(dstinput, shiftdst), _mm_set1_epi32(0xff)); - - // Inverse if needed - if (invsrc) src = _mm_sub_epi32(_mm_set1_epi32(0xff), src); - if (invdst) dst = _mm_sub_epi32(_mm_set1_epi32(0xff), dst); - - // Rescale 0-255 to 0-256 - src = _mm_add_epi32(src, _mm_srli_epi32(src, 7)); - dst = _mm_add_epi32(dst, _mm_srli_epi32(dst, 7)); - - // Multiply with input - __m128i mulsrc = _mm_and_si128(_mm_srlv_epi32(_mm_set1_epi32(inputs[2]), shiftmul), _mm_set1_epi32(0xff)); - __m128i muldst = _mm_and_si128(_mm_srlv_epi32(_mm_set1_epi32(inputs[1]), shiftmul), _mm_set1_epi32(0xff)); - __m128i mulresult = _mm_mullo_epi16(_mm_packs_epi32(src, dst), _mm_packs_epi32(mulsrc, muldst)); - src = _mm_unpacklo_epi16(mulresult, _mm_setzero_si128()); - dst = _mm_unpackhi_epi16(mulresult, _mm_setzero_si128()); - - // Apply blend operator - __m128i val; - if (OptT::Flags & SWBLEND_Sub) - { - val = _mm_sub_epi32(src, dst); - } - else if (OptT::Flags & SWBLEND_RevSub) - { - val = _mm_sub_epi32(dst, src); - } - else - { - val = _mm_add_epi32(src, dst); - } - - __m128i out = _mm_srli_epi32(_mm_add_epi32(val, _mm_set1_epi32(127)), 8); - out = _mm_packs_epi32(out, out); - out = _mm_packus_epi16(out, out); - line[x] = _mm_cvtsi128_si32(out); - } -} -#endif - -#ifdef NO_SSE -void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* dest = (uint32_t*)thread->dest; - uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - memcpy(line + x0, fragcolor + x0, (x1 - x0) * sizeof(uint32_t)); -} -#else -void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* dest = (uint32_t*)thread->dest; - uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int ssecount = ((x1 - x0) & ~3); - int sseend = x0 + ssecount; - - for (int x = x0; x < sseend; x += 4) - { - __m128i v = _mm_loadu_si128((__m128i*) & fragcolor[x]); - _mm_storeu_si128((__m128i*) & line[x], v); - } - - for (int x = sseend; x < x1; x++) - { - line[x] = fragcolor[x]; - } -} -#endif - -void BlendColorAdd_Src_InvSrc(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)&line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)&fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = _mm_shufflehi_epi16(_mm_shufflelo_epi16(src, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - __m128i dstscale = _mm_sub_epi16(_mm_set1_epi16(256), srcscale); - - __m128i out = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_mullo_epi16(dst, dstscale)), _mm_set1_epi16(127)), 8); - _mm_storel_epi64((__m128i*)&line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale = APART(src); - srcscale += srcscale >> 7; - uint32_t dstscale = 256 - srcscale; - - uint32_t a = ((APART(src) * srcscale + APART(dst) * dstscale) + 127) >> 8; - uint32_t r = ((RPART(src) * srcscale + RPART(dst) * dstscale) + 127) >> 8; - uint32_t g = ((GPART(src) * srcscale + GPART(dst) * dstscale) + 127) >> 8; - uint32_t b = ((BPART(src) * srcscale + BPART(dst) * dstscale) + 127) >> 8; - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorAdd_SrcCol_InvSrcCol(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = src; - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - __m128i dstscale = _mm_sub_epi16(_mm_set1_epi16(256), srcscale); - - __m128i out = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_mullo_epi16(dst, dstscale)), _mm_set1_epi16(127)), 8); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale_a = APART(src); - uint32_t srcscale_r = RPART(src); - uint32_t srcscale_g = GPART(src); - uint32_t srcscale_b = BPART(src); - srcscale_a += srcscale_a >> 7; - srcscale_r += srcscale_r >> 7; - srcscale_g += srcscale_g >> 7; - srcscale_b += srcscale_b >> 7; - uint32_t dstscale_a = 256 - srcscale_a; - uint32_t dstscale_r = 256 - srcscale_r; - uint32_t dstscale_g = 256 - srcscale_g; - uint32_t dstscale_b = 256 - srcscale_b; - - uint32_t a = ((APART(src) * srcscale_a + APART(dst) * dstscale_a) + 127) >> 8; - uint32_t r = ((RPART(src) * srcscale_r + RPART(dst) * dstscale_r) + 127) >> 8; - uint32_t g = ((GPART(src) * srcscale_g + GPART(dst) * dstscale_g) + 127) >> 8; - uint32_t b = ((BPART(src) * srcscale_b + BPART(dst) * dstscale_b) + 127) >> 8; - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorAdd_Src_One(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = _mm_shufflehi_epi16(_mm_shufflelo_epi16(src, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - - __m128i out = _mm_add_epi16(_mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_set1_epi16(127)), 8), dst); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale = APART(src); - srcscale += srcscale >> 7; - - uint32_t a = MIN((((APART(src) * srcscale) + 127) >> 8) + APART(dst), 255); - uint32_t r = MIN((((RPART(src) * srcscale) + 127) >> 8) + RPART(dst), 255); - uint32_t g = MIN((((GPART(src) * srcscale) + 127) >> 8) + GPART(dst), 255); - uint32_t b = MIN((((BPART(src) * srcscale) + 127) >> 8) + BPART(dst), 255); - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorAdd_SrcCol_One(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = src; - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - - __m128i out = _mm_add_epi16(_mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_set1_epi16(127)), 8), dst); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale_a = APART(src); - uint32_t srcscale_r = RPART(src); - uint32_t srcscale_g = GPART(src); - uint32_t srcscale_b = BPART(src); - srcscale_a += srcscale_a >> 7; - srcscale_r += srcscale_r >> 7; - srcscale_g += srcscale_g >> 7; - srcscale_b += srcscale_b >> 7; - - uint32_t a = MIN((((APART(src) * srcscale_a) + 127) >> 8) + APART(dst), 255); - uint32_t r = MIN((((RPART(src) * srcscale_r) + 127) >> 8) + RPART(dst), 255); - uint32_t g = MIN((((GPART(src) * srcscale_g) + 127) >> 8) + GPART(dst), 255); - uint32_t b = MIN((((BPART(src) * srcscale_b) + 127) >> 8) + BPART(dst), 255); - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorAdd_DstCol_Zero(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = dst; - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - - __m128i out = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_set1_epi16(127)), 8); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale_a = APART(dst); - uint32_t srcscale_r = RPART(dst); - uint32_t srcscale_g = GPART(dst); - uint32_t srcscale_b = BPART(dst); - srcscale_a += srcscale_a >> 7; - srcscale_r += srcscale_r >> 7; - srcscale_g += srcscale_g >> 7; - srcscale_b += srcscale_b >> 7; - - uint32_t a = (((APART(src) * srcscale_a) + 127) >> 8); - uint32_t r = (((RPART(src) * srcscale_r) + 127) >> 8); - uint32_t g = (((GPART(src) * srcscale_g) + 127) >> 8); - uint32_t b = (((BPART(src) * srcscale_b) + 127) >> 8); - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorAdd_InvDstCol_Zero(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = _mm_sub_epi16(_mm_set1_epi16(255), dst); - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - - __m128i out = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_set1_epi16(127)), 8); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale_a = 255 - APART(dst); - uint32_t srcscale_r = 255 - RPART(dst); - uint32_t srcscale_g = 255 - GPART(dst); - uint32_t srcscale_b = 255 - BPART(dst); - srcscale_a += srcscale_a >> 7; - srcscale_r += srcscale_r >> 7; - srcscale_g += srcscale_g >> 7; - srcscale_b += srcscale_b >> 7; - - uint32_t a = (((APART(src) * srcscale_a) + 127) >> 8); - uint32_t r = (((RPART(src) * srcscale_r) + 127) >> 8); - uint32_t g = (((GPART(src) * srcscale_g) + 127) >> 8); - uint32_t b = (((BPART(src) * srcscale_b) + 127) >> 8); - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorRevSub_Src_One(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - uint32_t* fragcolor = thread->scanline.FragColor; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~1); - sseend = x0 + ssecount; - for (int x = x0; x < sseend; x += 2) - { - __m128i dst = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & line[x]), _mm_setzero_si128()); - __m128i src = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*) & fragcolor[x]), _mm_setzero_si128()); - - __m128i srcscale = _mm_shufflehi_epi16(_mm_shufflelo_epi16(src, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); - srcscale = _mm_add_epi16(srcscale, _mm_srli_epi16(srcscale, 7)); - - __m128i out = _mm_sub_epi16(dst, _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(src, srcscale), _mm_set1_epi16(127)), 8)); - _mm_storel_epi64((__m128i*) & line[x], _mm_packus_epi16(out, out)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - uint32_t src = fragcolor[x]; - - uint32_t srcscale = APART(src); - srcscale += srcscale >> 7; - - uint32_t a = MAX(APART(dst) - (((APART(src) * srcscale) + 127) >> 8), 0); - uint32_t r = MAX(RPART(dst) - (((RPART(src) * srcscale) + 127) >> 8), 0); - uint32_t g = MAX(GPART(dst) - (((GPART(src) * srcscale) + 127) >> 8), 0); - uint32_t b = MAX(BPART(dst) - (((BPART(src) * srcscale) + 127) >> 8), 0); - - line[x] = MAKEARGB(a, r, g, b); - } -} - -void BlendColorColormap(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* line = (uint32_t*)thread->dest + y * (ptrdiff_t)thread->dest_pitch; - - // [GEC] I leave the default floating values. - float startR = thread->mainVertexShader.Data.uObjectColor.r; - float startG = thread->mainVertexShader.Data.uObjectColor.g; - float startB = thread->mainVertexShader.Data.uObjectColor.b; - float rangeR = thread->mainVertexShader.Data.uAddColor.r - startR; - float rangeG = thread->mainVertexShader.Data.uAddColor.g - startG; - float rangeB = thread->mainVertexShader.Data.uAddColor.b - startB; - - int sseend = x0; - for (int x = sseend; x < x1; x++) - { - uint32_t dst = line[x]; - - uint32_t a = APART(dst); - uint32_t r = RPART(dst); - uint32_t g = GPART(dst); - uint32_t b = BPART(dst); - - uint32_t gray = (r * 77 + g * 143 + b * 37) >> 8; - gray += (gray >> 7); // gray*=256/255 - - // [GEC] I use the same method as in shaders using floating values. - // This avoids errors in the invulneravility colormap in Doom and Heretic. - float fgray = (float)(gray / 255.f); - float fr = (startR + (fgray * rangeR)) * 2; - float fg = (startG + (fgray * rangeG)) * 2; - float fb = (startB + (fgray * rangeB)) * 2; - - fr = clamp(fr, 0.0f, 1.0f); - fg = clamp(fg, 0.0f, 1.0f); - fb = clamp(fb, 0.0f, 1.0f); - - r = (uint32_t)(fr * 255.f); - g = (uint32_t)(fg * 255.f); - b = (uint32_t)(fb * 255.f); - - line[x] = MAKEARGB(a, (uint8_t)r, (uint8_t)g, (uint8_t)b); - } -} - -void SelectWriteColorFunc(PolyTriangleThreadData* thread) -{ - FRenderStyle style = thread->RenderStyle; - if (thread->ColormapShader) - { - thread->WriteColorFunc = &BlendColorColormap; - } - else if (style.BlendOp == STYLEOP_Add) - { - if (style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero) - { - thread->WriteColorFunc = &BlendColorOpaque; - } - else if (style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_InvSrc) - { - thread->WriteColorFunc = &BlendColorAdd_Src_InvSrc; - } - else if (style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_InvSrcCol) - { - thread->WriteColorFunc = &BlendColorAdd_SrcCol_InvSrcCol; - } - else if (style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_One) - { - thread->WriteColorFunc = &BlendColorAdd_Src_One; - } - else if (style.SrcAlpha == STYLEALPHA_SrcCol && style.DestAlpha == STYLEALPHA_One) - { - thread->WriteColorFunc = &BlendColorAdd_SrcCol_One; - } - else if (style.SrcAlpha == STYLEALPHA_DstCol && style.DestAlpha == STYLEALPHA_Zero) - { - thread->WriteColorFunc = &BlendColorAdd_DstCol_Zero; - } - else if (style.SrcAlpha == STYLEALPHA_InvDstCol && style.DestAlpha == STYLEALPHA_Zero) - { - thread->WriteColorFunc = &BlendColorAdd_InvDstCol_Zero; - } - else - { - thread->WriteColorFunc = &BlendColor; - } - } - else if (style.BlendOp == STYLEOP_Sub) - { - thread->WriteColorFunc = &BlendColor; - } - else // if (style.BlendOp == STYLEOP_RevSub) - { - if (style.SrcAlpha == STYLEALPHA_Src && style.DestAlpha == STYLEALPHA_One) - { - thread->WriteColorFunc = &BlendColorRevSub_Src_One; - } - else - { - thread->WriteColorFunc = &BlendColor; - } - } -} diff --git a/src/common/rendering/polyrenderer/drawers/screen_blend.h b/src/common/rendering/polyrenderer/drawers/screen_blend.h deleted file mode 100644 index 101c151b0..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_blend.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 - -class PolyTriangleThreadData; - -enum SWBlendColor -{ - SWBLEND_Sub = 1, - SWBLEND_RevSub = 2 -}; - -struct BlendColorOpt_Add { static const int Flags = 0; }; -struct BlendColorOpt_Sub { static const int Flags = 1; }; -struct BlendColorOpt_RevSub { static const int Flags = 2; }; - -template -void BlendColor(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_Src_InvSrc(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_SrcCol_InvSrcCol(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_Src_One(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_SrcCol_One(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_DstCol_Zero(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorAdd_InvDstCol_Zero(int y, int x0, int x1, PolyTriangleThreadData* thread); -void BlendColorRevSub_Src_One(int y, int x0, int x1, PolyTriangleThreadData* thread); - -void SelectWriteColorFunc(PolyTriangleThreadData* thread); diff --git a/src/common/rendering/polyrenderer/drawers/screen_scanline_setup.cpp b/src/common/rendering/polyrenderer/drawers/screen_scanline_setup.cpp deleted file mode 100644 index 5aa4855d6..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_scanline_setup.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" -#include "poly_thread.h" -#include "screen_scanline_setup.h" -#include - -#ifndef NO_SSE -#include -#endif - -#ifdef NO_SSE -void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - float startX = x0 + (0.5f - args->v1->x); - float startY = y + (0.5f - args->v1->y); - - float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; - float stepW = args->gradientX.W; - float* w = thread->scanline.W; - for (int x = x0; x < x1; x++) - { - w[x] = 1.0f / posW; - posW += stepW; - } -} -#else -void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - float startX = x0 + (0.5f - args->v1->x); - float startY = y + (0.5f - args->v1->y); - - float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; - float stepW = args->gradientX.W; - float* w = thread->scanline.W; - - int ssecount = ((x1 - x0) & ~3); - int sseend = x0 + ssecount; - - __m128 mstepW = _mm_set1_ps(stepW * 4.0f); - __m128 mposW = _mm_setr_ps(posW, posW + stepW, posW + stepW + stepW, posW + stepW + stepW + stepW); - - for (int x = x0; x < sseend; x += 4) - { - // One Newton-Raphson iteration for 1/posW - __m128 res = _mm_rcp_ps(mposW); - __m128 muls = _mm_mul_ps(mposW, _mm_mul_ps(res, res)); - _mm_storeu_ps(w + x, _mm_sub_ps(_mm_add_ps(res, res), muls)); - mposW = _mm_add_ps(mposW, mstepW); - } - - mstepW = _mm_set_ss(stepW); - for (int x = sseend; x < x1; x++) - { - __m128 res = _mm_rcp_ss(mposW); - __m128 muls = _mm_mul_ss(mposW, _mm_mul_ss(res, res)); - _mm_store_ss(w + x, _mm_sub_ss(_mm_add_ss(res, res), muls)); - mposW = _mm_add_ss(mposW, mstepW); - } -} -#endif - -static void WriteDynLightArray(int x0, int x1, PolyTriangleThreadData* thread) -{ - int num_lights = thread->numPolyLights; - PolyLight* lights = thread->polyLights; - - float worldnormalX = thread->mainVertexShader.vWorldNormal.X; - float worldnormalY = thread->mainVertexShader.vWorldNormal.Y; - float worldnormalZ = thread->mainVertexShader.vWorldNormal.Z; - - uint32_t* lightarray = thread->scanline.lightarray; - float* worldposX = thread->scanline.WorldX; - float* worldposY = thread->scanline.WorldY; - float* worldposZ = thread->scanline.WorldZ; - - int sseend = x0; - -#ifndef NO_SSE - int ssecount = ((x1 - x0) & ~3); - sseend = x0 + ssecount; - - __m128 mworldnormalX = _mm_set1_ps(worldnormalX); - __m128 mworldnormalY = _mm_set1_ps(worldnormalY); - __m128 mworldnormalZ = _mm_set1_ps(worldnormalZ); - - for (int x = x0; x < sseend; x += 4) - { - __m128i lit = _mm_loadu_si128((__m128i*)&lightarray[x]); - __m128i litlo = _mm_unpacklo_epi8(lit, _mm_setzero_si128()); - __m128i lithi = _mm_unpackhi_epi8(lit, _mm_setzero_si128()); - - for (int i = 0; i < num_lights; i++) - { - __m128 lightposX = _mm_set1_ps(lights[i].x); - __m128 lightposY = _mm_set1_ps(lights[i].y); - __m128 lightposZ = _mm_set1_ps(lights[i].z); - __m128 light_radius = _mm_set1_ps(lights[i].radius); - __m128i light_color = _mm_shuffle_epi32(_mm_unpacklo_epi8(_mm_cvtsi32_si128(lights[i].color), _mm_setzero_si128()), _MM_SHUFFLE(1, 0, 1, 0)); - - __m128 is_attenuated = _mm_cmplt_ps(light_radius, _mm_setzero_ps()); - light_radius = _mm_andnot_ps(_mm_set1_ps(-0.0f), light_radius); // clear sign bit - - // L = light-pos - // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) - __m128 Lx = _mm_sub_ps(lightposX, _mm_loadu_ps(&worldposX[x])); - __m128 Ly = _mm_sub_ps(lightposY, _mm_loadu_ps(&worldposY[x])); - __m128 Lz = _mm_sub_ps(lightposZ, _mm_loadu_ps(&worldposZ[x])); - __m128 dist2 = _mm_add_ps(_mm_mul_ps(Lx, Lx), _mm_add_ps(_mm_mul_ps(Ly, Ly), _mm_mul_ps(Lz, Lz))); - __m128 rcp_dist = _mm_rsqrt_ps(dist2); - __m128 dist = _mm_mul_ps(dist2, rcp_dist); - __m128 distance_attenuation = _mm_sub_ps(_mm_set1_ps(256.0f), _mm_min_ps(_mm_mul_ps(dist, light_radius), _mm_set1_ps(256.0f))); - - // The simple light type - __m128 simple_attenuation = distance_attenuation; - - // The point light type - // diffuse = max(dot(N,normalize(L)),0) * attenuation - Lx = _mm_mul_ps(Lx, rcp_dist); - Ly = _mm_mul_ps(Ly, rcp_dist); - Lz = _mm_mul_ps(Lz, rcp_dist); - __m128 dotNL = _mm_add_ps(_mm_add_ps(_mm_mul_ps(mworldnormalX, Lx), _mm_mul_ps(mworldnormalY, Ly)), _mm_mul_ps(mworldnormalZ, Lz)); - __m128 point_attenuation = _mm_mul_ps(_mm_max_ps(dotNL, _mm_setzero_ps()), distance_attenuation); - - __m128i attenuation = _mm_cvtps_epi32(_mm_or_ps(_mm_and_ps(is_attenuated, point_attenuation), _mm_andnot_ps(is_attenuated, simple_attenuation))); - - attenuation = _mm_shufflehi_epi16(_mm_shufflelo_epi16(attenuation, _MM_SHUFFLE(2, 2, 0, 0)), _MM_SHUFFLE(2, 2, 0, 0)); - __m128i attenlo = _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(1, 1, 0, 0)); - __m128i attenhi = _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(3, 3, 2, 2)); - - litlo = _mm_add_epi16(litlo, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenlo), 8)); - lithi = _mm_add_epi16(lithi, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenhi), 8)); - } - - _mm_storeu_si128((__m128i*)&lightarray[x], _mm_packus_epi16(litlo, lithi)); - } -#endif - - for (int x = sseend; x < x1; x++) - { - uint32_t lit_a = APART(lightarray[x]); - uint32_t lit_r = RPART(lightarray[x]); - uint32_t lit_g = GPART(lightarray[x]); - uint32_t lit_b = BPART(lightarray[x]); - - for (int i = 0; i < num_lights; i++) - { - float lightposX = lights[i].x; - float lightposY = lights[i].y; - float lightposZ = lights[i].z; - float light_radius = lights[i].radius; - uint32_t light_color = lights[i].color; - - bool is_attenuated = light_radius < 0.0f; - if (is_attenuated) - light_radius = -light_radius; - - // L = light-pos - // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) - float Lx = lightposX - worldposX[x]; - float Ly = lightposY - worldposY[x]; - float Lz = lightposZ - worldposZ[x]; - float dist2 = Lx * Lx + Ly * Ly + Lz * Lz; -#ifdef NO_SSE - //float rcp_dist = 1.0f / sqrt(dist2); - float rcp_dist = 1.0f / (dist2 * 0.01f); -#else - float rcp_dist = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(dist2))); -#endif - float dist = dist2 * rcp_dist; - float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f); - - // The simple light type - float simple_attenuation = distance_attenuation; - - // The point light type - // diffuse = max(dot(N,normalize(L)),0) * attenuation - Lx *= rcp_dist; - Ly *= rcp_dist; - Lz *= rcp_dist; - float dotNL = worldnormalX * Lx + worldnormalY * Ly + worldnormalZ * Lz; - float point_attenuation = MAX(dotNL, 0.0f) * distance_attenuation; - - uint32_t attenuation = (uint32_t)(is_attenuated ? (int32_t)point_attenuation : (int32_t)simple_attenuation); - - lit_r += (RPART(light_color) * attenuation) >> 8; - lit_g += (GPART(light_color) * attenuation) >> 8; - lit_b += (BPART(light_color) * attenuation) >> 8; - } - - lit_r = MIN(lit_r, 255); - lit_g = MIN(lit_g, 255); - lit_b = MIN(lit_b, 255); - lightarray[x] = MAKEARGB(lit_a, lit_r, lit_g, lit_b); - - // Palette version: - // dynlights[x] = RGB256k.All[((lit_r >> 2) << 12) | ((lit_g >> 2) << 6) | (lit_b >> 2)]; - } -} - -static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - auto constants = thread->PushConstants; - - auto vColorR = thread->scanline.vColorR; - auto vColorG = thread->scanline.vColorG; - auto vColorB = thread->scanline.vColorB; - auto vColorA = thread->scanline.vColorA; - - if (thread->PushConstants->uLightLevel >= 0.0f) - { - float startX = x0 + (0.5f - args->v1->x); - float startY = y + (0.5f - args->v1->y); - float posW = args->v1->w + args->gradientX.W * startX + args->gradientY.W * startY; - float stepW = args->gradientX.W; - - float globVis = thread->mainVertexShader.Viewpoint->mGlobVis; - - uint32_t light = (int)(constants->uLightLevel * 255.0f); - fixed_t shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); - fixed_t lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); - fixed_t lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); - - fixed_t maxvis = 24 * FRACUNIT / 32; - fixed_t maxlight = 31 * FRACUNIT / 32; - - fixed_t lightend = lightpos + lightstep * (x1 - x0); - if (lightpos < maxvis && shade >= lightpos && shade - lightpos <= maxlight && - lightend < maxvis && shade >= lightend && shade - lightend <= maxlight) - { - lightpos += FRACUNIT - shade; - uint32_t* lightarray = thread->scanline.lightarray; - for (int x = x0; x < x1; x++) - { - uint32_t l = MIN(lightpos >> 8, 256); - - uint32_t r = vColorR[x]; - uint32_t g = vColorG[x]; - uint32_t b = vColorB[x]; - uint32_t a = vColorA[x]; - - // [GEC] DynLightColor On Sprite - r = (r * l) >> 8; - g = (g * l) >> 8; - b = (b * l) >> 8; - - if (constants->uLightIndex == -1) - { - r += (uint32_t)(constants->uDynLightColor.X * 255.0f); - g += (uint32_t)(constants->uDynLightColor.Y * 255.0f); - b += (uint32_t)(constants->uDynLightColor.Z * 255.0f); - - r = MIN(r, 255); - g = MIN(g, 255); - b = MIN(b, 255); - } - - lightarray[x] = MAKEARGB(a, r, g, b); - lightpos += lightstep; - } - } - else - { - uint32_t* lightarray = thread->scanline.lightarray; - for (int x = x0; x < x1; x++) - { - uint32_t l = MIN((FRACUNIT - clamp(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8, 256); - uint32_t r = vColorR[x]; - uint32_t g = vColorG[x]; - uint32_t b = vColorB[x]; - uint32_t a = vColorA[x]; - - // [GEC] DynLightColor On Sprite - r = (r * l) >> 8; - g = (g * l) >> 8; - b = (b * l) >> 8; - - if (constants->uLightIndex == -1) - { - r += (uint32_t)(constants->uDynLightColor.X * 255.0f); - g += (uint32_t)(constants->uDynLightColor.Y * 255.0f); - b += (uint32_t)(constants->uDynLightColor.Z * 255.0f); - - r = MIN(r, 255); - g = MIN(g, 255); - b = MIN(b, 255); - } - - lightarray[x] = MAKEARGB(a, r, g, b); - lightpos += lightstep; - } - } - } - else if (constants->uFogEnabled > 0) - { - float uLightDist = constants->uLightDist; - float uLightFactor = constants->uLightFactor; - float* w = thread->scanline.W; - uint32_t* lightarray = thread->scanline.lightarray; - for (int x = x0; x < x1; x++) - { - uint32_t a = thread->scanline.vColorA[x]; - uint32_t r = thread->scanline.vColorR[x]; - uint32_t g = thread->scanline.vColorG[x]; - uint32_t b = thread->scanline.vColorB[x]; - - float fogdist = MAX(16.0f, w[x]); - float fogfactor = std::exp2(constants->uFogDensity * fogdist); - - // brightening around the player for light mode 2: - if (fogdist < uLightDist) - { - uint32_t l = (int)((uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0)) * 256.0f); - r = (r * l) >> 8; - g = (g * l) >> 8; - b = (b * l) >> 8; - } - - // apply light diminishing through fog equation: mix(vec3(0.0, 0.0, 0.0), lightshade.rgb, fogfactor) - uint32_t t = (int)(fogfactor * 256.0f); - r = (r * t) >> 8; - g = (g * t) >> 8; - b = (b * t) >> 8; - - lightarray[x] = MAKEARGB(a, r, g, b); - } - } - else - { - uint32_t* lightarray = thread->scanline.lightarray; - for (int x = x0; x < x1; x++) - { - uint32_t a = thread->scanline.vColorA[x]; - uint32_t r = thread->scanline.vColorR[x]; - uint32_t g = thread->scanline.vColorG[x]; - uint32_t b = thread->scanline.vColorB[x]; - - // [GEC] DynLightColor On Weapon - if (constants->uLightIndex == -1) - { - r += (uint32_t)(constants->uDynLightColor.X * 255.0f); - g += (uint32_t)(constants->uDynLightColor.Y * 255.0f); - b += (uint32_t)(constants->uDynLightColor.Z * 255.0f); - - r = MIN(r, 255); - g = MIN(g, 255); - b = MIN(b, 255); - } - - lightarray[x] = MAKEARGB(a, r, g, b); - } - } -} - -#ifdef NO_SSE -static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) -{ - for (int x = x0; x < x1; x++) - { - varying[x] = pos * w[x]; - pos += step; - } -} -#else -static void WriteVarying(float pos, float step, int x0, int x1, const float* w, float* varying) -{ - int ssecount = ((x1 - x0) & ~3); - int sseend = x0 + ssecount; - - __m128 mstep = _mm_set1_ps(step * 4.0f); - __m128 mpos = _mm_setr_ps(pos, pos + step, pos + step + step, pos + step + step + step); - - for (int x = x0; x < sseend; x += 4) - { - _mm_storeu_ps(varying + x, _mm_mul_ps(mpos, _mm_loadu_ps(w + x))); - mpos = _mm_add_ps(mpos, mstep); - } - - pos += ssecount * step; - for (int x = sseend; x < x1; x++) - { - varying[x] = pos * w[x]; - pos += step; - } -} -#endif - -#ifdef NO_SSE -static void WriteVaryingWrap(float pos, float step, int x0, int x1, const float* w, uint16_t* varying) -{ - for (int x = x0; x < x1; x++) - { - float value = pos * w[x]; - value = value - std::floor(value); - varying[x] = static_cast(static_cast(value * static_cast(0x1000'0000)) << 4) >> 16; - pos += step; - } -} -#else -static void WriteVaryingWrap(float pos, float step, int x0, int x1, const float* w, uint16_t* varying) -{ - int ssecount = ((x1 - x0) & ~3); - int sseend = x0 + ssecount; - - __m128 mstep = _mm_set1_ps(step * 4.0f); - __m128 mpos = _mm_setr_ps(pos, pos + step, pos + step + step, pos + step + step + step); - - for (int x = x0; x < sseend; x += 4) - { - __m128 value = _mm_mul_ps(mpos, _mm_loadu_ps(w + x)); - __m128 f = value; - __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); - __m128 r = _mm_sub_ps(t, _mm_and_ps(_mm_cmplt_ps(f, t), _mm_set1_ps(1.0f))); - value = _mm_sub_ps(f, r); - - __m128i ivalue = _mm_srli_epi32(_mm_slli_epi32(_mm_cvttps_epi32(_mm_mul_ps(value, _mm_set1_ps(static_cast(0x1000'0000)))), 4), 17); - _mm_storel_epi64((__m128i*)(varying + x), _mm_slli_epi16(_mm_packs_epi32(ivalue, ivalue), 1)); - mpos = _mm_add_ps(mpos, mstep); - } - - pos += ssecount * step; - for (int x = sseend; x < x1; x++) - { - float value = pos * w[x]; - __m128 f = _mm_set_ss(value); - __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(f)); - __m128 r = _mm_sub_ss(t, _mm_and_ps(_mm_cmplt_ps(f, t), _mm_set_ss(1.0f))); - value = _mm_cvtss_f32(_mm_sub_ss(f, r)); - - varying[x] = static_cast(static_cast(value * static_cast(0x1000'0000)) << 4) >> 16; - pos += step; - } -} -#endif - -static void WriteVaryingWarp1(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread) -{ - float pi2 = 3.14159265358979323846f * 2.0f; - float timer = thread->mainVertexShader.Data.timer * 0.125f; - - const float* w = thread->scanline.W; - uint16_t* scanlineU = thread->scanline.U; - uint16_t* scanlineV = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - float u = posU * w[x]; - float v = posV * w[x]; - - v += (float)g_sin(pi2 * (u + timer)) * 0.1f; - u += (float)g_sin(pi2 * (v + timer)) * 0.1f; - - u = u - std::floor(u); - v = v - std::floor(v); - scanlineU[x] = static_cast(static_cast(u * static_cast(0x1000'0000)) << 4) >> 16; - scanlineV[x] = static_cast(static_cast(v * static_cast(0x1000'0000)) << 4) >> 16; - - posU += stepU; - posV += stepV; - } -} - -static void WriteVaryingWarp2(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread) -{ - float pi2 = 3.14159265358979323846f * 2.0f; - float timer = thread->mainVertexShader.Data.timer; - - const float* w = thread->scanline.W; - uint16_t* scanlineU = thread->scanline.U; - uint16_t* scanlineV = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - float u = posU * w[x]; - float v = posV * w[x]; - - v += (0.5f + (float)g_sin(pi2 * (v + timer * 0.61f + 900.f/8192.f)) + (float)g_sin(pi2 * (u * 2.0f + timer * 0.36f + 300.0f/8192.0f))) * 0.025f; - u += (0.5f + (float)g_sin(pi2 * (v + timer * 0.49f + 700.f/8192.f)) + (float)g_sin(pi2 * (u * 2.0f + timer * 0.49f + 1200.0f/8192.0f))) * 0.025f; - - u = u - std::floor(u); - v = v - std::floor(v); - scanlineU[x] = static_cast(static_cast(u * static_cast(0x1000'0000)) << 4) >> 16; - scanlineV[x] = static_cast(static_cast(v * static_cast(0x1000'0000)) << 4) >> 16; - - posU += stepU; - posV += stepV; - } -} - -#ifdef NO_SSE -static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying) -{ - for (int x = x0; x < x1; x++) - { - varying[x] = clamp(static_cast(pos * w[x] * 255.0f), 0, 255); - pos += step; - } -} -#else -static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying) -{ - int ssecount = ((x1 - x0) & ~3); - int sseend = x0 + ssecount; - - __m128 mstep = _mm_set1_ps(step * 4.0f); - __m128 mpos = _mm_setr_ps(pos, pos + step, pos + step + step, pos + step + step + step); - - for (int x = x0; x < sseend; x += 4) - { - __m128i value = _mm_cvttps_epi32(_mm_mul_ps(_mm_mul_ps(mpos, _mm_loadu_ps(w + x)), _mm_set1_ps(255.0f))); - value = _mm_packs_epi32(value, value); - value = _mm_packus_epi16(value, value); - *(uint32_t*)(varying + x) = _mm_cvtsi128_si32(value); - mpos = _mm_add_ps(mpos, mstep); - } - - pos += ssecount * step; - for (int x = sseend; x < x1; x++) - { - varying[x] = clamp(static_cast(pos * w[x] * 255.0f), 0, 255); - pos += step; - } -} -#endif - -void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - float startX = x0 + (0.5f - args->v1->x); - float startY = y + (0.5f - args->v1->y); - - void (*useShader)(float posU, float posV, float stepU, float stepV, int x0, int x1, PolyTriangleThreadData* thread) = nullptr; - - if (thread->EffectState == SHADER_Warp1) - useShader = &WriteVaryingWarp1; - else if (thread->EffectState == SHADER_Warp2) - useShader = &WriteVaryingWarp2; - - if (useShader) - { - useShader( - args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, - args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, - args->gradientX.U, - args->gradientX.V, - x0, x1, - thread); - } - else - { - WriteVaryingWrap(args->v1->u * args->v1->w + args->gradientX.U * startX + args->gradientY.U * startY, args->gradientX.U, x0, x1, thread->scanline.W, thread->scanline.U); - WriteVaryingWrap(args->v1->v * args->v1->w + args->gradientX.V * startX + args->gradientY.V * startY, args->gradientX.V, x0, x1, thread->scanline.W, thread->scanline.V); - } - WriteVarying(args->v1->worldX * args->v1->w + args->gradientX.WorldX * startX + args->gradientY.WorldX * startY, args->gradientX.WorldX, x0, x1, thread->scanline.W, thread->scanline.WorldX); - WriteVarying(args->v1->worldY * args->v1->w + args->gradientX.WorldY * startX + args->gradientY.WorldY * startY, args->gradientX.WorldY, x0, x1, thread->scanline.W, thread->scanline.WorldY); - WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ); - WriteVarying(args->v1->gradientdistZ * args->v1->w + args->gradientX.GradientdistZ * startX + args->gradientY.GradientdistZ * startY, args->gradientX.GradientdistZ, x0, x1, thread->scanline.W, thread->scanline.GradientdistZ); - WriteVaryingColor(args->v1->a * args->v1->w + args->gradientX.A * startX + args->gradientY.A * startY, args->gradientX.A, x0, x1, thread->scanline.W, thread->scanline.vColorA); - WriteVaryingColor(args->v1->r * args->v1->w + args->gradientX.R * startX + args->gradientY.R * startY, args->gradientX.R, x0, x1, thread->scanline.W, thread->scanline.vColorR); - WriteVaryingColor(args->v1->g * args->v1->w + args->gradientX.G * startX + args->gradientY.G * startY, args->gradientX.G, x0, x1, thread->scanline.W, thread->scanline.vColorG); - WriteVaryingColor(args->v1->b * args->v1->w + args->gradientX.B * startX + args->gradientY.B * startY, args->gradientX.B, x0, x1, thread->scanline.W, thread->scanline.vColorB); - - if (thread->PushConstants->uFogEnabled != -3 && thread->PushConstants->uTextureMode != TM_FOGLAYER) - WriteLightArray(y, x0, x1, args, thread); - - if (thread->numPolyLights > 0) - WriteDynLightArray(x0, x1, thread); -} diff --git a/src/common/rendering/polyrenderer/drawers/screen_shader.cpp b/src/common/rendering/polyrenderer/drawers/screen_shader.cpp deleted file mode 100644 index 7e225bef1..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_shader.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" -#include "poly_thread.h" -#include "screen_scanline_setup.h" -#include - -static uint32_t SampleTexture(uint32_t u, uint32_t v, const void* texPixels, int texWidth, int texHeight, bool texBgra) -{ - int texelX = (u * texWidth) >> 16; - int texelY = (v * texHeight) >> 16; - int texelOffset = texelX + texelY * texWidth; - if (texBgra) - { - return static_cast(texPixels)[texelOffset]; - } - else - { - uint32_t c = static_cast(texPixels)[texelOffset]; - return (c << 16) | 0xff000000; - } -} - -static void EffectFogBoundary(int x0, int x1, PolyTriangleThreadData* thread) -{ - float uFogDensity = thread->PushConstants->uFogDensity; - uint32_t fogcolor = MAKEARGB( - 0, - static_cast(clamp(thread->mainVertexShader.Data.uFogColor.r, 0.0f, 1.0f) * 255.0f), - static_cast(clamp(thread->mainVertexShader.Data.uFogColor.g, 0.0f, 1.0f) * 255.0f), - static_cast(clamp(thread->mainVertexShader.Data.uFogColor.b, 0.0f, 1.0f) * 255.0f)); - - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) - { - float fogdist = thread->scanline.W[x]; - float fogfactor = std::exp2(uFogDensity * fogdist); - - // FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor): - uint32_t alpha = static_cast(clamp(1.0f - (1.0f / 255.0f), 0.0f, 1.0f) * 255.0f); - fragcolor[x] = fogcolor | alpha; - } -} - -static void EffectBurn(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - - int tex2Width = thread->textures[1].width; - int tex2Height = thread->textures[1].height; - const void* tex2Pixels = thread->textures[1].pixels; - bool tex2Bgra = thread->textures[1].bgra; - - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - for (int x = x0; x < x1; x++) - { - uint32_t frag_r = thread->scanline.vColorR[x]; - uint32_t frag_g = thread->scanline.vColorG[x]; - uint32_t frag_b = thread->scanline.vColorB[x]; - uint32_t frag_a = thread->scanline.vColorA[x]; - frag_r += frag_r >> 7; // 255 -> 256 - frag_g += frag_g >> 7; // 255 -> 256 - frag_b += frag_b >> 7; // 255 -> 256 - frag_a += frag_a >> 7; // 255 -> 256 - - uint32_t t1 = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - uint32_t t2 = SampleTexture(u[x], 0xffff - v[x], tex2Pixels, tex2Width, tex2Height, tex2Bgra); - - uint32_t r = (frag_r * RPART(t1)) >> 8; - uint32_t g = (frag_g * GPART(t1)) >> 8; - uint32_t b = (frag_b * BPART(t1)) >> 8; - uint32_t a = (frag_a * APART(t2)) >> 8; - - fragcolor[x] = MAKEARGB(a, r, g, b); - } -} - -static void EffectStencil(int x0, int x1, PolyTriangleThreadData* thread) -{ - /*for (int x = x0; x < x1; x++) - { - fragcolor[x] = 0x00ffffff; - }*/ -} - -static void FuncPaletted(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - const uint32_t* lut = (const uint32_t*)thread->textures[1].pixels; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - fragcolor[x] = lut[RPART(SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra))] | 0xff000000; - } -} - -static void FuncNoTexture(int x0, int x1, PolyTriangleThreadData* thread) -{ - auto& streamdata = thread->mainVertexShader.Data; - uint32_t a = (int)(streamdata.uObjectColor.a * 255.0f); - uint32_t r = (int)(streamdata.uObjectColor.r * 255.0f); - uint32_t g = (int)(streamdata.uObjectColor.g * 255.0f); - uint32_t b = (int)(streamdata.uObjectColor.b * 255.0f); - uint32_t texel = MAKEARGB(a, r, g, b); - - if (streamdata.uDesaturationFactor > 0.0f) - { - uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); - uint32_t inv_t = 256 - t; - uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; - texel = MAKEARGB( - APART(texel), - (RPART(texel) * inv_t + gray * t + 127) >> 8, - (GPART(texel) * inv_t + gray * t + 127) >> 8, - (BPART(texel) * inv_t + gray * t + 127) >> 8); - } - - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) - { - fragcolor[x] = texel; - } -} - -static void FuncNormal(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - fragcolor[x] = texel; - } -} - -static void FuncNormal_Stencil(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - fragcolor[x] = texel | 0x00ffffff; - } -} - -static void FuncNormal_Opaque(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - fragcolor[x] = texel | 0xff000000; - } -} - -static void FuncNormal_Inverse(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - fragcolor[x] = MAKEARGB(APART(texel), 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); - } -} - -static void FuncNormal_AlphaTexture(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; - uint32_t alpha = APART(texel); - alpha += alpha >> 7; - alpha = (alpha * gray + 127) >> 8; - texel = (alpha << 24) | 0x00ffffff; - fragcolor[x] = texel; - } -} - -static void FuncNormal_ClampY(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - fragcolor[x] = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - if (v[x] < 0.0 || v[x] > 1.0) - fragcolor[x] &= 0x00ffffff; - } -} - -static void FuncNormal_InvertOpaque(int x0, int x1, PolyTriangleThreadData* thread) -{ - int texWidth = thread->textures[0].width; - int texHeight = thread->textures[0].height; - const void* texPixels = thread->textures[0].pixels; - bool texBgra = thread->textures[0].bgra; - uint32_t* fragcolor = thread->scanline.FragColor; - uint16_t* u = thread->scanline.U; - uint16_t* v = thread->scanline.V; - - for (int x = x0; x < x1; x++) - { - uint32_t texel = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra); - fragcolor[x] = MAKEARGB(0xff, 0xff - RPART(texel), 0xff - BPART(texel), 0xff - GPART(texel)); - } -} - -static void FuncNormal_AddColor(int x0, int x1, PolyTriangleThreadData* thread) -{ - auto& streamdata = thread->mainVertexShader.Data; - uint32_t r = (int)(streamdata.uAddColor.r * 255.0f); - uint32_t g = (int)(streamdata.uAddColor.g * 255.0f); - uint32_t b = (int)(streamdata.uAddColor.b * 255.0f); - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) - { - uint32_t texel = fragcolor[x]; - fragcolor[x] = MAKEARGB( - APART(texel), - MIN(r + RPART(texel), (uint32_t)255), - MIN(g + GPART(texel), (uint32_t)255), - MIN(b + BPART(texel), (uint32_t)255)); - } -} - -static void FuncNormal_AddObjectColor(int x0, int x1, PolyTriangleThreadData* thread) -{ - auto& streamdata = thread->mainVertexShader.Data; - uint32_t r = (int)(streamdata.uObjectColor.r * 256.0f); - uint32_t g = (int)(streamdata.uObjectColor.g * 256.0f); - uint32_t b = (int)(streamdata.uObjectColor.b * 256.0f); - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) - { - uint32_t texel = fragcolor[x]; - fragcolor[x] = MAKEARGB( - APART(texel), - MIN((r * RPART(texel)) >> 8, (uint32_t)255), - MIN((g * GPART(texel)) >> 8, (uint32_t)255), - MIN((b * BPART(texel)) >> 8, (uint32_t)255)); - } -} - -static void FuncNormal_AddObjectColor2(int x0, int x1, PolyTriangleThreadData* thread) -{ - auto& streamdata = thread->mainVertexShader.Data; - float* gradientdistZ = thread->scanline.GradientdistZ; - uint32_t* fragcolor = thread->scanline.FragColor; - for (int x = x0; x < x1; x++) - { - float t = gradientdistZ[x]; - float inv_t = 1.0f - t; - uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f); - uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.g * t) * 256.0f); - uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.b * t) * 256.0f); - - uint32_t texel = fragcolor[x]; - fragcolor[x] = MAKEARGB( - APART(texel), - MIN((r * RPART(texel)) >> 8, (uint32_t)255), - MIN((g * GPART(texel)) >> 8, (uint32_t)255), - MIN((b * BPART(texel)) >> 8, (uint32_t)255)); - } -} - -static void FuncNormal_DesaturationFactor(int x0, int x1, PolyTriangleThreadData* thread) -{ - auto& streamdata = thread->mainVertexShader.Data; - uint32_t* fragcolor = thread->scanline.FragColor; - uint32_t t = (int)(streamdata.uDesaturationFactor * 256.0f); - uint32_t inv_t = 256 - t; - for (int x = x0; x < x1; x++) - { - uint32_t texel = fragcolor[x]; - uint32_t gray = (RPART(texel) * 77 + GPART(texel) * 143 + BPART(texel) * 37) >> 8; - fragcolor[x] = MAKEARGB( - APART(texel), - (RPART(texel) * inv_t + gray * t + 127) >> 8, - (GPART(texel) * inv_t + gray * t + 127) >> 8, - (BPART(texel) * inv_t + gray * t + 127) >> 8); - } -} - -static void RunAlphaTest(int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t alphaThreshold = thread->AlphaThreshold; - uint32_t* fragcolor = thread->scanline.FragColor; - uint8_t* discard = thread->scanline.discard; - for (int x = x0; x < x1; x++) - { - discard[x] = fragcolor[x] <= alphaThreshold; - } -} - -static void ProcessMaterial(int x0, int x1, PolyTriangleThreadData* thread) -{ - if (thread->EffectState == SHADER_Paletted) // func_paletted - { - FuncPaletted(x0, x1, thread); - } - else if (thread->EffectState == SHADER_NoTexture) // func_notexture - { - FuncNoTexture(x0, x1, thread); - } - else // func_normal - { - auto constants = thread->PushConstants; - - switch (constants->uTextureMode) - { - default: - case TM_NORMAL: - case TM_FOGLAYER: FuncNormal(x0, x1, thread); break; - case TM_STENCIL: FuncNormal_Stencil(x0, x1, thread); break; - case TM_OPAQUE: FuncNormal_Opaque(x0, x1, thread); break; - case TM_INVERSE: FuncNormal_Inverse(x0, x1, thread); break; - case TM_ALPHATEXTURE: FuncNormal_AlphaTexture(x0, x1, thread); break; - case TM_CLAMPY: FuncNormal_ClampY(x0, x1, thread); break; - case TM_INVERTOPAQUE: FuncNormal_InvertOpaque(x0, x1, thread); break; - } - - if (constants->uTextureMode != TM_FOGLAYER) - { - auto& streamdata = thread->mainVertexShader.Data; - - if (streamdata.uAddColor.r != 0.0f || streamdata.uAddColor.g != 0.0f || streamdata.uAddColor.b != 0.0f) - { - FuncNormal_AddColor(x0, x1, thread); - } - - if (streamdata.uObjectColor2.a == 0.0f) - { - if (streamdata.uObjectColor.r != 1.0f || streamdata.uObjectColor.g != 1.0f || streamdata.uObjectColor.b != 1.0f) - { - FuncNormal_AddObjectColor(x0, x1, thread); - } - } - else - { - FuncNormal_AddObjectColor2(x0, x1, thread); - } - - if (streamdata.uDesaturationFactor > 0.0f) - { - FuncNormal_DesaturationFactor(x0, x1, thread); - } - } - } -} - -static void GetLightColor(int x0, int x1, PolyTriangleThreadData* thread) -{ - uint32_t* fragcolor = thread->scanline.FragColor; - uint32_t* lightarray = thread->scanline.lightarray; - - if (thread->PushConstants->uFogEnabled >= 0) - { - for (int x = x0; x < x1; x++) - { - uint32_t fg = fragcolor[x]; - uint32_t lightshade = lightarray[x]; - - uint32_t mulA = APART(lightshade); - uint32_t mulR = RPART(lightshade); - uint32_t mulG = GPART(lightshade); - uint32_t mulB = BPART(lightshade); - mulA += mulA >> 7; - mulR += mulR >> 7; - mulG += mulG >> 7; - mulB += mulB >> 7; - - uint32_t a = (APART(fg) * mulA + 127) >> 8; - uint32_t r = (RPART(fg) * mulR + 127) >> 8; - uint32_t g = (GPART(fg) * mulG + 127) >> 8; - uint32_t b = (BPART(fg) * mulB + 127) >> 8; - - fragcolor[x] = MAKEARGB(a, r, g, b); - } - } - else - { - uint32_t fogR = (int)((thread->mainVertexShader.Data.uFogColor.r) * 255.0f); - uint32_t fogG = (int)((thread->mainVertexShader.Data.uFogColor.g) * 255.0f); - uint32_t fogB = (int)((thread->mainVertexShader.Data.uFogColor.b) * 255.0f); - float uFogDensity = thread->PushConstants->uFogDensity; - - float* w = thread->scanline.W; - for (int x = x0; x < x1; x++) - { - uint32_t fg = fragcolor[x]; - uint32_t lightshade = lightarray[x]; - - uint32_t mulA = APART(lightshade); - uint32_t mulR = RPART(lightshade); - uint32_t mulG = GPART(lightshade); - uint32_t mulB = BPART(lightshade); - mulA += mulA >> 7; - mulR += mulR >> 7; - mulG += mulG >> 7; - mulB += mulB >> 7; - - float fogdist = MAX(16.0f, w[x]); - float fogfactor = std::exp2(uFogDensity * fogdist); - - uint32_t a = (APART(fg) * mulA + 127) >> 8; - uint32_t r = (RPART(fg) * mulR + 127) >> 8; - uint32_t g = (GPART(fg) * mulG + 127) >> 8; - uint32_t b = (BPART(fg) * mulB + 127) >> 8; - - uint32_t t = (int)(fogfactor * 256.0f); - uint32_t inv_t = 256 - t; - r = (fogR * inv_t + r * t + 127) >> 8; - g = (fogG * inv_t + g * t + 127) >> 8; - b = (fogB * inv_t + b * t + 127) >> 8; - - fragcolor[x] = MAKEARGB(a, r, g, b); - } - } -} - -static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) -{ - ProcessMaterial(x0, x1, thread); - - if (thread->AlphaTest) - RunAlphaTest(x0, x1, thread); - - auto constants = thread->PushConstants; - if (constants->uFogEnabled != -3) - { - if (constants->uTextureMode != TM_FOGLAYER) - { - GetLightColor(x0, x1, thread); - } - else - { - /*float fogdist = 0.0f; - float fogfactor = 0.0f; - if (constants->uFogEnabled != 0) - { - fogdist = MAX(16.0f, w[x]); - fogfactor = std::exp2(constants->uFogDensity * fogdist); - } - frag = vec4(uFogColor.rgb, (1.0 - fogfactor) * frag.a * 0.75 * vColor.a);*/ - } - } - else // simple 2D (uses the fog color to add a color overlay) - { - uint32_t fogR = (int)((thread->mainVertexShader.Data.uFogColor.r) * 255.0f); - uint32_t fogG = (int)((thread->mainVertexShader.Data.uFogColor.g) * 255.0f); - uint32_t fogB = (int)((thread->mainVertexShader.Data.uFogColor.b) * 255.0f); - - auto vColorR = thread->scanline.vColorR; - auto vColorG = thread->scanline.vColorG; - auto vColorB = thread->scanline.vColorB; - auto vColorA = thread->scanline.vColorA; - uint32_t* fragcolor = thread->scanline.FragColor; - - if (constants->uTextureMode == TM_FIXEDCOLORMAP) - { - // float gray = grayscale(frag); - // vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2; - // frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a); - // frag = frag * vColor; - // frag.rgb = frag.rgb + uFogColor.rgb; - - // [GEC] I leave the default floating values. - float startR = thread->mainVertexShader.Data.uObjectColor.r; - float startG = thread->mainVertexShader.Data.uObjectColor.g; - float startB = thread->mainVertexShader.Data.uObjectColor.b; - float rangeR = thread->mainVertexShader.Data.uAddColor.r - startR; - float rangeG = thread->mainVertexShader.Data.uAddColor.g - startG; - float rangeB = thread->mainVertexShader.Data.uAddColor.b - startB; - - for (int x = x0; x < x1; x++) - { - uint32_t a = APART(fragcolor[x]); - uint32_t r = RPART(fragcolor[x]); - uint32_t g = GPART(fragcolor[x]); - uint32_t b = BPART(fragcolor[x]); - - uint32_t gray = (r * 77 + g * 143 + b * 37) >> 8; - gray += (gray >> 7); // gray*=256/255 - - // [GEC] I use the same method as in shaders using floating values. - // This avoids errors in the invulneravility colormap in Doom and Heretic. - float fgray = (float)(gray / 255.f); - float fr = (startR + (fgray * rangeR)) * 2; - float fg = (startG + (fgray * rangeG)) * 2; - float fb = (startB + (fgray * rangeB)) * 2; - - fr = clamp(fr, 0.0f, 1.0f); - fg = clamp(fg, 0.0f, 1.0f); - fb = clamp(fb, 0.0f, 1.0f); - - r = (uint32_t)(fr * 255.f); - g = (uint32_t)(fg * 255.f); - b = (uint32_t)(fb * 255.f); - - fragcolor[x] = MAKEARGB(a, (uint8_t)r, (uint8_t)g, (uint8_t)b); - } - } - else - { - for (int x = x0; x < x1; x++) - { - uint32_t a = vColorA[x]; - uint32_t r = vColorR[x]; - uint32_t g = vColorG[x]; - uint32_t b = vColorB[x]; - a += a >> 7; - r += r >> 7; - g += g >> 7; - b += b >> 7; - - // frag = frag * vColor; - a = (APART(fragcolor[x]) * a + 127) >> 8; - r = (RPART(fragcolor[x]) * r + 127) >> 8; - g = (GPART(fragcolor[x]) * g + 127) >> 8; - b = (BPART(fragcolor[x]) * b + 127) >> 8; - - // frag.rgb = frag.rgb + uFogColor.rgb; - r = MIN(r + fogR, (uint32_t)255); - g = MIN(g + fogG, (uint32_t)255); - b = MIN(b + fogB, (uint32_t)255); - - fragcolor[x] = MAKEARGB(a, r, g, b); - } - } - } -} - -void ColormapFP(int x0, int x1, PolyTriangleThreadData* thread) -{ - // This is implemented in BlendColorColormap. -} - -void SelectFragmentShader(PolyTriangleThreadData* thread) -{ - void (*fragshader)(int x0, int x1, PolyTriangleThreadData * thread); - - if (thread->ColormapShader) - { - fragshader = &ColormapFP; - } - else if (thread->SpecialEffect == EFF_FOGBOUNDARY) // fogboundary.fp - { - fragshader = &EffectFogBoundary; - } - else if (thread->SpecialEffect == EFF_BURN) // burn.fp - { - fragshader = &EffectBurn; - } - else if (thread->SpecialEffect == EFF_STENCIL) // stencil.fp - { - fragshader = &EffectStencil; - } - else - { - fragshader = &MainFP; - } - - thread->FragmentShader = fragshader; -} diff --git a/src/common/rendering/polyrenderer/drawers/screen_triangle.cpp b/src/common/rendering/polyrenderer/drawers/screen_triangle.cpp deleted file mode 100644 index 53c9afabe..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_triangle.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" - -#include "filesystem.h" -#include "v_video.h" -#include "poly_triangle.h" -#include "screen_triangle.h" -#include "screen_blend.h" -#include "screen_scanline_setup.h" -#include "screen_shader.h" -#include - -static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - float* line = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y; - - if (thread->DepthRangeScale != 0.0f) - { - float* w = thread->scanline.W; - for (int x = x0; x < x1; x++) - { - line[x] = w[x]; - } - } - else // portal fills always uses DepthRangeStart = 1 and DepthRangeScale = 0 - { - for (int x = x0; x < x1; x++) - { - line[x] = 65536.0f; - } - } -} - -static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread) -{ - uint8_t* line = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y; - uint8_t value = thread->StencilWriteValue; - for (int x = x0; x < x1; x++) - { - line[x] = value; - } -} - -static void RunFragmentShader(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - WriteVaryings(y, x0, x1, args, thread); - thread->FragmentShader(x0, x1, thread); -} - -static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - if (thread->WriteColor || thread->AlphaTest) - RunFragmentShader(y, x0, x1, args, thread); - - if (!thread->AlphaTest) - { - if (thread->WriteColor) - thread->WriteColorFunc(y, x0, x1, thread); - if (thread->WriteDepth) - WriteDepth(y, x0, x1, thread); - if (thread->WriteStencil) - WriteStencil(y, x0, x1, thread); - } - else - { - uint8_t* discard = thread->scanline.discard; - while (x0 < x1) - { - int xstart = x0; - while (!discard[x0] && x0 < x1) x0++; - - if (xstart < x0) - { - if (thread->WriteColor) - thread->WriteColorFunc(y, xstart, x0, thread); - if (thread->WriteDepth) - WriteDepth(y, xstart, x0, thread); - if (thread->WriteStencil) - WriteStencil(y, xstart, x0, thread); - } - - while (discard[x0] && x0 < x1) x0++; - } - } -} - -static void NoTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - WriteW(y, x0, x1, args, thread); - DrawSpan(y, x0, x1, args, thread); -} - -static void DepthTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - WriteW(y, x0, x1, args, thread); - - float* zbufferLine = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y; - float* w = thread->scanline.W; - float depthbias = thread->depthbias; - - int x = x0; - int xend = x1; - while (x < xend) - { - int xstart = x; - - while (zbufferLine[x] >= w[x] + depthbias && x < xend) - x++; - - if (x > xstart) - { - DrawSpan(y, xstart, x, args, thread); - } - - while (zbufferLine[x] < w[x] + depthbias && x < xend) - x++; - } -} - -static void DepthStencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y; - uint8_t stencilTestValue = thread->StencilTestValue; - - int x = x0; - int xend = x1; - while (x < xend) - { - int xstart = x; - while (stencilLine[x] == stencilTestValue && x < xend) - x++; - - if (x > xstart) - { - DepthTestSpan(y, xstart, x, args, thread); - } - - while (stencilLine[x] != stencilTestValue && x < xend) - x++; - } -} - -static void StencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y; - uint8_t stencilTestValue = thread->StencilTestValue; - - int x = x0; - int xend = x1; - while (x < xend) - { - int xstart = x; - while (stencilLine[x] == stencilTestValue && x < xend) - x++; - - if (x > xstart) - { - WriteW(y, x0, x1, args, thread); - DrawSpan(y, xstart, x, args, thread); - } - - while (stencilLine[x] != stencilTestValue && x < xend) - x++; - } -} - -static void SortVertices(const TriDrawTriangleArgs* args, ScreenTriVertex** sortedVertices) -{ - sortedVertices[0] = args->v1; - sortedVertices[1] = args->v2; - sortedVertices[2] = args->v3; - - if (sortedVertices[1]->y < sortedVertices[0]->y) - std::swap(sortedVertices[0], sortedVertices[1]); - if (sortedVertices[2]->y < sortedVertices[0]->y) - std::swap(sortedVertices[0], sortedVertices[2]); - if (sortedVertices[2]->y < sortedVertices[1]->y) - std::swap(sortedVertices[1], sortedVertices[2]); -} - -void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) -{ - // Sort vertices by Y position - ScreenTriVertex* sortedVertices[3]; - SortVertices(args, sortedVertices); - - int clipleft = thread->clip.left; - int cliptop = MAX(thread->clip.top, thread->numa_start_y); - int clipright = thread->clip.right; - int clipbottom = MIN(thread->clip.bottom, thread->numa_end_y); - - int topY = (int)(sortedVertices[0]->y + 0.5f); - int midY = (int)(sortedVertices[1]->y + 0.5f); - int bottomY = (int)(sortedVertices[2]->y + 0.5f); - - topY = MAX(topY, cliptop); - midY = MIN(midY, clipbottom); - bottomY = MIN(bottomY, clipbottom); - - if (topY >= bottomY) - return; - - SelectFragmentShader(thread); - SelectWriteColorFunc(thread); - - void(*testfunc)(int y, int x0, int x1, const TriDrawTriangleArgs * args, PolyTriangleThreadData * thread); - - int opt = 0; - if (thread->DepthTest) opt |= SWTRI_DepthTest; - if (thread->StencilTest) opt |= SWTRI_StencilTest; - testfunc = ScreenTriangle::TestSpanOpts[opt]; - - topY += thread->skipped_by_thread(topY); - int num_cores = thread->num_cores; - - // Find start/end X positions for each line covered by the triangle: - - int y = topY; - - float longDX = sortedVertices[2]->x - sortedVertices[0]->x; - float longDY = sortedVertices[2]->y - sortedVertices[0]->y; - float longStep = longDX / longDY; - float longPos = sortedVertices[0]->x + longStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; - longStep *= num_cores; - - if (y < midY) - { - float shortDX = sortedVertices[1]->x - sortedVertices[0]->x; - float shortDY = sortedVertices[1]->y - sortedVertices[0]->y; - float shortStep = shortDX / shortDY; - float shortPos = sortedVertices[0]->x + shortStep * (y + 0.5f - sortedVertices[0]->y) + 0.5f; - shortStep *= num_cores; - - while (y < midY) - { - int x0 = (int)shortPos; - int x1 = (int)longPos; - if (x1 < x0) std::swap(x0, x1); - x0 = clamp(x0, clipleft, clipright); - x1 = clamp(x1, clipleft, clipright); - - testfunc(y, x0, x1, args, thread); - - shortPos += shortStep; - longPos += longStep; - y += num_cores; - } - } - - if (y < bottomY) - { - float shortDX = sortedVertices[2]->x - sortedVertices[1]->x; - float shortDY = sortedVertices[2]->y - sortedVertices[1]->y; - float shortStep = shortDX / shortDY; - float shortPos = sortedVertices[1]->x + shortStep * (y + 0.5f - sortedVertices[1]->y) + 0.5f; - shortStep *= num_cores; - - while (y < bottomY) - { - int x0 = (int)shortPos; - int x1 = (int)longPos; - if (x1 < x0) std::swap(x0, x1); - x0 = clamp(x0, clipleft, clipright); - x1 = clamp(x1, clipleft, clipright); - - testfunc(y, x0, x1, args, thread); - - shortPos += shortStep; - longPos += longStep; - y += num_cores; - } - } -} - -void(*ScreenTriangle::TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) = -{ - &NoTestSpan, - &DepthTestSpan, - &StencilTestSpan, - &DepthStencilTestSpan -}; diff --git a/src/common/rendering/polyrenderer/drawers/screen_triangle.h b/src/common/rendering/polyrenderer/drawers/screen_triangle.h deleted file mode 100644 index db63f2547..000000000 --- a/src/common/rendering/polyrenderer/drawers/screen_triangle.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include -#include -#include "renderstyle.h" -//#include "rendering/swrenderer/drawers/r_draw.h" - -class FString; -class PolyTriangleThreadData; - -struct ScreenTriVertex -{ - float x, y, z, w; - float u, v; - float worldX, worldY, worldZ; - float a, r, g, b; - float gradientdistZ; -}; - -struct ScreenTriangleStepVariables -{ - float W, U, V; - float WorldX, WorldY, WorldZ; - float A, R, G, B; - float GradientdistZ; -}; - -struct TriDrawTriangleArgs -{ - ScreenTriVertex *v1; - ScreenTriVertex *v2; - ScreenTriVertex *v3; - ScreenTriangleStepVariables gradientX; - ScreenTriangleStepVariables gradientY; - - bool CalculateGradients() - { - float bottomX = (v2->x - v3->x) * (v1->y - v3->y) - (v1->x - v3->x) * (v2->y - v3->y); - float bottomY = (v1->x - v3->x) * (v2->y - v3->y) - (v2->x - v3->x) * (v1->y - v3->y); - if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON)) - return false; - - gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f); - gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u); - gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v); - gradientX.WorldX = FindGradientX(bottomX, v1->worldX, v2->worldX, v3->worldX); - gradientX.WorldY = FindGradientX(bottomX, v1->worldY, v2->worldY, v3->worldY); - gradientX.WorldZ = FindGradientX(bottomX, v1->worldZ, v2->worldZ, v3->worldZ); - gradientX.A = FindGradientX(bottomX, v1->a, v2->a, v3->a); - gradientX.R = FindGradientX(bottomX, v1->r, v2->r, v3->r); - gradientX.G = FindGradientX(bottomX, v1->g, v2->g, v3->g); - gradientX.B = FindGradientX(bottomX, v1->b, v2->b, v3->b); - gradientX.GradientdistZ = FindGradientX(bottomX, v1->gradientdistZ, v2->gradientdistZ, v3->gradientdistZ); - - gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f); - gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u); - gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v); - gradientY.WorldX = FindGradientY(bottomY, v1->worldX, v2->worldX, v3->worldX); - gradientY.WorldY = FindGradientY(bottomY, v1->worldY, v2->worldY, v3->worldY); - gradientY.WorldZ = FindGradientY(bottomY, v1->worldZ, v2->worldZ, v3->worldZ); - gradientY.A = FindGradientY(bottomY, v1->a, v2->a, v3->a); - gradientY.R = FindGradientY(bottomY, v1->r, v2->r, v3->r); - gradientY.G = FindGradientY(bottomY, v1->g, v2->g, v3->g); - gradientY.B = FindGradientY(bottomY, v1->b, v2->b, v3->b); - gradientY.GradientdistZ = FindGradientY(bottomY, v1->gradientdistZ, v2->gradientdistZ, v3->gradientdistZ); - - return true; - } - -private: - float FindGradientX(float bottomX, float c0, float c1, float c2) - { - c0 *= v1->w; - c1 *= v2->w; - c2 *= v3->w; - return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX; - } - - float FindGradientY(float bottomY, float c0, float c1, float c2) - { - c0 *= v1->w; - c1 *= v2->w; - c2 *= v3->w; - return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY; - } -}; - -class ScreenTriangle -{ -public: - static void Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); - -private: - static void(*TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); -}; - -enum SWTestSpan -{ - SWTRI_DepthTest = 1, - SWTRI_StencilTest = 2 -}; diff --git a/src/common/rendering/polyrenderer/poly_all.cpp b/src/common/rendering/polyrenderer/poly_all.cpp deleted file mode 100644 index 64098aa8e..000000000 --- a/src/common/rendering/polyrenderer/poly_all.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "drawers/poly_triangle.cpp" -#include "drawers/poly_thread.cpp" -#include "drawers/screen_triangle.cpp" -#include "drawers/screen_scanline_setup.cpp" -#include "drawers/screen_shader.cpp" -#include "drawers/screen_blend.cpp" diff --git a/src/common/rendering/r_thread.cpp b/src/common/rendering/r_thread.cpp index 0415bd40c..c13ffe8fe 100644 --- a/src/common/rendering/r_thread.cpp +++ b/src/common/rendering/r_thread.cpp @@ -21,21 +21,15 @@ */ #include -#include "templates.h" + #include "i_system.h" #include "filesystem.h" #include "v_video.h" #include "r_thread.h" #include "r_memory.h" -#include "poly_thread.h" #include "printf.h" -#include "polyrenderer/drawers/poly_triangle.h" #include -#ifdef WIN32 -void PeekThreadedErrorPane(); -#endif - CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Int, r_debug_draw, 0, 0); @@ -60,7 +54,7 @@ void DrawerThreads::Execute(DrawerCommandQueuePtr commands) { if (!commands || commands->commands.empty()) return; - + auto queue = Instance(); queue->StartThreads(); @@ -101,12 +95,7 @@ void DrawerThreads::WaitForWorkers() std::unique_lock end_lock(queue->end_mutex); if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; })) { -#ifdef WIN32 - PeekThreadedErrorPane(); -#endif - // Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing - int *threadCrashed = nullptr; - *threadCrashed = 0xdeadbeef; + I_FatalError("Drawer threads did not finish within 5 seconds!"); } end_lock.unlock(); @@ -139,11 +128,6 @@ void DrawerThreads::WorkerMain(DrawerThread *thread) thread->current_queue++; thread->numa_start_y = thread->numa_node * screen->GetHeight() / thread->num_numa_nodes; thread->numa_end_y = (thread->numa_node + 1) * screen->GetHeight() / thread->num_numa_nodes; - if (thread->poly) - { - thread->poly->numa_start_y = thread->numa_start_y; - thread->poly->numa_end_y = thread->numa_end_y; - } start_lock.unlock(); // Do the work: diff --git a/src/common/rendering/r_thread.h b/src/common/rendering/r_thread.h index 87319cf0c..4d44972ac 100644 --- a/src/common/rendering/r_thread.h +++ b/src/common/rendering/r_thread.h @@ -27,15 +27,13 @@ #include #include #include -#include "templates.h" + #include "c_cvars.h" #include "basics.h" // Use multiple threads when drawing EXTERN_CVAR(Int, r_multithreaded) -class PolyTriangleThreadData; - namespace swrenderer { class WallColumnDrawerArgs; } // Worker data for each thread executing drawer commands @@ -64,9 +62,6 @@ public: // Working buffer used by the tilted (sloped) span drawer const uint8_t *tiltlighting[MAXWIDTH]; - std::shared_ptr poly; - std::shared_ptr columndrawer; - size_t debug_draw_pos = 0; // Checks if a line is rendered by this thread @@ -78,7 +73,7 @@ public: // The number of lines to skip to reach the first line to be rendered by this thread int skipped_by_thread(int first_line) { - int clip_first_line = MAX(first_line, numa_start_y); + int clip_first_line = max(first_line, numa_start_y); int core_skip = (num_cores - (clip_first_line - core) % num_cores) % num_cores; return clip_first_line + core_skip - first_line; } @@ -86,9 +81,9 @@ public: // The number of lines to be rendered by this thread int count_for_thread(int first_line, int count) { - count = MIN(count, numa_end_y - first_line); + count = min(count, numa_end_y - first_line); int c = (count - skipped_by_thread(first_line) + num_cores - 1) / num_cores; - return MAX(c, 0); + return max(c, 0); } // Calculate the dest address for the first line to be rendered by this thread @@ -156,17 +151,17 @@ public: static void WaitForWorkers(); static void ResetDebugDrawPos(); - + private: DrawerThreads(); ~DrawerThreads(); - + void StartThreads(); void StopThreads(); void WorkerMain(DrawerThread *thread); static DrawerThreads *Instance(); - + std::mutex threads_mutex; std::vector threads; @@ -182,7 +177,7 @@ private: size_t debug_draw_end = 0; DrawerThread single_core_thread; - + friend class DrawerCommandQueue; }; @@ -192,9 +187,9 @@ class DrawerCommandQueue { public: DrawerCommandQueue(RenderMemory *memoryAllocator); - + void Clear() { commands.clear(); } - + // Queue command to be executed by drawer worker threads template void Push(Types &&... args) @@ -212,13 +207,13 @@ public: command.Execute(&threads->single_core_thread); } } - + private: // Allocate memory valid for the duration of a command execution void *AllocMemory(size_t size); - + std::vector commands; RenderMemory *FrameMemory; - + friend class DrawerThreads; }; diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index 1f5a7bb38..705fe905f 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -34,7 +34,7 @@ #include "c_dispatch.h" #include "c_cvars.h" #include "v_video.h" -#include "templates.h" + #include "r_videoscale.h" #include "cmdlib.h" #include "v_draw.h" @@ -105,7 +105,6 @@ namespace // minimum set in GZDoom 4.0.0, but only while those fonts are required. static bool lastspecialUI = false; - bool isInActualMenu = false; bool specialUI = (!sysCallbacks.IsSpecialUI || sysCallbacks.IsSpecialUI()); @@ -126,7 +125,7 @@ namespace min_height = VID_MIN_UI_HEIGHT; } } - + // the odd formatting of this struct definition is meant to resemble a table header. set your tab stops to 4 when editing this file. struct v_ScaleTable { bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; }; @@ -179,7 +178,7 @@ bool ViewportLinearScale() aspectmult = 1.f / aspectmult; if ((ViewportScaledWidth(x,y) > (x * aspectmult)) || (ViewportScaledHeight(x,y) > (y * aspectmult))) return true; - + return vid_scale_linear; } @@ -193,7 +192,7 @@ int ViewportScaledWidth(int width, int height) width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width; height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height; } - return (int)std::max((int32_t)min_width, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledWidth(width, height))); + return (int)max((int32_t)min_width, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledWidth(width, height))); } int ViewportScaledHeight(int width, int height) @@ -205,7 +204,7 @@ int ViewportScaledHeight(int width, int height) height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height; width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width; } - return (int)std::max((int32_t)min_height, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledHeight(width, height))); + return (int)max((int32_t)min_height, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledHeight(width, height))); } float ViewportPixelAspect() diff --git a/src/common/rendering/v_framebuffer.cpp b/src/common/rendering/v_framebuffer.cpp index d1f148f1b..271348bc1 100644 --- a/src/common/rendering/v_framebuffer.cpp +++ b/src/common/rendering/v_framebuffer.cpp @@ -170,6 +170,8 @@ void DFrameBuffer::SetViewportRects(IntRect *bounds) mSceneViewport = *bounds; mScreenViewport = *bounds; mOutputLetterbox = *bounds; + mGameScreenWidth = mScreenViewport.width; + mGameScreenHeight = mScreenViewport.height; return; } @@ -186,7 +188,7 @@ void DFrameBuffer::SetViewportRects(IntRect *bounds) int screenWidth = GetWidth(); int screenHeight = GetHeight(); float scaleX, scaleY; - scaleX = std::min(clientWidth / (float)screenWidth, clientHeight / ((float)screenHeight * ViewportPixelAspect())); + scaleX = min(clientWidth / (float)screenWidth, clientHeight / ((float)screenHeight * ViewportPixelAspect())); scaleY = scaleX * ViewportPixelAspect(); mOutputLetterbox.width = (int)round(screenWidth * scaleX); mOutputLetterbox.height = (int)round(screenHeight * scaleY); @@ -216,6 +218,9 @@ void DFrameBuffer::SetViewportRects(IntRect *bounds) mSceneViewport.width = (int)round(mSceneViewport.width * scaleX); mSceneViewport.height = (int)round(mSceneViewport.height * scaleY); } + + mGameScreenWidth = GetWidth(); + mGameScreenHeight = GetHeight(); } //=========================================================================== @@ -226,12 +231,12 @@ void DFrameBuffer::SetViewportRects(IntRect *bounds) int DFrameBuffer::ScreenToWindowX(int x) { - return mScreenViewport.left + (int)round(x * mScreenViewport.width / (float)GetWidth()); + return mScreenViewport.left + (int)round(x * mScreenViewport.width / (float)mGameScreenWidth); } int DFrameBuffer::ScreenToWindowY(int y) { - return mScreenViewport.top + mScreenViewport.height - (int)round(y * mScreenViewport.height / (float)GetHeight()); + return mScreenViewport.top + mScreenViewport.height - (int)round(y * mScreenViewport.height / (float)mGameScreenHeight); } void DFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y) diff --git a/src/common/rendering/v_video.cpp b/src/common/rendering/v_video.cpp index 047894466..47caad55e 100644 --- a/src/common/rendering/v_video.cpp +++ b/src/common/rendering/v_video.cpp @@ -61,7 +61,7 @@ #include "texturemanager.h" #include "i_interface.h" #include "v_draw.h" -#include "templates.h" + EXTERN_CVAR(Int, menu_resolution_custom_width) EXTERN_CVAR(Int, menu_resolution_custom_height) @@ -103,12 +103,10 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N { #ifdef HAVE_GLES2 case 3: + case 2: Printf("Selecting OpenGLES 2.0 backend...\n"); break; #endif - case 2: - Printf("Selecting SoftPoly backend...\n"); - break; #ifdef HAVE_VULKAN case 1: Printf("Selecting Vulkan backend...\n"); @@ -121,7 +119,14 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N Printf("Changing the video backend requires a restart for " GAMENAME ".\n"); } -CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window... +int V_GetBackend() +{ + int v = vid_preferbackend; + if (v == 3) v = 2; + else if (v < 0 || v > 3) v = 0; + return v; +} + CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL) { @@ -219,13 +224,13 @@ void DCanvas::Resize(int width, int height, bool optimizepitch) { Width = width; Height = height; - + // Making the pitch a power of 2 is very bad for performance // Try to maximize the number of cache lines that can be filled // for each column drawing operation by making the pitch slightly // longer than the width. The values used here are all based on // empirical evidence. - + if (width <= 640 || !optimizepitch) { // For low resolutions, just keep the pitch the same as the width. @@ -252,7 +257,7 @@ void DCanvas::Resize(int width, int height, bool optimizepitch) } else { - Pitch = width + MAX(0, CPU.DataL1LineSize - 8); + Pitch = width + max(0, CPU.DataL1LineSize - 8); } } int bytes_per_pixel = Bgra ? 4 : 1; @@ -275,13 +280,19 @@ void V_UpdateModeSize (int width, int height) // This reference size is being used so that on 800x450 (small 16:9) a scale of 2 gets used. - CleanXfac = std::max(std::min(screen->GetWidth() / 400, screen->GetHeight() / 240), 1); + CleanXfac = max(min(screen->GetWidth() / 400, screen->GetHeight() / 240), 1); if (CleanXfac >= 4) CleanXfac--; // Otherwise we do not have enough space for the episode/skill menus in some languages. CleanYfac = CleanXfac; CleanWidth = screen->GetWidth() / CleanXfac; CleanHeight = screen->GetHeight() / CleanYfac; int w = screen->GetWidth(); + int h = screen->GetHeight(); + + // clamp screen aspect ratio to 17:10, for anything wider the width will be reduced + double aspect = (double)w / h; + if (aspect > 1.7) w = int(w * 1.7 / aspect); + int factor; if (w < 640) factor = 1; else if (w >= 1024 && w < 1280) factor = 2; @@ -292,7 +303,7 @@ void V_UpdateModeSize (int width, int height) else if (w < 1920) factor = 2; else factor = int(factor * 0.7); - CleanYfac_1 = CleanXfac_1 = factor;// MAX(1, int(factor * 0.7)); + CleanYfac_1 = CleanXfac_1 = factor;// max(1, int(factor * 0.7)); CleanWidth_1 = width / CleanXfac_1; CleanHeight_1 = height / CleanYfac_1; @@ -337,15 +348,15 @@ void V_InitScreenSize () { const char *i; int width, height, bits; - + width = height = bits = 0; - + if ( (i = Args->CheckValue ("-width")) ) width = atoi (i); - + if ( (i = Args->CheckValue ("-height")) ) height = atoi (i); - + if (width == 0) { if (height == 0) @@ -374,8 +385,6 @@ void V_InitScreen() void V_Init2() { - float gamma = static_cast(screen)->Gamma; - { DFrameBuffer *s = screen; screen = NULL; @@ -385,7 +394,7 @@ void V_Init2() UCVarValue val; val.Bool = !!Args->CheckParm("-devparm"); - ticker.SetGenericRepDefault(val, CVAR_Bool); + ticker->SetGenericRepDefault(val, CVAR_Bool); I_InitGraphics(); diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index b78afd4b0..afba5784a 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -43,6 +43,7 @@ #include "v_2ddrawer.h" #include "intrect.h" #include "hw_shadowmap.h" +#include "hw_levelmesh.h" #include "buffers.h" @@ -58,6 +59,7 @@ struct HWDrawInfo; class FMaterial; class FGameTexture; class FRenderState; +class BoneBuffer; enum EHWCaps { @@ -142,8 +144,11 @@ public: FFlatVertexBuffer *mVertexData = nullptr; // Global vertex data HWViewpointBuffer *mViewpoints = nullptr; // Viewpoint render data. FLightBuffer *mLights = nullptr; // Dynamic lights + BoneBuffer* mBones = nullptr; // Model bones IShadowMap mShadowMap; + int mGameScreenWidth = 0; + int mGameScreenHeight = 0; IntRect mScreenViewport; IntRect mSceneViewport; IntRect mOutputLetterbox; @@ -151,17 +156,20 @@ public: int mPipelineNbr = 1; // Number of HW buffers to pipeline int mPipelineType = 0; - + public: DFrameBuffer (int width=1, int height=1); virtual ~DFrameBuffer(); virtual void InitializeState() = 0; // For stuff that needs 'screen' set. virtual bool IsVulkan() { return false; } virtual bool IsPoly() { return false; } + virtual int GetShaderCount(); + virtual bool CompileNextShader() { return true; } void SetAABBTree(hwrenderer::LevelAABBTree * tree) { mShadowMap.SetAABBTree(tree); } + virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { } bool allowSSBO() { #ifndef HW_BLOCK_SSBO @@ -219,7 +227,9 @@ public: 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 IVertexBuffer *CreateVertexBuffer() { return nullptr; } virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; } @@ -288,7 +298,6 @@ extern DFrameBuffer *screen; #define SCREENWIDTH (screen->GetWidth ()) #define SCREENHEIGHT (screen->GetHeight ()) -#define SCREENPITCH (screen->GetPitch ()) EXTERN_CVAR (Float, vid_gamma) @@ -301,6 +310,7 @@ void V_InitScreen(); void V_Init2 (); void V_Shutdown (); +int V_GetBackend(); inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; } extern bool setsizeneeded, setmodeneeded; diff --git a/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp b/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp new file mode 100644 index 000000000..1c36f865b --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp @@ -0,0 +1,291 @@ +/* +** 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_descriptorset.h" +#include "vk_streambuffer.h" +#include "vk_raytrace.h" +#include "vulkan/shaders/vk_shader.h" +#include "vulkan/textures/vk_samplers.h" +#include "vulkan/textures/vk_renderbuffers.h" +#include "vulkan/textures/vk_hwtexture.h" +#include "vulkan/textures/vk_texture.h" +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_hwbuffer.h" +#include "vulkan/system/vk_commandbuffer.h" +#include "vulkan/system/vk_buffer.h" +#include "flatvertices.h" +#include "hw_viewpointuniforms.h" +#include "v_2ddrawer.h" + +VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb) +{ + CreateHWBufferSetLayout(); + CreateFixedSetLayout(); + CreateHWBufferPool(); + CreateFixedSetPool(); +} + +VkDescriptorSetManager::~VkDescriptorSetManager() +{ + while (!Materials.empty()) + RemoveMaterial(Materials.back()); +} + +void VkDescriptorSetManager::Init() +{ + UpdateFixedSet(); + UpdateHWBufferSet(); +} + +void VkDescriptorSetManager::Deinit() +{ + while (!Materials.empty()) + RemoveMaterial(Materials.back()); +} + +void VkDescriptorSetManager::BeginFrame() +{ + UpdateFixedSet(); + UpdateHWBufferSet(); +} + +void VkDescriptorSetManager::UpdateHWBufferSet() +{ + fb->GetCommands()->DrawDeleteList->Add(std::move(HWBufferSet)); + + HWBufferSet = HWBufferDescriptorPool->tryAllocate(HWBufferSetLayout.get()); + if (!HWBufferSet) + { + fb->GetCommands()->WaitForCommands(false); + HWBufferSet = HWBufferDescriptorPool->allocate(HWBufferSetLayout.get()); + } + + WriteDescriptors() + .AddBuffer(HWBufferSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms)) + .AddBuffer(HWBufferSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO)) + .AddBuffer(HWBufferSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO)) + .AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightBufferSSO->mBuffer.get()) + .AddBuffer(HWBufferSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->BoneBufferSSO->mBuffer.get()) + .Execute(fb->device.get()); +} + +void VkDescriptorSetManager::UpdateFixedSet() +{ + fb->GetCommands()->DrawDeleteList->Add(std::move(FixedSet)); + + FixedSet = FixedDescriptorPool->tryAllocate(FixedSetLayout.get()); + if (!FixedSet) + { + fb->GetCommands()->WaitForCommands(false); + FixedSet = FixedDescriptorPool->allocate(FixedSetLayout.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->RaytracingEnabled()) + update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct()); + update.Execute(fb->device.get()); +} + +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->device.get()); + } + + return NullTextureDescriptorSet.get(); +} + +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->device.get())); + } + + 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->device.get()); + return layout.get(); +} + +void VkDescriptorSetManager::AddMaterial(VkMaterial* texture) +{ + texture->it = Materials.insert(Materials.end(), texture); +} + +void VkDescriptorSetManager::RemoveMaterial(VkMaterial* texture) +{ + texture->DeleteDescriptors(); + texture->fb = nullptr; + Materials.erase(texture->it); +} + +VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers) +{ + auto descriptors = AllocatePPDescriptorSet(passSetup->DescriptorLayout.get()); + descriptors->SetDebugName("VkPostprocess.descriptors"); + + WriteDescriptors write; + VkImageTransition imageTransition; + + for (unsigned int index = 0; index < textures.Size(); index++) + { + const PPTextureInput& input = textures[index]; + VulkanSampler* sampler = fb->GetSamplerManager()->Get(input.Filter, input.Wrap); + VkTextureImage* tex = fb->GetTextureManager()->GetTexture(input.Type, input.Texture); + + write.AddCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + } + + if (bindShadowMapBuffers) + { + write.AddBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get()); + write.AddBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get()); + write.AddBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get()); + } + + write.Execute(fb->device.get()); + imageTransition.Execute(fb->GetCommands()->GetDrawCommands()); + + VulkanDescriptorSet* set = descriptors.get(); + fb->GetCommands()->DrawDeleteList->Add(std::move(descriptors)); + return set; +} + +std::unique_ptr VkDescriptorSetManager::AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout) +{ + if (PPDescriptorPool) + { + auto descriptors = PPDescriptorPool->tryAllocate(layout); + if (descriptors) + return descriptors; + + fb->GetCommands()->DrawDeleteList->Add(std::move(PPDescriptorPool)); + } + + PPDescriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4) + .MaxSets(100) + .DebugName("PPDescriptorPool") + .Create(fb->device.get()); + + return PPDescriptorPool->allocate(layout); +} + +void VkDescriptorSetManager::CreateHWBufferSetLayout() +{ + HWBufferSetLayout = 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_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT) + .AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT) + .DebugName("VkDescriptorSetManager.HWBufferSetLayout") + .Create(fb->device.get()); +} + +void VkDescriptorSetManager::CreateFixedSetLayout() +{ + 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->RaytracingEnabled()) + builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.DebugName("VkDescriptorSetManager.FixedSetLayout"); + FixedSetLayout = builder.Create(fb->device.get()); +} + +void VkDescriptorSetManager::CreateHWBufferPool() +{ + HWBufferDescriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3 * maxSets) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 * maxSets) + .MaxSets(maxSets) + .DebugName("VkDescriptorSetManager.HWBufferDescriptorPool") + .Create(fb->device.get()); +} + +void VkDescriptorSetManager::CreateFixedSetPool() +{ + DescriptorPoolBuilder poolbuilder; + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets); + if (fb->RaytracingEnabled()) + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets); + poolbuilder.MaxSets(maxSets); + poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool"); + FixedDescriptorPool = poolbuilder.Create(fb->device.get()); +} diff --git a/src/common/rendering/vulkan/renderer/vk_descriptorset.h b/src/common/rendering/vulkan/renderer/vk_descriptorset.h new file mode 100644 index 000000000..bbba2a918 --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_descriptorset.h @@ -0,0 +1,71 @@ + +#pragma once + +#include "zvulkan/vulkanobjects.h" +#include +#include "tarray.h" + +class VulkanRenderDevice; +class VkMaterial; +class PPTextureInput; +class VkPPRenderPassSetup; + +class VkDescriptorSetManager +{ +public: + VkDescriptorSetManager(VulkanRenderDevice* fb); + ~VkDescriptorSetManager(); + + void Init(); + void Deinit(); + void BeginFrame(); + void UpdateFixedSet(); + void UpdateHWBufferSet(); + void ResetHWTextureSets(); + + VulkanDescriptorSetLayout* GetHWBufferSetLayout() { return HWBufferSetLayout.get(); } + VulkanDescriptorSetLayout* GetFixedSetLayout() { return FixedSetLayout.get(); } + VulkanDescriptorSetLayout* GetTextureSetLayout(int numLayers); + + VulkanDescriptorSet* GetHWBufferDescriptorSet() { return HWBufferSet.get(); } + VulkanDescriptorSet* GetFixedDescriptorSet() { return FixedSet.get(); } + VulkanDescriptorSet* GetNullTextureDescriptorSet(); + + std::unique_ptr AllocateTextureDescriptorSet(int numLayers); + + VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers); + + void AddMaterial(VkMaterial* texture); + void RemoveMaterial(VkMaterial* texture); + +private: + void CreateHWBufferSetLayout(); + void CreateFixedSetLayout(); + void CreateHWBufferPool(); + void CreateFixedSetPool(); + + std::unique_ptr AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout); + + VulkanRenderDevice* fb = nullptr; + + std::unique_ptr HWBufferSetLayout; + std::unique_ptr FixedSetLayout; + std::vector> TextureSetLayouts; + + std::unique_ptr HWBufferDescriptorPool; + std::unique_ptr FixedDescriptorPool; + + std::unique_ptr PPDescriptorPool; + + int TextureDescriptorSetsLeft = 0; + int TextureDescriptorsLeft = 0; + std::vector> TextureDescriptorPools; + + std::unique_ptr HWBufferSet; + std::unique_ptr FixedSet; + std::unique_ptr NullTextureDescriptorSet; + + std::list Materials; + + static const int maxSets = 10; +}; diff --git a/src/common/rendering/vulkan/renderer/vk_postprocess.cpp b/src/common/rendering/vulkan/renderer/vk_postprocess.cpp index 9d1702834..20ca83fd6 100644 --- a/src/common/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/common/rendering/vulkan/renderer/vk_postprocess.cpp @@ -21,26 +21,30 @@ */ #include "vk_postprocess.h" -#include "vk_renderbuffers.h" #include "vulkan/shaders/vk_shader.h" -#include "vulkan/system/vk_builders.h" -#include "vulkan/system/vk_framebuffer.h" -#include "vulkan/system/vk_buffers.h" -#include "vulkan/system/vk_swapchain.h" +#include +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_hwbuffer.h" +#include "vulkan/system/vk_commandbuffer.h" #include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/renderer/vk_pprenderstate.h" +#include "vulkan/shaders/vk_ppshader.h" +#include "vulkan/textures/vk_pptexture.h" +#include "vulkan/textures/vk_renderbuffers.h" #include "vulkan/textures/vk_imagetransition.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/textures/vk_framebuffer.h" #include "hw_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" #include "hw_vrmodes.h" #include "flatvertices.h" #include "r_videoscale.h" -#include "filesystem.h" -#include "templates.h" EXTERN_CVAR(Int, gl_dither_bpc) -VkPostprocess::VkPostprocess() +VkPostprocess::VkPostprocess(VulkanRenderDevice* fb) : fb(fb) { } @@ -50,23 +54,22 @@ VkPostprocess::~VkPostprocess() void VkPostprocess::SetActiveRenderTarget() { - auto fb = GetVulkanFrameBuffer(); auto buffers = fb->GetBuffers(); - VkImageTransition imageTransition; - imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); - imageTransition.execute(fb->GetDrawCommands()); + VkImageTransition() + .AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false) + .AddImage(&buffers->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false) + .Execute(fb->GetCommands()->GetDrawCommands()); - fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, 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) { - auto fb = GetVulkanFrameBuffer(); int sceneWidth = fb->GetBuffers()->GetSceneWidth(); int sceneHeight = fb->GetBuffers()->GetSceneHeight(); - VkPPRenderState renderstate; + VkPPRenderState renderstate(fb); hw_postprocess.Pass1(&renderstate, fixedcm, sceneWidth, sceneHeight); SetActiveRenderTarget(); @@ -76,19 +79,17 @@ void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::functi void VkPostprocess::BlitSceneToPostprocess() { - auto fb = GetVulkanFrameBuffer(); - fb->GetRenderState()->EndRenderPass(); auto buffers = fb->GetBuffers(); - auto cmdbuffer = fb->GetDrawCommands(); + auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); mCurrentPipelineImage = 0; - VkImageTransition imageTransition; - imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); - imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - imageTransition.execute(fb->GetDrawCommands()); + VkImageTransition() + .AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false) + .AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true) + .Execute(fb->GetCommands()->GetDrawCommands()); if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT) { @@ -135,30 +136,27 @@ void VkPostprocess::BlitSceneToPostprocess() void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout) { - auto fb = GetVulkanFrameBuffer(); auto buffers = fb->GetBuffers(); - VkImageTransition imageTransition; - imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.execute(fb->GetDrawCommands()); + VkImageTransition() + .AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout) + .AddImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout) + .AddImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout) + .AddImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout) + .Execute(fb->GetCommands()->GetDrawCommands()); } void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout) { - auto fb = GetVulkanFrameBuffer(); - fb->GetRenderState()->EndRenderPass(); auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage]; - auto cmdbuffer = fb->GetDrawCommands(); + auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); - VkImageTransition imageTransition0; - imageTransition0.addImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); - imageTransition0.addImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - imageTransition0.execute(cmdbuffer); + VkImageTransition() + .AddImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false) + .AddImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true) + .Execute(cmdbuffer); VkImageBlit blit = {}; blit.srcOffsets[0] = { 0, 0, 0 }; @@ -173,21 +171,20 @@ void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout f blit.dstSubresource.mipLevel = 0; blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.layerCount = 1; + cmdbuffer->blitImage( srcimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); - VkImageTransition imageTransition1; - imageTransition1.addImage(dstimage, finallayout, false); - imageTransition1.execute(cmdbuffer); + VkImageTransition() + .AddImage(dstimage, finallayout, false) + .Execute(cmdbuffer); } void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot) { - auto fb = GetVulkanFrameBuffer(); - - VkPPRenderState renderstate; + VkPPRenderState renderstate(fb); if (!screenshot) // Already applied as we are actually copying the last frame here (GetScreenshotBuffer is called after swap) hw_postprocess.customShaders.Run(&renderstate, "screen"); @@ -221,7 +218,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool uniforms.Offset = { 0.0f, 1.0f }; } - if (applyGamma && fb->swapChain->IsHdrModeActive() && !screenshot) + if (applyGamma && fb->GetFramebufferManager()->SwapChain->Format().colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT && !screenshot) { uniforms.HdrMode = 1; } @@ -246,11 +243,10 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool void VkPostprocess::AmbientOccludeScene(float m5) { - auto fb = GetVulkanFrameBuffer(); int sceneWidth = fb->GetBuffers()->GetSceneWidth(); int sceneHeight = fb->GetBuffers()->GetSceneHeight(); - VkPPRenderState renderstate; + VkPPRenderState renderstate(fb); hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight); ImageTransitionScene(false); @@ -258,11 +254,10 @@ void VkPostprocess::AmbientOccludeScene(float m5) void VkPostprocess::BlurScene(float gameinfobluramount) { - auto fb = GetVulkanFrameBuffer(); int sceneWidth = fb->GetBuffers()->GetSceneWidth(); int sceneHeight = fb->GetBuffers()->GetSceneHeight(); - VkPPRenderState renderstate; + VkPPRenderState renderstate(fb); auto vrmode = VRMode::GetVRMode(true); int eyeCount = vrmode->mEyeCount; @@ -282,537 +277,17 @@ void VkPostprocess::UpdateShadowMap() { if (screen->mShadowMap.PerformUpdate()) { - VkPPRenderState renderstate; + VkPPRenderState renderstate(fb); hw_postprocess.shadowmap.Update(&renderstate); - auto fb = GetVulkanFrameBuffer(); - auto buffers = fb->GetBuffers(); - - VkImageTransition imageTransition; - imageTransition.addImage(&buffers->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - imageTransition.execute(fb->GetDrawCommands()); + VkImageTransition() + .AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .Execute(fb->GetCommands()->GetDrawCommands()); screen->mShadowMap.FinishUpdate(); } } -std::unique_ptr VkPostprocess::AllocateDescriptorSet(VulkanDescriptorSetLayout *layout) -{ - if (mDescriptorPool) - { - auto descriptors = mDescriptorPool->tryAllocate(layout); - if (descriptors) - return descriptors; - - GetVulkanFrameBuffer()->FrameDeleteList.DescriptorPools.push_back(std::move(mDescriptorPool)); - } - - DescriptorPoolBuilder builder; - builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200); - builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4); - builder.setMaxSets(100); - mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device); - mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool"); - - return mDescriptorPool->allocate(layout); -} - -void VkPostprocess::RenderBuffersReset() -{ - mRenderPassSetup.clear(); -} - -VulkanSampler *VkPostprocess::GetSampler(PPFilterMode filter, PPWrapMode wrap) -{ - int index = (((int)filter) << 1) | (int)wrap; - auto &sampler = mSamplers[index]; - if (sampler) - return sampler.get(); - - SamplerBuilder builder; - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); - builder.setMagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); - builder.setAddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT); - sampler = builder.create(GetVulkanFrameBuffer()->device); - sampler->SetDebugName("VkPostprocess.mSamplers"); - return sampler.get(); -} - void VkPostprocess::NextEye(int eyeCount) { } - -///////////////////////////////////////////////////////////////////////////// - -VkPPTexture::VkPPTexture(PPTexture *texture) -{ - auto fb = GetVulkanFrameBuffer(); - - VkFormat format; - int pixelsize; - switch (texture->Format) - { - default: - case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break; - case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break; - case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break; - case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break; - case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break; - } - - ImageBuilder imgbuilder; - imgbuilder.setFormat(format); - imgbuilder.setSize(texture->Width, texture->Height); - if (texture->Data) - imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - else - imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - if (!imgbuilder.isFormatSupported(fb->device)) - I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n"); - TexImage.Image = imgbuilder.create(fb->device); - TexImage.Image->SetDebugName("VkPPTexture"); - Format = format; - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(TexImage.Image.get(), format); - TexImage.View = viewbuilder.create(fb->device); - TexImage.View->SetDebugName("VkPPTextureView"); - - if (texture->Data) - { - size_t totalsize = texture->Width * texture->Height * pixelsize; - BufferBuilder stagingbuilder; - stagingbuilder.setSize(totalsize); - stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - Staging = stagingbuilder.create(fb->device); - Staging->SetDebugName("VkPPTextureStaging"); - - VkImageTransition barrier0; - barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - barrier0.execute(fb->GetTransferCommands()); - - void *data = Staging->Map(0, totalsize); - memcpy(data, texture->Data.get(), totalsize); - Staging->Unmap(); - - VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.depth = 1; - region.imageExtent.width = texture->Width; - region.imageExtent.height = texture->Height; - fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - - VkImageTransition barrier1; - barrier1.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - barrier1.execute(fb->GetTransferCommands()); - } - else - { - VkImageTransition barrier; - barrier.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier.execute(fb->GetTransferCommands()); - } -} - -VkPPTexture::~VkPPTexture() -{ - if (auto fb = GetVulkanFrameBuffer()) - { - if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image)); - if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View)); - if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView)); - if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer)); - if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging)); - } -} - -///////////////////////////////////////////////////////////////////////////// - -VkPPShader::VkPPShader(PPShader *shader) -{ - auto fb = GetVulkanFrameBuffer(); - - FString prolog; - if (!shader->Uniforms.empty()) - prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1); - prolog += shader->Defines; - - ShaderBuilder vertbuilder; - vertbuilder.setVertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version)); - VertexShader = vertbuilder.create(shader->VertexShader.GetChars(), fb->device); - VertexShader->SetDebugName(shader->VertexShader.GetChars()); - - ShaderBuilder fragbuilder; - fragbuilder.setFragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version)); - FragmentShader = fragbuilder.create(shader->FragmentShader.GetChars(), fb->device); - FragmentShader->SetDebugName(shader->FragmentShader.GetChars()); -} - -FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version) -{ - int lump = fileSystem.CheckNumForFullName(lumpName); - if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars()); - FString code = fileSystem.ReadFile(lump).GetString().GetChars(); - - FString patchedCode; - patchedCode.AppendFormat("#version %d\n", 450); - patchedCode << defines; - patchedCode << "#line 1\n"; - patchedCode << code; - return patchedCode; -} - -///////////////////////////////////////////////////////////////////////////// - -void VkPPRenderState::PushGroup(const FString &name) -{ - GetVulkanFrameBuffer()->PushGroup(name); -} - -void VkPPRenderState::PopGroup() -{ - GetVulkanFrameBuffer()->PopGroup(); -} - -void VkPPRenderState::Draw() -{ - auto fb = GetVulkanFrameBuffer(); - auto pp = fb->GetPostprocess(); - - fb->GetRenderState()->EndRenderPass(); - - VkPPRenderPassKey key; - key.BlendMode = BlendMode; - key.InputTextures = Textures.Size(); - key.Uniforms = Uniforms.Data.Size(); - key.Shader = GetVkShader(Shader); - key.SwapChain = (Output.Type == PPTextureType::SwapChain); - key.ShadowMapBuffers = ShadowMapBuffers; - if (Output.Type == PPTextureType::PPTexture) - key.OutputFormat = GetVkTexture(Output.Texture)->Format; - else if (Output.Type == PPTextureType::SwapChain) - key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format; - else if (Output.Type == PPTextureType::ShadowMap) - key.OutputFormat = VK_FORMAT_R32_SFLOAT; - else - key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; - - if (Output.Type == PPTextureType::SceneColor) - { - key.StencilTest = 1; - key.Samples = fb->GetBuffers()->GetSceneSamples(); - } - else - { - key.StencilTest = 0; - key.Samples = VK_SAMPLE_COUNT_1_BIT; - } - - auto &passSetup = pp->mRenderPassSetup[key]; - if (!passSetup) - passSetup.reset(new VkPPRenderPassSetup(key)); - - int framebufferWidth = 0, framebufferHeight = 0; - VulkanDescriptorSet *input = GetInput(passSetup.get(), Textures, ShadowMapBuffers); - VulkanFramebuffer *output = GetOutput(passSetup.get(), Output, key.StencilTest, framebufferWidth, framebufferHeight); - - RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest); - - // Advance to next PP texture if our output was sent there - if (Output.Type == PPTextureType::NextPipelineTexture) - { - pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages; - } -} - -void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest) -{ - auto fb = GetVulkanFrameBuffer(); - auto cmdbuffer = fb->GetDrawCommands(); - - VkViewport viewport = { }; - viewport.x = (float)x; - viewport.y = (float)y; - viewport.width = (float)width; - viewport.height = (float)height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = { }; - scissor.offset.x = 0; - scissor.offset.y = 0; - scissor.extent.width = framebufferWidth; - scissor.extent.height = framebufferHeight; - - RenderPassBegin beginInfo; - beginInfo.setRenderPass(passSetup->RenderPass.get()); - beginInfo.setRenderArea(0, 0, framebufferWidth, framebufferHeight); - beginInfo.setFramebuffer(framebuffer); - beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - VkBuffer vertexBuffers[] = { static_cast(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer }; - VkDeviceSize offsets[] = { 0 }; - - cmdbuffer->beginRenderPass(beginInfo); - cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get()); - cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet); - cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets); - cmdbuffer->setViewport(0, 1, &viewport); - cmdbuffer->setScissor(0, 1, &scissor); - if (stencilTest) - cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue); - if (pushConstantsSize > 0) - cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants); - cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0); - cmdbuffer->endRenderPass(); -} - -VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures, bool bindShadowMapBuffers) -{ - auto fb = GetVulkanFrameBuffer(); - auto pp = fb->GetPostprocess(); - auto descriptors = pp->AllocateDescriptorSet(passSetup->DescriptorLayout.get()); - descriptors->SetDebugName("VkPostprocess.descriptors"); - - WriteDescriptors write; - VkImageTransition imageTransition; - - for (unsigned int index = 0; index < textures.Size(); index++) - { - const PPTextureInput &input = textures[index]; - VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap); - VkTextureImage *tex = GetTexture(input.Type, input.Texture); - - write.addCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageTransition.addImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - } - - if (bindShadowMapBuffers) - { - write.addBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightNodes->mBuffer.get()); - write.addBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightLines->mBuffer.get()); - write.addBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightList->mBuffer.get()); - } - - write.updateSets(fb->device); - imageTransition.execute(fb->GetDrawCommands()); - - VulkanDescriptorSet *set = descriptors.get(); - fb->FrameDeleteList.Descriptors.push_back(std::move(descriptors)); - return set; -} - -VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight) -{ - auto fb = GetVulkanFrameBuffer(); - - VkTextureImage *tex = GetTexture(output.Type, output.Texture); - - VkImageView view; - std::unique_ptr *framebufferptr = nullptr; - int w, h; - if (tex) - { - VkImageTransition imageTransition; - imageTransition.addImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture); - if (stencilTest) - imageTransition.addImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); - imageTransition.execute(fb->GetDrawCommands()); - - view = tex->View->view; - w = tex->Image->width; - h = tex->Image->height; - framebufferptr = &tex->PPFramebuffer; - } - else - { - view = fb->swapChain->swapChainImageViews[fb->presentImageIndex]; - framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex]; - w = fb->swapChain->actualExtent.width; - h = fb->swapChain->actualExtent.height; - } - - auto &framebuffer = *framebufferptr; - if (!framebuffer) - { - FramebufferBuilder builder; - builder.setRenderPass(passSetup->RenderPass.get()); - builder.setSize(w, h); - builder.addAttachment(view); - if (stencilTest) - builder.addAttachment(fb->GetBuffers()->SceneDepthStencil.View.get()); - framebuffer = builder.create(GetVulkanFrameBuffer()->device); - } - - framebufferWidth = w; - framebufferHeight = h; - return framebuffer.get(); -} - -VkTextureImage *VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture) -{ - auto fb = GetVulkanFrameBuffer(); - - if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture) - { - int idx = fb->GetPostprocess()->mCurrentPipelineImage; - if (type == PPTextureType::NextPipelineTexture) - idx = (idx + 1) % VkRenderBuffers::NumPipelineImages; - - return &fb->GetBuffers()->PipelineImage[idx]; - } - else if (type == PPTextureType::PPTexture) - { - auto vktex = GetVkTexture(pptexture); - return &vktex->TexImage; - } - else if (type == PPTextureType::SceneColor) - { - return &fb->GetBuffers()->SceneColor; - } - else if (type == PPTextureType::SceneNormal) - { - return &fb->GetBuffers()->SceneNormal; - } - else if (type == PPTextureType::SceneFog) - { - return &fb->GetBuffers()->SceneFog; - } - else if (type == PPTextureType::SceneDepth) - { - return &fb->GetBuffers()->SceneDepthStencil; - } - else if (type == PPTextureType::ShadowMap) - { - return &fb->GetBuffers()->Shadowmap; - } - else if (type == PPTextureType::SwapChain) - { - return nullptr; - } - else - { - I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type"); - return nullptr; - } -} - -VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader) -{ - if (!shader->Backend) - shader->Backend = std::make_unique(shader); - return static_cast(shader->Backend.get()); -} - -VkPPTexture *VkPPRenderState::GetVkTexture(PPTexture *texture) -{ - if (!texture->Backend) - texture->Backend = std::make_unique(texture); - return static_cast(texture->Backend.get()); -} - -///////////////////////////////////////////////////////////////////////////// - -VkPPRenderPassSetup::VkPPRenderPassSetup(const VkPPRenderPassKey &key) -{ - CreateDescriptorLayout(key); - CreatePipelineLayout(key); - CreateRenderPass(key); - CreatePipeline(key); -} - -void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey &key) -{ - DescriptorSetLayoutBuilder builder; - for (int i = 0; i < key.InputTextures; i++) - builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - if (key.ShadowMapBuffers) - { - builder.addBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - } - DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device); - DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout"); -} - -void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey &key) -{ - PipelineLayoutBuilder builder; - builder.addSetLayout(DescriptorLayout.get()); - if (key.Uniforms > 0) - builder.addPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms); - PipelineLayout = builder.create(GetVulkanFrameBuffer()->device); - PipelineLayout->SetDebugName("VkPPRenderPassSetup.PipelineLayout"); -} - -void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey &key) -{ - GraphicsPipelineBuilder builder; - builder.addVertexShader(key.Shader->VertexShader.get()); - builder.addFragmentShader(key.Shader->FragmentShader.get()); - - builder.addVertexBufferBinding(0, sizeof(FFlatVertex)); - builder.addVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x)); - builder.addVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u)); - builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT); - builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR); - // Note: the actual values are ignored since we use dynamic viewport+scissor states - builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f); - builder.setScissor(0, 0, 320, 200); - if (key.StencilTest) - { - builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); - builder.setDepthStencilEnable(false, false, true); - builder.setStencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0); - } - builder.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); - builder.setBlendMode(key.BlendMode); - builder.setRasterizationSamples(key.Samples); - builder.setLayout(PipelineLayout.get()); - builder.setRenderPass(RenderPass.get()); - Pipeline = builder.create(GetVulkanFrameBuffer()->device); - Pipeline->SetDebugName("VkPPRenderPassSetup.Pipeline"); -} - -void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key) -{ - RenderPassBuilder builder; - if (key.SwapChain) - builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - else - builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - if (key.StencilTest) - { - builder.addDepthStencilAttachment( - GetVulkanFrameBuffer()->GetBuffers()->SceneDepthStencilFormat, key.Samples, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - } - - builder.addSubpass(); - builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - if (key.StencilTest) - { - builder.addSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - builder.addExternalSubpassDependency( - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT); - } - else - { - builder.addExternalSubpassDependency( - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT); - } - - RenderPass = builder.create(GetVulkanFrameBuffer()->device); - RenderPass->SetDebugName("VkPPRenderPassSetup.RenderPass"); -} diff --git a/src/common/rendering/vulkan/renderer/vk_postprocess.h b/src/common/rendering/vulkan/renderer/vk_postprocess.h index 67660fe51..138113837 100644 --- a/src/common/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/common/rendering/vulkan/renderer/vk_postprocess.h @@ -6,43 +6,23 @@ #include #include "hwrenderer/postprocessing/hw_postprocess.h" -#include "vulkan/system/vk_objects.h" -#include "vulkan/system/vk_builders.h" +#include "zvulkan/vulkanobjects.h" +#include "zvulkan/vulkanbuilders.h" #include "vulkan/textures/vk_imagetransition.h" class FString; class VkPPShader; class VkPPTexture; -class VkPPRenderPassSetup; class PipelineBarrier; - -class VkPPRenderPassKey -{ -public: - VkPPShader *Shader; - int Uniforms; - int InputTextures; - PPBlendMode BlendMode; - VkFormat OutputFormat; - int SwapChain; - int ShadowMapBuffers; - int StencilTest; - VkSampleCountFlagBits Samples; - - bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; } - bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; } - bool operator!=(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; } -}; +class VulkanRenderDevice; class VkPostprocess { public: - VkPostprocess(); + VkPostprocess(VulkanRenderDevice* fb); ~VkPostprocess(); - void RenderBuffersReset(); - void SetActiveRenderTarget(); void PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D); @@ -58,76 +38,14 @@ public: void BlitCurrentToImage(VkTextureImage *image, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot); + int GetCurrentPipelineImage() const { return mCurrentPipelineImage; } + private: void NextEye(int eyeCount); - std::unique_ptr AllocateDescriptorSet(VulkanDescriptorSetLayout *layout); - VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap); + VulkanRenderDevice* fb = nullptr; - std::array, 4> mSamplers; - std::map> mRenderPassSetup; - std::unique_ptr mDescriptorPool; int mCurrentPipelineImage = 0; friend class VkPPRenderState; }; - -class VkPPShader : public PPShaderBackend -{ -public: - VkPPShader(PPShader *shader); - - std::unique_ptr VertexShader; - std::unique_ptr FragmentShader; - -private: - FString LoadShaderCode(const FString &lumpname, const FString &defines, int version); -}; - -class VkPPTexture : public PPTextureBackend -{ -public: - VkPPTexture(PPTexture *texture); - ~VkPPTexture(); - - VkTextureImage TexImage; - std::unique_ptr Staging; - VkFormat Format; -}; - -class VkPPRenderPassSetup -{ -public: - VkPPRenderPassSetup(const VkPPRenderPassKey &key); - - std::unique_ptr DescriptorLayout; - std::unique_ptr PipelineLayout; - std::unique_ptr RenderPass; - std::unique_ptr Pipeline; - -private: - void CreateDescriptorLayout(const VkPPRenderPassKey &key); - void CreatePipelineLayout(const VkPPRenderPassKey &key); - void CreatePipeline(const VkPPRenderPassKey &key); - void CreateRenderPass(const VkPPRenderPassKey &key); -}; - -class VkPPRenderState : public PPRenderState -{ -public: - void PushGroup(const FString &name) override; - void PopGroup() override; - - void Draw() override; - -private: - void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest); - - VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures, bool bindShadowMapBuffers); - VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight); - - VkPPShader *GetVkShader(PPShader *shader); - VkPPTexture *GetVkTexture(PPTexture *texture); - - VkTextureImage *GetTexture(const PPTextureType &type, PPTexture *tex); -}; diff --git a/src/common/rendering/vulkan/renderer/vk_pprenderstate.cpp b/src/common/rendering/vulkan/renderer/vk_pprenderstate.cpp new file mode 100644 index 000000000..838ca3fe2 --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_pprenderstate.cpp @@ -0,0 +1,139 @@ +/* +** 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_pprenderstate.h" +#include "vk_postprocess.h" +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" +#include +#include "vulkan/system/vk_buffer.h" +#include "vulkan/shaders/vk_ppshader.h" +#include "vulkan/textures/vk_pptexture.h" +#include "vulkan/textures/vk_renderbuffers.h" +#include "vulkan/textures/vk_samplers.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/textures/vk_framebuffer.h" +#include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/renderer/vk_descriptorset.h" +#include "flatvertices.h" + +VkPPRenderState::VkPPRenderState(VulkanRenderDevice* fb) : fb(fb) +{ +} + +void VkPPRenderState::PushGroup(const FString &name) +{ + fb->GetCommands()->PushGroup(name); +} + +void VkPPRenderState::PopGroup() +{ + fb->GetCommands()->PopGroup(); +} + +void VkPPRenderState::Draw() +{ + fb->GetRenderState()->EndRenderPass(); + + VkPPRenderPassKey key; + key.BlendMode = BlendMode; + key.InputTextures = Textures.Size(); + key.Uniforms = Uniforms.Data.Size(); + key.Shader = fb->GetShaderManager()->GetVkShader(Shader); + key.SwapChain = (Output.Type == PPTextureType::SwapChain); + key.ShadowMapBuffers = ShadowMapBuffers; + if (Output.Type == PPTextureType::PPTexture) + key.OutputFormat = fb->GetTextureManager()->GetTextureFormat(Output.Texture); + else if (Output.Type == PPTextureType::SwapChain) + key.OutputFormat = fb->GetFramebufferManager()->SwapChain->Format().format; + else if (Output.Type == PPTextureType::ShadowMap) + key.OutputFormat = VK_FORMAT_R32_SFLOAT; + else + key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; + + if (Output.Type == PPTextureType::SceneColor) + { + key.StencilTest = WhichDepthStencil::Scene; + key.Samples = fb->GetBuffers()->GetSceneSamples(); + } + else + { + key.StencilTest = WhichDepthStencil::None; + key.Samples = VK_SAMPLE_COUNT_1_BIT; + } + + auto passSetup = fb->GetRenderPassManager()->GetPPRenderPass(key); + + int framebufferWidth = 0, framebufferHeight = 0; + VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers); + VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight); + + RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest == WhichDepthStencil::Scene); + + // Advance to next PP texture if our output was sent there + if (Output.Type == PPTextureType::NextPipelineTexture) + { + auto pp = fb->GetPostprocess(); + pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages; + } +} + +void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest) +{ + auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); + + VkViewport viewport = { }; + viewport.x = (float)x; + viewport.y = (float)y; + viewport.width = (float)width; + viewport.height = (float)height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = { }; + scissor.offset.x = 0; + scissor.offset.y = 0; + scissor.extent.width = framebufferWidth; + scissor.extent.height = framebufferHeight; + + RenderPassBegin() + .RenderPass(passSetup->RenderPass.get()) + .RenderArea(0, 0, framebufferWidth, framebufferHeight) + .Framebuffer(framebuffer) + .AddClearColor(0.0f, 0.0f, 0.0f, 1.0f) + .Execute(cmdbuffer); + + VkBuffer vertexBuffers[] = { static_cast(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer }; + VkDeviceSize offsets[] = { 0 }; + + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet); + cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets); + cmdbuffer->setViewport(0, 1, &viewport); + cmdbuffer->setScissor(0, 1, &scissor); + if (stencilTest) + cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue); + if (pushConstantsSize > 0) + cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants); + cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0); + cmdbuffer->endRenderPass(); +} diff --git a/src/common/rendering/vulkan/renderer/vk_pprenderstate.h b/src/common/rendering/vulkan/renderer/vk_pprenderstate.h new file mode 100644 index 000000000..b0824bc18 --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_pprenderstate.h @@ -0,0 +1,27 @@ + +#pragma once + +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include + +class VkPPRenderPassSetup; +class VkPPShader; +class VkPPTexture; +class VkTextureImage; +class VulkanRenderDevice; + +class VkPPRenderState : public PPRenderState +{ +public: + VkPPRenderState(VulkanRenderDevice* fb); + + void PushGroup(const FString &name) override; + void PopGroup() override; + + void Draw() override; + +private: + void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest); + + VulkanRenderDevice* fb = nullptr; +}; diff --git a/src/common/rendering/vulkan/renderer/vk_raytrace.cpp b/src/common/rendering/vulkan/renderer/vk_raytrace.cpp new file mode 100644 index 000000000..084c475eb --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_raytrace.cpp @@ -0,0 +1,279 @@ +/* +** 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/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" +#include "hw_levelmesh.h" + +VkRaytrace::VkRaytrace(VulkanRenderDevice* fb) : fb(fb) +{ + 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); + + SetLevelMesh(nullptr); +} + +void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh) +{ + if (!mesh) + mesh = &NullMesh; + + if (mesh != Mesh) + { + Reset(); + Mesh = mesh; + if (fb->RaytracingEnabled()) + { + 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(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(); + CreateBottomLevelAccelerationStructure(); + CreateTopLevelAccelerationStructure(); +} + +void VkRaytrace::CreateVertexAndIndexBuffers() +{ + static_assert(sizeof(FVector3) == 3 * 4, "sizeof(FVector3) is not 12 bytes!"); + + size_t vertexbuffersize = (size_t)Mesh->MeshVertices.Size() * sizeof(FVector3); + size_t indexbuffersize = (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t); + size_t transferbuffersize = vertexbuffersize + indexbuffersize; + size_t vertexoffset = 0; + size_t indexoffset = vertexoffset + vertexbuffersize; + + transferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(transferbuffersize) + .DebugName("transferBuffer") + .Create(fb->device.get()); + + uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize); + memcpy(data + vertexoffset, Mesh->MeshVertices.Data(), vertexbuffersize); + memcpy(data + indexoffset, Mesh->MeshElements.Data(), indexbuffersize); + transferBuffer->Unmap(); + + vertexBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR) + .Size(vertexbuffersize) + .DebugName("vertexBuffer") + .Create(fb->device.get()); + + indexBuffer = BufferBuilder() + .Usage( + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR) + .Size(indexbuffersize) + .DebugName("indexBuffer") + .Create(fb->device.get()); + + fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset); + fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset); + + // Finish transfer before using it for building + 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); +} + +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_R32G32B32_SFLOAT; + accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress(); + accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector3); + 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->device->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->device.get()); + + blAccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + .Buffer(blAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("blAccelStruct") + .Create(fb->device.get()); + + blScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .DebugName("blScratchBuffer") + .Create(fb->device.get()); + + 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->device.get()); + + 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->device.get()); + + 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->device->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->device.get()); + + tlAccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) + .Buffer(tlAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("tlAccelStruct") + .Create(fb->device.get()); + + tlScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .DebugName("tlScratchBuffer") + .Create(fb->device.get()); + + 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); +} diff --git a/src/common/rendering/vulkan/renderer/vk_raytrace.h b/src/common/rendering/vulkan/renderer/vk_raytrace.h new file mode 100644 index 000000000..e54a9c623 --- /dev/null +++ b/src/common/rendering/vulkan/renderer/vk_raytrace.h @@ -0,0 +1,43 @@ + +#pragma once + +#include "zvulkan/vulkanobjects.h" +#include "hw_levelmesh.h" + +class VulkanRenderDevice; + +class VkRaytrace +{ +public: + VkRaytrace(VulkanRenderDevice* fb); + + void SetLevelMesh(hwrenderer::LevelMesh* mesh); + + VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); } + +private: + void Reset(); + void CreateVulkanObjects(); + void CreateVertexAndIndexBuffers(); + void CreateBottomLevelAccelerationStructure(); + void CreateTopLevelAccelerationStructure(); + + VulkanRenderDevice* fb = nullptr; + + hwrenderer::LevelMesh NullMesh; + hwrenderer::LevelMesh* Mesh = nullptr; + + std::unique_ptr vertexBuffer; + std::unique_ptr indexBuffer; + std::unique_ptr transferBuffer; + + 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; +}; diff --git a/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp deleted file mode 100644 index 75288a4f2..000000000 --- a/src/common/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ /dev/null @@ -1,271 +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_renderbuffers.h" -#include "vk_renderpass.h" -#include "vk_postprocess.h" -#include "vulkan/shaders/vk_shader.h" -#include "vulkan/system/vk_builders.h" -#include "vulkan/system/vk_framebuffer.h" -#include "hw_cvars.h" -#include "templates.h" - -VkRenderBuffers::VkRenderBuffers() -{ -} - -VkRenderBuffers::~VkRenderBuffers() -{ -} - -VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount() -{ - auto fb = GetVulkanFrameBuffer(); - const auto &limits = fb->device->PhysicalDevice.Properties.limits; - VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts; - - int requestedSamples = clamp((int)gl_multisample, 0, 64); - - int samples = 1; - VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT; - VkSampleCountFlags best = bit; - while (samples < requestedSamples) - { - if (deviceSampleCounts & bit) - { - best = bit; - } - samples <<= 1; - bit <<= 1; - } - return (VkSampleCountFlagBits)best; -} - -void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int sceneHeight) -{ - VkSampleCountFlagBits samples = GetBestSampleCount(); - - if (width != mWidth || height != mHeight || mSamples != samples) - { - auto fb = GetVulkanFrameBuffer(); - fb->GetRenderPassManager()->RenderBuffersReset(); - fb->GetPostprocess()->RenderBuffersReset(); - } - - if (width != mWidth || height != mHeight) - CreatePipeline(width, height); - - if (width != mWidth || height != mHeight || mSamples != samples) - CreateScene(width, height, samples); - - CreateShadowmap(); - - mWidth = width; - mHeight = height; - mSamples = samples; - mSceneWidth = sceneWidth; - mSceneHeight = sceneHeight; -} - -void VkRenderBuffers::CreatePipeline(int width, int height) -{ - auto fb = GetVulkanFrameBuffer(); - - for (int i = 0; i < NumPipelineImages; i++) - { - PipelineImage[i].reset(); - } - - VkImageTransition barrier; - for (int i = 0; i < NumPipelineImages; i++) - { - ImageBuilder builder; - builder.setSize(width, height); - builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); - builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - PipelineImage[i].Image = builder.create(fb->device); - PipelineImage[i].Image->SetDebugName("VkRenderBuffers.PipelineImage"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT); - PipelineImage[i].View = viewbuilder.create(fb->device); - PipelineImage[i].View->SetDebugName("VkRenderBuffers.PipelineView"); - - barrier.addImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - } - barrier.execute(fb->GetDrawCommands()); -} - -void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples) -{ - auto fb = GetVulkanFrameBuffer(); - - SceneColor.reset(); - SceneDepthStencil.reset(); - SceneNormal.reset(); - SceneFog.reset(); - - CreateSceneColor(width, height, samples); - CreateSceneDepthStencil(width, height, samples); - CreateSceneNormal(width, height, samples); - CreateSceneFog(width, height, samples); - - VkImageTransition barrier; - barrier.addImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier.addImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); - barrier.addImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier.addImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier.execute(fb->GetDrawCommands()); -} - -void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples) -{ - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder builder; - builder.setSize(width, height); - builder.setSamples(samples); - builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); - builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - SceneColor.Image = builder.create(fb->device); - SceneColor.Image->SetDebugName("VkRenderBuffers.SceneColor"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT); - SceneColor.View = viewbuilder.create(fb->device); - SceneColor.View->SetDebugName("VkRenderBuffers.SceneColorView"); -} - -void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples) -{ - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder builder; - builder.setSize(width, height); - builder.setSamples(samples); - builder.setFormat(SceneDepthStencilFormat); - builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - if (!builder.isFormatSupported(fb->device)) - { - SceneDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT; - builder.setFormat(SceneDepthStencilFormat); - if (!builder.isFormatSupported(fb->device)) - { - I_FatalError("This device does not support any of the required depth stencil image formats."); - } - } - SceneDepthStencil.Image = builder.create(fb->device); - SceneDepthStencil.Image->SetDebugName("VkRenderBuffers.SceneDepthStencil"); - SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - SceneDepthStencil.View = viewbuilder.create(fb->device); - SceneDepthStencil.View->SetDebugName("VkRenderBuffers.SceneDepthStencilView"); - - viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT); - SceneDepthStencil.DepthOnlyView = viewbuilder.create(fb->device); - SceneDepthStencil.DepthOnlyView->SetDebugName("VkRenderBuffers.SceneDepthView"); -} - -void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples) -{ - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder builder; - builder.setSize(width, height); - builder.setSamples(samples); - builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); - builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - SceneFog.Image = builder.create(fb->device); - SceneFog.Image->SetDebugName("VkRenderBuffers.SceneFog"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM); - SceneFog.View = viewbuilder.create(fb->device); - SceneFog.View->SetDebugName("VkRenderBuffers.SceneFogView"); -} - -void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples) -{ - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder builder; - builder.setSize(width, height); - builder.setSamples(samples); - builder.setFormat(SceneNormalFormat); - builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) - { - SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; - builder.setFormat(SceneNormalFormat); - } - SceneNormal.Image = builder.create(fb->device); - SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat); - SceneNormal.View = viewbuilder.create(fb->device); - SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView"); -} - -void VkRenderBuffers::CreateShadowmap() -{ - if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality) - return; - - Shadowmap.reset(); - - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder builder; - builder.setSize(gl_shadowmap_quality, 1024); - builder.setFormat(SceneNormalFormat); - builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) - { - SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; - builder.setFormat(SceneNormalFormat); - } - Shadowmap.Image = builder.create(fb->device); - Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT); - Shadowmap.View = viewbuilder.create(fb->device); - Shadowmap.View->SetDebugName("VkRenderBuffers.ShadowmapView"); - - VkImageTransition barrier; - barrier.addImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); - barrier.execute(fb->GetDrawCommands()); - - if (!ShadowmapSampler) - { - SamplerBuilder builder; - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMinFilter(VK_FILTER_NEAREST); - builder.setMagFilter(VK_FILTER_NEAREST); - builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - ShadowmapSampler = builder.create(fb->device); - ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler"); - } -} diff --git a/src/common/rendering/vulkan/renderer/vk_renderpass.cpp b/src/common/rendering/vulkan/renderer/vk_renderpass.cpp index 44c325ecf..5ecb3f65e 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/renderer/vk_renderpass.cpp @@ -21,61 +21,75 @@ */ #include "vk_renderpass.h" -#include "vk_renderbuffers.h" #include "vk_renderstate.h" +#include "vk_descriptorset.h" +#include "vk_raytrace.h" +#include "vulkan/textures/vk_renderbuffers.h" #include "vulkan/textures/vk_samplers.h" #include "vulkan/shaders/vk_shader.h" -#include "vulkan/system/vk_builders.h" -#include "vulkan/system/vk_framebuffer.h" -#include "vulkan/system/vk_buffers.h" +#include "vulkan/shaders/vk_ppshader.h" +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_hwbuffer.h" #include "flatvertices.h" #include "hw_viewpointuniforms.h" #include "v_2ddrawer.h" +#include "i_specialpaths.h" -VkRenderPassManager::VkRenderPassManager() +VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb) { + FString path = M_GetCachePath(true); + CreatePath(path); + CacheFilename = path + "/pipelinecache.zdpc"; + + PipelineCacheBuilder builder; + builder.DebugName("PipelineCache"); + + try + { + FileReader fr; + if (fr.OpenFile(CacheFilename)) + { + std::vector data; + data.resize(fr.GetLength()); + if (fr.Read(data.data(), data.size()) == data.size()) + { + builder.InitialData(data.data(), data.size()); + } + } + } + catch (...) + { + } + + PipelineCache = builder.Create(fb->device.get()); } VkRenderPassManager::~VkRenderPassManager() { - DynamicSet.reset(); // Needed since it must come before destruction of DynamicDescriptorPool -} - -void VkRenderPassManager::Init() -{ - CreateDynamicSetLayout(); - CreateDescriptorPool(); - CreateDynamicSet(); - CreateNullTexture(); + try + { + auto data = PipelineCache->GetCacheData(); + std::unique_ptr fw(FileWriter::Open(CacheFilename)); + if (fw) + fw->Write(data.data(), data.size()); + } + catch (...) + { + } } void VkRenderPassManager::RenderBuffersReset() { RenderPassSetup.clear(); -} - -void VkRenderPassManager::TextureSetPoolReset() -{ - if (auto fb = GetVulkanFrameBuffer()) - { - auto &deleteList = fb->FrameDeleteList; - - for (auto &desc : TextureDescriptorPools) - { - deleteList.DescriptorPools.push_back(std::move(desc)); - } - } - NullTextureDescriptorSet.reset(); - TextureDescriptorPools.clear(); - TextureDescriptorSetsLeft = 0; - TextureDescriptorsLeft = 0; + PPRenderPassSetup.clear(); } VkRenderPassSetup *VkRenderPassManager::GetRenderPass(const VkRenderPassKey &key) { auto &item = RenderPassSetup[key]; if (!item) - item.reset(new VkRenderPassSetup(key)); + item.reset(new VkRenderPassSetup(fb, key)); return item.get(); } @@ -122,37 +136,6 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index) return &VertexFormats[index]; } -void VkRenderPassManager::CreateDynamicSetLayout() -{ - DescriptorSetLayoutBuilder builder; - builder.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device); - DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout"); -} - -VulkanDescriptorSetLayout *VkRenderPassManager::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); - } - layout = builder.create(GetVulkanFrameBuffer()->device); - layout->SetDebugName("VkRenderPassManager.TextureSetLayout"); - return layout.get(); -} - VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers) { if (PipelineLayouts.size() <= (size_t)numLayers) @@ -162,156 +145,68 @@ VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers) if (layout) return layout.get(); + auto descriptors = fb->GetDescriptorSetManager(); + PipelineLayoutBuilder builder; - builder.addSetLayout(DynamicSetLayout.get()); + builder.AddSetLayout(descriptors->GetFixedSetLayout()); + builder.AddSetLayout(descriptors->GetHWBufferSetLayout()); if (numLayers != 0) - builder.addSetLayout(GetTextureSetLayout(numLayers)); - builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)); - layout = builder.create(GetVulkanFrameBuffer()->device); - layout->SetDebugName("VkRenderPassManager.PipelineLayout"); + builder.AddSetLayout(descriptors->GetTextureSetLayout(numLayers)); + builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)); + builder.DebugName("VkRenderPassManager.PipelineLayout"); + layout = builder.Create(fb->device.get()); return layout.get(); } -void VkRenderPassManager::CreateDescriptorPool() +VkPPRenderPassSetup* VkRenderPassManager::GetPPRenderPass(const VkPPRenderPassKey& key) { - DescriptorPoolBuilder builder; - builder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3); - builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1); - builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1); - builder.setMaxSets(1); - DynamicDescriptorPool = builder.create(GetVulkanFrameBuffer()->device); - DynamicDescriptorPool->SetDebugName("VkRenderPassManager.DynamicDescriptorPool"); -} - -void VkRenderPassManager::CreateDynamicSet() -{ - DynamicSet = DynamicDescriptorPool->allocate(DynamicSetLayout.get()); - if (!DynamicSet) - I_FatalError("CreateDynamicSet failed.\n"); -} - -void VkRenderPassManager::CreateNullTexture() -{ - auto fb = GetVulkanFrameBuffer(); - - ImageBuilder imgbuilder; - imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); - imgbuilder.setSize(1, 1); - imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT); - NullTexture = imgbuilder.create(fb->device); - NullTexture->SetDebugName("VkRenderPassManager.NullTexture"); - - ImageViewBuilder viewbuilder; - viewbuilder.setImage(NullTexture.get(), VK_FORMAT_R8G8B8A8_UNORM); - NullTextureView = viewbuilder.create(fb->device); - NullTextureView->SetDebugName("VkRenderPassManager.NullTextureView"); - - PipelineBarrier barrier; - barrier.addImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT); - barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); -} - -VulkanDescriptorSet* VkRenderPassManager::GetNullTextureDescriptorSet() -{ - if (!NullTextureDescriptorSet) - { - NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS); - - auto fb = GetVulkanFrameBuffer(); - WriteDescriptors update; - for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) - { - update.addCombinedImageSampler(NullTextureDescriptorSet.get(), i, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } - update.updateSets(fb->device); - } - - return NullTextureDescriptorSet.get(); -} - -VulkanImageView* VkRenderPassManager::GetNullTextureView() -{ - return NullTextureView.get(); -} - -void VkRenderPassManager::UpdateDynamicSet() -{ - auto fb = GetVulkanFrameBuffer(); - - // In some rare cases drawing commands may already have been created before VulkanFrameBuffer::BeginFrame is called. - // Make sure there there are no active command buffers using DynamicSet when we update it: - fb->GetRenderState()->EndRenderPass(); - fb->WaitForCommands(false); - - WriteDescriptors update; - update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms)); - update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get()); - update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO)); - update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO)); - update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.updateSets(fb->device); -} - -std::unique_ptr VkRenderPassManager::AllocateTextureDescriptorSet(int numLayers) -{ - if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers) - { - TextureDescriptorSetsLeft = 1000; - TextureDescriptorsLeft = 2000; - - DescriptorPoolBuilder builder; - builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft); - builder.setMaxSets(TextureDescriptorSetsLeft); - TextureDescriptorPools.push_back(builder.create(GetVulkanFrameBuffer()->device)); - TextureDescriptorPools.back()->SetDebugName("VkRenderPassManager.TextureDescriptorPool"); - } - - TextureDescriptorSetsLeft--; - TextureDescriptorsLeft -= numLayers; - return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers)); + auto& passSetup = PPRenderPassSetup[key]; + if (!passSetup) + passSetup.reset(new VkPPRenderPassSetup(fb, key)); + return passSetup.get(); } ///////////////////////////////////////////////////////////////////////////// -VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key) : PassKey(key) +VkRenderPassSetup::VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb) { } std::unique_ptr VkRenderPassSetup::CreateRenderPass(int clearTargets) { - auto buffers = GetVulkanFrameBuffer()->GetBuffers(); + auto buffers = fb->GetBuffers(); VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat }; RenderPassBuilder builder; - builder.addAttachment( + builder.AddAttachment( PassKey.DrawBufferFormat, (VkSampleCountFlagBits)PassKey.Samples, (clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); for (int i = 1; i < PassKey.DrawBuffers; i++) { - builder.addAttachment( - drawBufferFormats[i], buffers->GetSceneSamples(), + builder.AddAttachment( + drawBufferFormats[i], (VkSampleCountFlagBits)PassKey.Samples, (clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } if (PassKey.DepthStencil) { - builder.addDepthStencilAttachment( - buffers->SceneDepthStencilFormat, PassKey.DrawBufferFormat == VK_FORMAT_R8G8B8A8_UNORM ? VK_SAMPLE_COUNT_1_BIT : buffers->GetSceneSamples(), + builder.AddDepthStencilAttachment( + buffers->SceneDepthStencilFormat, (VkSampleCountFlagBits)PassKey.Samples, (clearTargets & CT_Depth) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, (clearTargets & CT_Stencil) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } - builder.addSubpass(); + builder.AddSubpass(); for (int i = 0; i < PassKey.DrawBuffers; i++) - builder.addSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + builder.AddSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); if (PassKey.DepthStencil) { - builder.addSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - builder.addExternalSubpassDependency( + builder.AddSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + builder.AddExternalSubpassDependency( VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, @@ -319,15 +214,14 @@ std::unique_ptr VkRenderPassSetup::CreateRenderPass(int clearT } else { - builder.addExternalSubpassDependency( + builder.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); } - auto renderpass = builder.create(GetVulkanFrameBuffer()->device); - renderpass->SetDebugName("VkRenderPassSetup.RenderPass"); - return renderpass; + builder.DebugName("VkRenderPassSetup.RenderPass"); + return builder.Create(fb->device.get()); } VulkanRenderPass *VkRenderPassSetup::GetRenderPass(int clearTargets) @@ -347,8 +241,8 @@ VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key) std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key) { - auto fb = GetVulkanFrameBuffer(); GraphicsPipelineBuilder builder; + builder.Cache(fb->GetRenderPassManager()->GetCache()); VkShaderProgram *program; if (key.SpecialEffect != EFF_NONE) @@ -359,13 +253,13 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli { program = fb->GetShaderManager()->Get(key.EffectState, key.AlphaTest, PassKey.DrawBuffers > 1 ? GBUFFER_PASS : NORMAL_PASS); } - builder.addVertexShader(program->vert.get()); - builder.addFragmentShader(program->frag.get()); + builder.AddVertexShader(program->vert.get()); + 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); + builder.AddVertexBufferBinding(i, vfmt.Stride); const static VkFormat vkfmts[] = { VK_FORMAT_R32G32B32A32_SFLOAT, @@ -373,38 +267,34 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, - VK_FORMAT_A2B10G10R10_SNORM_PACK32 + VK_FORMAT_A2B10G10R10_SNORM_PACK32, + VK_FORMAT_R8G8B8A8_UINT }; - bool inputLocations[6] = { false, false, false, false, false, false }; + bool inputLocations[VATTR_MAX] = {}; for (size_t i = 0; i < vfmt.Attrs.size(); i++) { const auto &attr = vfmt.Attrs[i]; - builder.addVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset); + builder.AddVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset); inputLocations[attr.location] = true; } // Vulkan requires an attribute binding for each location specified in the shader - for (int i = 0; i < 6; i++) + for (int i = 0; i < VATTR_MAX; i++) { if (!inputLocations[i]) - builder.addVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0); + builder.AddVertexAttribute(i, 0, i != 8 ? VK_FORMAT_R32G32B32_SFLOAT : VK_FORMAT_R8G8B8A8_UINT, 0); } - builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT); - builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR); - // builder.addDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); - builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS); - // builder.addDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); - // builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS); - // builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); - // builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); - builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); + builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT); + builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR); + builder.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS); + builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); // Note: the actual values are ignored since we use dynamic viewport+scissor states - builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f); - builder.setScissor(0, 0, 320, 200); + builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f); + builder.Scissor(0, 0, 320, 200); static const VkPrimitiveTopology vktopology[] = { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, @@ -417,26 +307,180 @@ std::unique_ptr VkRenderPassSetup::CreatePipeline(const VkPipeli static const VkStencilOp op2vk[] = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP }; static const VkCompareOp depthfunc2vk[] = { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS }; - builder.setTopology(vktopology[key.DrawType]); - builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest); - builder.setDepthFunc(depthfunc2vk[key.DepthFunc]); - if (fb->device->UsedDeviceFeatures.depthClamp) - builder.setDepthClampEnable(key.DepthClamp); - builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f); + builder.Topology(vktopology[key.DrawType]); + builder.DepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest); + builder.DepthFunc(depthfunc2vk[key.DepthFunc]); + if (fb->device->EnabledFeatures.Features.depthClamp) + builder.DepthClampEnable(key.DepthClamp); + builder.DepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f); // Note: CCW and CW is intentionally swapped here because the vulkan and opengl coordinate systems differ. // 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.setCull(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.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.setColorWriteMask((VkColorComponentFlags)key.ColorMask); - builder.setStencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0); - builder.setBlendMode(key.RenderStyle); - builder.setSubpassColorAttachmentCount(PassKey.DrawBuffers); - builder.setRasterizationSamples((VkSampleCountFlagBits)PassKey.Samples); + 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); + builder.RasterizationSamples((VkSampleCountFlagBits)PassKey.Samples); - builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers)); - builder.setRenderPass(GetRenderPass(0)); - auto pipeline = builder.create(fb->device); - pipeline->SetDebugName("VkRenderPassSetup.Pipeline"); - return pipeline; + builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers)); + builder.RenderPass(GetRenderPass(0)); + builder.DebugName("VkRenderPassSetup.Pipeline"); + + return builder.Create(fb->device.get()); +} + +///////////////////////////////////////////////////////////////////////////// + +VkPPRenderPassSetup::VkPPRenderPassSetup(VulkanRenderDevice* fb, const VkPPRenderPassKey& key) : fb(fb) +{ + CreateDescriptorLayout(key); + CreatePipelineLayout(key); + CreateRenderPass(key); + CreatePipeline(key); +} + +void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey& key) +{ + DescriptorSetLayoutBuilder builder; + for (int i = 0; i < key.InputTextures; i++) + builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + if (key.ShadowMapBuffers) + { + builder.AddBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + } + builder.DebugName("VkPPRenderPassSetup.DescriptorLayout"); + DescriptorLayout = builder.Create(fb->device.get()); +} + +void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey& key) +{ + PipelineLayoutBuilder builder; + builder.AddSetLayout(DescriptorLayout.get()); + if (key.Uniforms > 0) + builder.AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms); + builder.DebugName("VkPPRenderPassSetup.PipelineLayout"); + PipelineLayout = builder.Create(fb->device.get()); +} + +void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key) +{ + GraphicsPipelineBuilder builder; + builder.Cache(fb->GetRenderPassManager()->GetCache()); + builder.AddVertexShader(key.Shader->VertexShader.get()); + builder.AddFragmentShader(key.Shader->FragmentShader.get()); + + builder.AddVertexBufferBinding(0, sizeof(FFlatVertex)); + builder.AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x)); + builder.AddVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u)); + builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT); + builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR); + // Note: the actual values are ignored since we use dynamic viewport+scissor states + builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f); + builder.Scissor(0, 0, 320, 200); + if (key.StencilTest != WhichDepthStencil::None) + { + builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); + builder.DepthStencilEnable(false, false, true); + 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); + builder.RasterizationSamples(key.Samples); + builder.Layout(PipelineLayout.get()); + builder.RenderPass(RenderPass.get()); + builder.DebugName("VkPPRenderPassSetup.Pipeline"); + Pipeline = builder.Create(fb->device.get()); +} + +void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey& key) +{ + RenderPassBuilder builder; + if (key.SwapChain) + builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + else + builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + if (key.StencilTest == WhichDepthStencil::Scene) + { + builder.AddDepthStencilAttachment( + fb->GetBuffers()->SceneDepthStencilFormat, key.Samples, + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + if (key.StencilTest == WhichDepthStencil::Pipeline) + { + builder.AddDepthStencilAttachment( + fb->GetBuffers()->PipelineDepthStencilFormat, key.Samples, + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + + builder.AddSubpass(); + builder.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + if (key.StencilTest != WhichDepthStencil::None) + { + builder.AddSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + builder.AddExternalSubpassDependency( + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT); + } + else + { + builder.AddExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT); + } + + builder.DebugName("VkPPRenderPassSetup.RenderPass"); + RenderPass = builder.Create(fb->device.get()); +} + +///////////////////////////////////////////////////////////////////////////// + +GraphicsPipelineBuilder& BlendMode(GraphicsPipelineBuilder& 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) + { + return builder; + } + + static const int blendstyles[] = { + VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_ONE, + VK_BLEND_FACTOR_SRC_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + VK_BLEND_FACTOR_SRC_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + VK_BLEND_FACTOR_DST_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, + VK_BLEND_FACTOR_DST_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, + }; + + static const int renderops[] = { + 0, VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + int srcblend = blendstyles[style.SrcAlpha % STYLEALPHA_MAX]; + int dstblend = blendstyles[style.DestAlpha % STYLEALPHA_MAX]; + int blendequation = renderops[style.BlendOp & 15]; + + if (blendequation == -1) // This was a fuzz style. + { + srcblend = VK_BLEND_FACTOR_DST_COLOR; + dstblend = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendequation = VK_BLEND_OP_ADD; + } + + return builder.BlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend); } diff --git a/src/common/rendering/vulkan/renderer/vk_renderpass.h b/src/common/rendering/vulkan/renderer/vk_renderpass.h index f19252522..25fd7d186 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/common/rendering/vulkan/renderer/vk_renderpass.h @@ -1,14 +1,17 @@ #pragma once -#include "vulkan/system/vk_objects.h" +#include "zvulkan/vulkanobjects.h" #include "renderstyle.h" #include "hwrenderer/data/buffers.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" #include "hw_renderstate.h" #include #include -class VKDataBuffer; +class VulkanRenderDevice; +class VkPPShader; +class GraphicsPipelineBuilder; class VkPipelineKey { @@ -51,7 +54,7 @@ public: class VkRenderPassSetup { public: - VkRenderPassSetup(const VkRenderPassKey &key); + VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key); VulkanRenderPass *GetRenderPass(int clearTargets); VulkanPipeline *GetPipeline(const VkPipelineKey &key); @@ -63,6 +66,8 @@ public: private: std::unique_ptr CreateRenderPass(int clearTargets); std::unique_ptr CreatePipeline(const VkPipelineKey &key); + + VulkanRenderDevice* fb = nullptr; }; class VkVertexFormat @@ -74,50 +79,73 @@ public: int UseVertexData; }; +enum class WhichDepthStencil; + +class VkPPRenderPassKey +{ +public: + VkPPShader* Shader; + int Uniforms; + int InputTextures; + PPBlendMode BlendMode; + VkFormat OutputFormat; + int SwapChain; + int ShadowMapBuffers; + WhichDepthStencil StencilTest; + VkSampleCountFlagBits Samples; + + bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; } + bool operator==(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; } + bool operator!=(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; } +}; + +class VkPPRenderPassSetup +{ +public: + VkPPRenderPassSetup(VulkanRenderDevice* fb, const VkPPRenderPassKey& key); + + std::unique_ptr DescriptorLayout; + std::unique_ptr PipelineLayout; + std::unique_ptr RenderPass; + std::unique_ptr Pipeline; + +private: + void CreateDescriptorLayout(const VkPPRenderPassKey& key); + void CreatePipelineLayout(const VkPPRenderPassKey& key); + void CreatePipeline(const VkPPRenderPassKey& key); + void CreateRenderPass(const VkPPRenderPassKey& key); + + VulkanRenderDevice* fb = nullptr; +}; + +GraphicsPipelineBuilder& BlendMode(GraphicsPipelineBuilder& builder, const FRenderStyle& style); + class VkRenderPassManager { public: - VkRenderPassManager(); + VkRenderPassManager(VulkanRenderDevice* fb); ~VkRenderPassManager(); - void Init(); void RenderBuffersReset(); - void UpdateDynamicSet(); - void TextureSetPoolReset(); VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key); int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); - VkVertexFormat *GetVertexFormat(int index); - - std::unique_ptr AllocateTextureDescriptorSet(int numLayers); VulkanPipelineLayout* GetPipelineLayout(int numLayers); - VulkanDescriptorSet* GetNullTextureDescriptorSet(); - VulkanImageView* GetNullTextureView(); + VkPPRenderPassSetup* GetPPRenderPass(const VkPPRenderPassKey& key); - std::unique_ptr DynamicSetLayout; - std::map> RenderPassSetup; - - std::unique_ptr DynamicSet; + VulkanPipelineCache* GetCache() { return PipelineCache.get(); } private: - void CreateDynamicSetLayout(); - void CreateDescriptorPool(); - void CreateDynamicSet(); - void CreateNullTexture(); + VulkanRenderDevice* fb = nullptr; - VulkanDescriptorSetLayout *GetTextureSetLayout(int numLayers); - - int TextureDescriptorSetsLeft = 0; - int TextureDescriptorsLeft = 0; - std::vector> TextureDescriptorPools; - std::unique_ptr DynamicDescriptorPool; - std::vector> TextureSetLayouts; + std::map> RenderPassSetup; std::vector> PipelineLayouts; std::vector VertexFormats; - std::unique_ptr NullTexture; - std::unique_ptr NullTextureView; - std::unique_ptr NullTextureDescriptorSet; + std::map> PPRenderPassSetup; + + FString CacheFilename; + std::unique_ptr PipelineCache; }; diff --git a/src/common/rendering/vulkan/renderer/vk_renderstate.cpp b/src/common/rendering/vulkan/renderer/vk_renderstate.cpp index a2df4a28e..76bd35cb0 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/renderer/vk_renderstate.cpp @@ -21,12 +21,15 @@ */ #include "vk_renderstate.h" -#include "vulkan/system/vk_framebuffer.h" -#include "vulkan/system/vk_builders.h" +#include "vulkan/system/vk_renderdevice.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/system/vk_commandbuffer.h" +#include "vulkan/system/vk_buffer.h" #include "vulkan/renderer/vk_renderpass.h" -#include "vulkan/renderer/vk_renderbuffers.h" +#include "vulkan/renderer/vk_descriptorset.h" +#include "vulkan/textures/vk_renderbuffers.h" #include "vulkan/textures/vk_hwtexture.h" -#include "templates.h" + #include "hw_skydome.h" #include "hw_viewpointuniforms.h" #include "hw_lightbuffer.h" @@ -39,7 +42,7 @@ CVAR(Int, vk_submit_size, 1000, 0); EXTERN_CVAR(Bool, r_skipmats) -VkRenderState::VkRenderState() +VkRenderState::VkRenderState(VulkanRenderDevice* fb) : fb(fb), mStreamBufferWriter(fb), mMatrixBufferWriter(fb) { Reset(); } @@ -182,7 +185,7 @@ void VkRenderState::Apply(int dt) mApplyCount++; if (mApplyCount >= vk_submit_size) { - GetVulkanFrameBuffer()->FlushCommands(false); + fb->GetCommands()->FlushCommands(false); mApplyCount = 0; } @@ -195,7 +198,7 @@ void VkRenderState::Apply(int dt) ApplyDepthBias(); ApplyPushConstants(); ApplyVertexBuffers(); - ApplyDynamicSet(); + ApplyHWBufferSet(); ApplyMaterial(); mNeedApply = false; @@ -216,7 +219,7 @@ void VkRenderState::ApplyRenderPass(int dt) // Find a pipeline that matches our state VkPipelineKey pipelineKey; pipelineKey.DrawType = dt; - pipelineKey.VertexFormat = static_cast(mVertexBuffer)->VertexFormat; + pipelineKey.VertexFormat = static_cast(mVertexBuffer)->VertexFormat; pipelineKey.RenderStyle = mRenderStyle; pipelineKey.DepthTest = mDepthTest; pipelineKey.DepthWrite = mDepthTest && mDepthWrite; @@ -228,7 +231,7 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.ColorMask = mColorMask; pipelineKey.CullMode = mCullMode; pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->NumLayers() : 0; - pipelineKey.NumTextureLayers = std::max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it + 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.SpecialEffect = mSpecialEffect; @@ -251,7 +254,7 @@ void VkRenderState::ApplyRenderPass(int dt) if (!inRenderPass) { - mCommandBuffer = GetVulkanFrameBuffer()->GetDrawCommands(); + mCommandBuffer = fb->GetCommands()->GetDrawCommands(); mScissorChanged = true; mViewportChanged = true; mStencilRefChanged = true; @@ -333,10 +336,9 @@ void VkRenderState::ApplyViewport() void VkRenderState::ApplyStreamData() { - auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - mStreamData.useVertexData = passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData; + mStreamData.useVertexData = passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData; if (mMaterial.mMaterial && mMaterial.mMaterial->Source()) mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.); @@ -389,9 +391,9 @@ void VkRenderState::ApplyPushConstants() } mPushConstants.uLightIndex = mLightIndex; + mPushConstants.uBoneIndexBase = mBoneIndexBase; mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex(); - auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); } @@ -409,8 +411,8 @@ void VkRenderState::ApplyVertexBuffers() { if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1]) && mVertexBuffer) { - auto vkbuf = static_cast(mVertexBuffer); - const VkVertexFormat *format = GetVulkanFrameBuffer()->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat); + 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 }; mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets); @@ -421,7 +423,7 @@ void VkRenderState::ApplyVertexBuffers() if (mIndexBuffer != mLastIndexBuffer && mIndexBuffer) { - mCommandBuffer->bindIndexBuffer(static_cast(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); + mCommandBuffer->bindIndexBuffer(static_cast(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); mLastIndexBuffer = mIndexBuffer; } } @@ -430,29 +432,31 @@ void VkRenderState::ApplyMaterial() { if (mMaterial.mChanged) { - auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); + auto descriptors = fb->GetDescriptorSetManager(); if (mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) static_cast(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate(); - VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet(); + VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : descriptors->GetNullTextureDescriptorSet(); - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet()); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 2, descriptorset); mMaterial.mChanged = false; } } -void VkRenderState::ApplyDynamicSet() +void VkRenderState::ApplyHWBufferSet() { - auto fb = GetVulkanFrameBuffer(); uint32_t matrixOffset = mMatrixBufferWriter.Offset(); uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset(); if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset) { auto passManager = fb->GetRenderPassManager(); + auto descriptors = fb->GetDescriptorSetManager(); uint32_t offsets[3] = { mViewpointOffset, matrixOffset, streamDataOffset }; - mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet()); + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptors->GetHWBufferDescriptorSet(), 3, offsets); mLastViewpointOffset = mViewpointOffset; mLastMatricesOffset = matrixOffset; @@ -462,7 +466,7 @@ void VkRenderState::ApplyDynamicSet() void VkRenderState::WaitForStreamBuffers() { - GetVulkanFrameBuffer()->WaitForCommands(false); + fb->WaitForCommands(false); mApplyCount = 0; mStreamBufferWriter.Reset(); mMatrixBufferWriter.Reset(); @@ -528,8 +532,6 @@ void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *dept void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) { - auto fb = GetVulkanFrameBuffer(); - VkRenderPassKey key = {}; key.DrawBufferFormat = mRenderTarget.Format; key.Samples = mRenderTarget.Samples; @@ -543,17 +545,17 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) { auto buffers = fb->GetBuffers(); FramebufferBuilder builder; - builder.setRenderPass(mPassSetup->GetRenderPass(0)); - builder.setSize(mRenderTarget.Width, mRenderTarget.Height); - builder.addAttachment(mRenderTarget.Image->View.get()); + builder.RenderPass(mPassSetup->GetRenderPass(0)); + builder.Size(mRenderTarget.Width, mRenderTarget.Height); + builder.AddAttachment(mRenderTarget.Image->View.get()); if (key.DrawBuffers > 1) - builder.addAttachment(buffers->SceneFog.View.get()); + builder.AddAttachment(buffers->SceneFog.View.get()); if (key.DrawBuffers > 2) - builder.addAttachment(buffers->SceneNormal.View.get()); + builder.AddAttachment(buffers->SceneNormal.View.get()); if (key.DepthStencil) - builder.addAttachment(mRenderTarget.DepthStencil); - framebuffer = builder.create(GetVulkanFrameBuffer()->device); - framebuffer->SetDebugName("VkRenderPassSetup.Framebuffer"); + builder.AddAttachment(mRenderTarget.DepthStencil); + builder.DebugName("VkRenderPassSetup.Framebuffer"); + framebuffer = builder.Create(fb->device.get()); } // Only clear depth+stencil if the render target actually has that @@ -561,16 +563,16 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) mClearTargets &= ~(CT_Depth | CT_Stencil); RenderPassBegin beginInfo; - beginInfo.setRenderPass(mPassSetup->GetRenderPass(mClearTargets)); - beginInfo.setRenderArea(0, 0, mRenderTarget.Width, mRenderTarget.Height); - beginInfo.setFramebuffer(framebuffer.get()); - beginInfo.addClearColor(screen->mSceneClearColor[0], screen->mSceneClearColor[1], screen->mSceneClearColor[2], screen->mSceneClearColor[3]); + beginInfo.RenderPass(mPassSetup->GetRenderPass(mClearTargets)); + beginInfo.RenderArea(0, 0, mRenderTarget.Width, mRenderTarget.Height); + beginInfo.Framebuffer(framebuffer.get()); + beginInfo.AddClearColor(screen->mSceneClearColor[0], screen->mSceneClearColor[1], screen->mSceneClearColor[2], screen->mSceneClearColor[3]); if (key.DrawBuffers > 1) - beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f); + beginInfo.AddClearColor(0.0f, 0.0f, 0.0f, 0.0f); if (key.DrawBuffers > 2) - beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f); - beginInfo.addClearDepthStencil(1.0f, 0); - cmdbuffer->beginRenderPass(beginInfo); + beginInfo.AddClearColor(0.0f, 0.0f, 0.0f, 0.0f); + beginInfo.AddClearDepthStencil(1.0f, 0); + beginInfo.Execute(cmdbuffer); mMaterial.mChanged = true; mClearTargets = 0; @@ -583,7 +585,7 @@ void VkRenderStateMolten::Draw(int dt, int index, int count, bool apply) if (dt == DT_TriangleFan) { IIndexBuffer *oldIndexBuffer = mIndexBuffer; - mIndexBuffer = GetVulkanFrameBuffer()->FanToTrisIndexBuffer.get(); + mIndexBuffer = fb->GetBufferManager()->FanToTrisIndexBuffer.get(); if (apply || mNeedApply) Apply(DT_Triangles); diff --git a/src/common/rendering/vulkan/renderer/vk_renderstate.h b/src/common/rendering/vulkan/renderer/vk_renderstate.h index d4df3a774..cc2e0d908 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/common/rendering/vulkan/renderer/vk_renderstate.h @@ -1,7 +1,7 @@ #pragma once -#include "vulkan/system/vk_buffers.h" +#include "vulkan/system/vk_hwbuffer.h" #include "vulkan/shaders/vk_shader.h" #include "vulkan/renderer/vk_renderpass.h" #include "vulkan/renderer/vk_streambuffer.h" @@ -11,13 +11,14 @@ #include "hw_renderstate.h" #include "hw_material.h" +class VulkanRenderDevice; class VkRenderPassSetup; class VkTextureImage; class VkRenderState : public FRenderState { public: - VkRenderState(); + VkRenderState(VulkanRenderDevice* fb); virtual ~VkRenderState() = default; // Draw commands @@ -59,13 +60,15 @@ protected: void ApplyStreamData(); void ApplyMatrices(); void ApplyPushConstants(); - void ApplyDynamicSet(); + void ApplyHWBufferSet(); void ApplyVertexBuffers(); void ApplyMaterial(); void BeginRenderPass(VulkanCommandBuffer *cmdbuffer); void WaitForStreamBuffers(); + VulkanRenderDevice* fb = nullptr; + bool mDepthClamp = true; VulkanCommandBuffer *mCommandBuffer = nullptr; VkPipelineKey mPipelineKey = {}; diff --git a/src/common/rendering/vulkan/renderer/vk_streambuffer.cpp b/src/common/rendering/vulkan/renderer/vk_streambuffer.cpp index 5a40be371..0db0fb71a 100644 --- a/src/common/rendering/vulkan/renderer/vk_streambuffer.cpp +++ b/src/common/rendering/vulkan/renderer/vk_streambuffer.cpp @@ -21,39 +21,14 @@ */ #include "vk_renderstate.h" -#include "vulkan/system/vk_framebuffer.h" -#include "vulkan/system/vk_builders.h" +#include "vulkan/system/vk_renderdevice.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/system/vk_buffer.h" #include "vulkan/renderer/vk_streambuffer.h" -VkStreamBuffer::VkStreamBuffer(size_t structSize, size_t count) +VkStreamBufferWriter::VkStreamBufferWriter(VulkanRenderDevice* fb) { - mBlockSize = static_cast((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment); - - UniformBuffer = (VKDataBuffer*)GetVulkanFrameBuffer()->CreateDataBuffer(-1, false, false); - UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent); -} - -VkStreamBuffer::~VkStreamBuffer() -{ - delete UniformBuffer; -} - -uint32_t VkStreamBuffer::NextStreamDataBlock() -{ - mStreamDataOffset += mBlockSize; - if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size()) - { - mStreamDataOffset = 0; - return 0xffffffff; - } - return mStreamDataOffset; -} - -///////////////////////////////////////////////////////////////////////////// - -VkStreamBufferWriter::VkStreamBufferWriter() -{ - mBuffer = GetVulkanFrameBuffer()->StreamBuffer; + mBuffer = fb->GetBufferManager()->StreamBuffer.get(); } bool VkStreamBufferWriter::Write(const StreamData& data) @@ -80,9 +55,9 @@ void VkStreamBufferWriter::Reset() ///////////////////////////////////////////////////////////////////////////// -VkMatrixBufferWriter::VkMatrixBufferWriter() +VkMatrixBufferWriter::VkMatrixBufferWriter(VulkanRenderDevice* fb) { - mBuffer = GetVulkanFrameBuffer()->MatrixBuffer; + mBuffer = fb->GetBufferManager()->MatrixBuffer.get(); mIdentityMatrix.loadIdentity(); } diff --git a/src/common/rendering/vulkan/renderer/vk_streambuffer.h b/src/common/rendering/vulkan/renderer/vk_streambuffer.h index 21c15867a..3bae01fb1 100644 --- a/src/common/rendering/vulkan/renderer/vk_streambuffer.h +++ b/src/common/rendering/vulkan/renderer/vk_streambuffer.h @@ -1,7 +1,7 @@ #pragma once -#include "vulkan/system/vk_buffers.h" +#include "vulkan/system/vk_hwbuffer.h" #include "vulkan/shaders/vk_shader.h" class VkStreamBuffer; @@ -10,7 +10,7 @@ class VkMatrixBuffer; class VkStreamBufferWriter { public: - VkStreamBufferWriter(); + VkStreamBufferWriter(VulkanRenderDevice* fb); bool Write(const StreamData& data); void Reset(); @@ -27,7 +27,7 @@ private: class VkMatrixBufferWriter { public: - VkMatrixBufferWriter(); + VkMatrixBufferWriter(VulkanRenderDevice* fb); bool Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled); void Reset(); @@ -40,19 +40,3 @@ private: VSMatrix mIdentityMatrix; uint32_t mOffset = 0; }; - -class VkStreamBuffer -{ -public: - VkStreamBuffer(size_t structSize, size_t count); - ~VkStreamBuffer(); - - uint32_t NextStreamDataBlock(); - void Reset() { mStreamDataOffset = 0; } - - VKDataBuffer* UniformBuffer = nullptr; - -private: - uint32_t mBlockSize = 0; - uint32_t mStreamDataOffset = 0; -}; diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp new file mode 100644 index 000000000..287762f77 --- /dev/null +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp @@ -0,0 +1,77 @@ +/* +** 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_ppshader.h" +#include "vk_shader.h" +#include "vulkan/system/vk_renderdevice.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/system/vk_commandbuffer.h" +#include "filesystem.h" + +VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb) +{ + FString prolog; + if (!shader->Uniforms.empty()) + prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1); + prolog += shader->Defines; + + VertexShader = ShaderBuilder() + .VertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars()) + .DebugName(shader->VertexShader.GetChars()) + .Create(shader->VertexShader.GetChars(), fb->device.get()); + + FragmentShader = ShaderBuilder() + .FragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars()) + .DebugName(shader->FragmentShader.GetChars()) + .Create(shader->FragmentShader.GetChars(), fb->device.get()); + + fb->GetShaderManager()->AddVkPPShader(this); +} + +VkPPShader::~VkPPShader() +{ + if (fb) + fb->GetShaderManager()->RemoveVkPPShader(this); +} + +void VkPPShader::Reset() +{ + if (fb) + { + fb->GetCommands()->DrawDeleteList->Add(std::move(VertexShader)); + fb->GetCommands()->DrawDeleteList->Add(std::move(FragmentShader)); + } +} + +FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version) +{ + int lump = fileSystem.CheckNumForFullName(lumpName); + if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars()); + FString code = fileSystem.ReadFile(lump).GetString().GetChars(); + + FString patchedCode; + patchedCode.AppendFormat("#version %d\n", 450); + patchedCode << defines; + patchedCode << "#line 1\n"; + patchedCode << code; + return patchedCode; +} diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.h b/src/common/rendering/vulkan/shaders/vk_ppshader.h new file mode 100644 index 000000000..6bb5ce475 --- /dev/null +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include +#include + +class VulkanRenderDevice; + +class VkPPShader : public PPShaderBackend +{ +public: + VkPPShader(VulkanRenderDevice* fb, PPShader *shader); + ~VkPPShader(); + + void Reset(); + + VulkanRenderDevice* fb = nullptr; + std::list::iterator it; + + std::unique_ptr VertexShader; + std::unique_ptr FragmentShader; + +private: + FString LoadShaderCode(const FString &lumpname, const FString &defines, int version); +}; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index df065e1ce..25b585531 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -21,68 +21,115 @@ */ #include "vk_shader.h" -#include "vulkan/system/vk_builders.h" +#include "vk_ppshader.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/system/vk_renderdevice.h" #include "hw_shaderpatcher.h" #include "filesystem.h" #include "engineerrors.h" #include "version.h" -#include -VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device) +bool VkShaderManager::CompileNextShader() { - ShInitialize(); - const char *mainvp = "shaders/glsl/main.vp"; const char *mainfp = "shaders/glsl/main.fp"; + int i = compileIndex; - for (int j = 0; j < MAX_PASS_TYPES; j++) + if (compileState == 0) { - bool gbufferpass = j; - for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++) + // regular material shaders + + VkShaderProgram prog; + prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, compilePass == GBUFFER_PASS); + mMaterialShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (defaultshaders[compileIndex].ShaderName == nullptr) { - VkShaderProgram prog; - prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass); - mMaterialShaders[j].push_back(std::move(prog)); - - if (i < SHADER_NoTexture) - { - VkShaderProgram natprog; - natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass); - mMaterialShadersNAT[j].push_back(std::move(natprog)); - } - } - - for (unsigned i = 0; i < usershaders.Size(); i++) - { - FString name = ExtractFileBase(usershaders[i].shader); - FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; - - VkShaderProgram prog; - prog.vert = LoadVertShader(name, mainvp, defines); - prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass); - mMaterialShaders[j].push_back(std::move(prog)); - } - - for (int i = 0; i < MAX_EFFECTS; i++) - { - VkShaderProgram prog; - prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines); - prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, gbufferpass); - mEffectShaders[j].push_back(std::move(prog)); + compileIndex = 0; + compileState++; } } + else if (compileState == 1) + { + // NAT material shaders + + VkShaderProgram natprog; + natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, compilePass == GBUFFER_PASS); + mMaterialShadersNAT[compilePass].push_back(std::move(natprog)); + + compileIndex++; + if (compileIndex == SHADER_NoTexture) + { + compileIndex = 0; + compileState++; + if (usershaders.Size() == 0) compileState++; + } + } + else if (compileState == 2) + { + // user shaders + + const FString& name = ExtractFileBase(usershaders[i].shader); + FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; + + VkShaderProgram prog; + prog.vert = LoadVertShader(name, mainvp, defines); + prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, compilePass == GBUFFER_PASS); + mMaterialShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (compileIndex >= (int)usershaders.Size()) + { + compileIndex = 0; + compileState++; + } + } + else if (compileState == 3) + { + // Effect shaders + + VkShaderProgram prog; + prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines); + prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, compilePass == GBUFFER_PASS); + mEffectShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (compileIndex >= MAX_EFFECTS) + { + compileIndex = 0; + compilePass++; + if (compilePass == MAX_PASS_TYPES) + { + compileIndex = -1; // we're done. + return true; + } + compileState = 0; + } + } + return false; +} + +VkShaderManager::VkShaderManager(VulkanRenderDevice* fb) : fb(fb) +{ + CompileNextShader(); } VkShaderManager::~VkShaderManager() { - ShFinalize(); +} + +void VkShaderManager::Deinit() +{ + while (!PPShaders.empty()) + RemoveVkPPShader(PPShaders.back()); } VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType) { - if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag) + if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag) { return &mEffectShaders[passType][effect]; } @@ -91,8 +138,10 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType) VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) { + if (compileIndex != -1) + return &mMaterialShaders[0][0]; // indices 0-2 match the warping modes, 3 no texture, the following are custom - if (!alphateston && eff <= 2) + if (!alphateston && eff < SHADER_NoTexture) { return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway } @@ -105,8 +154,14 @@ VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassT static const char *shaderBindings = R"( + layout(set = 0, binding = 0) uniform sampler2D ShadowMap; + layout(set = 0, binding = 1) uniform sampler2DArray LightMap; + #ifdef SUPPORTS_RAYTRACING + layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS; + #endif + // This must match the HWViewpointUniforms struct - layout(set = 0, binding = 0, std140) uniform ViewpointUBO { + layout(set = 1, binding = 0, std140) uniform ViewpointUBO { mat4 ProjectionMatrix; mat4 ViewMatrix; mat4 NormalViewMatrix; @@ -120,15 +175,11 @@ static const char *shaderBindings = R"( float uClipHeight; float uClipHeightDirection; int uShadowmapFilter; + + int uLightBlendMode; }; - // light buffers - layout(set = 0, binding = 1, std430) buffer LightBufferSSO - { - vec4 lights[]; - }; - - layout(set = 0, binding = 2, std140) uniform MatricesUBO { + layout(set = 1, binding = 1, std140) uniform MatricesUBO { mat4 ModelMatrix; mat4 NormalModelMatrix; mat4 TextureMatrix; @@ -150,7 +201,7 @@ static const char *shaderBindings = R"( int useVertexData; vec4 uVertexColor; vec4 uVertexNormal; - + vec4 uGlowTopPlane; vec4 uGlowTopColor; vec4 uGlowBottomPlane; @@ -167,24 +218,35 @@ static const char *shaderBindings = R"( vec4 padding1, padding2, padding3; }; - layout(set = 0, binding = 3, std140) uniform StreamUBO { + layout(set = 1, binding = 2, std140) uniform StreamUBO { StreamData data[MAX_STREAM_DATA]; }; - layout(set = 0, binding = 4) uniform sampler2D ShadowMap; + // light buffers + layout(set = 1, binding = 3, std430) buffer LightBufferSSO + { + vec4 lights[]; + }; + + // bone matrix buffers + layout(set = 1, binding = 4, std430) buffer BoneBufferSSO + { + mat4 bones[]; + }; // textures - layout(set = 1, binding = 0) uniform sampler2D tex; - layout(set = 1, binding = 1) uniform sampler2D texture2; - layout(set = 1, binding = 2) uniform sampler2D texture3; - layout(set = 1, binding = 3) uniform sampler2D texture4; - layout(set = 1, binding = 4) uniform sampler2D texture5; - layout(set = 1, binding = 5) uniform sampler2D texture6; - layout(set = 1, binding = 6) uniform sampler2D texture7; - layout(set = 1, binding = 7) uniform sampler2D texture8; - layout(set = 1, binding = 8) uniform sampler2D texture9; - layout(set = 1, binding = 9) uniform sampler2D texture10; - layout(set = 1, binding = 10) uniform sampler2D texture11; + 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; + layout(set = 2, binding = 11) uniform sampler2D texture12; // This must match the PushConstants struct layout(push_constant) uniform PushConstants @@ -206,8 +268,11 @@ static const char *shaderBindings = R"( // Blinn glossiness and specular level vec2 uSpecularMaterial; + // bone animation + int uBoneIndexBase; + int uDataIndex; - int padding1, padding2, padding3; + int padding2, padding3; }; // material types @@ -281,18 +346,21 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername code << "#define NPOT_EMULATION\n"; #endif code << shaderBindings; - if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; + if (!fb->device->EnabledFeatures.Features.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; code << "#line 1\n"; code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n"; - ShaderBuilder builder; - builder.setVertexShader(code); - return builder.create(shadername.GetChars(), device); + return ShaderBuilder() + .VertexShader(code.GetChars()) + .DebugName(shadername.GetChars()) + .Create(shadername.GetChars(), fb->device.get()); } std::unique_ptr VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass) { FString code = GetTargetGlslVersion(); + if (fb->RaytracingEnabled()) + code << "\n#define SUPPORTS_RAYTRACING\n"; code << defines; code << "\n$placeholder$"; // here the code can later add more needed #defines. code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; @@ -302,7 +370,7 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername code << shaderBindings; FString placeholder = "\n"; - if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; + if (!fb->device->EnabledFeatures.Features.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; if (!alphatest) code << "#define NO_ALPHATEST\n"; if (gbufferpass) code << "#define GBUFFER_PASS\n"; @@ -374,14 +442,22 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername code << LoadPrivateShaderLump(light_lump).GetChars(); } - ShaderBuilder builder; - builder.setFragmentShader(code); - return builder.create(shadername.GetChars(), device); + return ShaderBuilder() + .FragmentShader(code.GetChars()) + .DebugName(shadername.GetChars()) + .Create(shadername.GetChars(), fb->device.get()); } FString VkShaderManager::GetTargetGlslVersion() { - return "#version 450 core\n"; + if (fb->device->Instance->ApiVersion == VK_API_VERSION_1_2) + { + return "#version 460\n#extension GL_EXT_ray_query : enable\n"; + } + else + { + return "#version 450 core\n"; + } } FString VkShaderManager::LoadPublicShaderLump(const char *lumpname) @@ -400,3 +476,22 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname) FileData data = fileSystem.ReadFile(lump); return data.GetString(); } + +VkPPShader* VkShaderManager::GetVkShader(PPShader* shader) +{ + if (!shader->Backend) + shader->Backend = std::make_unique(fb, shader); + return static_cast(shader->Backend.get()); +} + +void VkShaderManager::AddVkPPShader(VkPPShader* shader) +{ + shader->it = PPShaders.insert(PPShaders.end(), shader); +} + +void VkShaderManager::RemoveVkPPShader(VkPPShader* shader) +{ + shader->Reset(); + shader->fb = nullptr; + PPShaders.erase(shader->it); +} diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index daa9dc845..cac924916 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -7,11 +7,15 @@ #include "matrix.h" #include "name.h" #include "hw_renderstate.h" +#include -#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 8 +#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 11 +class VulkanRenderDevice; class VulkanDevice; class VulkanShader; +class VkPPShader; +class PPShader; struct MatricesUBO { @@ -46,6 +50,9 @@ struct PushConstants // Blinn glossiness and specular level FVector2 uSpecularMaterial; + // bone animation + int uBoneIndexBase; + int uDataIndex; int padding1, padding2, padding3; }; @@ -60,11 +67,19 @@ public: class VkShaderManager { public: - VkShaderManager(VulkanDevice *device); + VkShaderManager(VulkanRenderDevice* fb); ~VkShaderManager(); + void Deinit(); + VkShaderProgram *GetEffect(int effect, EPassType passType); VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType); + bool CompileNextShader(); + + VkPPShader* GetVkShader(PPShader* shader); + + void AddVkPPShader(VkPPShader* shader); + void RemoveVkPPShader(VkPPShader* shader); private: std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines); @@ -74,9 +89,13 @@ private: FString LoadPublicShaderLump(const char *lumpname); FString LoadPrivateShaderLump(const char *lumpname); - VulkanDevice *device; + VulkanRenderDevice* fb = nullptr; std::vector mMaterialShaders[MAX_PASS_TYPES]; std::vector mMaterialShadersNAT[MAX_PASS_TYPES]; std::vector mEffectShaders[MAX_PASS_TYPES]; + uint8_t compilePass = 0, compileState = 0; + int compileIndex = 0; + + std::list PPShaders; }; diff --git a/src/common/rendering/vulkan/system/vk_buffer.cpp b/src/common/rendering/vulkan/system/vk_buffer.cpp new file mode 100644 index 000000000..cc1d04387 --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_buffer.cpp @@ -0,0 +1,134 @@ +/* +** 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_buffer.h" +#include "vk_hwbuffer.h" +#include "vulkan/renderer/vk_streambuffer.h" +#include "hwrenderer/data/shaderuniforms.h" + +VkBufferManager::VkBufferManager(VulkanRenderDevice* fb) : fb(fb) +{ +} + +VkBufferManager::~VkBufferManager() +{ +} + +void VkBufferManager::Init() +{ + MatrixBuffer.reset(new VkStreamBuffer(this, sizeof(MatricesUBO), 50000)); + StreamBuffer.reset(new VkStreamBuffer(this, sizeof(StreamUBO), 300)); + + CreateFanToTrisIndexBuffer(); +} + +void VkBufferManager::Deinit() +{ + while (!Buffers.empty()) + RemoveBuffer(Buffers.back()); +} + +void VkBufferManager::AddBuffer(VkHardwareBuffer* buffer) +{ + buffer->it = Buffers.insert(Buffers.end(), buffer); +} + +void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer) +{ + buffer->Reset(); + buffer->fb = nullptr; + Buffers.erase(buffer->it); + + for (VkHardwareDataBuffer** knownbuf : { &ViewpointUBO, &LightBufferSSO, &LightNodes, &LightLines, &LightList, &BoneBufferSSO }) + { + if (buffer == *knownbuf) *knownbuf = nullptr; + } +} + +IVertexBuffer* VkBufferManager::CreateVertexBuffer() +{ + return new VkHardwareVertexBuffer(fb); +} + +IIndexBuffer* VkBufferManager::CreateIndexBuffer() +{ + return new VkHardwareIndexBuffer(fb); +} + +IDataBuffer* VkBufferManager::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) +{ + auto buffer = new VkHardwareDataBuffer(fb, bindingpoint, ssbo, needsresize); + + switch (bindingpoint) + { + case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break; + case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break; + case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break; + case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break; + case LIGHTLIST_BINDINGPOINT: LightList = buffer; break; + case BONEBUF_BINDINGPOINT: BoneBufferSSO = buffer; break; + case POSTPROCESS_BINDINGPOINT: break; + default: break; + } + + return buffer; +} + +void VkBufferManager::CreateFanToTrisIndexBuffer() +{ + TArray data; + for (int i = 2; i < 1000; i++) + { + data.Push(0); + data.Push(i - 1); + data.Push(i); + } + + FanToTrisIndexBuffer.reset(CreateIndexBuffer()); + FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static); +} + +///////////////////////////////////////////////////////////////////////////// + +VkStreamBuffer::VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count) +{ + mBlockSize = static_cast((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment); + + UniformBuffer = (VkHardwareDataBuffer*)buffers->CreateDataBuffer(-1, false, false); + UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent); +} + +VkStreamBuffer::~VkStreamBuffer() +{ + delete UniformBuffer; +} + +uint32_t VkStreamBuffer::NextStreamDataBlock() +{ + mStreamDataOffset += mBlockSize; + if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size()) + { + mStreamDataOffset = 0; + return 0xffffffff; + } + return mStreamDataOffset; +} diff --git a/src/common/rendering/vulkan/system/vk_buffer.h b/src/common/rendering/vulkan/system/vk_buffer.h new file mode 100644 index 000000000..21ee7765f --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_buffer.h @@ -0,0 +1,65 @@ + +#pragma once + +#include "zvulkan/vulkanobjects.h" +#include + +class VulkanRenderDevice; +class VkHardwareBuffer; +class VkHardwareDataBuffer; +class VkStreamBuffer; +class IIndexBuffer; +class IVertexBuffer; +class IDataBuffer; + +class VkBufferManager +{ +public: + VkBufferManager(VulkanRenderDevice* fb); + ~VkBufferManager(); + + void Init(); + void Deinit(); + + IVertexBuffer* CreateVertexBuffer(); + IIndexBuffer* CreateIndexBuffer(); + IDataBuffer* CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize); + + void AddBuffer(VkHardwareBuffer* buffer); + void RemoveBuffer(VkHardwareBuffer* buffer); + + VkHardwareDataBuffer* ViewpointUBO = nullptr; + VkHardwareDataBuffer* LightBufferSSO = nullptr; + VkHardwareDataBuffer* LightNodes = nullptr; + VkHardwareDataBuffer* LightLines = nullptr; + VkHardwareDataBuffer* LightList = nullptr; + VkHardwareDataBuffer* BoneBufferSSO = nullptr; + + std::unique_ptr MatrixBuffer; + std::unique_ptr StreamBuffer; + + std::unique_ptr FanToTrisIndexBuffer; + +private: + void CreateFanToTrisIndexBuffer(); + + VulkanRenderDevice* fb = nullptr; + + std::list Buffers; +}; + +class VkStreamBuffer +{ +public: + VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count); + ~VkStreamBuffer(); + + uint32_t NextStreamDataBlock(); + void Reset() { mStreamDataOffset = 0; } + + VkHardwareDataBuffer* UniformBuffer = nullptr; + +private: + uint32_t mBlockSize = 0; + uint32_t mStreamDataOffset = 0; +}; diff --git a/src/common/rendering/vulkan/system/vk_buffers.cpp b/src/common/rendering/vulkan/system/vk_buffers.cpp deleted file mode 100644 index 96835419f..000000000 --- a/src/common/rendering/vulkan/system/vk_buffers.cpp +++ /dev/null @@ -1,253 +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_buffers.h" -#include "vk_builders.h" -#include "vk_framebuffer.h" -#include "vulkan/renderer/vk_renderstate.h" -#include "vulkan/renderer/vk_renderpass.h" -#include "engineerrors.h" - -VKBuffer *VKBuffer::First = nullptr; - -VKBuffer::VKBuffer() -{ - Next = First; - First = this; - if (Next) Next->Prev = this; -} - -VKBuffer::~VKBuffer() -{ - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - if (mBuffer && map) - mBuffer->Unmap(); - - auto fb = GetVulkanFrameBuffer(); - if (fb && mBuffer) - fb->FrameDeleteList.Buffers.push_back(std::move(mBuffer)); -} - -void VKBuffer::ResetAll() -{ - for (VKBuffer *cur = VKBuffer::First; cur; cur = cur->Next) - cur->Reset(); -} - -void VKBuffer::Reset() -{ - if (mBuffer && map) - mBuffer->Unmap(); - mBuffer.reset(); - mStaging.reset(); -} - -void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage) -{ - auto fb = GetVulkanFrameBuffer(); - - size_t bufsize = std::max(size, (size_t)16); // For supporting zero byte buffers - - if (usage == BufferUsageType::Static || usage == BufferUsageType::Stream) - { - // Note: we could recycle buffers here for the stream usage type to improve performance - - mPersistent = false; - - BufferBuilder builder; - builder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY); - builder.setSize(bufsize); - mBuffer = builder.create(fb->device); - - BufferBuilder builder2; - builder2.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - builder2.setSize(bufsize); - mStaging = builder2.create(fb->device); - - if (data) - { - void* dst = mStaging->Map(0, bufsize); - memcpy(dst, data, size); - mStaging->Unmap(); - } - - fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get()); - } - else if (usage == BufferUsageType::Persistent) - { - mPersistent = true; - - BufferBuilder builder; - builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); - builder.setMemoryType( - 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); - builder.setSize(bufsize); - mBuffer = builder.create(fb->device); - - map = mBuffer->Map(0, bufsize); - if (data) - memcpy(map, data, size); - } - else if (usage == BufferUsageType::Mappable) - { - mPersistent = false; - - BufferBuilder builder; - builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, 0); - builder.setMemoryType( - 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); - builder.setSize(bufsize); - mBuffer = builder.create(fb->device); - - if (data) - { - void* dst = mBuffer->Map(0, bufsize); - memcpy(dst, data, size); - mBuffer->Unmap(); - } - } - - buffersize = size; -} - -void VKBuffer::SetSubData(size_t offset, size_t size, const void *data) -{ - size = std::max(size, (size_t)16); // For supporting zero byte buffers - - auto fb = GetVulkanFrameBuffer(); - if (mStaging) - { - void *dst = mStaging->Map(offset, size); - memcpy(dst, data, size); - mStaging->Unmap(); - - fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size); - } - else - { - void *dst = mBuffer->Map(offset, size); - memcpy(dst, data, size); - mBuffer->Unmap(); - } -} - -void VKBuffer::Resize(size_t newsize) -{ - newsize = std::max(newsize, (size_t)16); // For supporting zero byte buffers - - auto fb = GetVulkanFrameBuffer(); - - // Grab old buffer - size_t oldsize = buffersize; - std::unique_ptr oldBuffer = std::move(mBuffer); - oldBuffer->Unmap(); - map = nullptr; - - // Create new buffer - BufferBuilder builder; - builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); - builder.setMemoryType( - 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); - builder.setSize(newsize); - mBuffer = builder.create(fb->device); - buffersize = newsize; - - // Transfer data from old to new - fb->GetTransferCommands()->copyBuffer(oldBuffer.get(), mBuffer.get(), 0, 0, oldsize); - fb->WaitForCommands(false); - - // Fetch pointer to new buffer - map = mBuffer->Map(0, newsize); - - // Old buffer may be part of the dynamic set - fb->GetRenderPassManager()->UpdateDynamicSet(); -} - -void VKBuffer::Map() -{ - if (!mPersistent) - map = mBuffer->Map(0, mBuffer->size); -} - -void VKBuffer::Unmap() -{ - if (!mPersistent) - { - mBuffer->Unmap(); - map = nullptr; - } -} - -void *VKBuffer::Lock(unsigned int size) -{ - size = std::max(size, (unsigned int)16); // For supporting zero byte buffers - - if (!mBuffer) - { - // The model mesh loaders lock multiple non-persistent buffers at the same time. This is not allowed in vulkan. - // VkDeviceMemory can only be mapped once and multiple non-persistent buffers may come from the same device memory object. - mStaticUpload.Resize(size); - map = mStaticUpload.Data(); - } - else if (!mPersistent) - { - map = mBuffer->Map(0, size); - } - return map; -} - -void VKBuffer::Unlock() -{ - if (!mBuffer) - { - map = nullptr; - SetData(mStaticUpload.Size(), mStaticUpload.Data(), BufferUsageType::Static); - mStaticUpload.Clear(); - } - else if (!mPersistent) - { - mBuffer->Unmap(); - map = nullptr; - } -} - -///////////////////////////////////////////////////////////////////////////// - -void VKVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) -{ - VertexFormat = GetVulkanFrameBuffer()->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs); -} - -///////////////////////////////////////////////////////////////////////////// - - -void VKDataBuffer::BindRange(FRenderState* state, size_t start, size_t length) -{ - static_cast(state)->Bind(bindingpoint, (uint32_t)start); -} - diff --git a/src/common/rendering/vulkan/system/vk_builders.cpp b/src/common/rendering/vulkan/system/vk_builders.cpp deleted file mode 100644 index 344b73a06..000000000 --- a/src/common/rendering/vulkan/system/vk_builders.cpp +++ /dev/null @@ -1,250 +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_builders.h" -#include "engineerrors.h" -#include "renderstyle.h" -#include -#include - -static const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - - /* .limits = */ { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - } -}; - -ShaderBuilder::ShaderBuilder() -{ -} - -void ShaderBuilder::setVertexShader(const FString &c) -{ - code = c; - stage = EShLanguage::EShLangVertex; -} - -void ShaderBuilder::setFragmentShader(const FString &c) -{ - code = c; - stage = EShLanguage::EShLangFragment; -} - -std::unique_ptr ShaderBuilder::create(const char *shadername, VulkanDevice *device) -{ - EShLanguage stage = (EShLanguage)this->stage; - const char *sources[] = { code.GetChars() }; - - TBuiltInResource resources = DefaultTBuiltInResource; - - glslang::TShader shader(stage); - shader.setStrings(sources, 1); - shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); - bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules); - if (!compileSuccess) - { - I_FatalError("Shader '%s' could not be compiled:\n%s\n", shadername, shader.getInfoLog()); - } - - glslang::TProgram program; - program.addShader(&shader); - bool linkSuccess = program.link(EShMsgDefault); - if (!linkSuccess) - { - I_FatalError("Shader '%s' could not be linked:\n%s\n", shadername, program.getInfoLog()); - } - - glslang::TIntermediate *intermediate = program.getIntermediate(stage); - if (!intermediate) - { - I_FatalError("Internal shader compiler error while processing '%s'\n", shadername); - } - - glslang::SpvOptions spvOptions; - spvOptions.generateDebugInfo = false; - spvOptions.disableOptimizer = false; - spvOptions.optimizeSize = true; - - std::vector spirv; - spv::SpvBuildLogger logger; - glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions); - - VkShaderModuleCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = spirv.size() * sizeof(unsigned int); - createInfo.pCode = spirv.data(); - - VkShaderModule shaderModule; - VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); - if (result != VK_SUCCESS) - { - FString msg; - msg.Format("Could not create vulkan shader module for '%s': %s", shadername, VkResultToString(result).GetChars()); - VulkanError(msg.GetChars()); - } - - return std::make_unique(device, shaderModule); -} - -///////////////////////////////////////////////////////////////////////////// - -void GraphicsPipelineBuilder::setBlendMode(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) - { - colorBlendAttachment.blendEnable = VK_FALSE; - return; - } - - static const int blendstyles[] = { - VK_BLEND_FACTOR_ZERO, - VK_BLEND_FACTOR_ONE, - VK_BLEND_FACTOR_SRC_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - VK_BLEND_FACTOR_SRC_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - VK_BLEND_FACTOR_DST_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, - VK_BLEND_FACTOR_DST_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, - }; - - static const int renderops[] = { - 0, VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - - int srcblend = blendstyles[style.SrcAlpha%STYLEALPHA_MAX]; - int dstblend = blendstyles[style.DestAlpha%STYLEALPHA_MAX]; - int blendequation = renderops[style.BlendOp & 15]; - - if (blendequation == -1) // This was a fuzz style. - { - srcblend = VK_BLEND_FACTOR_DST_COLOR; - dstblend = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blendequation = VK_BLEND_OP_ADD; - } - - setBlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend); -} diff --git a/src/common/rendering/vulkan/system/vk_builders.h b/src/common/rendering/vulkan/system/vk_builders.h deleted file mode 100644 index af9cbc3eb..000000000 --- a/src/common/rendering/vulkan/system/vk_builders.h +++ /dev/null @@ -1,1382 +0,0 @@ -#pragma once - -#include "vk_objects.h" -#include "zstring.h" -#include - -template -class FixedSizeVector -{ -public: - const T *data() const { return mItems; } - T *data() { return mItems; } - - size_t size() const { return mCount; } - - const T &back() const { return mItems[mCount - 1]; } - T &back() { return mItems[mCount - 1]; } - - void push_back(T && value) - { - assert(mCount != maxsize && "FixedSizeVector is too small"); - mItems[mCount++] = std::move(value); - } - - void push_back(const T &value) - { - assert(mCount != maxsize && "FixedSizeVector is too small"); - mItems[mCount++] = value; - } - -private: - T mItems[maxsize]; - size_t mCount = 0; -}; - -class ImageBuilder -{ -public: - ImageBuilder(); - - void setSize(int width, int height, int miplevels = 1); - void setSamples(VkSampleCountFlagBits samples); - void setFormat(VkFormat format); - void setUsage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); - void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); - void setLinearTiling(); - - bool isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0); - - std::unique_ptr create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); - std::unique_ptr tryCreate(VulkanDevice *device); - -private: - VkImageCreateInfo imageInfo = {}; - VmaAllocationCreateInfo allocInfo = {}; -}; - -class ImageViewBuilder -{ -public: - ImageViewBuilder(); - - void setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkImageViewCreateInfo viewInfo = {}; -}; - -class SamplerBuilder -{ -public: - SamplerBuilder(); - - void setAddressMode(VkSamplerAddressMode addressMode); - void setAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w); - void setMinFilter(VkFilter minFilter); - void setMagFilter(VkFilter magFilter); - void setMipmapMode(VkSamplerMipmapMode mode); - void setAnisotropy(float maxAnisotropy); - void setMaxLod(float value); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkSamplerCreateInfo samplerInfo = {}; -}; - -class BufferBuilder -{ -public: - BufferBuilder(); - - void setSize(size_t size); - void setUsage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); - void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkBufferCreateInfo bufferInfo = {}; - VmaAllocationCreateInfo allocInfo = {}; -}; - -class ShaderBuilder -{ -public: - ShaderBuilder(); - - void setVertexShader(const FString &code); - void setFragmentShader(const FString &code); - - std::unique_ptr create(const char *shadername, VulkanDevice *device); - -private: - FString code; - int stage; -}; - -class ComputePipelineBuilder -{ -public: - ComputePipelineBuilder(); - - void setLayout(VulkanPipelineLayout *layout); - void setComputeShader(VulkanShader *shader); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkComputePipelineCreateInfo pipelineInfo = {}; - VkPipelineShaderStageCreateInfo stageInfo = {}; -}; - -class DescriptorSetLayoutBuilder -{ -public: - DescriptorSetLayoutBuilder(); - - void addBinding(int binding, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkDescriptorSetLayoutCreateInfo layoutInfo = {}; - TArray bindings; -}; - -class DescriptorPoolBuilder -{ -public: - DescriptorPoolBuilder(); - - void setMaxSets(int value); - void addPoolSize(VkDescriptorType type, int count); - - std::unique_ptr create(VulkanDevice *device); - -private: - FixedSizeVector poolSizes; - VkDescriptorPoolCreateInfo poolInfo = {}; -}; - -class QueryPoolBuilder -{ -public: - QueryPoolBuilder(); - - void setQueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics = 0); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkQueryPoolCreateInfo poolInfo = {}; -}; - -class FramebufferBuilder -{ -public: - FramebufferBuilder(); - - void setRenderPass(VulkanRenderPass *renderPass); - void addAttachment(VulkanImageView *view); - void addAttachment(VkImageView view); - void setSize(int width, int height, int layers = 1); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkFramebufferCreateInfo framebufferInfo = {}; - FixedSizeVector attachments; -}; - -union FRenderStyle; - -class GraphicsPipelineBuilder -{ -public: - GraphicsPipelineBuilder(); - - void setSubpass(int subpass); - void setLayout(VulkanPipelineLayout *layout); - void setRenderPass(VulkanRenderPass *renderPass); - void setTopology(VkPrimitiveTopology topology); - void setViewport(float x, float y, float width, float height, float minDepth = 0.0f, float maxDepth = 1.0f); - void setScissor(int x, int y, int width, int height); - void setRasterizationSamples(VkSampleCountFlagBits samples); - - void setCull(VkCullModeFlags cullMode, VkFrontFace frontFace); - void setDepthStencilEnable(bool test, bool write, bool stencil); - void setDepthFunc(VkCompareOp func); - void setDepthClampEnable(bool value); - void setDepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor); - void setColorWriteMask(VkColorComponentFlags mask); - void setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference); - - void setAdditiveBlendMode(); - void setAlphaBlendMode(); - void setBlendMode(const FRenderStyle &style); - void setBlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); - void setSubpassColorAttachmentCount(int count); - - void addVertexShader(VulkanShader *shader); - void addFragmentShader(VulkanShader *shader); - - void addVertexBufferBinding(int index, size_t stride); - void addVertexAttribute(int location, int binding, VkFormat format, size_t offset); - - void addDynamicState(VkDynamicState state); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkGraphicsPipelineCreateInfo pipelineInfo = { }; - VkPipelineVertexInputStateCreateInfo vertexInputInfo = { }; - VkPipelineInputAssemblyStateCreateInfo inputAssembly = { }; - VkViewport viewport = { }; - VkRect2D scissor = { }; - VkPipelineViewportStateCreateInfo viewportState = { }; - VkPipelineRasterizationStateCreateInfo rasterizer = { }; - VkPipelineMultisampleStateCreateInfo multisampling = { }; - VkPipelineColorBlendAttachmentState colorBlendAttachment = { }; - VkPipelineColorBlendStateCreateInfo colorBlending = { }; - VkPipelineDepthStencilStateCreateInfo depthStencil = { }; - VkPipelineDynamicStateCreateInfo dynamicState = {}; - - std::vector shaderStages; - std::vector colorBlendAttachments; - std::vector vertexInputBindings; - std::vector vertexInputAttributes; - std::vector dynamicStates; -}; - -class PipelineLayoutBuilder -{ -public: - PipelineLayoutBuilder(); - - void addSetLayout(VulkanDescriptorSetLayout *setLayout); - void addPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; - std::vector setLayouts; - std::vector pushConstantRanges; -}; - -class RenderPassBuilder -{ -public: - RenderPassBuilder(); - - void addAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout); - void addDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout); - - void addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - - void addSubpass(); - void addSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout); - void addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout); - - std::unique_ptr create(VulkanDevice *device); - -private: - VkRenderPassCreateInfo renderPassInfo = { }; - - FixedSizeVector attachments; - FixedSizeVector dependencies; - FixedSizeVector subpasses; - - struct SubpassData - { - FixedSizeVector colorRefs; - VkAttachmentReference depthRef = { }; - }; - - FixedSizeVector, 8> subpassData; -}; - -class PipelineBarrier -{ -public: - void addMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - void addImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - void addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - - void execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags = 0); - -private: - FixedSizeVector memoryBarriers; - FixedSizeVector bufferMemoryBarriers; - FixedSizeVector imageMemoryBarriers; -}; - -class QueueSubmit -{ -public: - QueueSubmit(); - - void addCommandBuffer(VulkanCommandBuffer *buffer); - void addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore); - void addSignal(VulkanSemaphore *semaphore); - void execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence = nullptr); - -private: - VkSubmitInfo submitInfo = {}; - FixedSizeVector waitSemaphores; - FixedSizeVector waitStages; - FixedSizeVector signalSemaphores; - FixedSizeVector commandBuffers; -}; - -class WriteDescriptors -{ -public: - void addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer); - void addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range); - void addStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout); - void addCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout); - - void updateSets(VulkanDevice *device); - -private: - struct WriteExtra - { - VkDescriptorImageInfo imageInfo; - VkDescriptorBufferInfo bufferInfo; - VkBufferView bufferView; - }; - - std::vector writes; - std::vector> writeExtras; -}; - -///////////////////////////////////////////////////////////////////////////// - -inline ImageBuilder::ImageBuilder() -{ - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent.depth = 1; - imageInfo.arrayLayers = 1; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Note: must either be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.flags = 0; -} - -inline void ImageBuilder::setSize(int width, int height, int mipLevels) -{ - imageInfo.extent.width = width; - imageInfo.extent.height = height; - imageInfo.mipLevels = mipLevels; -} - -inline void ImageBuilder::setSamples(VkSampleCountFlagBits samples) -{ - imageInfo.samples = samples; -} - -inline void ImageBuilder::setFormat(VkFormat format) -{ - imageInfo.format = format; -} - -inline void ImageBuilder::setLinearTiling() -{ - imageInfo.tiling = VK_IMAGE_TILING_LINEAR; -} - -inline void ImageBuilder::setUsage(VkImageUsageFlags usage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) -{ - imageInfo.usage = usage; - allocInfo.usage = memoryUsage; - allocInfo.flags = allocFlags; -} - -inline void ImageBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) -{ - allocInfo.requiredFlags = requiredFlags; - allocInfo.preferredFlags = preferredFlags; - allocInfo.memoryTypeBits = memoryTypeBits; -} - -inline bool ImageBuilder::isFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures) -{ - VkImageFormatProperties properties = { }; - VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); - if (result != VK_SUCCESS) return false; - if (imageInfo.extent.width > properties.maxExtent.width) return false; - if (imageInfo.extent.height > properties.maxExtent.height) return false; - if (imageInfo.extent.depth > properties.maxExtent.depth) return false; - if (imageInfo.mipLevels > properties.maxMipLevels) return false; - if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; - if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; - if (bufferFeatures != 0) - { - VkFormatProperties formatProperties = { }; - vkGetPhysicalDeviceFormatProperties(device->PhysicalDevice.Device, imageInfo.format, &formatProperties); - if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures) - return false; - } - return true; -} - -inline std::unique_ptr ImageBuilder::create(VulkanDevice *device, VkDeviceSize* allocatedBytes) -{ - VkImage image; - VmaAllocation allocation; - - VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); - CheckVulkanError(result, "Could not create vulkan image"); - - if (allocatedBytes != nullptr) - { - VmaAllocationInfo allocatedInfo; - vmaGetAllocationInfo(device->allocator, allocation, &allocatedInfo); - - *allocatedBytes = allocatedInfo.size; - } - - return std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels); -} - -inline std::unique_ptr ImageBuilder::tryCreate(VulkanDevice *device) -{ - VkImage image; - VmaAllocation allocation; - - VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); - if (result != VK_SUCCESS) - return nullptr; - - return std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels); -} - -///////////////////////////////////////////////////////////////////////////// - -inline ImageViewBuilder::ImageViewBuilder() -{ - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; -} - -inline void ImageViewBuilder::setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask) -{ - viewInfo.image = image->image; - viewInfo.format = format; - viewInfo.subresourceRange.levelCount = image->mipLevels; - viewInfo.subresourceRange.aspectMask = aspectMask; -} - -inline std::unique_ptr ImageViewBuilder::create(VulkanDevice *device) -{ - VkImageView view; - VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view); - CheckVulkanError(result, "Could not create texture image view"); - - return std::make_unique(device, view); -} - -///////////////////////////////////////////////////////////////////////////// - -inline SamplerBuilder::SamplerBuilder() -{ - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.anisotropyEnable = VK_FALSE; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 100.0f; -} - -inline void SamplerBuilder::setAddressMode(VkSamplerAddressMode addressMode) -{ - samplerInfo.addressModeU = addressMode; - samplerInfo.addressModeV = addressMode; - samplerInfo.addressModeW = addressMode; -} - -inline void SamplerBuilder::setAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w) -{ - samplerInfo.addressModeU = u; - samplerInfo.addressModeV = v; - samplerInfo.addressModeW = w; -} - -inline void SamplerBuilder::setMinFilter(VkFilter minFilter) -{ - samplerInfo.minFilter = minFilter; -} - -inline void SamplerBuilder::setMagFilter(VkFilter magFilter) -{ - samplerInfo.magFilter = magFilter; -} - -inline void SamplerBuilder::setMipmapMode(VkSamplerMipmapMode mode) -{ - samplerInfo.mipmapMode = mode; -} - -inline void SamplerBuilder::setAnisotropy(float maxAnisotropy) -{ - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = maxAnisotropy; -} - -inline void SamplerBuilder::setMaxLod(float value) -{ - samplerInfo.maxLod = value; -} - -inline std::unique_ptr SamplerBuilder::create(VulkanDevice *device) -{ - VkSampler sampler; - VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler); - CheckVulkanError(result, "Could not create texture sampler"); - return std::make_unique(device, sampler); -} - -///////////////////////////////////////////////////////////////////////////// - -inline BufferBuilder::BufferBuilder() -{ - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; -} - -inline void BufferBuilder::setSize(size_t size) -{ - bufferInfo.size = std::max(size, (size_t)16); -} - -inline void BufferBuilder::setUsage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) -{ - bufferInfo.usage = bufferUsage; - allocInfo.usage = memoryUsage; - allocInfo.flags = allocFlags; -} - -inline void BufferBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) -{ - allocInfo.requiredFlags = requiredFlags; - allocInfo.preferredFlags = preferredFlags; - allocInfo.memoryTypeBits = memoryTypeBits; -} - -inline std::unique_ptr BufferBuilder::create(VulkanDevice *device) -{ - VkBuffer buffer; - VmaAllocation allocation; - - VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); - CheckVulkanError(result, "Could not allocate memory for vulkan buffer"); - - return std::make_unique(device, buffer, allocation, bufferInfo.size); -} - -///////////////////////////////////////////////////////////////////////////// - -inline ComputePipelineBuilder::ComputePipelineBuilder() -{ - pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; -} - -inline void ComputePipelineBuilder::setLayout(VulkanPipelineLayout *layout) -{ - pipelineInfo.layout = layout->layout; -} - -inline void ComputePipelineBuilder::setComputeShader(VulkanShader *shader) -{ - stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; - stageInfo.module = shader->module; - stageInfo.pName = "main"; - - pipelineInfo.stage = stageInfo; -} - -inline std::unique_ptr ComputePipelineBuilder::create(VulkanDevice *device) -{ - VkPipeline pipeline; - vkCreateComputePipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - return std::make_unique(device, pipeline); -} - -///////////////////////////////////////////////////////////////////////////// - -inline DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder() -{ - layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; -} - -inline void DescriptorSetLayoutBuilder::addBinding(int index, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags) -{ - VkDescriptorSetLayoutBinding binding = { }; - binding.binding = index; - binding.descriptorType = type; - binding.descriptorCount = arrayCount; - binding.stageFlags = stageFlags; - binding.pImmutableSamplers = nullptr; - bindings.Push(binding); - - layoutInfo.bindingCount = (uint32_t)bindings.Size(); - layoutInfo.pBindings = &bindings[0]; -} - -inline std::unique_ptr DescriptorSetLayoutBuilder::create(VulkanDevice *device) -{ - VkDescriptorSetLayout layout; - VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout); - CheckVulkanError(result, "Could not create descriptor set layout"); - return std::make_unique(device, layout); -} - -///////////////////////////////////////////////////////////////////////////// - -inline DescriptorPoolBuilder::DescriptorPoolBuilder() -{ - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.maxSets = 1; - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; -} - -inline void DescriptorPoolBuilder::setMaxSets(int value) -{ - poolInfo.maxSets = value; -} - -inline void DescriptorPoolBuilder::addPoolSize(VkDescriptorType type, int count) -{ - VkDescriptorPoolSize size; - size.type = type; - size.descriptorCount = count; - poolSizes.push_back(size); - - poolInfo.poolSizeCount = (uint32_t)poolSizes.size(); - poolInfo.pPoolSizes = poolSizes.data(); -} - -inline std::unique_ptr DescriptorPoolBuilder::create(VulkanDevice *device) -{ - VkDescriptorPool descriptorPool; - VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool); - CheckVulkanError(result, "Could not create descriptor pool"); - return std::make_unique(device, descriptorPool); -} - -///////////////////////////////////////////////////////////////////////////// - -inline QueryPoolBuilder::QueryPoolBuilder() -{ - poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; -} - -inline void QueryPoolBuilder::setQueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics) -{ - poolInfo.queryType = type; - poolInfo.queryCount = count; - poolInfo.pipelineStatistics = pipelineStatistics; -} - -inline std::unique_ptr QueryPoolBuilder::create(VulkanDevice *device) -{ - VkQueryPool queryPool; - VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool); - CheckVulkanError(result, "Could not create query pool"); - return std::make_unique(device, queryPool); -} - -///////////////////////////////////////////////////////////////////////////// - -inline FramebufferBuilder::FramebufferBuilder() -{ - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; -} - -inline void FramebufferBuilder::setRenderPass(VulkanRenderPass *renderPass) -{ - framebufferInfo.renderPass = renderPass->renderPass; -} - -inline void FramebufferBuilder::addAttachment(VulkanImageView *view) -{ - attachments.push_back(view->view); - - framebufferInfo.attachmentCount = (uint32_t)attachments.size(); - framebufferInfo.pAttachments = attachments.data(); -} - -inline void FramebufferBuilder::addAttachment(VkImageView view) -{ - attachments.push_back(view); - - framebufferInfo.attachmentCount = (uint32_t)attachments.size(); - framebufferInfo.pAttachments = attachments.data(); -} - -inline void FramebufferBuilder::setSize(int width, int height, int layers) -{ - framebufferInfo.width = width; - framebufferInfo.height = height; - framebufferInfo.layers = 1; -} - -inline std::unique_ptr FramebufferBuilder::create(VulkanDevice *device) -{ - VkFramebuffer framebuffer = 0; - VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer); - CheckVulkanError(result, "Could not create framebuffer"); - return std::make_unique(device, framebuffer); -} - -///////////////////////////////////////////////////////////////////////////// - -inline GraphicsPipelineBuilder::GraphicsPipelineBuilder() -{ - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pDepthStencilState = &depthStencil; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - pipelineInfo.basePipelineIndex = -1; - - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 0; - vertexInputInfo.pVertexBindingDescriptions = nullptr; - vertexInputInfo.vertexAttributeDescriptionCount = 0; - vertexInputInfo.pVertexAttributeDescriptions = nullptr; - - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - - depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - depthStencil.depthBoundsTestEnable = VK_FALSE; - depthStencil.minDepthBounds = 0.0f; - depthStencil.maxDepthBounds = 1.0f; - depthStencil.stencilTestEnable = VK_FALSE; - depthStencil.front = {}; - depthStencil.back = {}; - - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_NONE; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - rasterizer.depthBiasConstantFactor = 0.0f; - rasterizer.depthBiasClamp = 0.0f; - rasterizer.depthBiasSlopeFactor = 0.0f; - - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampling.minSampleShading = 1.0f; - multisampling.pSampleMask = nullptr; - 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; - colorBlending.blendConstants[3] = 0.0f; - - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; -} - -inline void GraphicsPipelineBuilder::setRasterizationSamples(VkSampleCountFlagBits samples) -{ - multisampling.rasterizationSamples = samples; -} - -inline void GraphicsPipelineBuilder::setSubpass(int subpass) -{ - pipelineInfo.subpass = subpass; -} - -inline void GraphicsPipelineBuilder::setLayout(VulkanPipelineLayout *layout) -{ - pipelineInfo.layout = layout->layout; -} - -inline void GraphicsPipelineBuilder::setRenderPass(VulkanRenderPass *renderPass) -{ - pipelineInfo.renderPass = renderPass->renderPass; -} - -inline void GraphicsPipelineBuilder::setTopology(VkPrimitiveTopology topology) -{ - inputAssembly.topology = topology; -} - -inline void GraphicsPipelineBuilder::setViewport(float x, float y, float width, float height, float minDepth, float maxDepth) -{ - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = width; - viewport.height = height; - viewport.minDepth = minDepth; - viewport.maxDepth = maxDepth; - - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; -} - -inline void GraphicsPipelineBuilder::setScissor(int x, int y, int width, int height) -{ - scissor.offset.x = x; - scissor.offset.y = y; - scissor.extent.width = width; - scissor.extent.height = height; - - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; -} - -inline void GraphicsPipelineBuilder::setCull(VkCullModeFlags cullMode, VkFrontFace frontFace) -{ - rasterizer.cullMode = cullMode; - rasterizer.frontFace = frontFace; -} - -inline void GraphicsPipelineBuilder::setDepthStencilEnable(bool test, bool write, bool stencil) -{ - depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE; - depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE; - depthStencil.stencilTestEnable = stencil ? VK_TRUE : VK_FALSE; -} - -inline void GraphicsPipelineBuilder::setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference) -{ - depthStencil.front.failOp = failOp; - depthStencil.front.passOp = passOp; - depthStencil.front.depthFailOp = depthFailOp; - depthStencil.front.compareOp = compareOp; - depthStencil.front.compareMask = compareMask; - depthStencil.front.writeMask = writeMask; - depthStencil.front.reference = reference; - - depthStencil.back.failOp = failOp; - depthStencil.back.passOp = passOp; - depthStencil.back.depthFailOp = depthFailOp; - depthStencil.back.compareOp = compareOp; - depthStencil.back.compareMask = compareMask; - depthStencil.back.writeMask = writeMask; - depthStencil.back.reference = reference; -} - -inline void GraphicsPipelineBuilder::setDepthFunc(VkCompareOp func) -{ - depthStencil.depthCompareOp = func; -} - -inline void GraphicsPipelineBuilder::setDepthClampEnable(bool value) -{ - rasterizer.depthClampEnable = value ? VK_TRUE : VK_FALSE; -} - -inline void GraphicsPipelineBuilder::setDepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor) -{ - rasterizer.depthBiasEnable = enable ? VK_TRUE : VK_FALSE; - rasterizer.depthBiasConstantFactor = biasConstantFactor; - rasterizer.depthBiasClamp = biasClamp; - rasterizer.depthBiasSlopeFactor = biasSlopeFactor; -} - -inline void GraphicsPipelineBuilder::setColorWriteMask(VkColorComponentFlags mask) -{ - colorBlendAttachment.colorWriteMask = mask; -} - -inline void GraphicsPipelineBuilder::setAdditiveBlendMode() -{ - 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; -} - -inline void GraphicsPipelineBuilder::setAlphaBlendMode() -{ - 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; -} - -inline void GraphicsPipelineBuilder::setBlendMode(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; -} - -inline void GraphicsPipelineBuilder::setSubpassColorAttachmentCount(int count) -{ - colorBlendAttachments.resize(count, colorBlendAttachment); - colorBlending.pAttachments = colorBlendAttachments.data(); - colorBlending.attachmentCount = (uint32_t)colorBlendAttachments.size(); -} - -inline void GraphicsPipelineBuilder::addVertexShader(VulkanShader *shader) -{ - VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = shader->module; - vertShaderStageInfo.pName = "main"; - shaderStages.push_back(vertShaderStageInfo); - - pipelineInfo.stageCount = (uint32_t)shaderStages.size(); - pipelineInfo.pStages = shaderStages.data(); -} - -inline void GraphicsPipelineBuilder::addFragmentShader(VulkanShader *shader) -{ - VkPipelineShaderStageCreateInfo fragShaderStageInfo = {}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = shader->module; - fragShaderStageInfo.pName = "main"; - shaderStages.push_back(fragShaderStageInfo); - - pipelineInfo.stageCount = (uint32_t)shaderStages.size(); - pipelineInfo.pStages = shaderStages.data(); -} - -inline void GraphicsPipelineBuilder::addVertexBufferBinding(int index, size_t stride) -{ - VkVertexInputBindingDescription desc = {}; - desc.binding = index; - desc.stride = (uint32_t)stride; - desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vertexInputBindings.push_back(desc); - - vertexInputInfo.vertexBindingDescriptionCount = (uint32_t)vertexInputBindings.size(); - vertexInputInfo.pVertexBindingDescriptions = vertexInputBindings.data(); -} - -inline void GraphicsPipelineBuilder::addVertexAttribute(int location, int binding, VkFormat format, size_t offset) -{ - VkVertexInputAttributeDescription desc = { }; - desc.location = location; - desc.binding = binding; - desc.format = format; - desc.offset = (uint32_t)offset; - vertexInputAttributes.push_back(desc); - - vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)vertexInputAttributes.size(); - vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributes.data(); -} - -inline void GraphicsPipelineBuilder::addDynamicState(VkDynamicState state) -{ - dynamicStates.push_back(state); - dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size(); - dynamicState.pDynamicStates = dynamicStates.data(); -} - -inline std::unique_ptr GraphicsPipelineBuilder::create(VulkanDevice *device) -{ - VkPipeline pipeline = 0; - VkResult result = vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - CheckVulkanError(result, "Could not create graphics pipeline"); - return std::make_unique(device, pipeline); -} - -///////////////////////////////////////////////////////////////////////////// - -inline PipelineLayoutBuilder::PipelineLayoutBuilder() -{ - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; -} - -inline void PipelineLayoutBuilder::addSetLayout(VulkanDescriptorSetLayout *setLayout) -{ - setLayouts.push_back(setLayout->layout); - pipelineLayoutInfo.setLayoutCount = (uint32_t)setLayouts.size(); - pipelineLayoutInfo.pSetLayouts = setLayouts.data(); -} - -inline void PipelineLayoutBuilder::addPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size) -{ - VkPushConstantRange range = { }; - range.stageFlags = stageFlags; - range.offset = (uint32_t)offset; - range.size = (uint32_t)size; - pushConstantRanges.push_back(range); - pipelineLayoutInfo.pushConstantRangeCount = (uint32_t)pushConstantRanges.size(); - pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data(); -} - -inline std::unique_ptr PipelineLayoutBuilder::create(VulkanDevice *device) -{ - VkPipelineLayout pipelineLayout; - VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout); - CheckVulkanError(result, "Could not create pipeline layout"); - return std::make_unique(device, pipelineLayout); -} - -///////////////////////////////////////////////////////////////////////////// - -inline RenderPassBuilder::RenderPassBuilder() -{ - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; -} - -inline void RenderPassBuilder::addAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout) -{ - VkAttachmentDescription attachment = {}; - attachment.format = format; - attachment.samples = samples; - attachment.loadOp = load; - attachment.storeOp = store; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment.initialLayout = initialLayout; - attachment.finalLayout = finalLayout; - attachments.push_back(attachment); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.attachmentCount = (uint32_t)attachments.size(); -} - -inline void RenderPassBuilder::addDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout) -{ - VkAttachmentDescription attachment = {}; - attachment.format = format; - attachment.samples = samples; - attachment.loadOp = load; - attachment.storeOp = store; - attachment.stencilLoadOp = stencilLoad; - attachment.stencilStoreOp = stencilStore; - attachment.initialLayout = initialLayout; - attachment.finalLayout = finalLayout; - attachments.push_back(attachment); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.attachmentCount = (uint32_t)attachments.size(); -} - -inline void RenderPassBuilder::addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = srcStageMask; - dependency.srcAccessMask = srcAccessMask; - dependency.dstStageMask = dstStageMask; - dependency.dstAccessMask = dstAccessMask; - - dependencies.push_back(dependency); - renderPassInfo.pDependencies = dependencies.data(); - renderPassInfo.dependencyCount = (uint32_t)dependencies.size(); -} - -inline void RenderPassBuilder::addSubpass() -{ - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - - subpasses.push_back(subpass); - renderPassInfo.pSubpasses = subpasses.data(); - renderPassInfo.subpassCount = (uint32_t)subpasses.size(); - - subpassData.push_back(std::make_unique()); -} - -inline void RenderPassBuilder::addSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout) -{ - VkAttachmentReference colorAttachmentRef = {}; - colorAttachmentRef.attachment = index; - colorAttachmentRef.layout = layout; - - subpassData.back()->colorRefs.push_back(colorAttachmentRef); - subpasses.back().pColorAttachments = subpassData.back()->colorRefs.data(); - subpasses.back().colorAttachmentCount = (uint32_t)subpassData.back()->colorRefs.size(); -} - -inline void RenderPassBuilder::addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout) -{ - VkAttachmentReference &depthAttachmentRef = subpassData.back()->depthRef; - depthAttachmentRef.attachment = index; - depthAttachmentRef.layout = layout; - - VkSubpassDescription &subpass = subpasses.back(); - subpass.pDepthStencilAttachment = &depthAttachmentRef; -} - -inline std::unique_ptr RenderPassBuilder::create(VulkanDevice *device) -{ - VkRenderPass renderPass = 0; - VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass); - CheckVulkanError(result, "Could not create render pass"); - return std::make_unique(device, renderPass); -} - -///////////////////////////////////////////////////////////////////////////// - -inline void PipelineBarrier::addMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - memoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - addBuffer(buffer, 0, buffer->size, srcAccessMask, dstAccessMask); -} - -inline void PipelineBarrier::addBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkBufferMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.buffer = buffer->buffer; - barrier.offset = offset; - barrier.size = size; - bufferMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - addImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount); -} - -inline void PipelineBarrier::addImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - VkImageMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - barrier.subresourceRange.aspectMask = aspectMask; - barrier.subresourceRange.baseMipLevel = baseMipLevel; - barrier.subresourceRange.levelCount = levelCount; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - imageMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkBufferMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.srcQueueFamilyIndex = srcFamily; - barrier.dstQueueFamilyIndex = dstFamily; - barrier.buffer = buffer->buffer; - barrier.offset = 0; - barrier.size = buffer->size; - bufferMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - VkImageMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = layout; - barrier.newLayout = layout; - barrier.srcQueueFamilyIndex = srcFamily; - barrier.dstQueueFamilyIndex = dstFamily; - barrier.image = image->image; - barrier.subresourceRange.aspectMask = aspectMask; - barrier.subresourceRange.baseMipLevel = baseMipLevel; - barrier.subresourceRange.levelCount = levelCount; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - imageMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags) -{ - commandBuffer->pipelineBarrier( - srcStageMask, dstStageMask, dependencyFlags, - (uint32_t)memoryBarriers.size(), memoryBarriers.data(), - (uint32_t)bufferMemoryBarriers.size(), bufferMemoryBarriers.data(), - (uint32_t)imageMemoryBarriers.size(), imageMemoryBarriers.data()); -} - -///////////////////////////////////////////////////////////////////////////// - -inline QueueSubmit::QueueSubmit() -{ - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; -} - -inline void QueueSubmit::addCommandBuffer(VulkanCommandBuffer *buffer) -{ - commandBuffers.push_back(buffer->buffer); - submitInfo.pCommandBuffers = commandBuffers.data(); - submitInfo.commandBufferCount = (uint32_t)commandBuffers.size(); -} - -inline void QueueSubmit::addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore) -{ - waitStages.push_back(waitStageMask); - waitSemaphores.push_back(semaphore->semaphore); - - submitInfo.pWaitDstStageMask = waitStages.data(); - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size(); -} - -inline void QueueSubmit::addSignal(VulkanSemaphore *semaphore) -{ - signalSemaphores.push_back(semaphore->semaphore); - submitInfo.pSignalSemaphores = signalSemaphores.data(); - submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.size(); -} - -inline void QueueSubmit::execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence) -{ - VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE); - CheckVulkanError(result, "Could not submit command buffer"); -} - -///////////////////////////////////////////////////////////////////////////// - -inline void WriteDescriptors::addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer) -{ - addBuffer(descriptorSet, binding, type, buffer, 0, buffer->size); -} - -inline void WriteDescriptors::addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range) -{ - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = buffer->buffer; - bufferInfo.offset = offset; - bufferInfo.range = range; - - auto extra = std::make_unique(); - extra->bufferInfo = bufferInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = type; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &extra->bufferInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::addStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout) -{ - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = view->view; - imageInfo.imageLayout = imageLayout; - - auto extra = std::make_unique(); - extra->imageInfo = imageInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pImageInfo = &extra->imageInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::addCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout) -{ - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = view->view; - imageInfo.sampler = sampler->sampler; - imageInfo.imageLayout = imageLayout; - - auto extra = std::make_unique(); - extra->imageInfo = imageInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pImageInfo = &extra->imageInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::updateSets(VulkanDevice *device) -{ - vkUpdateDescriptorSets(device->device, (uint32_t)writes.size(), writes.data(), 0, nullptr); -} diff --git a/src/common/rendering/vulkan/system/vk_commandbuffer.cpp b/src/common/rendering/vulkan/system/vk_commandbuffer.cpp new file mode 100644 index 000000000..59d19719d --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_commandbuffer.cpp @@ -0,0 +1,264 @@ +/* +** 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_commandbuffer.h" +#include "vk_renderdevice.h" +#include "zvulkan/vulkanswapchain.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/textures/vk_framebuffer.h" +#include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/renderer/vk_postprocess.h" +#include "hw_clock.h" +#include "v_video.h" + +extern int rendered_commandbuffers; +int current_rendered_commandbuffers; + +extern bool gpuStatActive; +extern bool keepGpuStatActive; +extern FString gpuStatOutput; + +VkCommandBufferManager::VkCommandBufferManager(VulkanRenderDevice* fb) : fb(fb) +{ + mCommandPool = CommandPoolBuilder() + .QueueFamily(fb->device->GraphicsFamily) + .DebugName("mCommandPool") + .Create(fb->device.get()); + + for (auto& semaphore : mSubmitSemaphore) + semaphore.reset(new VulkanSemaphore(fb->device.get())); + + for (auto& fence : mSubmitFence) + fence.reset(new VulkanFence(fb->device.get())); + + for (int i = 0; i < maxConcurrentSubmitCount; i++) + mSubmitWaitFences[i] = mSubmitFence[i]->fence; + + if (fb->device->GraphicsTimeQueries) + { + mTimestampQueryPool = QueryPoolBuilder() + .QueryType(VK_QUERY_TYPE_TIMESTAMP, MaxTimestampQueries) + .Create(fb->device.get()); + + GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, MaxTimestampQueries); + } +} + +VkCommandBufferManager::~VkCommandBufferManager() +{ +} + +VulkanCommandBuffer* VkCommandBufferManager::GetTransferCommands() +{ + if (!mTransferCommands) + { + mTransferCommands = mCommandPool->createBuffer(); + mTransferCommands->SetDebugName("VulkanRenderDevice.mTransferCommands"); + mTransferCommands->begin(); + } + return mTransferCommands.get(); +} + +VulkanCommandBuffer* VkCommandBufferManager::GetDrawCommands() +{ + if (!mDrawCommands) + { + mDrawCommands = mCommandPool->createBuffer(); + mDrawCommands->SetDebugName("VulkanRenderDevice.mDrawCommands"); + mDrawCommands->begin(); + } + return mDrawCommands.get(); +} + +void VkCommandBufferManager::BeginFrame() +{ + if (mNextTimestampQuery > 0) + { + GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery); + mNextTimestampQuery = 0; + } +} + +void VkCommandBufferManager::FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit) +{ + int currentIndex = mNextSubmit % maxConcurrentSubmitCount; + + if (mNextSubmit >= maxConcurrentSubmitCount) + { + vkWaitForFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence, VK_TRUE, std::numeric_limits::max()); + vkResetFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence); + } + + QueueSubmit submit; + + for (size_t i = 0; i < count; i++) + submit.AddCommandBuffer(commands[i]); + + if (mNextSubmit > 0) + submit.AddWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mSubmitSemaphore[(mNextSubmit - 1) % maxConcurrentSubmitCount].get()); + + if (finish && fb->GetFramebufferManager()->PresentImageIndex != -1) + { + submit.AddWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, fb->GetFramebufferManager()->SwapChainImageAvailableSemaphore.get()); + submit.AddSignal(fb->GetFramebufferManager()->RenderFinishedSemaphore.get()); + } + + if (!lastsubmit) + submit.AddSignal(mSubmitSemaphore[currentIndex].get()); + + submit.Execute(fb->device.get(), fb->device->GraphicsQueue, mSubmitFence[currentIndex].get()); + mNextSubmit++; +} + +void VkCommandBufferManager::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly) +{ + if (!uploadOnly) + fb->GetRenderState()->EndRenderPass(); + + if ((!uploadOnly && mDrawCommands) || mTransferCommands) + { + VulkanCommandBuffer* commands[2]; + size_t count = 0; + + if (mTransferCommands) + { + mTransferCommands->end(); + commands[count++] = mTransferCommands.get(); + TransferDeleteList->Add(std::move(mTransferCommands)); + } + + if (!uploadOnly && mDrawCommands) + { + mDrawCommands->end(); + commands[count++] = mDrawCommands.get(); + DrawDeleteList->Add(std::move(mDrawCommands)); + } + + FlushCommands(commands, count, finish, lastsubmit); + + current_rendered_commandbuffers += (int)count; + } +} + +void VkCommandBufferManager::WaitForCommands(bool finish, bool uploadOnly) +{ + if (finish) + { + Finish.Reset(); + Finish.Clock(); + + fb->GetFramebufferManager()->AcquireImage(); + } + + FlushCommands(finish, true, uploadOnly); + + if (finish) + { + fb->FPSLimit(); + fb->GetFramebufferManager()->QueuePresent(); + } + + int numWaitFences = min(mNextSubmit, (int)maxConcurrentSubmitCount); + + if (numWaitFences > 0) + { + vkWaitForFences(fb->device->device, numWaitFences, mSubmitWaitFences, VK_TRUE, std::numeric_limits::max()); + vkResetFences(fb->device->device, numWaitFences, mSubmitWaitFences); + } + + DeleteFrameObjects(uploadOnly); + mNextSubmit = 0; + + if (finish) + { + Finish.Unclock(); + rendered_commandbuffers = current_rendered_commandbuffers; + current_rendered_commandbuffers = 0; + } +} + +void VkCommandBufferManager::DeleteFrameObjects(bool uploadOnly) +{ + TransferDeleteList = std::make_unique(); + if (!uploadOnly) + DrawDeleteList = std::make_unique(); +} + +void VkCommandBufferManager::PushGroup(const FString& name) +{ + if (!gpuStatActive) + return; + + if (mNextTimestampQuery < MaxTimestampQueries && fb->device->GraphicsTimeQueries) + { + TimestampQuery q; + q.name = name; + q.startIndex = mNextTimestampQuery++; + q.endIndex = 0; + GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex); + mGroupStack.push_back(timeElapsedQueries.size()); + timeElapsedQueries.push_back(q); + } +} + +void VkCommandBufferManager::PopGroup() +{ + if (!gpuStatActive || mGroupStack.empty()) + return; + + TimestampQuery& q = timeElapsedQueries[mGroupStack.back()]; + mGroupStack.pop_back(); + + if (mNextTimestampQuery < MaxTimestampQueries && fb->device->GraphicsTimeQueries) + { + q.endIndex = mNextTimestampQuery++; + GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex); + } +} + +void VkCommandBufferManager::UpdateGpuStats() +{ + uint64_t timestamps[MaxTimestampQueries]; + if (mNextTimestampQuery > 0) + mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + + double timestampPeriod = fb->device->PhysicalDevice.Properties.limits.timestampPeriod; + + gpuStatOutput = ""; + for (auto& q : timeElapsedQueries) + { + if (q.endIndex <= q.startIndex) + continue; + + int64_t timeElapsed = max(static_cast(timestamps[q.endIndex] - timestamps[q.startIndex]), (int64_t)0); + double timeNS = timeElapsed * timestampPeriod; + + FString out; + out.Format("%s=%04.2f ms\n", q.name.GetChars(), timeNS / 1000000.0f); + gpuStatOutput += out; + } + timeElapsedQueries.clear(); + mGroupStack.clear(); + + gpuStatActive = keepGpuStatActive; + keepGpuStatActive = false; +} diff --git a/src/common/rendering/vulkan/system/vk_commandbuffer.h b/src/common/rendering/vulkan/system/vk_commandbuffer.h new file mode 100644 index 000000000..1ce16b021 --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_commandbuffer.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include "zstring.h" + +class VulkanRenderDevice; + +class VkCommandBufferManager +{ +public: + VkCommandBufferManager(VulkanRenderDevice* fb); + ~VkCommandBufferManager(); + + void BeginFrame(); + + VulkanCommandBuffer* GetTransferCommands(); + VulkanCommandBuffer* GetDrawCommands(); + + void FlushCommands(bool finish, bool lastsubmit = false, bool uploadOnly = false); + + void WaitForCommands(bool finish) { WaitForCommands(finish, false); } + void WaitForCommands(bool finish, bool uploadOnly); + + void PushGroup(const FString& name); + void PopGroup(); + void UpdateGpuStats(); + + class DeleteList + { + public: + std::vector> Buffers; + std::vector> Samplers; + std::vector> Images; + std::vector> ImageViews; + std::vector> Framebuffers; + std::vector> AccelStructs; + std::vector> DescriptorPools; + std::vector> Descriptors; + std::vector> Shaders; + std::vector> CommandBuffers; + size_t TotalSize = 0; + + void Add(std::unique_ptr obj) { if (obj) { TotalSize += obj->size; Buffers.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { Samplers.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { Images.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { ImageViews.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { Framebuffers.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { AccelStructs.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { DescriptorPools.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { Descriptors.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { CommandBuffers.push_back(std::move(obj)); } } + void Add(std::unique_ptr obj) { if (obj) { Shaders.push_back(std::move(obj)); } } + }; + + std::unique_ptr TransferDeleteList = std::make_unique(); + std::unique_ptr DrawDeleteList = std::make_unique(); + + void DeleteFrameObjects(bool uploadOnly = false); + +private: + void FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit); + + VulkanRenderDevice* fb = nullptr; + + std::unique_ptr mCommandPool; + + std::unique_ptr mTransferCommands; + std::unique_ptr mDrawCommands; + + enum { maxConcurrentSubmitCount = 8 }; + std::unique_ptr mSubmitSemaphore[maxConcurrentSubmitCount]; + std::unique_ptr mSubmitFence[maxConcurrentSubmitCount]; + VkFence mSubmitWaitFences[maxConcurrentSubmitCount]; + int mNextSubmit = 0; + + struct TimestampQuery + { + FString name; + uint32_t startIndex; + uint32_t endIndex; + }; + + enum { MaxTimestampQueries = 100 }; + std::unique_ptr mTimestampQueryPool; + int mNextTimestampQuery = 0; + std::vector mGroupStack; + std::vector timeElapsedQueries; +}; diff --git a/src/common/rendering/vulkan/system/vk_device.cpp b/src/common/rendering/vulkan/system/vk_device.cpp deleted file mode 100644 index f6ce072af..000000000 --- a/src/common/rendering/vulkan/system/vk_device.cpp +++ /dev/null @@ -1,573 +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 "volk/volk.h" - -#ifdef _WIN32 -#undef max -#undef min -#endif - -#include -#include -#include -#include -#include -#include - -#include "vk_device.h" -#include "vk_swapchain.h" -#include "vk_objects.h" -#include "c_cvars.h" -#include "c_dispatch.h" -#include "i_system.h" -#include "version.h" -#include "engineerrors.h" -#include "v_text.h" - -bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names); -bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); - -FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames); - -// Physical device info -static std::vector AvailableDevices; -static std::vector SupportedDevices; - -CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) -{ - Printf("This won't take effect until " GAMENAME " is restarted.\n"); -} - -CVAR(Bool, vk_debug_callstack, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - -CUSTOM_CVAR(Int, vk_device, 0, 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++) - { - Printf("#%d - %s\n", (int)i, SupportedDevices[i].device->Properties.deviceName); - } -} - -VulkanDevice::VulkanDevice() -{ - try - { - InitVolk(); - CreateInstance(); - CreateSurface(); - SelectPhysicalDevice(); - SelectFeatures(); - CreateDevice(); - CreateAllocator(); - } - catch (...) - { - ReleaseResources(); - throw; - } -} - -VulkanDevice::~VulkanDevice() -{ - ReleaseResources(); -} - -void VulkanDevice::SelectFeatures() -{ - UsedDeviceFeatures.samplerAnisotropy = PhysicalDevice.Features.samplerAnisotropy; - UsedDeviceFeatures.fragmentStoresAndAtomics = PhysicalDevice.Features.fragmentStoresAndAtomics; - UsedDeviceFeatures.depthClamp = PhysicalDevice.Features.depthClamp; - UsedDeviceFeatures.shaderClipDistance = PhysicalDevice.Features.shaderClipDistance; -} - -bool VulkanDevice::CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f) -{ - return - f.samplerAnisotropy == VK_TRUE && - f.fragmentStoresAndAtomics == VK_TRUE; -} - -void VulkanDevice::SelectPhysicalDevice() -{ - AvailableDevices = GetPhysicalDevices(instance); - if (AvailableDevices.empty()) - VulkanError("No Vulkan devices found. Either the graphics card has no vulkan support or the driver is too old."); - - for (size_t idx = 0; idx < AvailableDevices.size(); idx++) - { - const auto &info = AvailableDevices[idx]; - - if (!CheckRequiredFeatures(info.Features)) - continue; - - std::set requiredExtensionSearch(EnabledDeviceExtensions.begin(), EnabledDeviceExtensions.end()); - for (const auto &ext : info.Extensions) - requiredExtensionSearch.erase(ext.extensionName); - if (!requiredExtensionSearch.empty()) - continue; - - VulkanCompatibleDevice dev; - dev.device = &AvailableDevices[idx]; - - // Figure out what can present - for (int i = 0; i < (int)info.QueueFamilies.size(); i++) - { - VkBool32 presentSupport = false; - VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(info.Device, i, surface, &presentSupport); - if (result == VK_SUCCESS && info.QueueFamilies[i].queueCount > 0 && presentSupport) - { - dev.presentFamily = i; - break; - } - } - - // The vulkan spec states that graphics and compute queues can always do transfer. - // Furthermore the spec states that graphics queues always can do compute. - // Last, the spec makes it OPTIONAL whether the VK_QUEUE_TRANSFER_BIT is set for such queues, but they MUST support transfer. - // - // In short: pick the first graphics queue family for everything. - for (int i = 0; i < (int)info.QueueFamilies.size(); i++) - { - const auto &queueFamily = info.QueueFamilies[i]; - if (queueFamily.queueCount > 0 && (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) - { - dev.graphicsFamily = i; - dev.graphicsTimeQueries = queueFamily.timestampValidBits != 0; - break; - } - } - - if (dev.graphicsFamily != -1 && dev.presentFamily != -1) - { - SupportedDevices.push_back(dev); - } - } - - if (SupportedDevices.empty()) - VulkanError("No Vulkan device supports the minimum requirements of this application"); - - // The device order returned by Vulkan can be anything. Prefer discrete > integrated > virtual gpu > cpu > other - std::stable_sort(SupportedDevices.begin(), SupportedDevices.end(), [&](const auto &a, const auto b) { - - // Sort by GPU type first. This will ensure the "best" device is most likely to map to vk_device 0 - static const int typeSort[] = { 4, 1, 0, 2, 3 }; - int sortA = a.device->Properties.deviceType < 5 ? typeSort[a.device->Properties.deviceType] : (int)a.device->Properties.deviceType; - int sortB = b.device->Properties.deviceType < 5 ? typeSort[b.device->Properties.deviceType] : (int)b.device->Properties.deviceType; - 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.pipelineCacheUUID, b.device->Properties.pipelineCacheUUID, VK_UUID_SIZE); - return sortUUID < 0; - }); - - size_t selected = vk_device; - if (selected >= SupportedDevices.size()) - selected = 0; - - // Enable optional extensions we are interested in, if they are available on this device - for (const auto &ext : SupportedDevices[selected].device->Extensions) - { - for (const auto &opt : OptionalDeviceExtensions) - { - if (strcmp(ext.extensionName, opt) == 0) - { - EnabledDeviceExtensions.push_back(opt); - } - } - } - - PhysicalDevice = *SupportedDevices[selected].device; - graphicsFamily = SupportedDevices[selected].graphicsFamily; - presentFamily = SupportedDevices[selected].presentFamily; - graphicsTimeQueries = SupportedDevices[selected].graphicsTimeQueries; -} - -bool VulkanDevice::SupportsDeviceExtension(const char *ext) const -{ - return std::find(EnabledDeviceExtensions.begin(), EnabledDeviceExtensions.end(), ext) != EnabledDeviceExtensions.end(); -} - -void VulkanDevice::CreateAllocator() -{ - VmaAllocatorCreateInfo allocinfo = {}; - if (SupportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) - allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; - allocinfo.physicalDevice = PhysicalDevice.Device; - allocinfo.device = device; - allocinfo.instance = instance; - allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024; - if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS) - VulkanError("Unable to create allocator"); -} - -void VulkanDevice::CreateDevice() -{ - float queuePriority = 1.0f; - std::vector queueCreateInfos; - - std::set neededFamilies; - neededFamilies.insert(graphicsFamily); - neededFamilies.insert(presentFamily); - - for (int index : neededFamilies) - { - VkDeviceQueueCreateInfo queueCreateInfo = {}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = index; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } - - VkDeviceCreateInfo deviceCreateInfo = {}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size(); - deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data(); - deviceCreateInfo.pEnabledFeatures = &UsedDeviceFeatures; - deviceCreateInfo.enabledExtensionCount = (uint32_t)EnabledDeviceExtensions.size(); - deviceCreateInfo.ppEnabledExtensionNames = EnabledDeviceExtensions.data(); - deviceCreateInfo.enabledLayerCount = 0; - - VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device); - CheckVulkanError(result, "Could not create vulkan device"); - - volkLoadDevice(device); - - vkGetDeviceQueue(device, graphicsFamily, 0, &graphicsQueue); - vkGetDeviceQueue(device, presentFamily, 0, &presentQueue); -} - -void VulkanDevice::CreateSurface() -{ - if (!I_CreateVulkanSurface(instance, &surface)) - { - VulkanError("Could not create vulkan surface"); - } -} - -void VulkanDevice::CreateInstance() -{ - AvailableLayers = GetAvailableLayers(); - Extensions = GetExtensions(); - EnabledExtensions = GetPlatformExtensions(); - - std::string debugLayer = "VK_LAYER_LUNARG_standard_validation"; - bool wantDebugLayer = vk_debug; - bool debugLayerFound = false; - for (const VkLayerProperties &layer : AvailableLayers) - { - if (layer.layerName == debugLayer && wantDebugLayer) - { - EnabledValidationLayers.push_back(debugLayer.c_str()); - EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - debugLayerFound = true; - } - } - - // Enable optional instance extensions we are interested in - for (const auto &ext : Extensions) - { - for (const auto &opt : OptionalExtensions) - { - if (strcmp(ext.extensionName, opt) == 0) - { - EnabledExtensions.push_back(opt); - } - } - } - - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "GZDoom"; - appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION); - appInfo.pEngineName = "GZDoom"; - appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION); - appInfo.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size(); - createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size(); - createInfo.ppEnabledLayerNames = EnabledValidationLayers.data(); - createInfo.ppEnabledExtensionNames = EnabledExtensions.data(); - - VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); - CheckVulkanError(result, "Could not create vulkan instance"); - - volkLoadInstance(instance); - - if (debugLayerFound) - { - VkDebugUtilsMessengerCreateInfoEXT createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = - //VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - //VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.messageType = - VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - createInfo.pfnUserCallback = DebugCallback; - createInfo.pUserData = this; - result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger); - CheckVulkanError(result, "vkCreateDebugUtilsMessengerEXT failed"); - - DebugLayerActive = true; - } -} - -VkBool32 VulkanDevice::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData) -{ - VulkanDevice *device = (VulkanDevice*)userData; - - static std::mutex mtx; - static std::set seenMessages; - static int totalMessages; - - std::unique_lock lock(mtx); - - FString msg = callbackData->pMessage; - - // For patent-pending reasons the validation layer apparently can't do this itself.. - for (uint32_t i = 0; i < callbackData->objectCount; i++) - { - if (callbackData->pObjects[i].pObjectName) - { - FString hexname; - hexname.Format("0x%" PRIx64, callbackData->pObjects[i].objectHandle); - msg.Substitute(hexname.GetChars(), callbackData->pObjects[i].pObjectName); - } - } - - bool found = seenMessages.find(msg) != seenMessages.end(); - if (!found) - { - if (totalMessages < 20) - { - totalMessages++; - seenMessages.insert(msg); - - const char *typestr; - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) - { - typestr = "vulkan error"; - } - else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) - { - typestr = "vulkan warning"; - } - else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) - { - typestr = "vulkan info"; - } - else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) - { - typestr = "vulkan verbose"; - } - else - { - typestr = "vulkan"; - } - - Printf("\n"); - Printf(TEXTCOLOR_RED "[%s] ", typestr); - Printf(TEXTCOLOR_WHITE "%s\n", msg.GetChars()); - - if (vk_debug_callstack) - { - FString callstack = JitCaptureStackTrace(0, true); - if (!callstack.IsEmpty()) - Printf("%s\n", callstack.GetChars()); - } - } - } - - return VK_FALSE; -} - -std::vector VulkanDevice::GetAvailableLayers() -{ - uint32_t layerCount; - VkResult result = vkEnumerateInstanceLayerProperties(&layerCount, nullptr); - - std::vector availableLayers(layerCount); - result = vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); - return availableLayers; -} - -std::vector VulkanDevice::GetExtensions() -{ - uint32_t extensionCount = 0; - VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - - std::vector extensions(extensionCount); - result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); - return extensions; -} - -std::vector VulkanDevice::GetPhysicalDevices(VkInstance instance) -{ - uint32_t deviceCount = 0; - VkResult result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); - if (result == VK_ERROR_INITIALIZATION_FAILED) // Some drivers return this when a card does not support vulkan - return {}; - CheckVulkanError(result, "vkEnumeratePhysicalDevices failed"); - if (deviceCount == 0) - return {}; - - std::vector devices(deviceCount); - result = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); - CheckVulkanError(result, "vkEnumeratePhysicalDevices failed (2)"); - - std::vector devinfo(deviceCount); - for (size_t i = 0; i < devices.size(); i++) - { - auto &dev = devinfo[i]; - dev.Device = devices[i]; - - vkGetPhysicalDeviceMemoryProperties(dev.Device, &dev.MemoryProperties); - vkGetPhysicalDeviceProperties(dev.Device, &dev.Properties); - vkGetPhysicalDeviceFeatures(dev.Device, &dev.Features); - - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, nullptr); - dev.QueueFamilies.resize(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, dev.QueueFamilies.data()); - - uint32_t deviceExtensionCount = 0; - vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, nullptr); - dev.Extensions.resize(deviceExtensionCount); - vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, dev.Extensions.data()); - } - return devinfo; -} - -std::vector VulkanDevice::GetPlatformExtensions() -{ - uint32_t extensionCount = 0; - if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr)) - VulkanError("Cannot obtain number of Vulkan extensions"); - - std::vector extensions(extensionCount); - if (!I_GetVulkanPlatformExtensions(&extensionCount, extensions.data())) - VulkanError("Cannot obtain list of Vulkan extensions"); - return extensions; -} - -void VulkanDevice::InitVolk() -{ - if (volkInitialize() != VK_SUCCESS) - { - VulkanError("Unable to find Vulkan"); - } - auto iver = volkGetInstanceVersion(); - if (iver == 0) - { - VulkanError("Vulkan not supported"); - } -} - -void VulkanDevice::ReleaseResources() -{ - if (device) - vkDeviceWaitIdle(device); - - if (allocator) - vmaDestroyAllocator(allocator); - - if (device) - vkDestroyDevice(device, nullptr); - device = nullptr; - - if (surface) - vkDestroySurfaceKHR(instance, surface, nullptr); - surface = 0; - - if (debugMessenger) - vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); - - if (instance) - vkDestroyInstance(instance, nullptr); - instance = nullptr; -} - -uint32_t VulkanDevice::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) -{ - for (uint32_t i = 0; i < PhysicalDevice.MemoryProperties.memoryTypeCount; i++) - { - if ((typeFilter & (1 << i)) && (PhysicalDevice.MemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) - return i; - } - - VulkanError("failed to find suitable memory type!"); - return 0; -} - -FString VkResultToString(VkResult result) -{ - switch (result) - { - case VK_SUCCESS: return "success"; - case VK_NOT_READY: return "not ready"; - case VK_TIMEOUT: return "timeout"; - case VK_EVENT_SET: return "event set"; - case VK_EVENT_RESET: return "event reset"; - case VK_INCOMPLETE: return "incomplete"; - case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory"; - case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory"; - case VK_ERROR_INITIALIZATION_FAILED: return "initialization failed"; - case VK_ERROR_DEVICE_LOST: return "device lost"; - case VK_ERROR_MEMORY_MAP_FAILED: return "memory map failed"; - case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present"; - case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present"; - case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present"; - case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver"; - case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects"; - case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported"; - case VK_ERROR_FRAGMENTED_POOL: return "fragmented pool"; - case VK_ERROR_OUT_OF_POOL_MEMORY: return "out of pool memory"; - case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "invalid external handle"; - case VK_ERROR_SURFACE_LOST_KHR: return "surface lost"; - case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "native window in use"; - case VK_SUBOPTIMAL_KHR: return "suboptimal"; - case VK_ERROR_OUT_OF_DATE_KHR: return "out of date"; - case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "incompatible display"; - case VK_ERROR_VALIDATION_FAILED_EXT: return "validation failed"; - case VK_ERROR_INVALID_SHADER_NV: return "invalid shader"; - case VK_ERROR_FRAGMENTATION_EXT: return "fragmentation"; - case VK_ERROR_NOT_PERMITTED_EXT: return "not permitted"; - default: break; - } - FString res; - res.Format("vkResult %d", (int)result); - return result; -} diff --git a/src/common/rendering/vulkan/system/vk_device.h b/src/common/rendering/vulkan/system/vk_device.h deleted file mode 100644 index 435ffc187..000000000 --- a/src/common/rendering/vulkan/system/vk_device.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include "volk/volk.h" -#include "vk_mem_alloc/vk_mem_alloc.h" -#include "engineerrors.h" -#include -#include -#include -#include -#include "zstring.h" - -class VulkanSwapChain; -class VulkanSemaphore; -class VulkanFence; - -class VulkanPhysicalDevice -{ -public: - VkPhysicalDevice Device = VK_NULL_HANDLE; - - std::vector Extensions; - std::vector QueueFamilies; - VkPhysicalDeviceProperties Properties = {}; - VkPhysicalDeviceFeatures Features = {}; - VkPhysicalDeviceMemoryProperties MemoryProperties = {}; -}; - -class VulkanCompatibleDevice -{ -public: - VulkanPhysicalDevice *device = nullptr; - int graphicsFamily = -1; - int presentFamily = -1; - bool graphicsTimeQueries = false; -}; - -class VulkanDevice -{ -public: - VulkanDevice(); - ~VulkanDevice(); - - void SetDebugObjectName(const char *name, uint64_t handle, VkObjectType type) - { - if (!DebugLayerActive) return; - - VkDebugUtilsObjectNameInfoEXT info = {}; - info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; - info.objectHandle = handle; - info.objectType = type; - info.pObjectName = name; - vkSetDebugUtilsObjectNameEXT(device, &info); - } - - uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); - - // Instance setup - std::vector AvailableLayers; - std::vector Extensions; - std::vector EnabledExtensions; - std::vector OptionalExtensions = { VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME }; - std::vector EnabledValidationLayers; - - // Device setup - VkPhysicalDeviceFeatures UsedDeviceFeatures = {}; - std::vector EnabledDeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - std::vector OptionalDeviceExtensions = { VK_EXT_HDR_METADATA_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME }; - VulkanPhysicalDevice PhysicalDevice; - bool DebugLayerActive = false; - - VkInstance instance = VK_NULL_HANDLE; - VkSurfaceKHR surface = VK_NULL_HANDLE; - VkDevice device = VK_NULL_HANDLE; - VmaAllocator allocator = VK_NULL_HANDLE; - - VkQueue graphicsQueue = VK_NULL_HANDLE; - VkQueue presentQueue = VK_NULL_HANDLE; - - int graphicsFamily = -1; - int presentFamily = -1; - bool graphicsTimeQueries = false; - -private: - void CreateInstance(); - void CreateSurface(); - void SelectPhysicalDevice(); - void SelectFeatures(); - void CreateDevice(); - void CreateAllocator(); - void ReleaseResources(); - - bool SupportsDeviceExtension(const char *ext) const; - - static bool CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f); - - VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; - - static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); - - static void InitVolk(); - static std::vector GetAvailableLayers(); - static std::vector GetExtensions(); - static std::vector GetPlatformExtensions(); - static std::vector GetPhysicalDevices(VkInstance instance); -}; - -FString VkResultToString(VkResult result); - -class CVulkanError : public CEngineError -{ -public: - CVulkanError() : CEngineError() {} - CVulkanError(const char* message) : CEngineError(message) {} -}; - - -inline void VulkanError(const char *text) -{ - throw CVulkanError(text); -} - -inline void CheckVulkanError(VkResult result, const char *text) -{ - if (result >= VK_SUCCESS) - return; - - FString msg; - msg.Format("%s: %s", text, VkResultToString(result).GetChars()); - throw CVulkanError(msg.GetChars()); -} diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.cpp b/src/common/rendering/vulkan/system/vk_framebuffer.cpp deleted file mode 100644 index 131a3e6fb..000000000 --- a/src/common/rendering/vulkan/system/vk_framebuffer.cpp +++ /dev/null @@ -1,757 +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 "volk/volk.h" - -#include - -#include "v_video.h" -#include "m_png.h" -#include "templates.h" -#include "r_videoscale.h" -#include "i_time.h" -#include "v_text.h" -#include "version.h" -#include "v_draw.h" - -#include "hw_clock.h" -#include "hw_vrmodes.h" -#include "hw_cvars.h" -#include "hw_skydome.h" -#include "hwrenderer/data/hw_viewpointbuffer.h" -#include "flatvertices.h" -#include "hwrenderer/data/shaderuniforms.h" -#include "hw_lightbuffer.h" - -#include "vk_framebuffer.h" -#include "vk_buffers.h" -#include "vulkan/renderer/vk_renderstate.h" -#include "vulkan/renderer/vk_renderpass.h" -#include "vulkan/renderer/vk_streambuffer.h" -#include "vulkan/renderer/vk_postprocess.h" -#include "vulkan/renderer/vk_renderbuffers.h" -#include "vulkan/shaders/vk_shader.h" -#include "vulkan/textures/vk_samplers.h" -#include "vulkan/textures/vk_hwtexture.h" -#include "vulkan/system/vk_builders.h" -#include "vulkan/system/vk_swapchain.h" -#include "engineerrors.h" -#include "c_dispatch.h" - -void Draw2D(F2DDrawer *drawer, FRenderState &state); - -EXTERN_CVAR(Bool, r_drawvoxels) -EXTERN_CVAR(Int, gl_tonemap) -EXTERN_CVAR(Int, screenblocks) -EXTERN_CVAR(Bool, cl_capfps) - -extern int rendered_commandbuffers; -int current_rendered_commandbuffers; - -extern bool gpuStatActive; -extern bool keepGpuStatActive; -extern FString gpuStatOutput; - -CCMD(vk_memstats) -{ - VmaStats stats = {}; - vmaCalculateStats(GetVulkanFrameBuffer()->device->allocator, &stats); - Printf("Allocated objects: %d, used bytes: %d MB\n", (int)stats.total.allocationCount, (int)stats.total.usedBytes / (1024 * 1024)); - Printf("Unused range count: %d, unused bytes: %d MB\n", (int)stats.total.unusedRangeCount, (int)stats.total.unusedBytes / (1024 * 1024)); -} - -VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevice *dev) : - Super(hMonitor, fullscreen) -{ - device = dev; - - swapChain = std::make_unique(device); - mSwapChainImageAvailableSemaphore.reset(new VulkanSemaphore(device)); - mRenderFinishedSemaphore.reset(new VulkanSemaphore(device)); - - for (auto &semaphore : mSubmitSemaphore) - semaphore.reset(new VulkanSemaphore(device)); - - for (auto &fence : mSubmitFence) - fence.reset(new VulkanFence(device)); - - for (int i = 0; i < maxConcurrentSubmitCount; i++) - mSubmitWaitFences[i] = mSubmitFence[i]->fence; -} - -VulkanFrameBuffer::~VulkanFrameBuffer() -{ - vkDeviceWaitIdle(device->device); // make sure the GPU is no longer using any objects before RAII tears them down - - // screen is already null at this point, but VkHardwareTexture::ResetAll needs it during clean up. Is there a better way we can do this? - auto tmp = screen; - screen = this; - - // All descriptors must be destroyed before the descriptor pool in renderpass manager is destroyed - VkHardwareTexture::ResetAll(); - VKBuffer::ResetAll(); - PPResource::ResetAll(); - - delete MatrixBuffer; - delete StreamBuffer; - delete mVertexData; - delete mSkyData; - delete mViewpoints; - delete mLights; - mShadowMap.Reset(); - - screen = tmp; - - DeleteFrameObjects(); -} - -void VulkanFrameBuffer::InitializeState() -{ - static bool first = true; - if (first) - { - PrintStartupLog(); - first = false; - } - - // Use the same names here as OpenGL returns. - switch (device->PhysicalDevice.Properties.vendorID) - { - case 0x1002: vendorstring = "ATI Technologies Inc."; break; - case 0x10DE: vendorstring = "NVIDIA Corporation"; break; - case 0x8086: vendorstring = "Intel"; break; - default: vendorstring = "Unknown"; break; - } - - hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; - glslversion = 4.50f; - uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment; - maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange; - - mCommandPool.reset(new VulkanCommandPool(device, device->graphicsFamily)); - - mScreenBuffers.reset(new VkRenderBuffers()); - mSaveBuffers.reset(new VkRenderBuffers()); - mActiveRenderBuffers = mScreenBuffers.get(); - - mPostprocess.reset(new VkPostprocess()); - mRenderPassManager.reset(new VkRenderPassManager()); - - mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); - mSkyData = new FSkyVertexBuffer; - mViewpoints = new HWViewpointBuffer; - mLights = new FLightBuffer(); - - CreateFanToTrisIndexBuffer(); - - // To do: move this to HW renderer interface maybe? - MatrixBuffer = new VkStreamBuffer(sizeof(MatricesUBO), 50000); - StreamBuffer = new VkStreamBuffer(sizeof(StreamUBO), 300); - - mShaderManager.reset(new VkShaderManager(device)); - mSamplerManager.reset(new VkSamplerManager(device)); - mRenderPassManager->Init(); -#ifdef __APPLE__ - mRenderState.reset(new VkRenderStateMolten()); -#else - mRenderState.reset(new VkRenderState()); -#endif - - if (device->graphicsTimeQueries) - { - QueryPoolBuilder querybuilder; - querybuilder.setQueryType(VK_QUERY_TYPE_TIMESTAMP, MaxTimestampQueries); - mTimestampQueryPool = querybuilder.create(device); - - GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, MaxTimestampQueries); - } -} - -void VulkanFrameBuffer::Update() -{ - twoD.Reset(); - Flush3D.Reset(); - - Flush3D.Clock(); - - GetPostprocess()->SetActiveRenderTarget(); - - Draw2D(); - twod->Clear(); - - mRenderState->EndRenderPass(); - mRenderState->EndFrame(); - - Flush3D.Unclock(); - - WaitForCommands(true); - UpdateGpuStats(); - - Super::Update(); -} - -void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly) -{ - FrameTextureUpload.Buffers.clear(); - FrameTextureUpload.TotalSize = 0; - - if (!uploadOnly) - { - FrameDeleteList.Images.clear(); - FrameDeleteList.ImageViews.clear(); - FrameDeleteList.Framebuffers.clear(); - FrameDeleteList.Buffers.clear(); - FrameDeleteList.Descriptors.clear(); - FrameDeleteList.DescriptorPools.clear(); - FrameDeleteList.CommandBuffers.clear(); - } -} - -void VulkanFrameBuffer::FlushCommands(VulkanCommandBuffer **commands, size_t count, bool finish, bool lastsubmit) -{ - int currentIndex = mNextSubmit % maxConcurrentSubmitCount; - - if (mNextSubmit >= maxConcurrentSubmitCount) - { - vkWaitForFences(device->device, 1, &mSubmitFence[currentIndex]->fence, VK_TRUE, std::numeric_limits::max()); - vkResetFences(device->device, 1, &mSubmitFence[currentIndex]->fence); - } - - QueueSubmit submit; - - for (size_t i = 0; i < count; i++) - submit.addCommandBuffer(commands[i]); - - if (mNextSubmit > 0) - submit.addWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mSubmitSemaphore[(mNextSubmit - 1) % maxConcurrentSubmitCount].get()); - - if (finish && presentImageIndex != 0xffffffff) - { - submit.addWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mSwapChainImageAvailableSemaphore.get()); - submit.addSignal(mRenderFinishedSemaphore.get()); - } - - if (!lastsubmit) - submit.addSignal(mSubmitSemaphore[currentIndex].get()); - - submit.execute(device, device->graphicsQueue, mSubmitFence[currentIndex].get()); - mNextSubmit++; -} - -void VulkanFrameBuffer::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly) -{ - if (!uploadOnly) - mRenderState->EndRenderPass(); - - if ((!uploadOnly && mDrawCommands) || mTransferCommands) - { - VulkanCommandBuffer *commands[2]; - size_t count = 0; - - if (mTransferCommands) - { - mTransferCommands->end(); - commands[count++] = mTransferCommands.get(); - FrameDeleteList.CommandBuffers.push_back(std::move(mTransferCommands)); - } - - if (!uploadOnly && mDrawCommands) - { - mDrawCommands->end(); - commands[count++] = mDrawCommands.get(); - FrameDeleteList.CommandBuffers.push_back(std::move(mDrawCommands)); - } - - FlushCommands(commands, count, finish, lastsubmit); - - current_rendered_commandbuffers += (int)count; - } -} - -void VulkanFrameBuffer::WaitForCommands(bool finish, bool uploadOnly) -{ - if (finish) - { - Finish.Reset(); - Finish.Clock(); - - presentImageIndex = swapChain->AcquireImage(GetClientWidth(), GetClientHeight(), mSwapChainImageAvailableSemaphore.get()); - if (presentImageIndex != 0xffffffff) - mPostprocess->DrawPresentTexture(mOutputLetterbox, true, false); - } - - FlushCommands(finish, true, uploadOnly); - - if (finish) - { - FPSLimit(); - - if (presentImageIndex != 0xffffffff) - swapChain->QueuePresent(presentImageIndex, mRenderFinishedSemaphore.get()); - } - - int numWaitFences = MIN(mNextSubmit, (int)maxConcurrentSubmitCount); - - if (numWaitFences > 0) - { - vkWaitForFences(device->device, numWaitFences, mSubmitWaitFences, VK_TRUE, std::numeric_limits::max()); - vkResetFences(device->device, numWaitFences, mSubmitWaitFences); - } - - DeleteFrameObjects(uploadOnly); - mNextSubmit = 0; - - if (finish) - { - Finish.Unclock(); - rendered_commandbuffers = current_rendered_commandbuffers; - current_rendered_commandbuffers = 0; - } -} - -void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function renderFunc) -{ - auto BaseLayer = static_cast(tex->GetHardwareTexture(0, 0)); - - VkTextureImage *image = BaseLayer->GetImage(tex, 0, 0); - VkTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); - - mRenderState->EndRenderPass(); - - VkImageTransition barrier0; - barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - barrier0.execute(GetDrawCommands()); - - 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; - bounds.width = std::min(tex->GetWidth(), image->Image->width); - bounds.height = std::min(tex->GetHeight(), image->Image->height); - - renderFunc(bounds); - - mRenderState->EndRenderPass(); - - VkImageTransition barrier1; - barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - barrier1.execute(GetDrawCommands()); - - mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); - - tex->SetUpdated(true); -} - -void VulkanFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) -{ - if (!swscene) mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture - mPostprocess->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); -} - -const char* VulkanFrameBuffer::DeviceName() const -{ - const auto &props = device->PhysicalDevice.Properties; - return props.deviceName; -} - - -void VulkanFrameBuffer::SetVSync(bool vsync) -{ - // This is handled in VulkanSwapChain::AcquireImage. - cur_vsync = vsync; -} - -void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) -{ - if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; - - MaterialLayerInfo* layer; - - auto systex = static_cast(mat->GetLayer(0, translation, &layer)); - systex->GetImage(layer->layerTexture, translation, layer->scaleFlags); - - int numLayers = mat->NumLayers(); - for (int i = 1; i < numLayers; i++) - { - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - systex->GetImage(layer->layerTexture, 0, layer->scaleFlags); - } -} - -IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels) -{ - return new VkHardwareTexture(numchannels); -} - -FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) -{ - return new VkMaterial(tex, scaleflags); -} - -IVertexBuffer *VulkanFrameBuffer::CreateVertexBuffer() -{ - return new VKVertexBuffer(); -} - -IIndexBuffer *VulkanFrameBuffer::CreateIndexBuffer() -{ - return new VKIndexBuffer(); -} - -IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) -{ - auto buffer = new VKDataBuffer(bindingpoint, ssbo, needsresize); - - auto fb = GetVulkanFrameBuffer(); - switch (bindingpoint) - { - case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break; - case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break; - case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break; - case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break; - case LIGHTLIST_BINDINGPOINT: LightList = buffer; break; - case POSTPROCESS_BINDINGPOINT: break; - default: break; - } - - return buffer; -} - -void VulkanFrameBuffer::SetTextureFilterMode() -{ - if (mSamplerManager) - { - // Destroy the texture descriptors as they used the old samplers - VkMaterial::ResetAllDescriptors(); - - mSamplerManager->SetTextureFilterMode(); - } -} - -void VulkanFrameBuffer::StartPrecaching() -{ - // Destroy the texture descriptors to avoid problems with potentially stale textures. - VkMaterial::ResetAllDescriptors(); -} - -void VulkanFrameBuffer::BlurScene(float amount) -{ - if (mPostprocess) - mPostprocess->BlurScene(amount); -} - -void VulkanFrameBuffer::UpdatePalette() -{ - if (mPostprocess) - mPostprocess->ClearTonemapPalette(); -} - -FTexture *VulkanFrameBuffer::WipeStartScreen() -{ - SetViewportRects(nullptr); - - auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); - auto systex = static_cast(tex->GetSystemTexture()); - - systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen"); - - return tex; -} - -FTexture *VulkanFrameBuffer::WipeEndScreen() -{ - GetPostprocess()->SetActiveRenderTarget(); - Draw2D(); - twod->Clear(); - - auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); - auto systex = static_cast(tex->GetSystemTexture()); - - systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen"); - - return tex; -} - -void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, uint8_t *data) -{ - VkTextureImage image; - - // Convert from rgba16f to rgba8 using the GPU: - ImageBuilder imgbuilder; - imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); - imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - imgbuilder.setSize(w, h); - image.Image = imgbuilder.create(device); - GetPostprocess()->BlitCurrentToImage(&image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - // Staging buffer for download - BufferBuilder bufbuilder; - bufbuilder.setSize(w * h * 4); - bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU); - auto staging = bufbuilder.create(device); - - // Copy from image to buffer - VkBufferImageCopy region = {}; - region.imageExtent.width = w; - region.imageExtent.height = h; - region.imageExtent.depth = 1; - region.imageSubresource.layerCount = 1; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, ®ion); - - // Submit command buffers and wait for device to finish the work - WaitForCommands(false); - - // Map and convert from rgba8 to rgb8 - uint8_t *dest = (uint8_t*)data; - uint8_t *pixels = (uint8_t*)staging->Map(0, w * h * 4); - int dindex = 0; - for (int y = 0; y < h; y++) - { - int sindex = (h - y - 1) * w * 4; - for (int x = 0; x < w; x++) - { - dest[dindex] = pixels[sindex]; - dest[dindex + 1] = pixels[sindex + 1]; - dest[dindex + 2] = pixels[sindex + 2]; - dindex += 3; - sindex += 4; - } - } - staging->Unmap(); -} - -void VulkanFrameBuffer::SetActiveRenderTarget() -{ - mPostprocess->SetActiveRenderTarget(); -} - - -TArray VulkanFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) -{ - int w = SCREENWIDTH; - int h = SCREENHEIGHT; - - IntRect box; - box.left = 0; - box.top = 0; - box.width = w; - box.height = h; - mPostprocess->DrawPresentTexture(box, true, true); - - TArray ScreenshotBuffer(w * h * 3, true); - CopyScreenToBuffer(w, h, ScreenshotBuffer.Data()); - - pitch = w * 3; - color_type = SS_RGB; - gamma = 1.0f; - return ScreenshotBuffer; -} - -void VulkanFrameBuffer::BeginFrame() -{ - SetViewportRects(nullptr); - mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); - mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); - mRenderState->BeginFrame(); - mRenderPassManager->UpdateDynamicSet(); - - if (mNextTimestampQuery > 0) - { - GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery); - mNextTimestampQuery = 0; - } -} - -void VulkanFrameBuffer::PushGroup(const FString &name) -{ - if (!gpuStatActive) - return; - - if (mNextTimestampQuery < VulkanFrameBuffer::MaxTimestampQueries && device->graphicsTimeQueries) - { - TimestampQuery q; - q.name = name; - q.startIndex = mNextTimestampQuery++; - q.endIndex = 0; - GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex); - mGroupStack.push_back(timeElapsedQueries.size()); - timeElapsedQueries.push_back(q); - } -} - -void VulkanFrameBuffer::PopGroup() -{ - if (!gpuStatActive || mGroupStack.empty()) - return; - - TimestampQuery &q = timeElapsedQueries[mGroupStack.back()]; - mGroupStack.pop_back(); - - if (mNextTimestampQuery < VulkanFrameBuffer::MaxTimestampQueries && device->graphicsTimeQueries) - { - q.endIndex = mNextTimestampQuery++; - GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex); - } -} - -void VulkanFrameBuffer::UpdateGpuStats() -{ - uint64_t timestamps[MaxTimestampQueries]; - if (mNextTimestampQuery > 0) - mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); - - double timestampPeriod = device->PhysicalDevice.Properties.limits.timestampPeriod; - - gpuStatOutput = ""; - for (auto &q : timeElapsedQueries) - { - if (q.endIndex <= q.startIndex) - continue; - - int64_t timeElapsed = std::max(static_cast(timestamps[q.endIndex] - timestamps[q.startIndex]), (int64_t)0); - double timeNS = timeElapsed * timestampPeriod; - - FString out; - out.Format("%s=%04.2f ms\n", q.name.GetChars(), timeNS / 1000000.0f); - gpuStatOutput += out; - } - timeElapsedQueries.clear(); - mGroupStack.clear(); - - gpuStatActive = keepGpuStatActive; - keepGpuStatActive = false; -} - -void VulkanFrameBuffer::Draw2D() -{ - ::Draw2D(twod, *mRenderState); -} - -VulkanCommandBuffer *VulkanFrameBuffer::GetTransferCommands() -{ - if (!mTransferCommands) - { - mTransferCommands = mCommandPool->createBuffer(); - mTransferCommands->SetDebugName("VulkanFrameBuffer.mTransferCommands"); - mTransferCommands->begin(); - } - return mTransferCommands.get(); -} - -VulkanCommandBuffer *VulkanFrameBuffer::GetDrawCommands() -{ - if (!mDrawCommands) - { - mDrawCommands = mCommandPool->createBuffer(); - mDrawCommands->SetDebugName("VulkanFrameBuffer.mDrawCommands"); - mDrawCommands->begin(); - } - return mDrawCommands.get(); -} - -unsigned int VulkanFrameBuffer::GetLightBufferBlockSize() const -{ - return mLights->GetBlockSize(); -} - -void VulkanFrameBuffer::PrintStartupLog() -{ - const auto &props = device->PhysicalDevice.Properties; - - FString deviceType; - switch (props.deviceType) - { - case VK_PHYSICAL_DEVICE_TYPE_OTHER: deviceType = "other"; break; - case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: deviceType = "integrated gpu"; break; - case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: deviceType = "discrete gpu"; break; - case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: deviceType = "virtual gpu"; break; - case VK_PHYSICAL_DEVICE_TYPE_CPU: deviceType = "cpu"; break; - default: deviceType.Format("%d", (int)props.deviceType); break; - } - - 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)); - - Printf("Vulkan device: " TEXTCOLOR_ORANGE "%s\n", props.deviceName); - Printf("Vulkan device type: %s\n", deviceType.GetChars()); - Printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.GetChars(), driverVersion.GetChars()); - - Printf(PRINT_LOG, "Vulkan extensions:"); - for (const VkExtensionProperties &p : device->PhysicalDevice.Extensions) - { - Printf(PRINT_LOG, " %s", p.extensionName); - } - Printf(PRINT_LOG, "\n"); - - const auto &limits = props.limits; - Printf("Max. texture size: %d\n", limits.maxImageDimension2D); - Printf("Max. uniform buffer range: %d\n", limits.maxUniformBufferRange); - Printf("Min. uniform buffer offset alignment: %" PRIu64 "\n", limits.minUniformBufferOffsetAlignment); -} - -void VulkanFrameBuffer::CreateFanToTrisIndexBuffer() -{ - TArray data; - for (int i = 2; i < 1000; i++) - { - data.Push(0); - data.Push(i - 1); - data.Push(i); - } - - FanToTrisIndexBuffer.reset(CreateIndexBuffer()); - FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static); -} - -void VulkanFrameBuffer::UpdateShadowMap() -{ - mPostprocess->UpdateShadowMap(); -} - -void VulkanFrameBuffer::SetSaveBuffers(bool yes) -{ - if (yes) mActiveRenderBuffers = mSaveBuffers.get(); - else mActiveRenderBuffers = mScreenBuffers.get(); -} - -void VulkanFrameBuffer::ImageTransitionScene(bool unknown) -{ - mPostprocess->ImageTransitionScene(unknown); -} - - -FRenderState* VulkanFrameBuffer::RenderState() -{ - return mRenderState.get(); -} - -void VulkanFrameBuffer::AmbientOccludeScene(float m5) -{ - mPostprocess->AmbientOccludeScene(m5); -} - -void VulkanFrameBuffer::SetSceneRenderTarget(bool useSSAO) -{ - mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); -} diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.h b/src/common/rendering/vulkan/system/vk_framebuffer.h deleted file mode 100644 index 365278acb..000000000 --- a/src/common/rendering/vulkan/system/vk_framebuffer.h +++ /dev/null @@ -1,166 +0,0 @@ -#pragma once - -#include "gl_sysfb.h" -#include "vk_device.h" -#include "vk_objects.h" - -struct FRenderViewpoint; -class VkSamplerManager; -class VkShaderManager; -class VkRenderPassManager; -class VkRenderState; -class VkStreamBuffer; -class VKDataBuffer; -class VkHardwareTexture; -class VkRenderBuffers; -class VkPostprocess; -class SWSceneDrawer; - -class VulkanFrameBuffer : public SystemBaseFrameBuffer -{ - typedef SystemBaseFrameBuffer Super; - - -public: - VulkanDevice *device; - std::unique_ptr swapChain; - uint32_t presentImageIndex = 0xffffffff; - bool cur_vsync; - - VulkanCommandBuffer *GetTransferCommands(); - VulkanCommandBuffer *GetDrawCommands(); - VkShaderManager *GetShaderManager() { return mShaderManager.get(); } - VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); } - VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); } - VkRenderState *GetRenderState() { return mRenderState.get(); } - VkPostprocess *GetPostprocess() { return mPostprocess.get(); } - VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; } - FRenderState* RenderState() override; - - void FlushCommands(bool finish, bool lastsubmit = false, bool uploadOnly = false); - - unsigned int GetLightBufferBlockSize() const; - - VKDataBuffer *ViewpointUBO = nullptr; - VKDataBuffer *LightBufferSSO = nullptr; - VkStreamBuffer *MatrixBuffer = nullptr; - VkStreamBuffer *StreamBuffer = nullptr; - - VKDataBuffer *LightNodes = nullptr; - VKDataBuffer *LightLines = nullptr; - VKDataBuffer *LightList = nullptr; - - std::unique_ptr FanToTrisIndexBuffer; - - class DeleteList - { - public: - std::vector> Images; - std::vector> ImageViews; - std::vector> Framebuffers; - std::vector> Buffers; - std::vector> Descriptors; - std::vector> DescriptorPools; - std::vector> CommandBuffers; - } FrameDeleteList; - - struct - { - std::vector> Buffers; - size_t TotalSize = 0; - } FrameTextureUpload; - - VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevice *dev); - ~VulkanFrameBuffer(); - bool IsVulkan() override { return true; } - - void Update() override; - - void InitializeState() override; - - void PrecacheMaterial(FMaterial *mat, int translation) override; - void UpdatePalette() override; - const char* DeviceName() const override; - int Backend() override { return 1; } - void SetTextureFilterMode() override; - void StartPrecaching() override; - void BeginFrame() 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 UpdateShadowMap() override; - void SetSaveBuffers(bool yes) override; - void ImageTransitionScene(bool unknown) override; - void SetActiveRenderTarget() override; - - IHardwareTexture *CreateHardwareTexture(int numchannels) override; - FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags) override; - IVertexBuffer *CreateVertexBuffer() override; - IIndexBuffer *CreateIndexBuffer() override; - IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; - - FTexture *WipeStartScreen() override; - FTexture *WipeEndScreen() override; - - TArray GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override; - - void SetVSync(bool vsync) override; - - void Draw2D() override; - - void WaitForCommands(bool finish) override { WaitForCommands(finish, false); } - void WaitForCommands(bool finish, bool uploadOnly); - - void PushGroup(const FString &name); - void PopGroup(); - void UpdateGpuStats(); - IntRect SetupTextureView(FCanvasTexture* tex); - void FinishTextureView(FCanvasTexture* tex); - -private: - void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; - void PrintStartupLog(); - void CreateFanToTrisIndexBuffer(); - void CopyScreenToBuffer(int w, int h, uint8_t *data) override; - void DeleteFrameObjects(bool uploadOnly = false); - void FlushCommands(VulkanCommandBuffer **commands, size_t count, bool finish, bool lastsubmit); - - std::unique_ptr mShaderManager; - std::unique_ptr mSamplerManager; - std::unique_ptr mScreenBuffers; - std::unique_ptr mSaveBuffers; - std::unique_ptr mPostprocess; - std::unique_ptr mRenderPassManager; - std::unique_ptr mCommandPool; - std::unique_ptr mTransferCommands; - std::unique_ptr mRenderState; - - std::unique_ptr mDrawCommands; - - enum { maxConcurrentSubmitCount = 8}; - std::unique_ptr mSubmitSemaphore[maxConcurrentSubmitCount]; - std::unique_ptr mSubmitFence[maxConcurrentSubmitCount]; - VkFence mSubmitWaitFences[maxConcurrentSubmitCount]; - int mNextSubmit = 0; - - std::unique_ptr mSwapChainImageAvailableSemaphore; - std::unique_ptr mRenderFinishedSemaphore; - - VkRenderBuffers *mActiveRenderBuffers = nullptr; - - struct TimestampQuery - { - FString name; - uint32_t startIndex; - uint32_t endIndex; - }; - - enum { MaxTimestampQueries = 100 }; - std::unique_ptr mTimestampQueryPool; - int mNextTimestampQuery = 0; - std::vector mGroupStack; - std::vector timeElapsedQueries; -}; - -inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast(screen); } diff --git a/src/common/rendering/vulkan/system/vk_hwbuffer.cpp b/src/common/rendering/vulkan/system/vk_hwbuffer.cpp new file mode 100644 index 000000000..7edfd471a --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_hwbuffer.cpp @@ -0,0 +1,254 @@ +/* +** 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_hwbuffer.h" +#include "zvulkan/vulkanbuilders.h" +#include "vk_renderdevice.h" +#include "vk_commandbuffer.h" +#include "vk_buffer.h" +#include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/renderer/vk_descriptorset.h" +#include "engineerrors.h" + +VkHardwareBuffer::VkHardwareBuffer(VulkanRenderDevice* fb) : fb(fb) +{ + fb->GetBufferManager()->AddBuffer(this); +} + +VkHardwareBuffer::~VkHardwareBuffer() +{ + if (fb) + fb->GetBufferManager()->RemoveBuffer(this); +} + +void VkHardwareBuffer::Reset() +{ + if (fb) + { + if (mBuffer && map) + { + mBuffer->Unmap(); + map = nullptr; + } + if (mBuffer) + fb->GetCommands()->DrawDeleteList->Add(std::move(mBuffer)); + if (mStaging) + fb->GetCommands()->TransferDeleteList->Add(std::move(mStaging)); + } +} + +void VkHardwareBuffer::SetData(size_t size, const void *data, BufferUsageType usage) +{ + size_t bufsize = max(size, (size_t)16); // For supporting zero byte buffers + + // If SetData is called multiple times we have to keep the old buffers alive as there might still be draw commands referencing them + if (mBuffer) + { + fb->GetCommands()->DrawDeleteList->Add(std::move(mBuffer)); + } + if (mStaging) + { + fb->GetCommands()->TransferDeleteList->Add(std::move(mStaging)); + } + + if (usage == BufferUsageType::Static || usage == BufferUsageType::Stream) + { + // Note: we could recycle buffers here for the stream usage type to improve performance + + mPersistent = false; + + mBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY) + .Size(bufsize) + .DebugName(usage == BufferUsageType::Static ? "VkHardwareBuffer.Static" : "VkHardwareBuffer.Stream") + .Create(fb->device.get()); + + mStaging = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(bufsize) + .DebugName(usage == BufferUsageType::Static ? "VkHardwareBuffer.Staging.Static" : "VkHardwareBuffer.Staging.Stream") + .Create(fb->device.get()); + + if (data) + { + void* dst = mStaging->Map(0, bufsize); + memcpy(dst, data, size); + mStaging->Unmap(); + } + + fb->GetCommands()->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get()); + } + else if (usage == BufferUsageType::Persistent) + { + mPersistent = true; + + mBuffer = BufferBuilder() + .Usage(mBufferType, 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(bufsize) + .DebugName("VkHardwareBuffer.Persistent") + .Create(fb->device.get()); + + map = mBuffer->Map(0, bufsize); + if (data) + memcpy(map, data, size); + } + else if (usage == BufferUsageType::Mappable) + { + mPersistent = false; + + mBuffer = BufferBuilder() + .Usage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, 0) + .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(bufsize) + .DebugName("VkHardwareBuffer.Mappable") + .Create(fb->device.get()); + + if (data) + { + void* dst = mBuffer->Map(0, bufsize); + memcpy(dst, data, size); + mBuffer->Unmap(); + } + } + + buffersize = size; +} + +void VkHardwareBuffer::SetSubData(size_t offset, size_t size, const void *data) +{ + size = max(size, (size_t)16); // For supporting zero byte buffers + + if (mStaging) + { + void *dst = mStaging->Map(offset, size); + memcpy(dst, data, size); + mStaging->Unmap(); + + fb->GetCommands()->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size); + } + else + { + void *dst = mBuffer->Map(offset, size); + memcpy(dst, data, size); + mBuffer->Unmap(); + } +} + +void VkHardwareBuffer::Resize(size_t newsize) +{ + newsize = max(newsize, (size_t)16); // For supporting zero byte buffers + + // Grab old buffer + size_t oldsize = buffersize; + std::unique_ptr oldBuffer = std::move(mBuffer); + oldBuffer->Unmap(); + map = nullptr; + + // Create new buffer + mBuffer = BufferBuilder() + .Usage(mBufferType, 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(newsize) + .DebugName("VkHardwareBuffer.Resized") + .Create(fb->device.get()); + buffersize = newsize; + + // Transfer data from old to new + fb->GetCommands()->GetTransferCommands()->copyBuffer(oldBuffer.get(), mBuffer.get(), 0, 0, oldsize); + fb->GetCommands()->TransferDeleteList->Add(std::move(oldBuffer)); + fb->GetCommands()->WaitForCommands(false); + fb->GetDescriptorSetManager()->UpdateHWBufferSet(); // Old buffer may be part of the bound descriptor set + + // Fetch pointer to new buffer + map = mBuffer->Map(0, newsize); +} + +void VkHardwareBuffer::Map() +{ + if (!mPersistent) + map = mBuffer->Map(0, mBuffer->size); +} + +void VkHardwareBuffer::Unmap() +{ + if (!mPersistent) + { + mBuffer->Unmap(); + map = nullptr; + } +} + +void *VkHardwareBuffer::Lock(unsigned int size) +{ + size = max(size, (unsigned int)16); // For supporting zero byte buffers + + if (!mBuffer) + { + // The model mesh loaders lock multiple non-persistent buffers at the same time. This is not allowed in vulkan. + // VkDeviceMemory can only be mapped once and multiple non-persistent buffers may come from the same device memory object. + mStaticUpload.Resize(size); + map = mStaticUpload.Data(); + } + else if (!mPersistent) + { + map = mBuffer->Map(0, size); + } + return map; +} + +void VkHardwareBuffer::Unlock() +{ + if (!mBuffer) + { + map = nullptr; + SetData(mStaticUpload.Size(), mStaticUpload.Data(), BufferUsageType::Static); + mStaticUpload.Clear(); + } + else if (!mPersistent) + { + mBuffer->Unmap(); + map = nullptr; + } +} + +///////////////////////////////////////////////////////////////////////////// + +void VkHardwareVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) +{ + VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs); +} + +///////////////////////////////////////////////////////////////////////////// + + +void VkHardwareDataBuffer::BindRange(FRenderState* state, size_t start, size_t length) +{ + static_cast(state)->Bind(bindingpoint, (uint32_t)start); +} + diff --git a/src/common/rendering/vulkan/system/vk_buffers.h b/src/common/rendering/vulkan/system/vk_hwbuffer.h similarity index 54% rename from src/common/rendering/vulkan/system/vk_buffers.h rename to src/common/rendering/vulkan/system/vk_hwbuffer.h index 78f850148..95a023141 100644 --- a/src/common/rendering/vulkan/system/vk_buffers.h +++ b/src/common/rendering/vulkan/system/vk_hwbuffer.h @@ -1,22 +1,24 @@ #pragma once #include "hwrenderer/data/buffers.h" -#include "vk_objects.h" +#include "zvulkan/vulkanobjects.h" #include "tarray.h" +#include #ifdef _MSC_VER -// silence bogus warning C4250: 'VKVertexBuffer': inherits 'VKBuffer::VKBuffer::SetData' via dominance +// silence bogus warning C4250: 'VkHardwareVertexBuffer': inherits 'VkHardwareBuffer::VkHardwareBuffer::SetData' via dominance // According to internet infos, the warning is erroneously emitted in this case. #pragma warning(disable:4250) #endif -class VKBuffer : virtual public IBuffer +class VulkanRenderDevice; + +class VkHardwareBuffer : virtual public IBuffer { public: - VKBuffer(); - ~VKBuffer(); + VkHardwareBuffer(VulkanRenderDevice* fb); + ~VkHardwareBuffer(); - static void ResetAll(); void Reset(); void SetData(size_t size, const void *data, BufferUsageType usage) override; @@ -29,37 +31,35 @@ public: void *Lock(unsigned int size) override; void Unlock() override; + VulkanRenderDevice* fb = nullptr; + std::list::iterator it; + VkBufferUsageFlags mBufferType = 0; std::unique_ptr mBuffer; std::unique_ptr mStaging; bool mPersistent = false; TArray mStaticUpload; - -private: - static VKBuffer *First; - VKBuffer *Prev = nullptr; - VKBuffer *Next = nullptr; }; -class VKVertexBuffer : public IVertexBuffer, public VKBuffer +class VkHardwareVertexBuffer : public IVertexBuffer, public VkHardwareBuffer { public: - VKVertexBuffer() { mBufferType = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; } + VkHardwareVertexBuffer(VulkanRenderDevice* fb) : VkHardwareBuffer(fb) { mBufferType = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; } void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; int VertexFormat = -1; }; -class VKIndexBuffer : public IIndexBuffer, public VKBuffer +class VkHardwareIndexBuffer : public IIndexBuffer, public VkHardwareBuffer { public: - VKIndexBuffer() { mBufferType = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; } + VkHardwareIndexBuffer(VulkanRenderDevice* fb) : VkHardwareBuffer(fb) { mBufferType = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; } }; -class VKDataBuffer : public IDataBuffer, public VKBuffer +class VkHardwareDataBuffer : public IDataBuffer, public VkHardwareBuffer { public: - VKDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint) + VkHardwareDataBuffer(VulkanRenderDevice* fb, int bindingpoint, bool ssbo, bool needresize) : VkHardwareBuffer(fb), bindingpoint(bindingpoint) { mBufferType = ssbo ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; if (needresize) diff --git a/src/common/rendering/vulkan/system/vk_renderdevice.cpp b/src/common/rendering/vulkan/system/vk_renderdevice.cpp new file mode 100644 index 000000000..8f4f1b737 --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_renderdevice.cpp @@ -0,0 +1,590 @@ +/* +** 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 + +#include + +#include "v_video.h" +#include "m_png.h" + +#include "r_videoscale.h" +#include "i_time.h" +#include "v_text.h" +#include "version.h" +#include "v_draw.h" + +#include "hw_clock.h" +#include "hw_vrmodes.h" +#include "hw_cvars.h" +#include "hw_skydome.h" +#include "hwrenderer/data/hw_viewpointbuffer.h" +#include "flatvertices.h" +#include "hwrenderer/data/shaderuniforms.h" +#include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" + +#include "vk_renderdevice.h" +#include "vk_hwbuffer.h" +#include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/renderer/vk_renderpass.h" +#include "vulkan/renderer/vk_descriptorset.h" +#include "vulkan/renderer/vk_streambuffer.h" +#include "vulkan/renderer/vk_postprocess.h" +#include "vulkan/renderer/vk_raytrace.h" +#include "vulkan/shaders/vk_shader.h" +#include "vulkan/textures/vk_renderbuffers.h" +#include "vulkan/textures/vk_samplers.h" +#include "vulkan/textures/vk_hwtexture.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/textures/vk_framebuffer.h" +#include +#include +#include +#include +#include "vulkan/system/vk_commandbuffer.h" +#include "vulkan/system/vk_buffer.h" +#include "engineerrors.h" +#include "c_dispatch.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) + +CCMD(vk_memstats) +{ + if (screen->IsVulkan()) + { + VmaStats stats = {}; + vmaCalculateStats(static_cast(screen)->device->allocator, &stats); + Printf("Allocated objects: %d, used bytes: %d MB\n", (int)stats.total.allocationCount, (int)stats.total.usedBytes / (1024 * 1024)); + Printf("Unused range count: %d, unused bytes: %d MB\n", (int)stats.total.unusedRangeCount, (int)stats.total.unusedBytes / (1024 * 1024)); + } + else + { + Printf("Vulkan is not the current render device\n"); + } +} + +CVAR(Bool, vk_raytrace, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +// Physical device info +static std::vector SupportedDevices; + +CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} + +CVAR(Bool, vk_debug_callstack, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +CUSTOM_CVAR(Int, vk_device, 0, 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++) + { + Printf("#%d - %s\n", (int)i, SupportedDevices[i].Device->Properties.deviceName); + } +} + +void VulkanError(const char* text) +{ + throw CVulkanError(text); +} + +void VulkanPrintLog(const char* typestr, const std::string& msg) +{ + bool showcallstack = strstr(typestr, "error") != nullptr; + + if (showcallstack) + Printf("\n"); + + Printf(TEXTCOLOR_RED "[%s] ", typestr); + Printf(TEXTCOLOR_WHITE "%s\n", msg.c_str()); + + if (vk_debug_callstack && showcallstack) + { + FString callstack = JitCaptureStackTrace(0, true, 5); + if (!callstack.IsEmpty()) + Printf("%s\n", callstack.GetChars()); + } +} + +VulkanRenderDevice::VulkanRenderDevice(void *hMonitor, bool fullscreen, std::shared_ptr surface) : + Super(hMonitor, fullscreen) +{ + VulkanDeviceBuilder builder; + builder.OptionalRayQuery(); + builder.Surface(surface); + builder.SelectDevice(vk_device); + SupportedDevices = builder.FindDevices(surface->Instance); + device = builder.Create(surface->Instance); +} + +VulkanRenderDevice::~VulkanRenderDevice() +{ + vkDeviceWaitIdle(device->device); // make sure the GPU is no longer using any objects before RAII tears them down + + delete mVertexData; + delete mSkyData; + delete mViewpoints; + delete mLights; + delete mBones; + mShadowMap.Reset(); + + if (mDescriptorSetManager) + mDescriptorSetManager->Deinit(); + if (mTextureManager) + mTextureManager->Deinit(); + if (mBufferManager) + mBufferManager->Deinit(); + if (mShaderManager) + mShaderManager->Deinit(); + + mCommands->DeleteFrameObjects(); +} + +void VulkanRenderDevice::InitializeState() +{ + static bool first = true; + if (first) + { + PrintStartupLog(); + first = false; + } + + // Use the same names here as OpenGL returns. + switch (device->PhysicalDevice.Properties.vendorID) + { + case 0x1002: vendorstring = "ATI Technologies Inc."; break; + case 0x10DE: vendorstring = "NVIDIA Corporation"; break; + case 0x8086: vendorstring = "Intel"; break; + default: vendorstring = "Unknown"; break; + } + + hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE; + glslversion = 4.50f; + uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment; + maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange; + + mCommands.reset(new VkCommandBufferManager(this)); + + mSamplerManager.reset(new VkSamplerManager(this)); + mTextureManager.reset(new VkTextureManager(this)); + mFramebufferManager.reset(new VkFramebufferManager(this)); + mBufferManager.reset(new VkBufferManager(this)); + mBufferManager->Init(); + + mScreenBuffers.reset(new VkRenderBuffers(this)); + mSaveBuffers.reset(new VkRenderBuffers(this)); + mActiveRenderBuffers = mScreenBuffers.get(); + + mPostprocess.reset(new VkPostprocess(this)); + mDescriptorSetManager.reset(new VkDescriptorSetManager(this)); + mRenderPassManager.reset(new VkRenderPassManager(this)); + mRaytrace.reset(new VkRaytrace(this)); + + mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); + mSkyData = new FSkyVertexBuffer; + mViewpoints = new HWViewpointBuffer; + mLights = new FLightBuffer(); + mBones = new BoneBuffer(); + + mShaderManager.reset(new VkShaderManager(this)); + mDescriptorSetManager->Init(); +#ifdef __APPLE__ + mRenderState.reset(new VkRenderStateMolten(this)); +#else + mRenderState.reset(new VkRenderState(this)); +#endif +} + +void VulkanRenderDevice::Update() +{ + twoD.Reset(); + Flush3D.Reset(); + + Flush3D.Clock(); + + GetPostprocess()->SetActiveRenderTarget(); + + Draw2D(); + twod->Clear(); + + mRenderState->EndRenderPass(); + mRenderState->EndFrame(); + + Flush3D.Unclock(); + + mCommands->WaitForCommands(true); + mCommands->UpdateGpuStats(); + + Super::Update(); +} + +bool VulkanRenderDevice::CompileNextShader() +{ + return mShaderManager->CompileNextShader(); +} + +void VulkanRenderDevice::RenderTextureView(FCanvasTexture* tex, std::function renderFunc) +{ + auto BaseLayer = static_cast(tex->GetHardwareTexture(0, 0)); + + VkTextureImage *image = BaseLayer->GetImage(tex, 0, 0); + VkTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); + + mRenderState->EndRenderPass(); + + VkImageTransition() + .AddImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false) + .Execute(mCommands->GetDrawCommands()); + + 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; + bounds.width = min(tex->GetWidth(), image->Image->width); + bounds.height = min(tex->GetHeight(), image->Image->height); + + renderFunc(bounds); + + mRenderState->EndRenderPass(); + + VkImageTransition() + .AddImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .Execute(mCommands->GetDrawCommands()); + + mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + + tex->SetUpdated(true); +} + +void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) +{ + if (!swscene) mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture + mPostprocess->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); +} + +const char* VulkanRenderDevice::DeviceName() const +{ + const auto &props = device->PhysicalDevice.Properties; + return props.deviceName; +} + +void VulkanRenderDevice::SetVSync(bool vsync) +{ + mVSync = vsync; +} + +void VulkanRenderDevice::PrecacheMaterial(FMaterial *mat, int translation) +{ + if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; + + MaterialLayerInfo* layer; + + auto systex = static_cast(mat->GetLayer(0, translation, &layer)); + systex->GetImage(layer->layerTexture, translation, layer->scaleFlags); + + int numLayers = mat->NumLayers(); + for (int i = 1; i < numLayers; i++) + { + auto syslayer = static_cast(mat->GetLayer(i, 0, &layer)); + syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags); + } +} + +IHardwareTexture *VulkanRenderDevice::CreateHardwareTexture(int numchannels) +{ + return new VkHardwareTexture(this, numchannels); +} + +FMaterial* VulkanRenderDevice::CreateMaterial(FGameTexture* tex, int scaleflags) +{ + return new VkMaterial(this, tex, scaleflags); +} + +IVertexBuffer *VulkanRenderDevice::CreateVertexBuffer() +{ + return GetBufferManager()->CreateVertexBuffer(); +} + +IIndexBuffer *VulkanRenderDevice::CreateIndexBuffer() +{ + return GetBufferManager()->CreateIndexBuffer(); +} + +IDataBuffer *VulkanRenderDevice::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) +{ + return GetBufferManager()->CreateDataBuffer(bindingpoint, ssbo, needsresize); +} + +void VulkanRenderDevice::SetTextureFilterMode() +{ + if (mSamplerManager) + { + mDescriptorSetManager->ResetHWTextureSets(); + mSamplerManager->ResetHWSamplers(); + } +} + +void VulkanRenderDevice::StartPrecaching() +{ + // Destroy the texture descriptors to avoid problems with potentially stale textures. + mDescriptorSetManager->ResetHWTextureSets(); +} + +void VulkanRenderDevice::BlurScene(float amount) +{ + if (mPostprocess) + mPostprocess->BlurScene(amount); +} + +void VulkanRenderDevice::UpdatePalette() +{ + if (mPostprocess) + mPostprocess->ClearTonemapPalette(); +} + +FTexture *VulkanRenderDevice::WipeStartScreen() +{ + SetViewportRects(nullptr); + + auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen"); + + return tex; +} + +FTexture *VulkanRenderDevice::WipeEndScreen() +{ + GetPostprocess()->SetActiveRenderTarget(); + Draw2D(); + twod->Clear(); + + auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen"); + + return tex; +} + +void VulkanRenderDevice::CopyScreenToBuffer(int w, int h, uint8_t *data) +{ + VkTextureImage image; + + // Convert from rgba16f to rgba8 using the GPU: + image.Image = ImageBuilder() + .Format(VK_FORMAT_R8G8B8A8_UNORM) + .Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Size(w, h) + .DebugName("CopyScreenToBuffer") + .Create(device.get()); + + GetPostprocess()->BlitCurrentToImage(&image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + // Staging buffer for download + auto staging = BufferBuilder() + .Size(w * h * 4) + .Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU) + .DebugName("CopyScreenToBuffer") + .Create(device.get()); + + // Copy from image to buffer + VkBufferImageCopy region = {}; + region.imageExtent.width = w; + region.imageExtent.height = h; + region.imageExtent.depth = 1; + region.imageSubresource.layerCount = 1; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + mCommands->GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, ®ion); + + // Submit command buffers and wait for device to finish the work + mCommands->WaitForCommands(false); + + // Map and convert from rgba8 to rgb8 + uint8_t *dest = (uint8_t*)data; + uint8_t *pixels = (uint8_t*)staging->Map(0, w * h * 4); + int dindex = 0; + for (int y = 0; y < h; y++) + { + int sindex = (h - y - 1) * w * 4; + for (int x = 0; x < w; x++) + { + dest[dindex] = pixels[sindex]; + dest[dindex + 1] = pixels[sindex + 1]; + dest[dindex + 2] = pixels[sindex + 2]; + dindex += 3; + sindex += 4; + } + } + staging->Unmap(); +} + +void VulkanRenderDevice::SetActiveRenderTarget() +{ + mPostprocess->SetActiveRenderTarget(); +} + +TArray VulkanRenderDevice::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) +{ + int w = SCREENWIDTH; + int h = SCREENHEIGHT; + + IntRect box; + box.left = 0; + box.top = 0; + box.width = w; + box.height = h; + mPostprocess->DrawPresentTexture(box, true, true); + + TArray ScreenshotBuffer(w * h * 3, true); + CopyScreenToBuffer(w, h, ScreenshotBuffer.Data()); + + pitch = w * 3; + color_type = SS_RGB; + gamma = 1.0f; + return ScreenshotBuffer; +} + +void VulkanRenderDevice::BeginFrame() +{ + SetViewportRects(nullptr); + mViewpoints->Clear(); + mCommands->BeginFrame(); + mTextureManager->BeginFrame(); + mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); + mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); + 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 + } +} + +void VulkanRenderDevice::Draw2D() +{ + ::Draw2D(twod, *mRenderState); +} + +void VulkanRenderDevice::WaitForCommands(bool finish) +{ + mCommands->WaitForCommands(finish); +} + +unsigned int VulkanRenderDevice::GetLightBufferBlockSize() const +{ + return mLights->GetBlockSize(); +} + +void VulkanRenderDevice::PrintStartupLog() +{ + const auto &props = device->PhysicalDevice.Properties; + + FString deviceType; + switch (props.deviceType) + { + case VK_PHYSICAL_DEVICE_TYPE_OTHER: deviceType = "other"; break; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: deviceType = "integrated gpu"; break; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: deviceType = "discrete gpu"; break; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: deviceType = "virtual gpu"; break; + case VK_PHYSICAL_DEVICE_TYPE_CPU: deviceType = "cpu"; break; + default: deviceType.Format("%d", (int)props.deviceType); break; + } + + 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)); + + Printf("Vulkan device: " TEXTCOLOR_ORANGE "%s\n", props.deviceName); + Printf("Vulkan device type: %s\n", deviceType.GetChars()); + Printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.GetChars(), driverVersion.GetChars()); + + Printf(PRINT_LOG, "Vulkan extensions:"); + for (const VkExtensionProperties &p : device->PhysicalDevice.Extensions) + { + Printf(PRINT_LOG, " %s", p.extensionName); + } + Printf(PRINT_LOG, "\n"); + + const auto &limits = props.limits; + Printf("Max. texture size: %d\n", limits.maxImageDimension2D); + Printf("Max. uniform buffer range: %d\n", limits.maxUniformBufferRange); + Printf("Min. uniform buffer offset alignment: %" PRIu64 "\n", limits.minUniformBufferOffsetAlignment); +} + +void VulkanRenderDevice::SetLevelMesh(hwrenderer::LevelMesh* mesh) +{ + mRaytrace->SetLevelMesh(mesh); +} + +void VulkanRenderDevice::UpdateShadowMap() +{ + mPostprocess->UpdateShadowMap(); +} + +void VulkanRenderDevice::SetSaveBuffers(bool yes) +{ + if (yes) mActiveRenderBuffers = mSaveBuffers.get(); + else mActiveRenderBuffers = mScreenBuffers.get(); +} + +void VulkanRenderDevice::ImageTransitionScene(bool unknown) +{ + mPostprocess->ImageTransitionScene(unknown); +} + +FRenderState* VulkanRenderDevice::RenderState() +{ + return mRenderState.get(); +} + +void VulkanRenderDevice::AmbientOccludeScene(float m5) +{ + mPostprocess->AmbientOccludeScene(m5); +} + +void VulkanRenderDevice::SetSceneRenderTarget(bool useSSAO) +{ + mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); +} + +bool VulkanRenderDevice::RaytracingEnabled() +{ + return vk_raytrace && device->SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME); +} diff --git a/src/common/rendering/vulkan/system/vk_renderdevice.h b/src/common/rendering/vulkan/system/vk_renderdevice.h new file mode 100644 index 000000000..6b1153671 --- /dev/null +++ b/src/common/rendering/vulkan/system/vk_renderdevice.h @@ -0,0 +1,125 @@ +#pragma once + +#include "gl_sysfb.h" +#include "engineerrors.h" +#include +#include + +struct FRenderViewpoint; +class VkSamplerManager; +class VkBufferManager; +class VkTextureManager; +class VkShaderManager; +class VkCommandBufferManager; +class VkDescriptorSetManager; +class VkRenderPassManager; +class VkFramebufferManager; +class VkRaytrace; +class VkRenderState; +class VkStreamBuffer; +class VkHardwareDataBuffer; +class VkHardwareTexture; +class VkRenderBuffers; +class VkPostprocess; +class SWSceneDrawer; + +class VulkanRenderDevice : public SystemBaseFrameBuffer +{ + typedef SystemBaseFrameBuffer Super; + + +public: + std::shared_ptr device; + + VkCommandBufferManager* GetCommands() { return mCommands.get(); } + VkShaderManager *GetShaderManager() { return mShaderManager.get(); } + VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); } + VkBufferManager* GetBufferManager() { return mBufferManager.get(); } + VkTextureManager* GetTextureManager() { return mTextureManager.get(); } + VkFramebufferManager* GetFramebufferManager() { return mFramebufferManager.get(); } + VkDescriptorSetManager* GetDescriptorSetManager() { return mDescriptorSetManager.get(); } + VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); } + VkRaytrace* GetRaytrace() { return mRaytrace.get(); } + VkRenderState *GetRenderState() { return mRenderState.get(); } + VkPostprocess *GetPostprocess() { return mPostprocess.get(); } + VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; } + FRenderState* RenderState() override; + + unsigned int GetLightBufferBlockSize() const; + + VulkanRenderDevice(void *hMonitor, bool fullscreen, std::shared_ptr surface); + ~VulkanRenderDevice(); + bool IsVulkan() override { return true; } + + void Update() override; + + void InitializeState() override; + bool CompileNextShader() override; + void PrecacheMaterial(FMaterial *mat, int translation) override; + void UpdatePalette() override; + const char* DeviceName() const override; + int Backend() override { return 1; } + 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 UpdateShadowMap() override; + void SetSaveBuffers(bool yes) override; + void ImageTransitionScene(bool unknown) override; + void SetActiveRenderTarget() override; + + IHardwareTexture *CreateHardwareTexture(int numchannels) override; + FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags) override; + IVertexBuffer *CreateVertexBuffer() override; + IIndexBuffer *CreateIndexBuffer() override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; + + FTexture *WipeStartScreen() override; + FTexture *WipeEndScreen() override; + + TArray GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override; + + bool GetVSync() { return mVSync; } + void SetVSync(bool vsync) override; + + void Draw2D() override; + + void WaitForCommands(bool finish) override; + + bool RaytracingEnabled(); + +private: + void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; + void PrintStartupLog(); + void CopyScreenToBuffer(int w, int h, uint8_t *data) override; + + std::unique_ptr mCommands; + std::unique_ptr mBufferManager; + std::unique_ptr mSamplerManager; + std::unique_ptr mTextureManager; + std::unique_ptr mFramebufferManager; + std::unique_ptr mShaderManager; + std::unique_ptr mScreenBuffers; + std::unique_ptr mSaveBuffers; + std::unique_ptr mPostprocess; + std::unique_ptr mDescriptorSetManager; + std::unique_ptr mRenderPassManager; + std::unique_ptr mRaytrace; + std::unique_ptr mRenderState; + + VkRenderBuffers *mActiveRenderBuffers = nullptr; + + bool mVSync = false; +}; + +class CVulkanError : public CEngineError +{ +public: + CVulkanError() : CEngineError() {} + CVulkanError(const char* message) : CEngineError(message) {} +}; diff --git a/src/common/rendering/vulkan/system/vk_swapchain.cpp b/src/common/rendering/vulkan/system/vk_swapchain.cpp deleted file mode 100644 index dcacd1620..000000000 --- a/src/common/rendering/vulkan/system/vk_swapchain.cpp +++ /dev/null @@ -1,392 +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_swapchain.h" -#include "vk_objects.h" -#include "c_cvars.h" -#include "version.h" -#include "v_video.h" -#include "vk_framebuffer.h" - - -CVAR(Bool, vk_hdr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); - -void I_GetVulkanDrawableSize(int *width, int *height); - -VulkanSwapChain::VulkanSwapChain(VulkanDevice *device) : device(device) -{ -} - -VulkanSwapChain::~VulkanSwapChain() -{ - ReleaseResources(); -} - -uint32_t VulkanSwapChain::AcquireImage(int width, int height, VulkanSemaphore *semaphore, VulkanFence *fence) -{ - auto vsync = static_cast(screen)->cur_vsync; - if (lastSwapWidth != width || lastSwapHeight != height || lastVsync != vsync || lastHdr != vk_hdr || !swapChain) - { - Recreate(); - lastSwapWidth = width; - lastSwapHeight = height; - lastVsync = vsync; - lastHdr = vk_hdr; - } - - uint32_t imageIndex; - while (true) - { - if (!swapChain) - { - imageIndex = 0xffffffff; - break; - } - - VkResult result = vkAcquireNextImageKHR(device->device, swapChain, 1'000'000'000, semaphore ? semaphore->semaphore : VK_NULL_HANDLE, fence ? fence->fence : VK_NULL_HANDLE, &imageIndex); - if (result == VK_SUCCESS) - { - break; - } - else if (result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_SURFACE_LOST_KHR) - { - // Force the recreate to happen next frame. - // The spec is not very clear about what happens to the semaphore or the acquired image if the swapchain is recreated before the image is released with a call to vkQueuePresentKHR. - lastSwapWidth = 0; - lastSwapHeight = 0; - break; - } - else if (result == VK_ERROR_OUT_OF_DATE_KHR) - { - Recreate(); - } - else if (result == VK_NOT_READY || result == VK_TIMEOUT) - { - imageIndex = 0xffffffff; - break; - } - else if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY) - { - VulkanError("vkAcquireNextImageKHR failed: out of memory"); - } - else if (result == VK_ERROR_DEVICE_LOST) - { - VulkanError("vkAcquireNextImageKHR failed: device lost"); - } - else - { - VulkanError("vkAcquireNextImageKHR failed"); - } - } - return imageIndex; -} - -void VulkanSwapChain::QueuePresent(uint32_t imageIndex, VulkanSemaphore *semaphore) -{ - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = semaphore ? 1 : 0; - presentInfo.pWaitSemaphores = semaphore ? &semaphore->semaphore : VK_NULL_HANDLE; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &swapChain; - presentInfo.pImageIndices = &imageIndex; - presentInfo.pResults = nullptr; - VkResult result = vkQueuePresentKHR(device->presentQueue, &presentInfo); - if (result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_SURFACE_LOST_KHR) - { - lastSwapWidth = 0; - lastSwapHeight = 0; - } - else if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY) - { - // 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. - - VulkanError("vkQueuePresentKHR failed: out of memory"); - } - else if (result == VK_ERROR_DEVICE_LOST) - { - VulkanError("vkQueuePresentKHR failed: device lost"); - } - else if (result != VK_SUCCESS) - { - VulkanError("vkQueuePresentKHR failed"); - } -} - -void VulkanSwapChain::Recreate() -{ - ReleaseViews(); - swapChainImages.clear(); - - VkSwapchainKHR oldSwapChain = swapChain; - CreateSwapChain(oldSwapChain); - if (oldSwapChain) - vkDestroySwapchainKHR(device->device, oldSwapChain, nullptr); - - if (swapChain) - { - GetImages(); - CreateViews(); - } -} - -bool VulkanSwapChain::CreateSwapChain(VkSwapchainKHR oldSwapChain) -{ - SelectFormat(); - SelectPresentMode(); - - int width, height; - I_GetVulkanDrawableSize(&width, &height); - - VkSurfaceCapabilitiesKHR surfaceCapabilities = GetSurfaceCapabilities(); - - actualExtent = { static_cast(width), static_cast(height) }; - actualExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, actualExtent.width)); - actualExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, actualExtent.height)); - if (actualExtent.width == 0 || actualExtent.height == 0) - { - swapChain = VK_NULL_HANDLE; - return false; - } - - uint32_t imageCount = surfaceCapabilities.minImageCount + 1; - if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) - imageCount = surfaceCapabilities.maxImageCount; - - // When vsync is on we only want two images. This creates a slight performance penalty in exchange for reduced input latency (less mouse lag). - // When vsync is off we want three images as it allows us to generate new images even during the vertical blanking period where one entry is being used by the presentation engine. - if (swapChainPresentMode == VK_PRESENT_MODE_MAILBOX_KHR || swapChainPresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) - imageCount = std::min(imageCount, (uint32_t)3); - else - imageCount = std::min(imageCount, (uint32_t)2); - - VkSwapchainCreateInfoKHR swapChainCreateInfo = {}; - swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapChainCreateInfo.surface = device->surface; - swapChainCreateInfo.minImageCount = imageCount; - swapChainCreateInfo.imageFormat = swapChainFormat.format; - swapChainCreateInfo.imageColorSpace = swapChainFormat.colorSpace; - swapChainCreateInfo.imageExtent = actualExtent; - swapChainCreateInfo.imageArrayLayers = 1; - swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - uint32_t queueFamilyIndices[] = { (uint32_t)device->graphicsFamily, (uint32_t)device->presentFamily }; - if (device->graphicsFamily != device->presentFamily) - { - swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - swapChainCreateInfo.queueFamilyIndexCount = 2; - swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; - } - else - { - swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapChainCreateInfo.queueFamilyIndexCount = 0; - swapChainCreateInfo.pQueueFamilyIndices = nullptr; - } - - swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform; - swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // If alpha channel is passed on to the DWM or not - swapChainCreateInfo.presentMode = swapChainPresentMode; - swapChainCreateInfo.clipped = VK_TRUE; - swapChainCreateInfo.oldSwapchain = oldSwapChain; - - VkResult result = vkCreateSwapchainKHR(device->device, &swapChainCreateInfo, nullptr, &swapChain); - if (result != VK_SUCCESS) - { - swapChain = VK_NULL_HANDLE; - return false; - } - - return true; -} - -void VulkanSwapChain::CreateViews() -{ - framebuffers.resize(swapChainImages.size()); - swapChainImageViews.reserve(swapChainImages.size()); - for (size_t i = 0; i < swapChainImages.size(); i++) - { - device->SetDebugObjectName("SwapChainImage", (uint64_t)swapChainImages[i], VK_OBJECT_TYPE_IMAGE); - - VkImageViewCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.image = swapChainImages[i]; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = swapChainFormat.format; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - - VkImageView view; - VkResult result = vkCreateImageView(device->device, &createInfo, nullptr, &view); - CheckVulkanError(result, "Could not create image view for swapchain image"); - - device->SetDebugObjectName("SwapChainImageView", (uint64_t)view, VK_OBJECT_TYPE_IMAGE_VIEW); - - swapChainImageViews.push_back(view); - } -} - -bool VulkanSwapChain::IsHdrModeActive() const -{ - return swapChainFormat.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT || swapChainFormat.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT; -} - -void VulkanSwapChain::SelectFormat() -{ - std::vector surfaceFormats = GetSurfaceFormats(); - if (surfaceFormats.empty()) - VulkanError("No surface formats supported"); - - if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED) - { - swapChainFormat.format = VK_FORMAT_B8G8R8A8_UNORM; - swapChainFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - return; - } - - if (vk_hdr) - { - for (const auto& format : surfaceFormats) - { - if (format.format == VK_FORMAT_R16G16B16A16_SFLOAT && format.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT) - { - swapChainFormat = format; - return; - } - } - - // For older drivers that reported the wrong colorspace - for (const auto &format : surfaceFormats) - { - if (format.format == VK_FORMAT_R16G16B16A16_SFLOAT && format.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT) - { - swapChainFormat = format; - return; - } - } - } - - for (const auto &format : surfaceFormats) - { - if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - { - swapChainFormat = format; - return; - } - } - - swapChainFormat = surfaceFormats.front(); -} - -void VulkanSwapChain::SelectPresentMode() -{ - std::vector presentModes = GetPresentModes(); - - if (presentModes.empty()) - VulkanError("No surface present modes supported"); - - swapChainPresentMode = VK_PRESENT_MODE_FIFO_KHR; - auto vsync = static_cast(screen)->cur_vsync; - if (vsync) - { - bool supportsFifoRelaxed = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != presentModes.end(); - if (supportsFifoRelaxed) - swapChainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; - } - else - { - bool supportsMailbox = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != presentModes.end(); - bool supportsImmediate = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != presentModes.end(); - if (supportsMailbox) - swapChainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; - else if (supportsImmediate) - swapChainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; - } -} - -void VulkanSwapChain::GetImages() -{ - uint32_t imageCount; - VkResult result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, nullptr); - CheckVulkanError(result, "vkGetSwapchainImagesKHR failed"); - - swapChainImages.resize(imageCount); - result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, swapChainImages.data()); - CheckVulkanError(result, "vkGetSwapchainImagesKHR failed (2)"); -} - -void VulkanSwapChain::ReleaseViews() -{ - framebuffers.clear(); - for (auto &view : swapChainImageViews) - { - vkDestroyImageView(device->device, view, nullptr); - } - swapChainImageViews.clear(); -} - -void VulkanSwapChain::ReleaseResources() -{ - ReleaseViews(); - if (swapChain) - vkDestroySwapchainKHR(device->device, swapChain, nullptr); -} - -VkSurfaceCapabilitiesKHR VulkanSwapChain::GetSurfaceCapabilities() -{ - VkSurfaceCapabilitiesKHR surfaceCapabilities; - VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities); - CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed"); - return surfaceCapabilities; -} - -std::vector VulkanSwapChain::GetSurfaceFormats() -{ - uint32_t surfaceFormatCount = 0; - VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, nullptr); - CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceFormatsKHR failed"); - if (surfaceFormatCount == 0) - return {}; - - std::vector surfaceFormats(surfaceFormatCount); - result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, surfaceFormats.data()); - CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceFormatsKHR failed"); - return surfaceFormats; -} - -std::vector VulkanSwapChain::GetPresentModes() -{ - uint32_t presentModeCount = 0; - VkResult result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, nullptr); - CheckVulkanError(result, "vkGetPhysicalDeviceSurfacePresentModesKHR failed"); - if (presentModeCount == 0) - return {}; - - std::vector presentModes(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, presentModes.data()); - CheckVulkanError(result, "vkGetPhysicalDeviceSurfacePresentModesKHR failed"); - return presentModes; -} diff --git a/src/common/rendering/vulkan/system/vk_swapchain.h b/src/common/rendering/vulkan/system/vk_swapchain.h deleted file mode 100644 index 51de64867..000000000 --- a/src/common/rendering/vulkan/system/vk_swapchain.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "vk_device.h" - -class VulkanSemaphore; -class VulkanFence; -class VulkanFramebuffer; - -class VulkanSwapChain -{ -public: - VulkanSwapChain(VulkanDevice *device); - ~VulkanSwapChain(); - - uint32_t AcquireImage(int width, int height, VulkanSemaphore *semaphore = nullptr, VulkanFence *fence = nullptr); - void QueuePresent(uint32_t imageIndex, VulkanSemaphore *semaphore = nullptr); - - void Recreate(); - - bool IsHdrModeActive() const; - - VkSwapchainKHR swapChain = VK_NULL_HANDLE; - VkSurfaceFormatKHR swapChainFormat; - VkPresentModeKHR swapChainPresentMode; - - std::vector swapChainImages; - std::vector swapChainImageViews; - std::vector> framebuffers; - - VkExtent2D actualExtent; - -private: - void SelectFormat(); - void SelectPresentMode(); - bool CreateSwapChain(VkSwapchainKHR oldSwapChain = VK_NULL_HANDLE); - void CreateViews(); - void GetImages(); - void ReleaseResources(); - void ReleaseViews(); - - VkSurfaceCapabilitiesKHR GetSurfaceCapabilities(); - std::vector GetSurfaceFormats(); - std::vector GetPresentModes(); - - VulkanDevice *device = nullptr; - - int lastSwapWidth = 0; - int lastSwapHeight = 0; - bool lastVsync = false; - bool lastHdr = false; - - VulkanSwapChain(const VulkanSwapChain &) = delete; - VulkanSwapChain &operator=(const VulkanSwapChain &) = delete; -}; diff --git a/src/common/rendering/vulkan/textures/vk_framebuffer.cpp b/src/common/rendering/vulkan/textures/vk_framebuffer.cpp new file mode 100644 index 000000000..c32e73b9d --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_framebuffer.cpp @@ -0,0 +1,79 @@ +/* +** 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 +#include +#include +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/renderer/vk_postprocess.h" +#include "vk_framebuffer.h" + +CVAR(Bool, vk_hdr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, vk_exclusivefullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); + +VkFramebufferManager::VkFramebufferManager(VulkanRenderDevice* fb) : fb(fb) +{ + SwapChain = VulkanSwapChainBuilder() + .Create(fb->device.get()); + + SwapChainImageAvailableSemaphore = SemaphoreBuilder() + .DebugName("SwapChainImageAvailableSemaphore") + .Create(fb->device.get()); + + RenderFinishedSemaphore = SemaphoreBuilder() + .DebugName("RenderFinishedSemaphore") + .Create(fb->device.get()); +} + +VkFramebufferManager::~VkFramebufferManager() +{ +} + +void VkFramebufferManager::AcquireImage() +{ + bool exclusiveFullscreen = fb->IsFullscreen() && vk_exclusivefullscreen; + if (SwapChain->Lost() || fb->GetClientWidth() != CurrentWidth || fb->GetClientHeight() != CurrentHeight || fb->GetVSync() != CurrentVSync || CurrentHdr != vk_hdr || CurrentExclusiveFullscreen != exclusiveFullscreen) + { + Framebuffers.clear(); + + CurrentWidth = fb->GetClientWidth(); + CurrentHeight = fb->GetClientHeight(); + CurrentVSync = fb->GetVSync(); + CurrentHdr = vk_hdr; + CurrentExclusiveFullscreen = exclusiveFullscreen; + + SwapChain->Create(CurrentWidth, CurrentHeight, CurrentVSync ? 2 : 3, CurrentVSync, CurrentHdr, CurrentExclusiveFullscreen); + } + + PresentImageIndex = SwapChain->AcquireImage(SwapChainImageAvailableSemaphore.get()); + if (PresentImageIndex != -1) + { + fb->GetPostprocess()->DrawPresentTexture(fb->mOutputLetterbox, true, false); + } +} + +void VkFramebufferManager::QueuePresent() +{ + if (PresentImageIndex != -1) + SwapChain->QueuePresent(PresentImageIndex, RenderFinishedSemaphore.get()); +} diff --git a/src/common/rendering/vulkan/textures/vk_framebuffer.h b/src/common/rendering/vulkan/textures/vk_framebuffer.h new file mode 100644 index 000000000..06cc6a261 --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_framebuffer.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "zvulkan/vulkanobjects.h" +#include +#include + +class VulkanRenderDevice; +enum class PPFilterMode; +enum class PPWrapMode; + +class VkFramebufferManager +{ +public: + VkFramebufferManager(VulkanRenderDevice* fb); + ~VkFramebufferManager(); + + void AcquireImage(); + void QueuePresent(); + + std::map> Framebuffers; + + std::shared_ptr SwapChain; + int PresentImageIndex = -1; + + std::unique_ptr SwapChainImageAvailableSemaphore; + std::unique_ptr RenderFinishedSemaphore; + +private: + VulkanRenderDevice* fb = nullptr; + int CurrentWidth = 0; + int CurrentHeight = 0; + bool CurrentVSync = false; + bool CurrentHdr = false; + bool CurrentExclusiveFullscreen = false; +}; diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp index 276f9fd09..b42a45a19 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -20,49 +20,38 @@ ** */ -#include "templates.h" + #include "c_cvars.h" #include "hw_material.h" #include "hw_cvars.h" #include "hw_renderstate.h" -#include "vulkan/system/vk_objects.h" -#include "vulkan/system/vk_builders.h" -#include "vulkan/system/vk_framebuffer.h" +#include +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" #include "vulkan/textures/vk_samplers.h" -#include "vulkan/renderer/vk_renderpass.h" +#include "vulkan/textures/vk_renderbuffers.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/renderer/vk_descriptorset.h" #include "vulkan/renderer/vk_postprocess.h" -#include "vulkan/renderer/vk_renderbuffers.h" #include "vulkan/shaders/vk_shader.h" #include "vk_hwtexture.h" -VkHardwareTexture *VkHardwareTexture::First = nullptr; - -VkHardwareTexture::VkHardwareTexture(int numchannels) +VkHardwareTexture::VkHardwareTexture(VulkanRenderDevice* fb, int numchannels) : fb(fb) { mTexelsize = numchannels; - Next = First; - First = this; - if (Next) Next->Prev = this; + fb->GetTextureManager()->AddTexture(this); } VkHardwareTexture::~VkHardwareTexture() { - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - Reset(); -} - -void VkHardwareTexture::ResetAll() -{ - for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next) - cur->Reset(); + if (fb) + fb->GetTextureManager()->RemoveTexture(this); } void VkHardwareTexture::Reset() { - if (auto fb = GetVulkanFrameBuffer()) + if (fb) { if (mappedSWFB) { @@ -70,15 +59,8 @@ void VkHardwareTexture::Reset() mappedSWFB = nullptr; } - auto &deleteList = fb->FrameDeleteList; - if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image)); - if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View)); - for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second)); - if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image)); - if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View)); - for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second)); - mImage.reset(); - mDepthStencil.reset(); + mImage.Reset(fb); + mDepthStencil.Reset(fb); } } @@ -95,29 +77,28 @@ VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex) { if (!mDepthStencil.View) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = fb->GetBuffers()->SceneDepthStencilFormat; int w = tex->GetWidth(); int h = tex->GetHeight(); - ImageBuilder builder; - builder.setSize(w, h); - builder.setSamples(VK_SAMPLE_COUNT_1_BIT); - builder.setFormat(format); - builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - mDepthStencil.Image = builder.create(fb->device); - mDepthStencil.Image->SetDebugName("VkHardwareTexture.DepthStencil"); + mDepthStencil.Image = ImageBuilder() + .Size(w, h) + .Samples(VK_SAMPLE_COUNT_1_BIT) + .Format(format) + .Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + .DebugName("VkHardwareTexture.DepthStencil") + .Create(fb->device.get()); + mDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - ImageViewBuilder viewbuilder; - viewbuilder.setImage(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - mDepthStencil.View = viewbuilder.create(fb->device); - mDepthStencil.View->SetDebugName("VkHardwareTexture.DepthStencilView"); + mDepthStencil.View = ImageViewBuilder() + .Image(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) + .DebugName("VkHardwareTexture.DepthStencilView") + .Create(fb->device.get()); - VkImageTransition barrier; - barrier.addImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); - barrier.execute(fb->GetTransferCommands()); + VkImageTransition() + .AddImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); } return &mDepthStencil; } @@ -132,29 +113,25 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } else { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; int w = tex->GetWidth(); int h = tex->GetHeight(); - ImageBuilder imgbuilder; - imgbuilder.setFormat(format); - imgbuilder.setSize(w, h); - imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - mImage.Image = imgbuilder.create(fb->device); - mImage.Image->SetDebugName("VkHardwareTexture.mImage"); + mImage.Image = ImageBuilder() + .Format(format) + .Size(w, h) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .DebugName("VkHardwareTexture.mImage") + .Create(fb->device.get()); - ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.Image.get(), format); - mImage.View = viewbuilder.create(fb->device); - mImage.View->SetDebugName("VkHardwareTexture.mImageView"); + mImage.View = ImageViewBuilder() + .Image(mImage.Image.get(), format) + .DebugName("VkHardwareTexture.mImageView") + .Create(fb->device.get()); - auto cmdbuffer = fb->GetTransferCommands(); - - VkImageTransition imageTransition; - imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); - imageTransition.execute(cmdbuffer); + VkImageTransition() + .AddImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); } } @@ -163,37 +140,35 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form if (w <= 0 || h <= 0) throw CVulkanError("Trying to create zero size texture"); - auto fb = GetVulkanFrameBuffer(); - int totalSize = w * h * pixelsize; - BufferBuilder bufbuilder; - bufbuilder.setSize(totalSize); - bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - std::unique_ptr stagingBuffer = bufbuilder.create(fb->device); - stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer"); + auto stagingBuffer = BufferBuilder() + .Size(totalSize) + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .DebugName("VkHardwareTexture.mStagingBuffer") + .Create(fb->device.get()); uint8_t *data = (uint8_t*)stagingBuffer->Map(0, totalSize); memcpy(data, pixels, totalSize); stagingBuffer->Unmap(); - ImageBuilder imgbuilder; - imgbuilder.setFormat(format); - imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h)); - imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - mImage.Image = imgbuilder.create(fb->device); - mImage.Image->SetDebugName("VkHardwareTexture.mImage"); + mImage.Image = ImageBuilder() + .Format(format) + .Size(w, h, !mipmap ? 1 : GetMipLevels(w, h)) + .Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .DebugName("VkHardwareTexture.mImage") + .Create(fb->device.get()); - ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.Image.get(), format); - mImage.View = viewbuilder.create(fb->device); - mImage.View->SetDebugName("VkHardwareTexture.mImageView"); + mImage.View = ImageViewBuilder() + .Image(mImage.Image.get(), format) + .DebugName("VkHardwareTexture.mImageView") + .Create(fb->device.get()); - auto cmdbuffer = fb->GetTransferCommands(); + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - VkImageTransition imageTransition; - imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - imageTransition.execute(cmdbuffer); + VkImageTransition() + .AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true) + .Execute(cmdbuffer); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -203,14 +178,12 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form region.imageExtent.height = h; cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - fb->FrameTextureUpload.Buffers.push_back(std::move(stagingBuffer)); - if (mipmap) mImage.GenerateMipmaps(cmdbuffer); // If we queued more than 64 MB of data already: wait until the uploads finish before continuing - fb->FrameTextureUpload.TotalSize += totalSize; - if (fb->FrameTextureUpload.TotalSize > 64 * 1024 * 1024) - fb->WaitForCommands(false, true); + fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); + if (fb->GetCommands()->TransferDeleteList->TotalSize > 64 * 1024 * 1024) + fb->GetCommands()->WaitForCommands(false, true); } int VkHardwareTexture::GetMipLevels(int w, int h) @@ -218,8 +191,8 @@ int VkHardwareTexture::GetMipLevels(int w, int h) int levels = 1; while (w > 1 || h > 1) { - w = std::max(w >> 1, 1); - h = std::max(h >> 1, 1); + w = max(w >> 1, 1); + h = max(h >> 1, 1); levels++; } return levels; @@ -234,33 +207,30 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) if (!mImage.Image) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = texelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM; - ImageBuilder imgbuilder; VkDeviceSize allocatedBytes = 0; - imgbuilder.setFormat(format); - imgbuilder.setSize(w, h); - imgbuilder.setLinearTiling(); - imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT); - imgbuilder.setMemoryType( - 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); - mImage.Image = imgbuilder.create(fb->device, &allocatedBytes); - mImage.Image->SetDebugName("VkHardwareTexture.mImage"); + mImage.Image = ImageBuilder() + .Format(format) + .Size(w, h) + .LinearTiling() + .Usage(VK_IMAGE_USAGE_SAMPLED_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) + .DebugName("VkHardwareTexture.mImage") + .Create(fb->device.get(), &allocatedBytes); + mTexelsize = texelsize; - ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.Image.get(), format); - mImage.View = viewbuilder.create(fb->device); - mImage.View->SetDebugName("VkHardwareTexture.mImageView"); + mImage.View = ImageViewBuilder() + .Image(mImage.Image.get(), format) + .DebugName("VkHardwareTexture.mImageView") + .Create(fb->device.get()); - auto cmdbuffer = fb->GetTransferCommands(); - - VkImageTransition imageTransition; - imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true); - imageTransition.execute(cmdbuffer); + VkImageTransition() + .AddImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); bufferpitch = int(allocatedBytes / h / texelsize); } @@ -283,22 +253,21 @@ unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = VK_FORMAT_B8G8R8A8_UNORM; - ImageBuilder imgbuilder; - imgbuilder.setFormat(format); - imgbuilder.setSize(w, h); - imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); - mImage.Image = imgbuilder.create(fb->device); - mImage.Image->SetDebugName(name); + mImage.Image = ImageBuilder() + .Format(format) + .Size(w, h) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY) + .DebugName(name) + .Create(fb->device.get()); + mTexelsize = 4; - ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.Image.get(), format); - mImage.View = viewbuilder.create(fb->device); - mImage.View->SetDebugName(name); + mImage.View = ImageViewBuilder() + .Image(mImage.Image.get(), format) + .DebugName(name) + .Create(fb->device.get()); if (fb->GetBuffers()->GetWidth() > 0 && fb->GetBuffers()->GetHeight() > 0) { @@ -309,9 +278,9 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) // hwrenderer asked image data from a frame buffer that was never written into. Let's give it that.. // (ideally the hwrenderer wouldn't do this, but the calling code is too complex for me to fix) - VkImageTransition transition0; - transition0.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - transition0.execute(fb->GetTransferCommands()); + VkImageTransition() + .AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); VkImageSubresourceRange range = {}; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -323,56 +292,38 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) value.float32[1] = 0.0f; value.float32[2] = 0.0f; value.float32[3] = 1.0f; - fb->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range); + fb->GetCommands()->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range); - VkImageTransition transition1; - transition1.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); - transition1.execute(fb->GetTransferCommands()); + VkImageTransition() + .AddImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .Execute(fb->GetCommands()->GetTransferCommands()); } } +///////////////////////////////////////////////////////////////////////////// -VkMaterial* VkMaterial::First = nullptr; - -VkMaterial::VkMaterial(FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags) +VkMaterial::VkMaterial(VulkanRenderDevice* fb, FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags), fb(fb) { - Next = First; - First = this; - if (Next) Next->Prev = this; + fb->GetDescriptorSetManager()->AddMaterial(this); } VkMaterial::~VkMaterial() { - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - DeleteDescriptors(); + if (fb) + fb->GetDescriptorSetManager()->RemoveMaterial(this); } void VkMaterial::DeleteDescriptors() { - if (auto fb = GetVulkanFrameBuffer()) + if (fb) { - auto& deleteList = fb->FrameDeleteList; - + auto deleteList = fb->GetCommands()->DrawDeleteList.get(); for (auto& it : mDescriptorSets) { - deleteList.Descriptors.push_back(std::move(it.descriptor)); + deleteList->Add(std::move(it.descriptor)); } + mDescriptorSets.clear(); } - - mDescriptorSets.clear(); -} - -void VkMaterial::ResetAllDescriptors() -{ - for (VkMaterial* cur = First; cur; cur = cur->Next) - cur->DeleteDescriptors(); - - auto fb = GetVulkanFrameBuffer(); - if (fb) - fb->GetRenderPassManager()->TextureSetPoolReset(); } VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) @@ -380,18 +331,18 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) auto base = Source(); int clampmode = state.mClampMode; int translation = state.mTranslation; + auto translationp = IsLuminosityTranslation(translation)? translation : intptr_t(GPalette.GetTranslation(GetTranslationType(translation), GetTranslationIndex(translation))); clampmode = base->GetClampMode(clampmode); for (auto& set : mDescriptorSets) { - if (set.descriptor && set.clampmode == clampmode && set.flags == translation) return set.descriptor.get(); + if (set.descriptor && set.clampmode == clampmode && set.remap == translationp) return set.descriptor.get(); } int numLayers = NumLayers(); - auto fb = GetVulkanFrameBuffer(); - auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(std::max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); + auto descriptor = fb->GetDescriptorSetManager()->AllocateTextureDescriptorSet(max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); @@ -400,34 +351,37 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) WriteDescriptors update; MaterialLayerInfo *layer; auto systex = static_cast(GetLayer(0, state.mTranslation, &layer)); - update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags); + update.AddCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), sampler, systeximage->Layout); if (!(layer->scaleFlags & CTF_Indexed)) { for (int i = 1; i < numLayers; i++) { - auto systex = static_cast(GetLayer(i, 0, &layer)); - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + 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); } } else { for (int i = 1; i < 3; i++) { - auto systex = static_cast(GetLayer(i, translation, &layer)); - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer->layerTexture, 0, layer->scaleFlags)->View.get(), sampler, systex->mImage.Layout); + 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); } numLayers = 3; } - auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); + auto dummyImage = fb->GetTextureManager()->GetNullTextureView(); for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) { - update.addCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, systex->mImage.Layout); + update.AddCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - update.updateSets(fb->device); - mDescriptorSets.emplace_back(clampmode, translation, std::move(descriptor)); + update.Execute(fb->device.get()); + mDescriptorSets.emplace_back(clampmode, translationp, std::move(descriptor)); return mDescriptorSets.back().descriptor.get(); } diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.h b/src/common/rendering/vulkan/textures/vk_hwtexture.h index 22958c494..2711bdb33 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.h @@ -9,25 +9,26 @@ #include "tarray.h" #include "hw_ihwtexture.h" -#include "volk/volk.h" +#include #include "vk_imagetransition.h" #include "hw_material.h" +#include struct FMaterialState; class VulkanDescriptorSet; class VulkanImage; class VulkanImageView; class VulkanBuffer; +class VulkanRenderDevice; class FGameTexture; class VkHardwareTexture : public IHardwareTexture { friend class VkMaterial; public: - VkHardwareTexture(int numchannels); + VkHardwareTexture(VulkanRenderDevice* fb, int numchannels); ~VkHardwareTexture(); - static void ResetAll(); void Reset(); // Software renderer stuff @@ -41,6 +42,8 @@ public: VkTextureImage *GetImage(FTexture *tex, int translation, int flags); VkTextureImage *GetDepthStencil(FTexture *tex); + VulkanRenderDevice* fb = nullptr; + std::list::iterator it; private: void CreateImage(FTexture *tex, int translation, int flags); @@ -48,10 +51,6 @@ private: void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap); static int GetMipLevels(int w, int h); - static VkHardwareTexture *First; - VkHardwareTexture *Prev = nullptr; - VkHardwareTexture *Next = nullptr; - VkTextureImage mImage; int mTexelsize = 4; @@ -60,34 +59,33 @@ private: uint8_t* mappedSWFB = nullptr; }; - class VkMaterial : public FMaterial { - static VkMaterial* First; - VkMaterial* Prev = nullptr; - VkMaterial* Next = nullptr; +public: + VkMaterial(VulkanRenderDevice* fb, FGameTexture* tex, int scaleflags); + ~VkMaterial(); + VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); + + void DeleteDescriptors() override; + + VulkanRenderDevice* fb = nullptr; + std::list::iterator it; + +private: struct DescriptorEntry { int clampmode; - int flags; + intptr_t remap; std::unique_ptr descriptor; - DescriptorEntry(int cm, int f, std::unique_ptr&& d) + DescriptorEntry(int cm, intptr_t f, std::unique_ptr&& d) { clampmode = cm; - flags = f; + remap = f; descriptor = std::move(d); } }; std::vector mDescriptorSets; - -public: - VkMaterial(FGameTexture *tex, int scaleflags); - ~VkMaterial(); - VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); - void DeleteDescriptors() override; - static void ResetAllDescriptors(); - -}; \ No newline at end of file +}; diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp index a135a3f0f..dd281e7bd 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.cpp +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.cpp @@ -22,10 +22,10 @@ #include "vk_imagetransition.h" -void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout) +VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount) { if (image->Layout == targetLayout) - return; + return *this; VkAccessFlags srcAccess = 0; VkAccessFlags dstAccess = 0; @@ -84,22 +84,23 @@ void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayo dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dstAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; default: I_FatalError("Unimplemented dst image layout transition\n"); } - barrier.addImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask); + barrier.AddImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount); needbarrier = true; image->Layout = targetLayout; + return *this; } -void VkImageTransition::execute(VulkanCommandBuffer *cmdbuffer) +void VkImageTransition::Execute(VulkanCommandBuffer *cmdbuffer) { if (needbarrier) - barrier.execute(cmdbuffer, srcStageMask, dstStageMask); + barrier.Execute(cmdbuffer, srcStageMask, dstStageMask); } ///////////////////////////////////////////////////////////////////////////// @@ -111,14 +112,14 @@ void VkTextureImage::GenerateMipmaps(VulkanCommandBuffer *cmdbuffer) int i; for (i = 1; mipWidth > 1 || mipHeight > 1; i++) { - PipelineBarrier barrier0; - barrier0.addImage(Image.get(), Layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i); - barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + PipelineBarrier() + .AddImage(Image.get(), Layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1) + .AddImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); Layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - int nextWidth = std::max(mipWidth >> 1, 1); - int nextHeight = std::max(mipHeight >> 1, 1); + int nextWidth = max(mipWidth >> 1, 1); + int nextHeight = max(mipHeight >> 1, 1); VkImageBlit blit = {}; blit.srcOffsets[0] = { 0, 0, 0 }; @@ -135,17 +136,17 @@ void VkTextureImage::GenerateMipmaps(VulkanCommandBuffer *cmdbuffer) blit.dstSubresource.layerCount = 1; cmdbuffer->blitImage(Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); - PipelineBarrier barrier1; - barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + PipelineBarrier() + .AddImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); mipWidth = nextWidth; mipHeight = nextHeight; } - PipelineBarrier barrier2; - barrier2.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + PipelineBarrier() + .AddImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.h b/src/common/rendering/vulkan/textures/vk_imagetransition.h index 916f20c24..9f1194bbf 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.h +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.h @@ -1,22 +1,27 @@ #pragma once -#include "vulkan/system/vk_objects.h" -#include "vulkan/system/vk_builders.h" +#include "zvulkan/vulkanobjects.h" +#include "zvulkan/vulkanbuilders.h" +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" #include "vulkan/renderer/vk_renderpass.h" class VkTextureImage { public: - void reset() + void Reset(VulkanRenderDevice* fb) { AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; Layout = VK_IMAGE_LAYOUT_UNDEFINED; - PPFramebuffer.reset(); + auto deletelist = fb->GetCommands()->DrawDeleteList.get(); + deletelist->Add(std::move(PPFramebuffer)); + for (auto &it : RSFramebuffers) + deletelist->Add(std::move(it.second)); RSFramebuffers.clear(); - DepthOnlyView.reset(); - View.reset(); - Image.reset(); + deletelist->Add(std::move(DepthOnlyView)); + deletelist->Add(std::move(View)); + deletelist->Add(std::move(Image)); } void GenerateMipmaps(VulkanCommandBuffer *cmdbuffer); @@ -33,8 +38,8 @@ public: class VkImageTransition { public: - void addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout); - void execute(VulkanCommandBuffer *cmdbuffer); + VkImageTransition& AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1); + void Execute(VulkanCommandBuffer *cmdbuffer); private: PipelineBarrier barrier; diff --git a/src/common/rendering/vulkan/textures/vk_pptexture.cpp b/src/common/rendering/vulkan/textures/vk_pptexture.cpp new file mode 100644 index 000000000..94114d4b6 --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_pptexture.cpp @@ -0,0 +1,114 @@ +/* +** 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_pptexture.h" +#include "vk_texture.h" +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" + +VkPPTexture::VkPPTexture(VulkanRenderDevice* fb, PPTexture *texture) : fb(fb) +{ + VkFormat format; + int pixelsize; + switch (texture->Format) + { + default: + case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break; + case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break; + case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break; + case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break; + case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break; + } + + ImageBuilder imgbuilder; + imgbuilder.Format(format); + imgbuilder.Size(texture->Width, texture->Height); + if (texture->Data) + imgbuilder.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + else + imgbuilder.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + imgbuilder.DebugName("VkPPTexture"); + if (!imgbuilder.IsFormatSupported(fb->device.get())) + I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n"); + TexImage.Image = imgbuilder.Create(fb->device.get()); + Format = format; + + TexImage.View = ImageViewBuilder() + .Image(TexImage.Image.get(), format) + .DebugName("VkPPTextureView") + .Create(fb->device.get()); + + if (texture->Data) + { + size_t totalsize = texture->Width * texture->Height * pixelsize; + + Staging = BufferBuilder() + .Size(totalsize) + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .DebugName("VkPPTextureStaging") + .Create(fb->device.get()); + + VkImageTransition() + .AddImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); + + void *data = Staging->Map(0, totalsize); + memcpy(data, texture->Data.get(), totalsize); + Staging->Unmap(); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.depth = 1; + region.imageExtent.width = texture->Width; + region.imageExtent.height = texture->Height; + fb->GetCommands()->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageTransition() + .AddImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .Execute(fb->GetCommands()->GetTransferCommands()); + } + else + { + VkImageTransition() + .AddImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) + .Execute(fb->GetCommands()->GetTransferCommands()); + } + + fb->GetTextureManager()->AddPPTexture(this); +} + +VkPPTexture::~VkPPTexture() +{ + if (fb) + fb->GetTextureManager()->RemovePPTexture(this); +} + +void VkPPTexture::Reset() +{ + if (fb) + { + TexImage.Reset(fb); + if (Staging) + fb->GetCommands()->DrawDeleteList->Add(std::move(Staging)); + } +} diff --git a/src/common/rendering/vulkan/textures/vk_pptexture.h b/src/common/rendering/vulkan/textures/vk_pptexture.h new file mode 100644 index 000000000..e0544b0d0 --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_pptexture.h @@ -0,0 +1,25 @@ + +#pragma once + +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include +#include "vulkan/textures/vk_imagetransition.h" +#include + +class VulkanRenderDevice; + +class VkPPTexture : public PPTextureBackend +{ +public: + VkPPTexture(VulkanRenderDevice* fb, PPTexture *texture); + ~VkPPTexture(); + + void Reset(); + + VulkanRenderDevice* fb = nullptr; + std::list::iterator it; + + VkTextureImage TexImage; + std::unique_ptr Staging; + VkFormat Format; +}; diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp new file mode 100644 index 000000000..01bc8f59a --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -0,0 +1,305 @@ +/* +** 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_renderbuffers.h" +#include "vulkan/renderer/vk_postprocess.h" +#include "vulkan/textures/vk_texture.h" +#include "vulkan/textures/vk_framebuffer.h" +#include "vulkan/shaders/vk_shader.h" +#include +#include +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" +#include "hw_cvars.h" + +VkRenderBuffers::VkRenderBuffers(VulkanRenderDevice* fb) : fb(fb) +{ +} + +VkRenderBuffers::~VkRenderBuffers() +{ +} + +VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount() +{ + const auto &limits = fb->device->PhysicalDevice.Properties.limits; + VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts; + + int requestedSamples = clamp((int)gl_multisample, 0, 64); + + int samples = 1; + VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT; + VkSampleCountFlags best = bit; + while (samples <= requestedSamples) + { + if (deviceSampleCounts & bit) + { + best = bit; + } + samples <<= 1; + bit <<= 1; + } + return (VkSampleCountFlagBits)best; +} + +void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int sceneHeight) +{ + VkSampleCountFlagBits samples = GetBestSampleCount(); + + if (width != mWidth || height != mHeight || mSamples != samples) + { + fb->GetCommands()->WaitForCommands(false); + fb->GetRenderPassManager()->RenderBuffersReset(); + } + + if (width != mWidth || height != mHeight) + CreatePipeline(width, height); + + if (width != mWidth || height != mHeight || mSamples != samples) + CreateScene(width, height, samples); + + mWidth = width; + mHeight = height; + mSamples = samples; + mSceneWidth = sceneWidth; + mSceneHeight = sceneHeight; +} + +void VkRenderBuffers::CreatePipelineDepthStencil(int width, int height) +{ + ImageBuilder builder; + builder.Size(width, height); + builder.Format(PipelineDepthStencilFormat); + builder.Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.IsFormatSupported(fb->device.get())) + { + PipelineDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT; + builder.Format(PipelineDepthStencilFormat); + if (!builder.IsFormatSupported(fb->device.get())) + { + I_FatalError("This device does not support any of the required depth stencil image formats."); + } + } + builder.DebugName("VkRenderBuffers.PipelineDepthStencil"); + + PipelineDepthStencil.Image = builder.Create(fb->device.get()); + PipelineDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + + PipelineDepthStencil.View = ImageViewBuilder() + .Image(PipelineDepthStencil.Image.get(), PipelineDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) + .DebugName("VkRenderBuffers.PipelineDepthStencilView") + .Create(fb->device.get()); + + PipelineDepthStencil.DepthOnlyView = ImageViewBuilder() + .Image(PipelineDepthStencil.Image.get(), PipelineDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT) + .DebugName("VkRenderBuffers.PipelineDepthView") + .Create(fb->device.get()); +} + +void VkRenderBuffers::CreatePipeline(int width, int height) +{ + for (int i = 0; i < NumPipelineImages; i++) + { + PipelineImage[i].Reset(fb); + } + PipelineDepthStencil.Reset(fb); + + CreatePipelineDepthStencil(width, height); + + VkImageTransition barrier; + barrier.AddImage(&PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); + for (int i = 0; i < NumPipelineImages; i++) + { + PipelineImage[i].Image = ImageBuilder() + .Size(width, height) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .DebugName("VkRenderBuffers.PipelineImage") + .Create(fb->device.get()); + + PipelineImage[i].View = ImageViewBuilder() + .Image(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkRenderBuffers.PipelineView") + .Create(fb->device.get()); + + barrier.AddImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + } + barrier.Execute(fb->GetCommands()->GetDrawCommands()); +} + +void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples) +{ + SceneColor.Reset(fb); + SceneDepthStencil.Reset(fb); + SceneNormal.Reset(fb); + SceneFog.Reset(fb); + + CreateSceneColor(width, height, samples); + CreateSceneDepthStencil(width, height, samples); + CreateSceneNormal(width, height, samples); + CreateSceneFog(width, height, samples); + + VkImageTransition() + .AddImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) + .AddImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true) + .AddImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) + .AddImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true) + .Execute(fb->GetCommands()->GetDrawCommands()); +} + +void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples) +{ + SceneColor.Image = ImageBuilder() + .Size(width, height) + .Samples(samples) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) + .DebugName("VkRenderBuffers.SceneColor") + .Create(fb->device.get()); + + SceneColor.View = ImageViewBuilder() + .Image(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkRenderBuffers.SceneColorView") + .Create(fb->device.get()); +} + +void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples) +{ + ImageBuilder builder; + builder.Size(width, height); + builder.Samples(samples); + builder.Format(SceneDepthStencilFormat); + builder.Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.IsFormatSupported(fb->device.get())) + { + SceneDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT; + builder.Format(SceneDepthStencilFormat); + if (!builder.IsFormatSupported(fb->device.get())) + { + I_FatalError("This device does not support any of the required depth stencil image formats."); + } + } + builder.DebugName("VkRenderBuffers.SceneDepthStencil"); + + SceneDepthStencil.Image = builder.Create(fb->device.get()); + SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + + SceneDepthStencil.View = ImageViewBuilder() + .Image(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) + .DebugName("VkRenderBuffers.SceneDepthStencilView") + .Create(fb->device.get()); + + SceneDepthStencil.DepthOnlyView = ImageViewBuilder() + .Image(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT) + .DebugName("VkRenderBuffers.SceneDepthView") + .Create(fb->device.get()); +} + +void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples) +{ + SceneFog.Image = ImageBuilder() + .Size(width, height) + .Samples(samples) + .Format(VK_FORMAT_R8G8B8A8_UNORM) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .DebugName("VkRenderBuffers.SceneFog") + .Create(fb->device.get()); + + SceneFog.View = ImageViewBuilder() + .Image(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM) + .DebugName("VkRenderBuffers.SceneFogView") + .Create(fb->device.get()); +} + +void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples) +{ + ImageBuilder builder; + builder.Size(width, height); + builder.Samples(samples); + builder.Format(SceneNormalFormat); + builder.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.IsFormatSupported(fb->device.get(), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) + { + SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; + builder.Format(SceneNormalFormat); + } + builder.DebugName("VkRenderBuffers.SceneNormal"); + + SceneNormal.Image = builder.Create(fb->device.get()); + + SceneNormal.View = ImageViewBuilder() + .Image(SceneNormal.Image.get(), SceneNormalFormat) + .DebugName("VkRenderBuffers.SceneNormalView") + .Create(fb->device.get()); +} + +VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, WhichDepthStencil stencilTest, int& framebufferWidth, int& framebufferHeight) +{ + VkTextureImage* tex = fb->GetTextureManager()->GetTexture(output.Type, output.Texture); + + VkImageView view; + std::unique_ptr* framebufferptr = nullptr; + int w, h; + if (tex) + { + VkImageTransition imageTransition; + imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture); + if (stencilTest == WhichDepthStencil::Scene) + imageTransition.AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); + + if (stencilTest == WhichDepthStencil::Pipeline) + imageTransition.AddImage(&fb->GetBuffers()->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); + + imageTransition.Execute(fb->GetCommands()->GetDrawCommands()); + + view = tex->View->view; + w = tex->Image->width; + h = tex->Image->height; + framebufferptr = &tex->PPFramebuffer; + } + else + { + view = fb->GetFramebufferManager()->SwapChain->GetImageView(fb->GetFramebufferManager()->PresentImageIndex)->view; + framebufferptr = &fb->GetFramebufferManager()->Framebuffers[fb->GetFramebufferManager()->PresentImageIndex]; + w = fb->GetFramebufferManager()->SwapChain->Width(); + h = fb->GetFramebufferManager()->SwapChain->Height(); + } + + auto& framebuffer = *framebufferptr; + if (!framebuffer) + { + FramebufferBuilder builder; + builder.RenderPass(passSetup->RenderPass.get()); + builder.Size(w, h); + builder.AddAttachment(view); + if (stencilTest == WhichDepthStencil::Scene) + builder.AddAttachment(fb->GetBuffers()->SceneDepthStencil.View.get()); + if (stencilTest == WhichDepthStencil::Pipeline) + builder.AddAttachment(fb->GetBuffers()->PipelineDepthStencil.View.get()); + builder.DebugName("PPOutputFB"); + framebuffer = builder.Create(fb->device.get()); + } + + framebufferWidth = w; + framebufferHeight = h; + return framebuffer.get(); +} diff --git a/src/common/rendering/vulkan/renderer/vk_renderbuffers.h b/src/common/rendering/vulkan/textures/vk_renderbuffers.h similarity index 71% rename from src/common/rendering/vulkan/renderer/vk_renderbuffers.h rename to src/common/rendering/vulkan/textures/vk_renderbuffers.h index 92ad9c5be..360b366ab 100644 --- a/src/common/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.h @@ -1,13 +1,23 @@ #pragma once -#include "vulkan/system/vk_objects.h" +#include "zvulkan/vulkanobjects.h" #include "vulkan/textures/vk_imagetransition.h" +class VulkanRenderDevice; +class VkPPRenderPassSetup; +class PPOutput; + +enum class WhichDepthStencil { + None, + Scene, + Pipeline, +}; + class VkRenderBuffers { public: - VkRenderBuffers(); + VkRenderBuffers(VulkanRenderDevice* fb); ~VkRenderBuffers(); void BeginFrame(int width, int height, int sceneWidth, int sceneHeight); @@ -23,25 +33,28 @@ public: VkTextureImage SceneNormal; VkTextureImage SceneFog; + VkFormat PipelineDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32; static const int NumPipelineImages = 2; + VkTextureImage PipelineDepthStencil; VkTextureImage PipelineImage[NumPipelineImages]; - VkTextureImage Shadowmap; - std::unique_ptr ShadowmapSampler; + VulkanFramebuffer* GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, WhichDepthStencil stencilTest, int& framebufferWidth, int& framebufferHeight); private: + void CreatePipelineDepthStencil(int width, int height); void CreatePipeline(int width, int height); void CreateScene(int width, int height, VkSampleCountFlagBits samples); void CreateSceneColor(int width, int height, VkSampleCountFlagBits samples); void CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples); void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples); void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples); - void CreateShadowmap(); VkSampleCountFlagBits GetBestSampleCount(); + VulkanRenderDevice* fb = nullptr; + int mWidth = 0; int mHeight = 0; int mSceneWidth = 0; diff --git a/src/common/rendering/vulkan/textures/vk_samplers.cpp b/src/common/rendering/vulkan/textures/vk_samplers.cpp index adc6dd2b4..1ce86fea0 100644 --- a/src/common/rendering/vulkan/textures/vk_samplers.cpp +++ b/src/common/rendering/vulkan/textures/vk_samplers.cpp @@ -20,16 +20,18 @@ ** */ -#include "volk/volk.h" +#include +#include +#include #include "c_cvars.h" #include "v_video.h" - #include "hw_cvars.h" -#include "vulkan/system/vk_device.h" -#include "vulkan/system/vk_builders.h" +#include "vulkan/system/vk_renderdevice.h" +#include "vulkan/system/vk_commandbuffer.h" #include "vk_samplers.h" #include "hw_material.h" #include "i_interface.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" struct VkTexFilter { @@ -37,16 +39,17 @@ struct VkTexFilter VkFilter magFilter; VkSamplerMipmapMode mipfilter; bool mipmapping; -} ; +}; -VkTexFilter TexFilter[]={ +static VkTexFilter TexFilter[] = +{ {VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, false}, {VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, true}, {VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, false}, {VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, true}, {VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_LINEAR, true}, {VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true}, - {VK_FILTER_LINEAR, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true}, + {VK_FILTER_LINEAR, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true} }; struct VkTexClamp @@ -55,89 +58,132 @@ struct VkTexClamp VkSamplerAddressMode clamp_v; }; -VkTexClamp TexClamp[] ={ +static VkTexClamp TexClamp[] = +{ { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT }, { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT }, { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE }, { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE }, }; -VkSamplerManager::VkSamplerManager(VulkanDevice *dev) +VkSamplerManager::VkSamplerManager(VulkanRenderDevice* fb) : fb(fb) { - vDevice = dev; - Create(); + CreateHWSamplers(); + CreateShadowmapSampler(); + CreateLightmapSampler(); } VkSamplerManager::~VkSamplerManager() { - Destroy(); } -void VkSamplerManager::SetTextureFilterMode() +void VkSamplerManager::ResetHWSamplers() { - Destroy(); - Create(); + DeleteHWSamplers(); + CreateHWSamplers(); } -void VkSamplerManager::Create() +void VkSamplerManager::CreateHWSamplers() { int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()? 0 : gl_texture_filter; - + for (int i = CLAMP_NONE; i <= CLAMP_XY; i++) { SamplerBuilder builder; - builder.setMagFilter(TexFilter[filter].magFilter); - builder.setMinFilter(TexFilter[filter].minFilter); - builder.setAddressMode(TexClamp[i].clamp_u, TexClamp[i].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT); - builder.setMipmapMode(TexFilter[filter].mipfilter); + builder.MagFilter(TexFilter[filter].magFilter); + builder.MinFilter(TexFilter[filter].minFilter); + builder.AddressMode(TexClamp[i].clamp_u, TexClamp[i].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT); + builder.MipmapMode(TexFilter[filter].mipfilter); if (TexFilter[filter].mipmapping) { - builder.setAnisotropy(gl_texture_filter_anisotropic); - builder.setMaxLod(100.0f); // According to the spec this value is clamped so something high makes it usable for all textures. + builder.Anisotropy(gl_texture_filter_anisotropic); + builder.MaxLod(100.0f); // According to the spec this value is clamped so something high makes it usable for all textures. } else { - builder.setMaxLod(0.25f); + builder.MaxLod(0.25f); } - mSamplers[i] = builder.create(vDevice); - mSamplers[i]->SetDebugName("VkSamplerManager.mSamplers"); - } - { - SamplerBuilder builder; - builder.setMagFilter(TexFilter[filter].magFilter); - builder.setMinFilter(TexFilter[filter].magFilter); - builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT); - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMaxLod(0.25f); - mSamplers[CLAMP_XY_NOMIP] = builder.create(vDevice); - mSamplers[CLAMP_XY_NOMIP]->SetDebugName("VkSamplerManager.mSamplers"); + builder.DebugName("VkSamplerManager.mSamplers"); + mSamplers[i] = builder.Create(fb->device.get()); } + + mSamplers[CLAMP_XY_NOMIP] = SamplerBuilder() + .MagFilter(TexFilter[filter].magFilter) + .MinFilter(TexFilter[filter].magFilter) + .AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT) + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .MaxLod(0.25f) + .DebugName("VkSamplerManager.mSamplers") + .Create(fb->device.get()); + for (int i = CLAMP_NOFILTER; i <= CLAMP_NOFILTER_XY; i++) { - SamplerBuilder builder; - builder.setMagFilter(VK_FILTER_NEAREST); - builder.setMinFilter(VK_FILTER_NEAREST); - builder.setAddressMode(TexClamp[i - CLAMP_NOFILTER].clamp_u, TexClamp[i - CLAMP_NOFILTER].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT); - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMaxLod(0.25f); - mSamplers[i] = builder.create(vDevice); - mSamplers[i]->SetDebugName("VkSamplerManager.mSamplers"); + mSamplers[i] = SamplerBuilder() + .MagFilter(VK_FILTER_NEAREST) + .MinFilter(VK_FILTER_NEAREST) + .AddressMode(TexClamp[i - CLAMP_NOFILTER].clamp_u, TexClamp[i - CLAMP_NOFILTER].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT) + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .MaxLod(0.25f) + .DebugName("VkSamplerManager.mSamplers") + .Create(fb->device.get()); } + // CAMTEX is repeating with texture filter and no mipmap + mSamplers[CLAMP_CAMTEX] = SamplerBuilder() + .MagFilter(TexFilter[filter].magFilter) + .MinFilter(TexFilter[filter].magFilter) + .AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT) + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .MaxLod(0.25f) + .DebugName("VkSamplerManager.mSamplers") + .Create(fb->device.get()); +} + +void VkSamplerManager::DeleteHWSamplers() +{ + for (auto& sampler : mSamplers) { - SamplerBuilder builder; - builder.setMagFilter(TexFilter[filter].magFilter); - builder.setMinFilter(TexFilter[filter].magFilter); - builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT); - builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); - builder.setMaxLod(0.25f); - mSamplers[CLAMP_CAMTEX] = builder.create(vDevice); - mSamplers[CLAMP_CAMTEX]->SetDebugName("VkSamplerManager.mSamplers"); + if (sampler) + fb->GetCommands()->DrawDeleteList->Add(std::move(sampler)); } } -void VkSamplerManager::Destroy() +VulkanSampler* VkSamplerManager::Get(PPFilterMode filter, PPWrapMode wrap) { - for (int i = 0; i < NUMSAMPLERS; i++) - mSamplers[i].reset(); + int index = (((int)filter) << 1) | (int)wrap; + auto& sampler = mPPSamplers[index]; + if (sampler) + return sampler.get(); + + sampler = SamplerBuilder() + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .MinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR) + .MagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR) + .AddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT) + .DebugName("VkPostprocess.mSamplers") + .Create(fb->device.get()); + + return sampler.get(); +} + +void VkSamplerManager::CreateShadowmapSampler() +{ + ShadowmapSampler = SamplerBuilder() + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST) + .MinFilter(VK_FILTER_NEAREST) + .MagFilter(VK_FILTER_NEAREST) + .AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) + .DebugName("VkRenderBuffers.ShadowmapSampler") + .Create(fb->device.get()); +} + +void VkSamplerManager::CreateLightmapSampler() +{ + LightmapSampler = SamplerBuilder() + .MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR) + .MinFilter(VK_FILTER_LINEAR) + .MagFilter(VK_FILTER_LINEAR) + .AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE) + .DebugName("VkRenderBuffers.LightmapSampler") + .Create(fb->device.get()); } diff --git a/src/common/rendering/vulkan/textures/vk_samplers.h b/src/common/rendering/vulkan/textures/vk_samplers.h index 59c49fbf4..a7f9ac68f 100644 --- a/src/common/rendering/vulkan/textures/vk_samplers.h +++ b/src/common/rendering/vulkan/textures/vk_samplers.h @@ -1,32 +1,34 @@ -#ifndef __VK_SAMPLERS_H -#define __VK_SAMPLERS_H -#include "vulkan/system/vk_objects.h" +#pragma once -class VulkanDevice; +#include "zvulkan/vulkanobjects.h" +#include + +class VulkanRenderDevice; +enum class PPFilterMode; +enum class PPWrapMode; class VkSamplerManager { - VulkanDevice *vDevice; - std::unique_ptr mSamplers[NUMSAMPLERS]; - - //void UnbindAll(); - - void Create(); - void Destroy(); - public: - - VkSamplerManager(VulkanDevice *dev); + VkSamplerManager(VulkanRenderDevice* fb); ~VkSamplerManager(); - //uint8_t Bind(int texunit, int num, int lastval); - void SetTextureFilterMode(); + void ResetHWSamplers(); VulkanSampler *Get(int no) const { return mSamplers[no].get(); } + VulkanSampler* Get(PPFilterMode filter, PPWrapMode wrap); + std::unique_ptr ShadowmapSampler; + std::unique_ptr LightmapSampler; + +private: + void CreateHWSamplers(); + void DeleteHWSamplers(); + void CreateShadowmapSampler(); + void CreateLightmapSampler(); + + VulkanRenderDevice* fb = nullptr; + std::array, NUMSAMPLERS> mSamplers; + std::array, 4> mPPSamplers; }; - - -#endif - diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp new file mode 100644 index 000000000..b7d88a08a --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -0,0 +1,253 @@ +/* +** 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_texture.h" +#include "vk_hwtexture.h" +#include "vk_pptexture.h" +#include "vk_renderbuffers.h" +#include "vulkan/renderer/vk_postprocess.h" +#include "hw_cvars.h" + +VkTextureManager::VkTextureManager(VulkanRenderDevice* fb) : fb(fb) +{ + CreateNullTexture(); + CreateShadowmap(); + CreateLightmap(); +} + +VkTextureManager::~VkTextureManager() +{ + while (!Textures.empty()) + RemoveTexture(Textures.back()); + while (!PPTextures.empty()) + RemovePPTexture(PPTextures.back()); +} + +void VkTextureManager::Deinit() +{ + while (!Textures.empty()) + RemoveTexture(Textures.back()); + while (!PPTextures.empty()) + RemovePPTexture(PPTextures.back()); +} + +void VkTextureManager::BeginFrame() +{ + if (!Shadowmap.Image || Shadowmap.Image->width != gl_shadowmap_quality) + { + Shadowmap.Reset(fb); + CreateShadowmap(); + } +} + +void VkTextureManager::AddTexture(VkHardwareTexture* texture) +{ + texture->it = Textures.insert(Textures.end(), texture); +} + +void VkTextureManager::RemoveTexture(VkHardwareTexture* texture) +{ + texture->Reset(); + texture->fb = nullptr; + Textures.erase(texture->it); +} + +void VkTextureManager::AddPPTexture(VkPPTexture* texture) +{ + texture->it = PPTextures.insert(PPTextures.end(), texture); +} + +void VkTextureManager::RemovePPTexture(VkPPTexture* texture) +{ + texture->Reset(); + texture->fb = nullptr; + PPTextures.erase(texture->it); +} + +VkTextureImage* VkTextureManager::GetTexture(const PPTextureType& type, PPTexture* pptexture) +{ + if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture) + { + int idx = fb->GetPostprocess()->GetCurrentPipelineImage(); + if (type == PPTextureType::NextPipelineTexture) + idx = (idx + 1) % VkRenderBuffers::NumPipelineImages; + + return &fb->GetBuffers()->PipelineImage[idx]; + } + else if (type == PPTextureType::PPTexture) + { + auto vktex = GetVkTexture(pptexture); + return &vktex->TexImage; + } + else if (type == PPTextureType::SceneColor) + { + return &fb->GetBuffers()->SceneColor; + } + else if (type == PPTextureType::SceneNormal) + { + return &fb->GetBuffers()->SceneNormal; + } + else if (type == PPTextureType::SceneFog) + { + return &fb->GetBuffers()->SceneFog; + } + else if (type == PPTextureType::SceneDepth) + { + return &fb->GetBuffers()->SceneDepthStencil; + } + else if (type == PPTextureType::ShadowMap) + { + return &Shadowmap; + } + else if (type == PPTextureType::SwapChain) + { + return nullptr; + } + else + { + I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type"); + return nullptr; + } +} + +VkFormat VkTextureManager::GetTextureFormat(PPTexture* texture) +{ + return GetVkTexture(texture)->Format; +} + +VkPPTexture* VkTextureManager::GetVkTexture(PPTexture* texture) +{ + if (!texture->Backend) + texture->Backend = std::make_unique(fb, texture); + return static_cast(texture->Backend.get()); +} + +void VkTextureManager::CreateNullTexture() +{ + NullTexture = ImageBuilder() + .Format(VK_FORMAT_R8G8B8A8_UNORM) + .Size(1, 1) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT) + .DebugName("VkDescriptorSetManager.NullTexture") + .Create(fb->device.get()); + + NullTextureView = ImageViewBuilder() + .Image(NullTexture.get(), VK_FORMAT_R8G8B8A8_UNORM) + .DebugName("VkDescriptorSetManager.NullTextureView") + .Create(fb->device.get()); + + PipelineBarrier() + .AddImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +} + +void VkTextureManager::CreateShadowmap() +{ + Shadowmap.Image = ImageBuilder() + .Size(gl_shadowmap_quality, 1024) + .Format(VK_FORMAT_R32_SFLOAT) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .DebugName("VkRenderBuffers.Shadowmap") + .Create(fb->device.get()); + + Shadowmap.View = ImageViewBuilder() + .Image(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT) + .DebugName("VkRenderBuffers.ShadowmapView") + .Create(fb->device.get()); + + VkImageTransition() + .AddImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true) + .Execute(fb->GetCommands()->GetDrawCommands()); +} + +void VkTextureManager::CreateLightmap() +{ + TArray data; + data.Push(0); + data.Push(0); + data.Push(0); + data.Push(0x3c00); // half-float 1.0 + SetLightmap(1, 1, data); +} + +void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const TArray& LMTextureData) +{ + int w = LMTextureSize; + int h = LMTextureSize; + int count = LMTextureCount; + int pixelsize = 8; + + Lightmap.Reset(fb); + + Lightmap.Image = ImageBuilder() + .Size(w, h, 1, count) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .DebugName("VkRenderBuffers.Lightmap") + .Create(fb->device.get()); + + Lightmap.View = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY) + .Image(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkRenderBuffers.LightmapView") + .Create(fb->device.get()); + + 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->device.get()); + + 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--) + { + *(data++) = *(src++); + *(data++) = *(src++); + *(data++) = *(src++); + *(data++) = one; + } + 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) + .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 new file mode 100644 index 000000000..16b49001a --- /dev/null +++ b/src/common/rendering/vulkan/textures/vk_texture.h @@ -0,0 +1,57 @@ + +#pragma once + +#include +#include "vulkan/textures/vk_imagetransition.h" +#include + +class VulkanRenderDevice; +class VkHardwareTexture; +class VkMaterial; +class VkPPTexture; +class VkTextureImage; +enum class PPTextureType; +class PPTexture; + +class VkTextureManager +{ +public: + VkTextureManager(VulkanRenderDevice* fb); + ~VkTextureManager(); + + void Deinit(); + + void BeginFrame(); + + void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray& LMTextureData); + + VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex); + VkFormat GetTextureFormat(PPTexture* texture); + + void AddTexture(VkHardwareTexture* texture); + void RemoveTexture(VkHardwareTexture* texture); + + void AddPPTexture(VkPPTexture* texture); + void RemovePPTexture(VkPPTexture* texture); + + VulkanImage* GetNullTexture() { return NullTexture.get(); } + VulkanImageView* GetNullTextureView() { return NullTextureView.get(); } + + VkTextureImage Shadowmap; + VkTextureImage Lightmap; + +private: + void CreateNullTexture(); + void CreateShadowmap(); + void CreateLightmap(); + + VkPPTexture* GetVkTexture(PPTexture* texture); + + VulkanRenderDevice* fb = nullptr; + + std::list Textures; + std::list PPTextures; + + std::unique_ptr NullTexture; + std::unique_ptr NullTextureView; +}; diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 5be4b48be..ac49b3a15 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -43,7 +43,7 @@ #include "texturemanager.h" #include "m_random.h" #include "v_font.h" -#include "templates.h" + extern FRandom pr_exrandom; FMemArena FxAlloc(65536); @@ -104,8 +104,8 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret if (fnc != nullptr) Class = fnc->OwningClass; } -FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate) - : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg) +FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate, const VersionInfo& info) + : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg), Version(info) { } @@ -177,12 +177,9 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) } } -// [ZZ] I find it really dumb that something called CheckReadOnly returns false for readonly. renamed. -bool FCompileContext::CheckWritable(int flags) +bool FCompileContext::IsWritable(int flags, int checkFileNo) { - if (!(flags & VARF_ReadOnly)) return false; - if (!(flags & VARF_InternalAccess)) return true; - return fileSystem.GetFileContainer(Lump) != 0; + return !(flags & VARF_ReadOnly) || ((flags & VARF_InternalAccess) && fileSystem.GetFileContainer(Lump) == checkFileNo); } FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) @@ -484,12 +481,15 @@ int EncodeRegType(ExpEmit reg) else if (reg.RegCount == 2) { regtype |= REGT_MULTIREG2; - } else if (reg.RegCount == 3) { regtype |= REGT_MULTIREG3; } + else if (reg.RegCount == 4) + { + regtype |= REGT_MULTIREG4; + } return regtype; } @@ -522,10 +522,10 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) } else { - PSymbolConstString *csym = dyn_cast(sym); - if (csym != nullptr) + PSymbolConstString *csymbol = dyn_cast(sym); + if (csymbol != nullptr) { - x = new FxConstant(csym->Str, pos); + x = new FxConstant(csymbol->Str, pos); } else { @@ -573,19 +573,20 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) // //========================================================================== -FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc) +FxVectorValue::FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, FxExpression* w, const FScriptPosition &sc) :FxExpression(EFX_VectorValue, sc) { - xyz[0] = x; - xyz[1] = y; - xyz[2] = z; + xyzw[0] = x; + xyzw[1] = y; + xyzw[2] = z; + xyzw[3] = w; isConst = false; ValueType = TypeVoid; // we do not know yet } FxVectorValue::~FxVectorValue() { - for (auto &a : xyz) + for (auto &a : xyzw) { SAFE_DELETE(a); } @@ -595,7 +596,8 @@ FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) { bool fails = false; - for (auto &a : xyz) + // Cast every scalar to float64 + for (auto &a : xyzw) { if (a != nullptr) { @@ -603,7 +605,7 @@ FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) if (a == nullptr) fails = true; else { - if (a->ValueType != TypeVector2) // a vec3 may be initialized with (vec2, z) + if (a->ValueType != TypeVector2 && a->ValueType != TypeVector3) // smaller vector can be used to initialize another vector { a = new FxFloatCast(a); a = a->Resolve(ctx); @@ -612,51 +614,89 @@ FxExpression *FxVectorValue::Resolve(FCompileContext&ctx) } } } + if (fails) { delete this; return nullptr; } - // at this point there are three legal cases: - // * two floats = vector2 - // * three floats = vector3 - // * vector2 + float = vector3 - if (xyz[0]->ValueType == TypeVector2) + + // The actual dimension of the Vector does not correspond to the amount of non-null elements in xyzw + // For example: '(asdf.xy, 1)' would be Vector3 where xyzw[0]->ValueType == TypeVector2 and xyzw[1]->ValueType == TypeFloat64 + + // Handle nesting and figure out the dimension of the vector + int vectorDimensions = 0; + + for (int i = 0; i < maxVectorDimensions && xyzw[i]; ++i) { - if (xyz[1]->ValueType != TypeFloat64 || xyz[2] != nullptr) + assert(dynamic_cast(xyzw[i])); + + if (xyzw[i]->ValueType == TypeFloat64) + { + vectorDimensions++; + } + else if (xyzw[i]->ValueType == TypeVector2 || xyzw[i]->ValueType == TypeVector3 || xyzw[i]->ValueType == TypeVector4) + { + // Solve nested vector + int regCount = xyzw[i]->ValueType->RegCount; + + if (regCount + vectorDimensions > maxVectorDimensions) + { + vectorDimensions += regCount; // Show proper number + goto too_big; + } + + // Nested initializer gets simplified + if (xyzw[i]->ExprType == EFX_VectorValue) + { + // Shifts current elements to leave space for unwrapping nested initialization + for (int l = maxVectorDimensions - 1; l > i; --l) + { + xyzw[l] = xyzw[l - regCount + 1]; + } + + auto vi = static_cast(xyzw[i]); + for (int j = 0; j < regCount; ++j) + { + xyzw[i + j] = vi->xyzw[j]; + vi->xyzw[j] = nullptr; // Preserve object after 'delete vi;' + } + delete vi; + + // We extracted something, let's iterate on that again: + --i; + continue; + } + else + { + vectorDimensions += regCount; + } + } + else { ScriptPosition.Message(MSG_ERROR, "Not a valid vector"); delete this; return nullptr; } - ValueType = TypeVector3; - if (xyz[0]->ExprType == EFX_VectorValue) - { - // If two vector initializers are nested, unnest them now. - auto vi = static_cast(xyz[0]); - xyz[2] = xyz[1]; - xyz[1] = vi->xyz[1]; - xyz[0] = vi->xyz[0]; - vi->xyz[0] = vi->xyz[1] = nullptr; // Don't delete our own expressions. - delete vi; - } } - else if (xyz[0]->ValueType == TypeFloat64 && xyz[1]->ValueType == TypeFloat64) + + switch (vectorDimensions) { - ValueType = xyz[2] == nullptr ? TypeVector2 : TypeVector3; - } - else - { - ScriptPosition.Message(MSG_ERROR, "Not a valid vector"); + case 2: ValueType = TypeVector2; break; + case 3: ValueType = TypeVector3; break; + case 4: ValueType = TypeVector4; break; + default: + too_big:; + ScriptPosition.Message(MSG_ERROR, "Vector of %d dimensions is not supported", vectorDimensions); delete this; return nullptr; } // check if all elements are constant. If so this can be emitted as a constant vector. isConst = true; - for (auto &a : xyz) + for (auto &a : xyzw) { - if (a != nullptr && !a->isConstant()) isConst = false; + if (a && !a->isConstant()) isConst = false; } return this; } @@ -674,102 +714,127 @@ static ExpEmit EmitKonst(VMFunctionBuilder *build, ExpEmit &emit) ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build) { - // no const handling here. Ultimately it's too rarely used (i.e. the only fully constant vector ever allocated in ZDoom is the 0-vector in a very few places) - // and the negatives (excessive allocation of float constants) outweigh the positives (saved a few instructions) - assert(xyz[0] != nullptr); - assert(xyz[1] != nullptr); - if (ValueType == TypeVector2) + int vectorDimensions = ValueType->RegCount; + int vectorElements = 0; + for (auto& e : xyzw) { - ExpEmit tempxval = xyz[0]->Emit(build); - ExpEmit tempyval = xyz[1]->Emit(build); - ExpEmit xval = EmitKonst(build, tempxval); - ExpEmit yval = EmitKonst(build, tempyval); - assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT); - if (yval.RegNum == xval.RegNum + 1) - { - // The results are already in two continuous registers so just return them as-is. - xval.RegCount++; - return xval; - } - else - { - // The values are not in continuous registers so they need to be copied together now. - ExpEmit out(build, REGT_FLOAT, 2); - build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); - build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum); - xval.Free(build); - yval.Free(build); - return out; - } + if (e) vectorElements++; } - else if (xyz[0]->ValueType == TypeVector2) // vec2+float + assert(vectorElements > 0 && vectorElements <= 4); + + // We got at most 4 elements + ExpEmit tempVal[4]; + ExpEmit val[4]; + + // Init ExpEmit + for (int i = 0; i < vectorElements; ++i) { - ExpEmit xyval = xyz[0]->Emit(build); - ExpEmit tempzval = xyz[1]->Emit(build); - ExpEmit zval = EmitKonst(build, tempzval); - assert(xyval.RegType == REGT_FLOAT && xyval.RegCount == 2 && zval.RegType == REGT_FLOAT); - if (zval.RegNum == xyval.RegNum + 2) - { - // The results are already in three continuous registers so just return them as-is. - xyval.RegCount++; - return xyval; - } - else - { - // The values are not in continuous registers so they need to be copied together now. - ExpEmit out(build, REGT_FLOAT, 3); - build->Emit(OP_MOVEV2, out.RegNum, xyval.RegNum); - build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); - xyval.Free(build); - zval.Free(build); - return out; - } + tempVal[i] = ExpEmit(xyzw[i]->Emit(build)); + val[i] = EmitKonst(build, tempVal[i]); } - else // 3*float + { - assert(xyz[2] != nullptr); - ExpEmit tempxval = xyz[0]->Emit(build); - ExpEmit tempyval = xyz[1]->Emit(build); - ExpEmit tempzval = xyz[2]->Emit(build); - ExpEmit xval = EmitKonst(build, tempxval); - ExpEmit yval = EmitKonst(build, tempyval); - ExpEmit zval = EmitKonst(build, tempzval); - assert(xval.RegType == REGT_FLOAT && yval.RegType == REGT_FLOAT && zval.RegType == REGT_FLOAT); - if (yval.RegNum == xval.RegNum + 1 && zval.RegNum == xval.RegNum + 2) + bool isContinuous = true; + + for (int i = 1; i < vectorElements; ++i) { - // The results are already in three continuous registers so just return them as-is. - xval.RegCount += 2; - return xval; - } - else - { - // The values are not in continuous registers so they need to be copied together now. - ExpEmit out(build, REGT_FLOAT, 3); - //Try to optimize a bit... - if (yval.RegNum == xval.RegNum + 1) + if (val[i - 1].RegNum + val[i - 1].RegCount != val[i].RegNum) { - build->Emit(OP_MOVEV2, out.RegNum, xval.RegNum); - build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); + isContinuous = false; + break; } - else if (zval.RegNum == yval.RegNum + 1) + } + + // all values are in continuous registers: + if (isContinuous) + { + val[0].RegCount = vectorDimensions; + return val[0]; + } + } + + ExpEmit out(build, REGT_FLOAT, vectorDimensions); + + { + auto emitRegMove = [&](int regsToMove, int dstRegIndex, int srcRegIndex) { + assert(dstRegIndex < vectorDimensions); + assert(srcRegIndex < vectorDimensions); + assert(regsToMove > 0 && regsToMove <= 4); + build->Emit(regsToMove == 1 ? OP_MOVEF : OP_MOVEV2 + regsToMove - 2, out.RegNum + dstRegIndex, val[srcRegIndex].RegNum); + static_assert(OP_MOVEV2 + 1 == OP_MOVEV3); + static_assert(OP_MOVEV3 + 1 == OP_MOVEV4); + }; + + int regsToPush = 0; + int nextRegNum = val[0].RegNum; + int lastElementIndex = 0; + int reg = 0; + + // Use larger MOVE OPs for any groups of registers that are continuous including those across individual xyzw[] elements + for (int elementIndex = 0; elementIndex < vectorElements; ++elementIndex) + { + int regCount = xyzw[elementIndex]->ValueType->RegCount; + + if (nextRegNum != val[elementIndex].RegNum) { - build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); - build->Emit(OP_MOVEV2, out.RegNum+1, yval.RegNum); + emitRegMove(regsToPush, reg, lastElementIndex); + + reg += regsToPush; + regsToPush = regCount; + nextRegNum = val[elementIndex].RegNum + val[elementIndex].RegCount; + lastElementIndex = elementIndex; } else { - build->Emit(OP_MOVEF, out.RegNum, xval.RegNum); - build->Emit(OP_MOVEF, out.RegNum + 1, yval.RegNum); - build->Emit(OP_MOVEF, out.RegNum + 2, zval.RegNum); + regsToPush += regCount; + nextRegNum = val[elementIndex].RegNum + val[elementIndex].RegCount; } - xval.Free(build); - yval.Free(build); - zval.Free(build); - return out; + } + + // Emit move instructions on the last register + if (regsToPush > 0) + { + emitRegMove(regsToPush, reg, lastElementIndex); } } + + for (int i = 0; i < vectorElements; ++i) + { + val[i].Free(build); + val[i].~ExpEmit(); + } + + return out; } +//========================================================================== +// +// +// +//========================================================================== + +FxQuaternionValue::FxQuaternionValue(FxExpression* x, FxExpression* y, FxExpression* z, FxExpression* w, const FScriptPosition& sc) : FxVectorValue(x, y, z, w, sc) +{ +} + +FxExpression* FxQuaternionValue::Resolve(FCompileContext& ctx) +{ + auto base = FxVectorValue::Resolve(ctx); + if (base) + { + if (base->ValueType->GetRegCount() != 4) + { + ScriptPosition.Message(MSG_ERROR, "Quat expression requires 4 arguments, got %d instead", base->ValueType->GetRegCount()); + delete base; + return nullptr; + } + + base->ValueType = TypeQuaternion; + } + return base; +} + + //========================================================================== // // @@ -1064,7 +1129,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build) { ExpEmit from = basex->Emit(build); - assert(!from.Konst); + //assert(!from.Konst); assert(basex->ValueType->GetRegType() == REGT_INT); from.Free(build); ExpEmit to(build, REGT_FLOAT); @@ -1232,7 +1297,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx) if (basex->isConstant()) { ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(soundEngine->GetSoundName(constval.GetInt()), ScriptPosition); + FxExpression *x = new FxConstant(soundEngine->GetSoundName(FSoundID::fromInt(constval.GetInt())), ScriptPosition); delete this; return x; } @@ -1408,7 +1473,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) if (basex->isConstant()) { ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(FSoundID(constval.GetString()), ScriptPosition); + FxExpression *x = new FxConstant(S_FindSound(constval.GetString()), ScriptPosition); delete this; return x; } @@ -1688,6 +1753,13 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if ((basex->IsVector2() && IsVector2()) || (basex->IsVector3() && IsVector3()) || (basex->IsVector4() && IsVector4()) || (basex->IsQuaternion() && IsQuaternion())) + { + auto x = basex; + basex = nullptr; + delete this; + return x; + } // todo: pointers to class objects. // All other types are only compatible to themselves and have already been handled above by the equality check. // Anything that falls through here is not compatible and must print an error. @@ -1753,7 +1825,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (Operand->IsNumeric() || Operand->IsVector()) + if (Operand->IsNumeric() || Operand->IsVector() || Operand->IsQuaternion()) { FxExpression *e = Operand; Operand = nullptr; @@ -1807,7 +1879,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); - if (Operand->IsNumeric() || Operand->IsVector()) + if (Operand->IsNumeric() || Operand->IsVector() || Operand->IsQuaternion()) { if (Operand->isConstant()) { @@ -1843,7 +1915,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx) ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) { - assert(ValueType == Operand->ValueType); + //assert(ValueType == Operand->ValueType); ExpEmit from = Operand->Emit(build); ExpEmit to; assert(from.Konst == 0); @@ -1880,6 +1952,10 @@ ExpEmit FxMinusSign::Emit(VMFunctionBuilder *build) build->Emit(OP_NEGV3, to.RegNum, from.RegNum); break; + case 4: + build->Emit(OP_NEGV4, to.RegNum, from.RegNum); + break; + } } return to; @@ -1964,7 +2040,7 @@ ExpEmit FxUnaryNotBitwise::Emit(VMFunctionBuilder *build) from.Free(build); ExpEmit to(build, REGT_INT); assert(!from.Konst); - + build->Emit(OP_NOT, to.RegNum, from.RegNum, 0); return to; } @@ -2391,7 +2467,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) delete this; return nullptr; } - if (!Base->IsVector() && Base->ValueType->isStruct()) + if (!Base->IsVector() && !Base->IsQuaternion() && Base->ValueType->isStruct()) { ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); delete this; @@ -2436,7 +2512,7 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) ExpEmit result; bool intconst = false; - int intconstval; + int intconstval = 0; if (Right->isConstant() && Right->ValueType->GetRegType() == REGT_INT) { @@ -2587,6 +2663,12 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) } auto VMRight = static_cast(Right); auto rets = VMRight->GetReturnTypes(); + if (Base.Size() == 1) + { + Right->ScriptPosition.Message(MSG_ERROR, "Multi-assignment with only one element in function %s", VMRight->Function->SymbolName.GetChars()); + delete this; + return nullptr; + } if (rets.Size() < Base.Size()) { Right->ScriptPosition.Message(MSG_ERROR, "Insufficient returns in function %s", VMRight->Function->SymbolName.GetChars()); @@ -2633,6 +2715,75 @@ ExpEmit FxMultiAssign::Emit(VMFunctionBuilder *build) return LocalVarContainer->Emit(build); } + +//========================================================================== +// +// +// +//========================================================================== + +FxMultiAssignDecl::FxMultiAssignDecl(FArgumentList &base, FxExpression *right, const FScriptPosition &pos) + :FxExpression(EFX_MultiAssignDecl, pos) +{ + Base = std::move(base); + Right = right; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxMultiAssignDecl::~FxMultiAssignDecl() +{ + SAFE_DELETE(Right); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxMultiAssignDecl::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Right, ctx); + if (Right->ExprType != EFX_VMFunctionCall) + { + Right->ScriptPosition.Message(MSG_ERROR, "Function call expected on right side of multi-assigment"); + delete this; + return nullptr; + } + auto VMRight = static_cast(Right); + auto rets = VMRight->GetReturnTypes(); + if (Base.Size() == 1) + { + Right->ScriptPosition.Message(MSG_ERROR, "Multi-assignment with only one element in function %s", VMRight->Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + if (rets.Size() < Base.Size()) + { + Right->ScriptPosition.Message(MSG_ERROR, "Insufficient returns in function %s", VMRight->Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + FxSequence * DeclAndAssign = new FxSequence(ScriptPosition); + const unsigned int n = Base.Size(); + for (unsigned int i = 0; i < n; i++) + { + assert(Base[i]->ExprType == EFX_Identifier); + DeclAndAssign->Add(new FxLocalVariableDeclaration(rets[i], ((FxIdentifier*)Base[i])->Identifier, nullptr, 0, Base[i]->ScriptPosition)); + } + DeclAndAssign->Add(new FxMultiAssign(Base, Right, ScriptPosition)); + Right = nullptr; + delete this; + return DeclAndAssign->Resolve(ctx); +} + + //========================================================================== // // @@ -2665,13 +2816,26 @@ FxBinary::~FxBinary() // //========================================================================== -bool FxBinary::Promote(FCompileContext &ctx, bool forceint) +bool FxBinary::Promote(FCompileContext &ctx, bool forceint, bool shiftop) { // math operations of unsigned ints results in an unsigned int. (16 and 8 bit values never get here, they get promoted to regular ints elsewhere already.) if (left->ValueType == TypeUInt32 && right->ValueType == TypeUInt32) { ValueType = TypeUInt32; } + // If one side is an unsigned 32-bit int and the other side is a signed 32-bit int, the signed side is implicitly converted to unsigned, + else if (!ctx.FromDecorate && left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0)) + { + right = new FxIntCast(right, false, false, true); + right = right->Resolve(ctx); + ValueType = TypeUInt32; + } + else if (!ctx.FromDecorate && left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32 && !shiftop && ctx.Version >= MakeVersion(4, 9, 0)) + { + left = new FxIntCast(left, false, false, true); + left = left->Resolve(ctx); + ValueType = TypeUInt32; + } else if (left->IsInteger() && right->IsInteger()) { ValueType = TypeSInt32; // Addition and subtraction forces all integer-derived types to signed int. @@ -2715,6 +2879,15 @@ bool FxBinary::Promote(FCompileContext &ctx, bool forceint) delete this; return false; } + + // shift operators are different: The left operand defines the type and the right operand must always be made unsigned + if (shiftop) + { + ValueType = left->ValueType == TypeUInt32 ? TypeUInt32 : TypeSInt32; + right = new FxIntCast(right, false, false, true); + right = right->Resolve(ctx); + } + return true; } @@ -2746,7 +2919,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) delete this; return nullptr; } - + if (compileEnvironment.CheckForCustomAddition) { auto result = compileEnvironment.CheckForCustomAddition(this, ctx); @@ -2756,15 +2929,19 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) goto goon; } } - + if (left->ValueType == TypeTextureID && right->IsInteger()) { ValueType = TypeTextureID; } + else if (left->IsQuaternion() && right->IsQuaternion()) + { + ValueType = left->ValueType; + } else if (left->IsVector() && right->IsVector()) { // a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand. - if (left->ValueType == right->ValueType || (left->ValueType == TypeVector3 && right->ValueType == TypeVector2)) + if (((left->IsVector3() || left->IsVector2()) && right->IsVector2()) || (left->IsVector3() && right->IsVector3()) || (left->IsVector4() && right->IsVector4())) { ValueType = left->ValueType; } @@ -2857,14 +3034,22 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) if (IsVector()) { assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - build->Emit(right->ValueType == TypeVector2? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum); - if (left->ValueType == TypeVector3 && right->ValueType == TypeVector2 && to.RegNum != op1.RegNum) + + build->Emit(right->IsVector4() ? OP_ADDV4_RR : right->IsVector3() ? OP_ADDV3_RR : OP_ADDV2_RR, to.RegNum, op1.RegNum, op2.RegNum); + if (left->IsVector3() && right->IsVector2() && to.RegNum != op1.RegNum) { // must move the z-coordinate build->Emit(OP_MOVEF, to.RegNum + 2, op1.RegNum + 2); } return to; } + else if (IsQuaternion()) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + assert(op1.RegCount == 4 && op2.RegCount == 4); + build->Emit(OP_ADDV4_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } else if (ValueType->GetRegType() == REGT_FLOAT) { assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); @@ -2890,7 +3075,14 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) if (IsVector()) { assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - build->Emit(right->ValueType == TypeVector2 ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + build->Emit(right->IsVector4() ? OP_SUBV4_RR : right->IsVector3() ? OP_SUBV3_RR : OP_SUBV2_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else if (IsQuaternion()) + { + assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); + assert(op1.RegCount == 4 && op2.RegCount == 4); + build->Emit(OP_SUBV4_RR, to.RegNum, op1.RegNum, op2.RegNum); return to; } else if (ValueType->GetRegType() == REGT_FLOAT) @@ -2958,7 +3150,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) return nullptr; } - if (left->IsVector() || right->IsVector()) + if (left->IsVector() || right->IsVector() || left->IsQuaternion() || right->IsQuaternion()) { switch (Operator) { @@ -2968,7 +3160,14 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) [[fallthrough]]; case '*': - if (left->IsVector() && right->IsNumeric()) + if (Operator == '*' && left->IsQuaternion() && (right->IsVector3() || right->IsQuaternion())) + { + // quat * vec3 + // quat * quat + ValueType = right->ValueType; + break; + } + else if ((left->IsVector() || left->IsQuaternion()) && right->IsNumeric()) { if (right->IsInteger()) { @@ -2983,7 +3182,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) ValueType = left->ValueType; break; } - else if (right->IsVector() && left->IsNumeric()) + else if ((right->IsVector() || right->IsQuaternion()) && left->IsNumeric()) { if (left->IsInteger()) { @@ -3083,21 +3282,37 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); - if (IsVector()) + if (Operator == '*' && left->IsQuaternion() && right->IsQuaternion()) + { + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(OP_MULQQ_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else if (Operator == '*' && left->IsQuaternion() && right->IsVector3()) + { + op1.Free(build); + op2.Free(build); + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(OP_MULQV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + return to; + } + else if (IsVector() || IsQuaternion()) { assert(Operator != '%'); - if (right->IsVector()) + if (left->IsFloat()) { std::swap(op1, op2); } int op; if (op2.Konst) { - op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RK : OP_MULVF3_RK) : (ValueType == TypeVector2 ? OP_DIVVF2_RK : OP_DIVVF3_RK); + op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RK : IsVector3() ? OP_MULVF3_RK : OP_MULVF4_RK) : (IsVector2() ? OP_DIVVF2_RK : IsVector3() ? OP_DIVVF3_RK : OP_DIVVF4_RK); } else { - op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RR : OP_MULVF3_RR) : (ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR); + op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RR : IsVector3() ? OP_MULVF3_RR : OP_MULVF4_RR) : (IsVector2() ? OP_DIVVF2_RR : IsVector3() ? OP_DIVVF3_RR : OP_DIVVF4_RR); } op1.Free(build); op2.Free(build); @@ -3310,6 +3525,59 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx) } else if (left->IsNumeric() && right->IsNumeric()) { + if (left->IsInteger() && right->IsInteger()) + { + if (ctx.Version >= MakeVersion(4, 9, 0)) + { + // We need to do more checks here to catch problem cases. + if (left->ValueType == TypeUInt32 && right->ValueType == TypeSInt32) + { + if (left->isConstant() && !right->isConstant()) + { + auto val = static_cast(left)->GetValue().GetUInt(); + if (val > INT_MAX) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant"); + } + } + else if (right->isConstant() && !left->isConstant()) + { + auto val = static_cast(right)->GetValue().GetInt(); + if (val < 0) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant"); + } + } + else if (!left->isConstant() && !right->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value"); + } + } + else if (left->ValueType == TypeSInt32 && right->ValueType == TypeUInt32) + { + if (left->isConstant() && !right->isConstant()) + { + auto val = static_cast(left)->GetValue().GetInt(); + if (val < 0) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of unsigned value with negative constant"); + } + } + else if (right->isConstant() && !left->isConstant()) + { + auto val = static_cast(right)->GetValue().GetUInt(); + if (val > INT_MAX) + { + ScriptPosition.Message(MSG_WARNING, "Comparison of signed value with out of range unsigned constant"); + } + } + else if (!left->isConstant() && !right->isConstant()) + { + ScriptPosition.Message(MSG_WARNING, "Comparison between signed and unsigned value"); + } + } + } + } Promote(ctx); } else @@ -3508,7 +3776,8 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return nullptr; } - if (left->ValueType != right->ValueType) // identical types are always comparable, if they can be placed in a register, so we can save most checks if this is the case. + // identical types are always comparable, if they can be placed in a register, so we can save most checks if this is the case. + if (left->ValueType != right->ValueType && !(left->IsVector2() && right->IsVector2()) && !(left->IsVector3() && right->IsVector3()) && !(left->IsVector4() && right->IsVector4()) && !(left->IsQuaternion() && right->IsQuaternion())) { FxExpression *x; if (left->IsNumeric() && right->ValueType == TypeString && (x = StringConstToChar(right))) @@ -3746,11 +4015,11 @@ ExpEmit FxCompareEq::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool std::swap(op1, op2); } assert(!op1.Konst); - assert(op1.RegCount >= 1 && op1.RegCount <= 3); + assert(op1.RegCount >= 1 && op1.RegCount <= 4); ExpEmit to(build, REGT_INT); - static int flops[] = { OP_EQF_R, OP_EQV2_R, OP_EQV3_R }; + static int flops[] = { OP_EQF_R, OP_EQV2_R, OP_EQV3_R, OP_EQV4_R }; instr = op1.RegType == REGT_INT ? OP_EQ_R : op1.RegType == REGT_FLOAT ? flops[op1.RegCount - 1] : OP_EQA_R; @@ -3914,7 +4183,7 @@ FxExpression *FxShift::Resolve(FCompileContext& ctx) if (left->IsNumeric() && right->IsNumeric()) { - if (!Promote(ctx, true)) return nullptr; + if (!Promote(ctx, true, true)) return nullptr; if ((left->ValueType == TypeUInt32 && ctx.Version >= MakeVersion(3, 7)) && Operator == TK_RShift) Operator = TK_URShift; } else @@ -4166,7 +4435,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) build->Emit(op1.RegType == REGT_INT ? OP_LK : op1.RegType == REGT_FLOAT ? OP_LKF : OP_LKP, nonconst.RegNum, op1.RegNum); op1 = nonconst; } - if (op1.RegType == REGT_FLOAT) cast = op1.RegCount == 1 ? CAST_F2S : op1.RegCount == 2 ? CAST_V22S : CAST_V32S; + if (op1.RegType == REGT_FLOAT) cast = op1.RegCount == 1 ? CAST_F2S : op1.RegCount == 2 ? CAST_V22S : op1.RegCount == 3 ? CAST_V32S : CAST_V42S; else if (left->ValueType == TypeUInt32) cast = CAST_U2S; else if (left->ValueType == TypeName) cast = CAST_N2S; else if (left->ValueType == TypeSound) cast = CAST_So2S; @@ -4199,7 +4468,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) build->Emit(op2.RegType == REGT_INT ? OP_LK : op2.RegType == REGT_FLOAT ? OP_LKF : OP_LKP, nonconst.RegNum, op2.RegNum); op2 = nonconst; } - if (op2.RegType == REGT_FLOAT) cast = op2.RegCount == 1 ? CAST_F2S : op2.RegCount == 2 ? CAST_V22S : CAST_V32S; + if (op2.RegType == REGT_FLOAT) cast = op2.RegCount == 1 ? CAST_F2S : op2.RegCount == 2 ? CAST_V22S : op2.RegCount == 3 ? CAST_V32S : CAST_V42S; else if (right->ValueType == TypeUInt32) cast = CAST_U2S; else if (right->ValueType == TypeName) cast = CAST_N2S; else if (right->ValueType == TypeSound) cast = CAST_So2S; @@ -4396,7 +4665,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0); build->Emit(OP_JMP, 1); build->BackpatchListToHere(no); - auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); + build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); list.DeleteAndClear(); list.ShrinkToFit(); return to; @@ -4462,7 +4731,7 @@ ExpEmit FxDotCross::Emit(VMFunctionBuilder *build) ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op1 = left->Emit(build); ExpEmit op2 = right->Emit(build); - int op = Operator == TK_Cross ? OP_CROSSV_RR : left->ValueType == TypeVector3 ? OP_DOTV3_RR : OP_DOTV2_RR; + int op = Operator == TK_Cross ? OP_CROSSV_RR : left->ValueType == TypeVector4 ? OP_DOTV4_RR : left->ValueType == TypeVector3 ? OP_DOTV3_RR : OP_DOTV2_RR; build->Emit(op, to.RegNum, op1.RegNum, op2.RegNum); op1.Free(build); op2.Free(build); @@ -4994,6 +5263,23 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx) return this; } +//========================================================================== +// +// The atan2 opcode only takes registers as parameters, so any constants +// must be loaded into registers first. +// +//========================================================================== +ExpEmit FxATan2::ToReg(VMFunctionBuilder* build, FxExpression* val) +{ + if (val->isConstant()) + { + ExpEmit reg(build, REGT_FLOAT); + build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast(val)->GetValue().GetFloat())); + return reg; + } + return val->Emit(build); +} + //========================================================================== // // @@ -5010,6 +5296,61 @@ ExpEmit FxATan2::Emit(VMFunctionBuilder *build) return out; } +//========================================================================== +// +// +// +//========================================================================== +FxATan2Vec::FxATan2Vec(FxExpression* v, const FScriptPosition& pos) + : FxExpression(EFX_ATan2Vec, pos) +{ + vval = v; +} + +//========================================================================== +// +// +// +//========================================================================== +FxATan2Vec::~FxATan2Vec() +{ + SAFE_DELETE(vval); +} + +//========================================================================== +// +// +// +//========================================================================== +FxExpression* FxATan2Vec::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(vval, ctx); + + if (!vval->IsVector()) + { + ScriptPosition.Message(MSG_ERROR, "vector value expected for parameter"); + delete this; + return nullptr; + } + ValueType = TypeFloat64; + return this; +} + +//========================================================================== +// +// +// +//========================================================================== +ExpEmit FxATan2Vec::Emit(VMFunctionBuilder* build) +{ + ExpEmit vreg = vval->Emit(build); + vreg.Free(build); + ExpEmit out(build, REGT_FLOAT); + build->Emit(OP_ATAN2, out.RegNum, vreg.RegNum + 1, vreg.RegNum); + return out; +} + //========================================================================== // // @@ -5125,16 +5466,16 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build) // Call DecoRandom to generate a random number. VMFunction *callfunc; auto sym = FindBuiltinFunction(compileEnvironment.CustomBuiltinNew != NAME_None? compileEnvironment.CustomBuiltinNew : NAME_BuiltinNew); - + assert(sym); callfunc = sym->Variants[0].Implementation; - + FunctionCallEmitter emitters(callfunc); int outerside = -1; if (!val->isConstant()) { - int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); + outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); if (outerside == FScopeBarrier::Side_Virtual) outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags); } @@ -5145,23 +5486,6 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build) return emitters.EmitCall(build); } -//========================================================================== -// -// The atan2 opcode only takes registers as parameters, so any constants -// must be loaded into registers first. -// -//========================================================================== -ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val) -{ - if (val->isConstant()) - { - ExpEmit reg(build, REGT_FLOAT); - build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast(val)->GetValue().GetFloat())); - return reg; - } - return val->Emit(build); -} - //========================================================================== // // @@ -5569,8 +5893,6 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) { - unsigned i; - assert(choices.Size() > 0); // Call BuiltinRandom to generate a random number. @@ -5603,7 +5925,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // Allocate space for the jump table. size_t jumptable = build->Emit(OP_JMP, 0); - for (i = 1; i < choices.Size(); ++i) + for (unsigned i = 1; i < choices.Size(); ++i) { build->Emit(OP_JMP, 0); } @@ -5639,7 +5961,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) } } // Backpatch each case (except the last, since it ends here) to jump to here. - for (i = 0; i < choices.Size() - 1; ++i) + for (unsigned i = 0; i < choices.Size() - 1; ++i) { build->BackpatchToHere(finishes[i]); } @@ -5888,7 +6210,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { PSymbol * sym; FxExpression *newex = nullptr; - + CHECKRESOLVED(); // Local variables have highest priority. @@ -6040,7 +6362,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } - + newex = new FxGlobalVariable(static_cast(sym), ScriptPosition); goto foundit; @@ -6070,7 +6392,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) newex = new FxCVar(cvar, ScriptPosition); goto foundit; } - + ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars()); delete this; return nullptr; @@ -6405,10 +6727,10 @@ FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = !ctx.CheckWritable(Variable->VarFlags); + if (writable != nullptr) *writable = ctx.IsWritable(Variable->VarFlags); return true; } - + ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { // 'Out' variables are actually pointers but this fact must be hidden to the script. @@ -6560,7 +6882,7 @@ FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos) bool FxGlobalVariable::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags); + if (writable != nullptr) *writable = AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo); return true; } @@ -6627,12 +6949,12 @@ FxExpression *FxCVar::Resolve(FCompileContext &ctx) switch (CVar->GetRealType()) { case CVAR_Bool: - case CVAR_DummyBool: + case CVAR_Flag: ValueType = TypeBool; break; case CVAR_Int: - case CVAR_DummyInt: + case CVAR_Mask: ValueType = TypeSInt32; break; @@ -6688,7 +7010,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) build->Emit(OP_LS, dest.RegNum, addr.RegNum, nul); break; - case CVAR_DummyBool: + case CVAR_Flag: { int *pVal; auto cv = static_cast(CVar); @@ -6701,7 +7023,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) break; } - case CVAR_DummyInt: + case CVAR_Mask: { auto cv = static_cast(CVar); build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value)); @@ -6753,7 +7075,7 @@ FxStackVariable::~FxStackVariable() bool FxStackVariable::RequestAddress(FCompileContext &ctx, bool *writable) { AddressRequested = true; - if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags); + if (writable != nullptr) *writable = AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo); return true; } @@ -6773,7 +7095,7 @@ FxExpression *FxStackVariable::Resolve(FCompileContext &ctx) ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) { int offsetreg = -1; - + if (membervar->Offset != 0) offsetreg = build->GetConstantInt((int)membervar->Offset); if (AddressRequested) @@ -6855,7 +7177,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) else if (writable != nullptr) { // [ZZ] original check. - bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) && + bool bWritable = (AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo) && (!classx->ValueType->isPointer() || !classx->ValueType->toPointer()->IsConst)); // [ZZ] implement write barrier between different scopes if (bWritable) @@ -6953,7 +7275,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) classx = nullptr; return x; } - else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers + else if (classx->ExprType == EFX_LocalVariable && (classx->IsVector() || classx->IsQuaternion())) // vectors are a special case because they are held in registers { // since this is a vector, all potential things that may get here are single float or an xy-vector. auto locvar = static_cast(classx); @@ -6965,7 +7287,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) { locvar->RegOffset = int(membervar->Offset); } - + locvar->ValueType = membervar->Type; classx = nullptr; delete this; @@ -7078,8 +7400,8 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition // //========================================================================== -FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index) -:FxExpression(EFX_ArrayElement, base->ScriptPosition) +FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index, bool nob) +:FxExpression(EFX_ArrayElement, base->ScriptPosition), noboundscheck(nob) { Array=base; index = _index; @@ -7247,7 +7569,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { PArray *arraytype; - + if (arrayispointer) { auto ptr = Array->ValueType->toPointer(); @@ -7269,7 +7591,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) ExpEmit start; ExpEmit bound; bool nestedarray = false; - + if (SizeAddr != ~0u) { bool ismeta = Array->ExprType == EFX_ClassMember && static_cast(Array)->membervar->Flags & VARF_Meta; @@ -7362,18 +7684,21 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) else { ExpEmit indexv(index->Emit(build)); - if (SizeAddr != ~0u || nestedarray) + if (!noboundscheck) // this is 'foreach' which is known to be inside the bounds. { - build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum); - bound.Free(build); - } - else if (arraytype->ElementCount > 65535) - { - build->Emit(OP_BOUND_K, indexv.RegNum, build->GetConstantInt(arraytype->ElementCount)); - } - else - { - build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + if (SizeAddr != ~0u || nestedarray) + { + build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum); + bound.Free(build); + } + else if (arraytype->ElementCount > 65535) + { + build->Emit(OP_BOUND_K, indexv.RegNum, build->GetConstantInt(arraytype->ElementCount)); + } + else + { + build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + } } if (!start.Konst) @@ -7418,7 +7743,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) else { static int LKR_Ops[] = { OP_LK_R, OP_LKF_R, OP_LKS_R, OP_LKP_R }; - assert(start.RegType == ValueType->GetRegType()); + //assert(start.RegType == ValueType->GetRegType()); ExpEmit dest(build, start.RegType); if (start.RegNum <= 255) { @@ -7671,7 +7996,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } } - + if (compileEnvironment.CheckCustomGlobalFunctions) { auto result = compileEnvironment.CheckCustomGlobalFunctions(this, ctx); @@ -7836,10 +8161,18 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_ATan2: case NAME_VectorAngle: - if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) + if (CheckArgSize(MethodName, ArgList, 1, 2, ScriptPosition)) { - func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition); - ArgList[0] = ArgList[1] = nullptr; + if (ArgList.Size() == 2) + { + func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition); + ArgList[0] = ArgList[1] = nullptr; + } + else + { + func = new FxATan2Vec(ArgList[0], ScriptPosition); + ArgList[0] = nullptr; + } } break; @@ -7855,8 +8188,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } else if (!ArgList.Size()) { - auto cls = static_cast(ctx.Class)->Descriptor; - ArgList.Push(new FxConstant(cls, NewClassPointer(cls), ScriptPosition)); + auto clss = static_cast(ctx.Class)->Descriptor; + ArgList.Push(new FxConstant(clss, NewClassPointer(clss), ScriptPosition)); } func = new FxNew(ArgList[0]); @@ -7864,6 +8197,25 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_FQuat: + case NAME_Quat: + if (CheckArgSize(MethodName, ArgList, 1, 4, ScriptPosition)) + { + // Reuse vector expression + func = new FxQuaternionValue( + ArgList[0], + ArgList.Size() >= 2 ? ArgList[1] : nullptr, + ArgList.Size() >= 3 ? ArgList[2] : nullptr, + ArgList.Size() >= 4 ? ArgList[3] : nullptr, + ScriptPosition + ); + ArgList.Clear(); + + delete this; + auto vector = func->Resolve(ctx); + return vector; + } + break; default: ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); @@ -7919,6 +8271,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) PContainerType *ccls = nullptr; + PFunction * afd_override = nullptr; + if (ctx.Class == nullptr) { // There's no way that a member function call can resolve to a constant so abort right away. @@ -7944,6 +8298,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) // because the resulting value type would cause problems in nearly every other place where identifiers are being used. // [ZZ] substitute ccls for String internal type. if (id == NAME_String) ccls = TypeStringStruct; + else if (id == NAME_Quat || id == NAME_FQuat) ccls = TypeQuaternionStruct; else ccls = FindContainerType(id, ctx); if (ccls != nullptr) static_cast(Self)->noglobal = true; } @@ -7991,7 +8346,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ValueType->isRealPointer()) { auto pointedType = Self->ValueType->toPointer()->PointedType; - if (pointedType && pointedType->isDynArray()) + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) { Self = new FxOutVarDereference(Self, Self->ScriptPosition); SAFE_RESOLVE(Self, ctx); @@ -8024,6 +8379,15 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) // Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later. // Texture builtins. + if (Self->ValueType->isNumeric()) + { + if (MethodName == NAME_ToVector) + { + Self = new FxToVector(Self); + SAFE_RESOLVE(Self, ctx); + return Self; + } + } else if (Self->ValueType == TypeTextureID) { if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) @@ -8036,7 +8400,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } // No need to create a dedicated node here, all builtins map directly to trivial operations. Self->ValueType = TypeSInt32; // all builtins treat the texture index as integer. - FxExpression *x; + FxExpression *x = nullptr; switch (MethodName.GetIndex()) { case NAME_IsValid: @@ -8069,8 +8433,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) else if (Self->IsVector()) { - // handle builtins: Vectors got 2: Length and Unit. - if (MethodName == NAME_Length || MethodName == NAME_Unit) + // handle builtins: Vectors got 5. + if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Sum || MethodName == NAME_Unit || MethodName == NAME_Angle) { if (ArgList.Size() > 0) { @@ -8083,8 +8447,40 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return x->Resolve(ctx); } + else if (MethodName == NAME_PlusZ && Self->IsVector3()) + { + if (ArgList.Size() != 1) + { + ScriptPosition.Message(MSG_ERROR, "Incorrect number of parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + auto x = new FxVectorPlusZ(Self, MethodName, ArgList[0]); + Self = nullptr; + ArgList[0] = nullptr; + delete this; + return x->Resolve(ctx); + } } + else if (Self->IsQuaternion()) + { + // Reuse vector built-ins for quaternion + if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit) + { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + auto x = new FxVectorBuiltin(Self, MethodName); + Self = nullptr; + delete this; + return x->Resolve(ctx); + } + Self->ValueType = TypeQuaternionStruct; + } else if (Self->ValueType == TypeString) { if (MethodName == NAME_Length) // This is an intrinsic because a dedicated opcode exists for it. @@ -8126,7 +8522,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (a->ValueType->isRealPointer()) { auto pointedType = a->ValueType->toPointer()->PointedType; - if (pointedType && pointedType->isDynArray()) + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) { a = new FxOutVarDereference(a, a->ScriptPosition); SAFE_RESOLVE(a, ctx); @@ -8220,7 +8616,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) member->membervar = newfield; Self = nullptr; delete this; - member->ValueType = TypeUInt32; + member->ValueType = TypeSInt32; return member; } else @@ -8233,6 +8629,193 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } } + else if(Self->IsMap()) + { + PMap * m = static_cast(Self->ValueType); + Self->ValueType = m->BackingType; + + auto mapKeyType = m->KeyType; + auto mapValueType = m->ValueType; + + bool isObjMap = mapValueType->isObjectPointer(); + + if (PFunction **Override; (Override = m->FnOverrides.CheckKey(MethodName))) + { + afd_override = *Override; + } + + // Adapted from DynArray codegen + + int idx = 0; + for (auto &a : ArgList) + { + a = a->Resolve(ctx); + if (a == nullptr) + { + delete this; + return nullptr; + } + if (a->ValueType->isRealPointer()) + { + auto pointedType = a->ValueType->toPointer()->PointedType; + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) + { + a = new FxOutVarDereference(a, a->ScriptPosition); + SAFE_RESOLVE(a, ctx); + } + } + if (isObjMap && (MethodName == NAME_Insert && idx == 1)) + { + // Null pointers are always valid. + if (!a->isConstant() || static_cast(a)->GetValue().GetPointer() != nullptr) + { + if (!a->ValueType->isObjectPointer() || + !static_cast(mapValueType)->PointedClass()->IsAncestorOf(static_cast(a->ValueType)->PointedClass())) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument"); + delete this; + return nullptr; + } + } + } + + 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 backingtype = o->BackingType; + if (mapKeyType != o->KeyType || mapValueType != o->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument"); + delete this; + return nullptr; + } + bool writable; + if (!a->RequestAddress(ctx, &writable)) + { + ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable"); + delete this; + return nullptr; + } + a->ValueType = NewPointer(backingtype); + + // Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.) + if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable) + { + auto member = static_cast(Self); + auto newfield = Create(NAME_None, backingtype, 0, member->membervar->Offset); + member->membervar = newfield; + } + } + else if (a->IsPointer() && Self->ValueType->isPointer()) + { + // the only case which must be checked up front is for pointer arrays receiving a new element. + // Since there is only one native backing class it uses a neutral void pointer as its argument, + // meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here. + if (a->ValueType != mapValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName()); + delete this; + return nullptr; + } + } + idx++; + + } + } + else if(Self->IsMapIterator()) + { + PMapIterator * mi = static_cast(Self->ValueType); + Self->ValueType = mi->BackingType; + + auto mapKeyType = mi->KeyType; + auto mapValueType = mi->ValueType; + + bool isObjMap = mapValueType->isObjectPointer(); + + if (PFunction **Override; (Override = mi->FnOverrides.CheckKey(MethodName))) + { + afd_override = *Override; + } + + // Adapted from DynArray codegen + + int idx = 0; + for (auto &a : ArgList) + { + a = a->Resolve(ctx); + if (a == nullptr) + { + delete this; + return nullptr; + } + if (a->ValueType->isRealPointer()) + { + auto pointedType = a->ValueType->toPointer()->PointedType; + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) + { + a = new FxOutVarDereference(a, a->ScriptPosition); + SAFE_RESOLVE(a, ctx); + } + } + if (isObjMap && (MethodName == NAME_SetValue && idx == 0)) + { + // Null pointers are always valid. + if (!a->isConstant() || static_cast(a)->GetValue().GetPointer() != nullptr) + { + if (!a->ValueType->isObjectPointer() || + !static_cast(mapValueType)->PointedClass()->IsAncestorOf(static_cast(a->ValueType)->PointedClass())) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument"); + delete this; + return nullptr; + } + } + } + + 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 backingtype = o->BackingType; + if (mapKeyType != o->KeyType || mapValueType != o->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument"); + delete this; + return nullptr; + } + bool writable; + if (!a->RequestAddress(ctx, &writable)) + { + ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable"); + delete this; + return nullptr; + } + a->ValueType = NewPointer(backingtype); + + // Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.) + if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable) + { + auto member = static_cast(Self); + auto newfield = Create(NAME_None, backingtype, 0, member->membervar->Offset); + member->membervar = newfield; + } + } + else if (a->IsPointer() && Self->ValueType->isPointer()) + { + // the only case which must be checked up front is for pointer arrays receiving a new element. + // Since there is only one native backing class it uses a neutral void pointer as its argument, + // meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here. + if (a->ValueType != mapValueType) + { + ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName()); + delete this; + return nullptr; + } + } + idx++; + } + } if (MethodName == NAME_GetParentClass && @@ -8307,7 +8890,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) isresolved: bool error = false; - PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate); + PFunction *afd = afd_override ? afd_override : FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate); if (error) { delete this; @@ -8369,8 +8952,8 @@ isresolved: if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual)) { auto clstype = PType::toClass(ctx.Class); - auto ccls = PType::toClass(cls); - if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor)) + auto cclss = PType::toClass(cls); + if (clstype == nullptr || cclss == nullptr || !clstype->Descriptor->IsDescendantOf(cclss->Descriptor)) { ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars()); delete this; @@ -8510,7 +9093,7 @@ VMFunction *FxVMFunctionCall::GetDirectFunction(PFunction *callingfunc, const Ve if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; return Function->Variants[0].Implementation; } - + return nullptr; } @@ -8569,7 +9152,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - + bool foundvarargs = false; PType * type = nullptr; int flag = 0; @@ -8652,12 +9235,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) else { // Vectors need special treatment because they are not normal constants - FxConstant *cs[3] = { nullptr }; + FxConstant *cs[4] = { nullptr }; for (int l = 0; l < ntype->GetRegCount(); l++) { cs[l] = new FxConstant(TypeFloat64, defaults[l + i + k + skipdefs + implicit], ScriptPosition); } - FxExpression *x = new FxVectorValue(cs[0], cs[1], cs[2], ScriptPosition); + FxExpression *x = new FxVectorValue(cs[0], cs[1], cs[2], cs[3], ScriptPosition); ArgList.Insert(i + k, x); skipdefs += ntype->GetRegCount() - 1; } @@ -8706,7 +9289,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (ArgList[i] && ArgList[i]->ValueType->isRealPointer()) { auto pointedType = ArgList[i]->ValueType->toPointer()->PointedType; - if (pointedType && pointedType->isDynArray()) + if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator())) { ArgList[i] = new FxOutVarDereference(ArgList[i], ArgList[i]->ScriptPosition); SAFE_RESOLVE(ArgList[i], ctx); @@ -8896,7 +9479,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) ArgList.ShrinkToFit(); if (!staticcall) emitters.SetVirtualReg(selfemit.RegNum); - int resultcount = vmfunc->Proto->ReturnTypes.Size() == 0 ? 0 : std::max(AssignCount, 1); + int resultcount = vmfunc->Proto->ReturnTypes.Size() == 0 ? 0 : max(AssignCount, 1); assert((unsigned)resultcount <= vmfunc->Proto->ReturnTypes.Size()); for (int i = 0; i < resultcount; i++) @@ -9058,8 +9641,26 @@ FxVectorBuiltin::~FxVectorBuiltin() FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx) { SAFE_RESOLVE(Self, ctx); - assert(Self->IsVector()); // should never be created for anything else. - ValueType = Function == NAME_Length ? TypeFloat64 : Self->ValueType; + assert(Self->IsVector() || Self->IsQuaternion()); // should never be created for anything else. + switch (Function.GetIndex()) + { + case NAME_Angle: + assert(Self->IsVector()); + case NAME_Length: + case NAME_LengthSquared: + case NAME_Sum: + ValueType = TypeFloat64; + break; + + case NAME_Unit: + ValueType = Self->ValueType; + break; + + default: + ValueType = TypeError; + assert(false); + break; + } return this; } @@ -9067,21 +9668,130 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) { ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); ExpEmit op = Self->Emit(build); + + const int vecSize = (Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2) ? 2 + : (Self->ValueType == TypeVector3 || Self->ValueType == TypeFVector3) ? 3 : 4; + if (Function == NAME_Length) { - build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum); + build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, to.RegNum, op.RegNum); } - else + else if (Function == NAME_LengthSquared) + { + build->Emit(vecSize == 2 ? OP_DOTV2_RR : vecSize == 3 ? OP_DOTV3_RR : OP_DOTV4_RR, to.RegNum, op.RegNum, op.RegNum); + } + else if (Function == NAME_Sum) + { + ExpEmit temp(build, ValueType->GetRegType(), 1); + build->Emit(OP_FLOP, to.RegNum, op.RegNum, FLOP_ABS); + build->Emit(OP_FLOP, temp.RegNum, op.RegNum + 1, FLOP_ABS); + build->Emit(OP_ADDF_RR, to.RegNum, to.RegNum, temp.RegNum); + if (vecSize > 2) + { + build->Emit(OP_FLOP, temp.RegNum, op.RegNum + 2, FLOP_ABS); + build->Emit(OP_ADDF_RR, to.RegNum, to.RegNum, temp.RegNum); + } + if (vecSize > 3) + { + build->Emit(OP_FLOP, temp.RegNum, op.RegNum + 3, FLOP_ABS); + build->Emit(OP_ADDF_RR, to.RegNum, to.RegNum, temp.RegNum); + } + } + else if (Function == NAME_Unit) { ExpEmit len(build, REGT_FLOAT); - build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum); - build->Emit(Self->ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum); + build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, len.RegNum, op.RegNum); + build->Emit(vecSize == 2 ? OP_DIVVF2_RR : vecSize == 3 ? OP_DIVVF3_RR : OP_DIVVF4_RR, to.RegNum, op.RegNum, len.RegNum); len.Free(build); } + else if (Function == NAME_Angle) + { + build->Emit(OP_ATAN2, to.RegNum, op.RegNum + 1, op.RegNum); + } op.Free(build); return to; } +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + + +FxVectorPlusZ::FxVectorPlusZ(FxExpression* self, FName name, FxExpression* z) + :FxExpression(EFX_VectorBuiltin, self->ScriptPosition), Function(name), Self(self), Z(new FxFloatCast(z)) +{ +} + +FxVectorPlusZ::~FxVectorPlusZ() +{ + SAFE_DELETE(Self); + SAFE_DELETE(Z); +} + +FxExpression* FxVectorPlusZ::Resolve(FCompileContext& ctx) +{ + SAFE_RESOLVE(Self, ctx); + SAFE_RESOLVE(Z, ctx); + assert(Self->IsVector3()); // should never be created for anything else. + ValueType = Self->ValueType; + return this; +} + +ExpEmit FxVectorPlusZ::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op = Self->Emit(build); + ExpEmit z = Z->Emit(build); + + build->Emit(OP_MOVEV2, to.RegNum, op.RegNum); + build->Emit(z.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum + 2, op.RegNum + 2, z.RegNum); + + op.Free(build); + z.Free(build); + return to; +} + + +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + + +FxToVector::FxToVector(FxExpression* self) + :FxExpression(EFX_ToVector, self->ScriptPosition), Self(new FxFloatCast(self)) +{ +} + +FxToVector::~FxToVector() +{ + SAFE_DELETE(Self); +} + +FxExpression* FxToVector::Resolve(FCompileContext& ctx) +{ + SAFE_RESOLVE(Self, ctx); + assert(Self->IsNumeric()); // should never be created for anything else. + ValueType = TypeVector2; + return this; +} + +ExpEmit FxToVector::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op = Self->Emit(build); + + build->Emit(OP_FLOP, to.RegNum, op.RegNum, FLOP_COS_DEG); + build->Emit(OP_FLOP, to.RegNum + 1, op.RegNum, FLOP_SIN_DEG); + + op.Free(build); + return to; +} + + //========================================================================== // // @@ -10228,6 +10938,77 @@ ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) return ExpEmit(); } +//========================================================================== +// +// FxForLoop +// +//========================================================================== + +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) +{ + ValueType = TypeVoid; + if (Array != nullptr) Array->NeedResult = false; + if (Array2 != nullptr) Array2->NeedResult = false; + if (Code != nullptr) Code->NeedResult = false; +} + +FxForEachLoop::~FxForEachLoop() +{ + SAFE_DELETE(Array); + SAFE_DELETE(Array2); + SAFE_DELETE(Code); +} + +FxExpression* FxForEachLoop::DoResolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Array, ctx); + SAFE_RESOLVE(Array2, ctx); + + // 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); +} + + //========================================================================== // // FxJumpStatement @@ -10348,7 +11129,7 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) else if (retCount == 1) { // If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.) - if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None) + if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None && Args[0]->ValueType != ctx.ReturnProto->ReturnTypes[0]) { Args[0] = new FxTypeCast(Args[0], ctx.ReturnProto->ReturnTypes[0], false, false); Args[0] = Args[0]->Resolve(ctx); @@ -10358,11 +11139,15 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx) } else { + assert(ctx.ReturnProto != nullptr); for (unsigned i = 0; i < retCount; i++) { - Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false); - Args[i] = Args[i]->Resolve(ctx); - if (Args[i] == nullptr) fail = true; + if (Args[i]->ValueType != ctx.ReturnProto->ReturnTypes[i]) + { + Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false); + Args[i] = Args[i]->Resolve(ctx); + if (Args[i] == nullptr) fail = true; + } } if (fail) { @@ -10511,7 +11296,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - + if (basex->ValueType != TypeName && basex->ValueType != TypeString) { ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to class type", basex->ValueType->DescriptiveName()); @@ -10528,7 +11313,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { if (Explicit) cls = FindClassType(clsname, ctx); else cls = PClass::FindClass(clsname); - + if (cls == nullptr || cls->VMType == nullptr) { /* lax */ @@ -10736,10 +11521,16 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) :FxExpression(EFX_LocalVariableDeclaration, p) { + // Local FVector isn't different from Vector + if (type == TypeFVector2) type = TypeVector2; + else if (type == TypeFVector3) type = TypeVector3; + else if (type == TypeFVector4) type = TypeVector4; + else if (type == TypeFQuaternion) type = TypeQuaternion; + ValueType = type; VarFlags = varflags; Name = name; - RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; + RegCount = type->RegCount; Init = initval; clearExpr = nullptr; } @@ -10763,7 +11554,7 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) { auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); StackOffset = sfunc->AllocExtraStack(ValueType); - + if (Init != nullptr) { ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); @@ -10784,14 +11575,23 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) delete this; return nullptr; } - SAFE_RESOLVE_OPT(Init, ctx); - if (Init->ValueType->RegType == REGT_NIL) - { - ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); - delete this; - return nullptr; - } + SAFE_RESOLVE(Init, ctx); ValueType = Init->ValueType; + if (ValueType->RegType == REGT_NIL) + { + if (Init->IsStruct()) + { + ValueType = NewPointer(ValueType); + Init = new FxTypeCast(Init, ValueType, false); + SAFE_RESOLVE(Init, ctx); + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot initialize non-scalar variable %s here", Name.GetChars()); + delete this; + return nullptr; + } + } // check for undersized ints and floats. These are not allowed as local variables. if (IsInteger() && ValueType->Align < sizeof(int)) ValueType = TypeSInt32; else if (IsFloat() && ValueType->Align < sizeof(double)) ValueType = TypeFloat64; @@ -11158,9 +11958,14 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) ClearDynamicArray(build); } + auto zero = build->GetConstantInt(0); auto elementSizeConst = build->GetConstantInt(static_cast(ValueType)->ElementSize); - auto arrOffsetReg = build->Registers[REGT_INT].Get(1); - build->Emit(OP_LK, arrOffsetReg, build->GetConstantInt(StackOffset)); + int arrOffsetReg = 0; + if (!isDynamicArray) + { + arrOffsetReg = build->Registers[REGT_POINTER].Get(1); + build->Emit(OP_ADDA_RK, arrOffsetReg, build->FramePointer.RegNum, build->GetConstantInt(StackOffset)); + } for (auto v : values) { @@ -11168,6 +11973,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) if (isDynamicArray) { + emitval.Free(build); continue; } @@ -11180,61 +11986,48 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) if (emitval.Konst) { auto constval = static_cast(v); - int regNum = build->Registers[regtype].Get(1); + auto regNum = build->Registers[regtype].Get(1); switch (regtype) { default: case REGT_INT: - build->Emit(OP_LK, regNum, build->GetConstantInt(constval->GetValue().GetInt())); - build->Emit(OP_SW_R, build->FramePointer.RegNum, regNum, arrOffsetReg); + build->Emit(OP_LK, regNum, emitval.RegNum); + build->Emit(OP_SW, arrOffsetReg, regNum, zero); break; case REGT_FLOAT: - build->Emit(OP_LKF, regNum, build->GetConstantFloat(constval->GetValue().GetFloat())); - build->Emit(OP_SDP_R, build->FramePointer.RegNum, regNum, arrOffsetReg); + build->Emit(OP_LKF, regNum, emitval.RegNum); + build->Emit(OP_SDP, arrOffsetReg, regNum, zero); break; case REGT_POINTER: - build->Emit(OP_LKP, regNum, build->GetConstantAddress(constval->GetValue().GetPointer())); - build->Emit(OP_SP_R, build->FramePointer.RegNum, regNum, arrOffsetReg); + build->Emit(OP_LKP, regNum, emitval.RegNum); + build->Emit(OP_SP, arrOffsetReg, regNum, zero); break; case REGT_STRING: - build->Emit(OP_LKS, regNum, build->GetConstantString(constval->GetValue().GetString())); - build->Emit(OP_SS_R, build->FramePointer.RegNum, regNum, arrOffsetReg); + build->Emit(OP_LKS, regNum, emitval.RegNum); + build->Emit(OP_SS, arrOffsetReg, regNum, zero); break; } + build->Registers[regtype].Return(regNum, 1); - - emitval.Free(build); } else { - switch (regtype) - { - default: - case REGT_INT: - build->Emit(OP_SW_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg); - break; - - case REGT_FLOAT: - build->Emit(OP_SDP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg); - break; - - case REGT_POINTER: - build->Emit(OP_SP_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg); - break; - - case REGT_STRING: - build->Emit(OP_SS_R, build->FramePointer.RegNum, emitval.RegNum, arrOffsetReg); - break; - } - emitval.Free(build); + build->Emit(v->ValueType->GetStoreOp(), arrOffsetReg, emitval.RegNum, zero); } + emitval.Free(build); - build->Emit(OP_ADD_RK, arrOffsetReg, arrOffsetReg, elementSizeConst); + if (!isDynamicArray) + { + build->Emit(OP_ADDA_RK, arrOffsetReg, arrOffsetReg, elementSizeConst); + } + } + if (!isDynamicArray) + { + build->Registers[REGT_POINTER].Return(arrOffsetReg, 1); } - build->Registers[REGT_INT].Return(arrOffsetReg, 1); return ExpEmit(); } @@ -11268,7 +12061,7 @@ FxExpression *FxOutVarDereference::Resolve(FCompileContext &ctx) SelfType = Self->ValueType->toPointer()->PointedType; ValueType = SelfType; - if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray()) + if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray() && !SelfType->isMap() && !SelfType->isMapIterator()) { ScriptPosition.Message(MSG_ERROR, "Cannot dereference pointer"); delete this; @@ -11297,7 +12090,7 @@ ExpEmit FxOutVarDereference::Emit(VMFunctionBuilder *build) regType = REGT_POINTER; loadOp = OP_LP; } - else if (SelfType->isDynArray()) + else if (SelfType->isDynArray() || SelfType->isMap() || SelfType->isMapIterator()) { regType = REGT_POINTER; loadOp = OP_MOVEA; diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index ac5f058ab..c12e33d3f 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -93,7 +93,7 @@ struct FCompileContext FString VersionString; FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver); - FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate); // only to be used to resolve constants! + FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate, const VersionInfo& ver); // only to be used to resolve constants! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); @@ -101,7 +101,7 @@ struct FCompileContext void HandleJumps(int token, FxExpression *handler); void CheckReturn(PPrototype *proto, FScriptPosition &pos); - bool CheckWritable(int flags); + bool IsWritable(int flags, int checkFileNo = 0); FxLocalVariableDeclaration *FindLocalVariable(FName name); }; @@ -206,7 +206,7 @@ struct ExpVal int regtype = Type->GetRegType(); return regtype == REGT_INT ? !!Int : regtype == REGT_FLOAT ? Float!=0. : false; } - + FName GetName() const { if (Type == TypeString) @@ -248,6 +248,7 @@ enum EFxType EFX_Conditional, EFX_Abs, EFX_ATan2, + EFX_ATan2Vec, EFX_New, EFX_MinMax, EFX_Random, @@ -271,6 +272,7 @@ enum EFxType EFX_WhileLoop, EFX_DoWhileLoop, EFX_ForLoop, + EFX_ForEachLoop, EFX_JumpStatement, EFX_ReturnStatement, EFX_ClassTypeCast, @@ -284,6 +286,7 @@ enum EFxType EFX_SwitchStatement, EFX_CaseStatement, EFX_VectorValue, + EFX_VectorPlusZ, EFX_VectorBuiltin, EFX_TypeCheck, EFX_DynamicCast, @@ -291,6 +294,7 @@ enum EFxType EFX_Super, EFX_StackVariable, EFX_MultiAssign, + EFX_MultiAssignDecl, EFX_StaticArray, EFX_StaticArrayVariable, EFX_CVar, @@ -305,6 +309,7 @@ enum EFxType EFX_FontCast, EFX_LocalArrayDeclaration, EFX_OutVarDereference, + EFX_ToVector, EFX_COUNT }; @@ -325,7 +330,7 @@ protected: public: virtual ~FxExpression() {} virtual FxExpression *Resolve(FCompileContext &ctx); - + virtual bool isConstant() const; virtual bool RequestAddress(FCompileContext &ctx, bool *writable); virtual PPrototype *ReturnProto(); @@ -336,12 +341,19 @@ public: bool IsFloat() const { return ValueType->isFloat(); } bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); } bool IsPointer() const { return ValueType->isPointer(); } - bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; + bool IsVector() const { return IsVector2() || IsVector3() || IsVector4(); }; + bool IsVector2() const { return ValueType == TypeVector2 || ValueType == TypeFVector2; }; + bool IsVector3() const { return ValueType == TypeVector3 || ValueType == TypeFVector3; }; + bool IsVector4() const { return ValueType == TypeVector4 || ValueType == TypeFVector4; }; + 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 IsDynamicArray() const { return (ValueType->isDynArray()); } + bool IsMap() const { return ValueType->isMap(); } + bool IsMapIterator() const { return ValueType->isMapIterator(); } + bool IsStruct() const { return ValueType->isStruct(); } bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast(ValueType)->isNative); } virtual ExpEmit Emit(VMFunctionBuilder *build); @@ -441,7 +453,7 @@ public: FxConstant(FSoundID val, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { ValueType = value.Type = TypeSound; - value.Int = val; + value.Int = val.index(); isresolved = true; } @@ -525,7 +537,7 @@ public: } ValueType = value.Type = type; } - + static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); bool isConstant() const @@ -548,26 +560,42 @@ public: class FxVectorValue : public FxExpression { - FxExpression *xyz[3]; + constexpr static int maxVectorDimensions = 4; bool isConst; // gets set to true if all element are const (used by function defaults parser) public: + FxExpression *xyzw[maxVectorDimensions]; friend class ZCCCompiler; - FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc); + FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, FxExpression* w, const FScriptPosition &sc); ~FxVectorValue(); FxExpression *Resolve(FCompileContext&); bool isConstVector(int dim) { - if (!isConst) return false; - return dim == 2 ? xyz[2] == nullptr : xyz[2] != nullptr; + if (!isConst) + return false; + return dim >= 0 && dim <= maxVectorDimensions && xyzw[dim - 1] && (dim == maxVectorDimensions || !xyzw[dim]); } ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// +// +//========================================================================== + +class FxQuaternionValue : public FxVectorValue +{ +public: + FxQuaternionValue(FxExpression* x, FxExpression* y, FxExpression* z, FxExpression* w, const FScriptPosition& sc); + FxExpression* Resolve(FCompileContext&); +}; + + //========================================================================== // // @@ -877,6 +905,17 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxMultiAssignDecl : public FxExpression +{ + FArgumentList Base; + FxExpression *Right; +public: + FxMultiAssignDecl(FArgumentList &base, FxExpression *right, const FScriptPosition &pos); + ~FxMultiAssignDecl(); + FxExpression *Resolve(FCompileContext&); + //ExpEmit Emit(VMFunctionBuilder *build); This node is transformed into Declarations + FxMultiAssign , so it won't ever be emitted itself +}; + //========================================================================== // // FxAssignSelf @@ -908,7 +947,7 @@ public: FxBinary(int, FxExpression*, FxExpression*); ~FxBinary(); - bool Promote(FCompileContext &ctx, bool forceint = false); + bool Promote(FCompileContext &ctx, bool forceint = false, bool shiftop = false); }; //========================================================================== @@ -1195,6 +1234,18 @@ private: ExpEmit ToReg(VMFunctionBuilder *build, FxExpression *val); }; +class FxATan2Vec : public FxExpression +{ + FxExpression* vval; + +public: + + FxATan2Vec(FxExpression* y, const FScriptPosition& pos); + ~FxATan2Vec(); + FxExpression* Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder* build); +}; + //========================================================================== // // @@ -1505,8 +1556,9 @@ public: bool AddressRequested; bool AddressWritable; bool arrayispointer = false; + bool noboundscheck; - FxArrayElement(FxExpression*, FxExpression*); + FxArrayElement(FxExpression*, FxExpression*, bool = false); ~FxArrayElement(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -1592,6 +1644,44 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + +class FxVectorPlusZ : public FxExpression +{ + FName Function; + FxExpression* Self; + FxExpression* Z; + +public: + + FxVectorPlusZ(FxExpression* self, FName name, FxExpression*); + ~FxVectorPlusZ(); + FxExpression* Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder* build); +}; + +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + +class FxToVector : public FxExpression +{ + FxExpression* Self; + +public: + + FxToVector(FxExpression* self); + ~FxToVector(); + FxExpression* Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder* build); +}; + //========================================================================== // // FxVectorBuiltin @@ -1864,7 +1954,7 @@ protected: : FxExpression(etype, pos) { } - + void Backpatch(VMFunctionBuilder *build, size_t loopstart, size_t loopend); FxExpression *Resolve(FCompileContext&) final; virtual FxExpression *DoResolve(FCompileContext&) = 0; @@ -1926,7 +2016,26 @@ public: FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos); ~FxForLoop(); FxExpression *DoResolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); + ExpEmit Emit(VMFunctionBuilder* build); +}; + +//========================================================================== +// +// FxForLoop +// +//========================================================================== + +class FxForEachLoop : public FxLoopStatement +{ + FName loopVarName; + FxExpression* Array; + FxExpression* Array2; + FxExpression* Code; + +public: + FxForEachLoop(FName vn, FxExpression* arrayvar, FxExpression* arrayvar2, FxExpression* code, const FScriptPosition& pos); + ~FxForEachLoop(); + FxExpression* DoResolve(FCompileContext&); }; //========================================================================== diff --git a/src/common/scripting/backend/vmbuilder.cpp b/src/common/scripting/backend/vmbuilder.cpp index 4c1401e8e..7d270af61 100644 --- a/src/common/scripting/backend/vmbuilder.cpp +++ b/src/common/scripting/backend/vmbuilder.cpp @@ -398,7 +398,7 @@ int VMFunctionBuilder::RegAvailability::Get(int count) { return -1; } - + mask = count == 32 ? ~0u : (1 << count) - 1; for (i = 0; i < 256 / 32; ++i) @@ -637,6 +637,7 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, VM_SHALF opbc) int chg; if (opa & REGT_MULTIREG2) chg = 2; else if (opa & REGT_MULTIREG3) chg = 3; + else if (opa & REGT_MULTIREG4) chg = 4; else chg = 1; ParamChange(chg); } diff --git a/src/common/scripting/core/dynarrays.cpp b/src/common/scripting/core/dynarrays.cpp index 21a362248..207c91fbc 100644 --- a/src/common/scripting/core/dynarrays.cpp +++ b/src/common/scripting/core/dynarrays.cpp @@ -114,7 +114,7 @@ template void ArrayResize(T *self, int amount) { // This must ensure that all new entries get cleared. const int fillCount = int(self->Size() - oldSize); - if (fillCount > 0) memset(&(*self)[oldSize], 0, sizeof(*self)[0] * fillCount); + if (fillCount > 0) memset((void*)&(*self)[oldSize], 0, sizeof(*self)[0] * fillCount); } } @@ -130,7 +130,7 @@ template<> unsigned int ArrayReserve(TArray *self, int amount) if (fillCount > 0) memset(&(*self)[oldSize], 0, sizeof(DObject*) * fillCount); - + return oldSize; } @@ -842,27 +842,45 @@ DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Ptr, Clear, ArrayClear) // //----------------------------------------------------- -DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Copy, ArrayCopy) +void ObjArrayCopy(FDynArray_Obj *self, FDynArray_Obj *other) { - PARAM_SELF_STRUCT_PROLOGUE(FDynArray_Obj); - PARAM_POINTER(other, FDynArray_Obj); + for (auto& elem : *other) GC::WriteBarrier(elem); *self = *other; - return 0; } -DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Move, ArrayMove) +DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Copy, ObjArrayCopy) { PARAM_SELF_STRUCT_PROLOGUE(FDynArray_Obj); PARAM_POINTER(other, FDynArray_Obj); + ObjArrayCopy(self, other); + return 0; +} + +void ObjArrayMove(FDynArray_Obj *self, FDynArray_Obj *other) +{ + for (auto& elem : *other) GC::WriteBarrier(elem); *self = std::move(*other); - return 0; } -DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Append, ArrayAppend) +DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Move, ObjArrayMove) { PARAM_SELF_STRUCT_PROLOGUE(FDynArray_Obj); PARAM_POINTER(other, FDynArray_Obj); + ObjArrayMove(self, other); + return 0; +} + +void ObjArrayAppend(FDynArray_Obj *self, FDynArray_Obj *other) +{ + for (auto& elem : *other) GC::WriteBarrier(elem); self->Append(*other); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Append, ObjArrayAppend) +{ + PARAM_SELF_STRUCT_PROLOGUE(FDynArray_Obj); + PARAM_POINTER(other, FDynArray_Obj); + ObjArrayAppend(self, other); return 0; } diff --git a/src/common/scripting/core/imports.cpp b/src/common/scripting/core/imports.cpp index 6db68bc46..c5a8cf9c5 100644 --- a/src/common/scripting/core/imports.cpp +++ b/src/common/scripting/core/imports.cpp @@ -175,7 +175,7 @@ static int fieldcmp(const void * a, const void * b) void InitImports() { - auto fontstruct = NewStruct("FFont", nullptr, true); + auto fontstruct = NewStruct("Font", nullptr, true); fontstruct->Size = sizeof(FFont); fontstruct->Align = alignof(FFont); NewPointer(fontstruct, false)->InstallHandlers( diff --git a/src/common/scripting/core/maps.cpp b/src/common/scripting/core/maps.cpp new file mode 100644 index 000000000..07522e2e1 --- /dev/null +++ b/src/common/scripting/core/maps.cpp @@ -0,0 +1,610 @@ +#include "tarray.h" +#include "dobject.h" +#include "zstring.h" +#include "vm.h" +#include "types.h" +#include "v_draw.h" +#include "maps.h" + + +//========================================================================== +// +// MAP_GC_WRITE_BARRIER +// +//========================================================================== + + +#define MAP_GC_WRITE_BARRIER(x) { \ + TMapIterator it(*x);\ + typename M::Pair * p;\ + while(it.NextPair(p)){\ + GC::WriteBarrier(p->Value);\ + }\ +} + + +//========================================================================== +// +// MapCopy +// +//========================================================================== + + +template void MapCopy(M * self, M * other) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(other); + } + *self = *other; // how does this handle self->info? TODO double check. + self->info->rev++; +} + + +//========================================================================== +// +// MapMove +// +//========================================================================== + + +template void MapMove(M * self, M * other) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(other); + } + self->TransferFrom(*other); + self->info->rev++; + other->info->rev++; +} + + +//========================================================================== +// +// MapSwap +// +//========================================================================== + + +template void MapSwap(M * self, M * other) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(other); + } + self->Swap(*other); + self->info->rev++; + other->info->rev++; +} + + +//========================================================================== +// +// MapClear +// +//========================================================================== + + +template void MapClear(M * self) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(self); + } + self->Clear(); + self->info->rev++; +} + + +//========================================================================== +// +// +// +//========================================================================== + + +template +using expand_types_vm = +std::conditional_t || std::is_same_v, uint32_t , /* expand 8/16-bit to 32-bit */ + std::conditional_t , double , /* expand float to double */ + std::conditional_t , const FString & , T>>>; /* change String to String ref */ + +template unsigned int MapCountUsed(M * self) +{ + return self->CountUsed(); +} + +template expand_types_vm MapGet(M * self,expand_types_vm key) +{ + typename M::ValueType * v = self->CheckKey(key); + if (v) + { + if constexpr(std::is_same_v) + { + return GC::ReadBarrier(*v); + } + else + { + return *v; + } + } + else + { + typename M::ValueType n {}; + self->Insert(key,n); + self->info->rev++; // invalidate iterators + return n; + } +} + +template void MapGetString(M * self,expand_types_vm key, FString &out) +{ + FString * v = self->CheckKey(key); + if (v) { + out = *v; + } + else + { + out = FString(); + self->Insert(key,out); + self->info->rev++; // invalidate iterators + } +} + +template expand_types_vm MapGetIfExists(M * self,expand_types_vm key) +{ + typename M::ValueType * v = self->CheckKey(key); + if (v) { + if constexpr(std::is_same_v) + { + return GC::ReadBarrier(*v); + } + else + { + return *v; + } + } + else + { + return {}; + } +} + +template void MapGetIfExistsString(M * self,expand_types_vm key, FString &out) +{ + FString * v = self->CheckKey(key); + if (v) { + out = *v; + } + else + { + out = FString(); + } +} + +template int MapCheckKey(M * self, expand_types_vm key) +{ + return self->CheckKey(key) != nullptr; +} + +template expand_types_vm MapCheckValue(M * self,expand_types_vm key, int * exists) +{ + typename M::ValueType * v = self->CheckKey(key); + if ((*exists = !!v)) { + if constexpr(std::is_same_v) + { + return GC::ReadBarrier(*v); + } + else + { + return *v; + } + } + else + { + return {}; + } +} + +template void MapCheckValueString(M * self,expand_types_vm key, int * exists, FString &out) +{ + FString * v = self->CheckKey(key); + if ((*exists = !!v)) { + out = *v; + } + else + { + out = FString(); + } +} + + +//========================================================================== +// +// MapInsert +// +//========================================================================== + + +template void MapInsert(M * self, expand_types_vm key, expand_types_vm value) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(self); + GC::WriteBarrier(value); + } + + if constexpr(std::is_same_v) + { + self->Insert(key,static_cast(value)); + } + else + { + self->Insert(key, value); + } + self->info->rev++; // invalidate iterators +} + + +//========================================================================== +// +// +// +//========================================================================== + + +template void MapInsertNew(M * self, expand_types_vm key) +{ + if constexpr(std::is_same_v) + { + MAP_GC_WRITE_BARRIER(self); + } + self->Insert(key,{}); + self->info->rev++; // invalidate iterators +} + +template void MapRemove(M * self, expand_types_vm key) +{ + self->Remove(key); + self->info->rev++; // invalidate iterators +} + + +//========================================================================== +// +// +// +//========================================================================== + + +template int MapIteratorInit(I * self, M * other) +{ + return self->Init(*other); +} + +template int MapIteratorReInit(I * self) +{ + return self->ReInit(); +} + +template int MapIteratorValid(I * self) +{ + return self->Valid(); +} + +template int MapIteratorNext(I * self) +{ + return self->Next(); +} + +template expand_types_vm MapIteratorGetKey(I * self) +{ + return self->GetKey(); +} + +template void MapIteratorGetKeyString(I * self, FString &out) +{ + out = self->GetKey(); +} + +template expand_types_vm MapIteratorGetValue(I * self) +{ + if constexpr(std::is_same_v) + { + return GC::ReadBarrier(self->GetValue()); + } + else + { + return self->GetValue(); + } +} + +template void MapIteratorGetValueString(I * self, FString &out) +{ + out = self->GetValue(); +} + +template void MapIteratorSetValue(I * self, expand_types_vm value) +{ + auto & val = self->GetValue(); + if constexpr(std::is_same_v) + { + GC::WriteBarrier(val); + GC::WriteBarrier(value); + } + + if constexpr(std::is_same_v) + { + val = static_cast(value); + } + else + { + val = value; + } +} + + +//========================================================================== +// +// +// +//========================================================================== + +#define PARAM_VOIDPOINTER(X) PARAM_POINTER( X , void ) +#define PARAM_OBJPOINTER(X) PARAM_OBJECT( X , DObject ) + +#define _DEF_MAP( name, key_type, value_type, PARAM_KEY, PARAM_VALUE ) \ + typedef ZSMap name;\ + DEFINE_ACTION_FUNCTION_NATIVE( name , Copy , MapCopy< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_POINTER( other, name ); \ + MapCopy(self , other); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Move , MapMove< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_POINTER( other, name ); \ + MapMove(self , other); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Swap , MapSwap< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_POINTER( other, name ); \ + MapSwap(self , other); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Clear , MapClear< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + MapClear(self); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, CountUsed, MapCountUsed< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_INT( MapCountUsed(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, CheckKey, MapCheckKey< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + ACTION_RETURN_BOOL( MapCheckKey(self, key) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, Insert, MapInsert< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + PARAM_VALUE( value ); \ + MapInsert(self, key, value); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, InsertNew, MapInsertNew< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + MapInsertNew(self, key); \ + return 0; \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, Remove, MapRemove< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + MapRemove(self, key); \ + return 0; \ + } + +#define DEF_MAP_X_X( name, key_type, value_type, PARAM_KEY, PARAM_VALUE , ACTION_RETURN_VALUE ) \ + _DEF_MAP( name , key_type , value_type , PARAM_KEY , PARAM_VALUE ) \ + DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGet< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + ACTION_RETURN_VALUE( MapGet(self, key) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, GetIfExists, MapGetIfExists< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + ACTION_RETURN_VALUE( MapGetIfExists(self, key) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, CheckValue, MapCheckValue< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + PARAM_OUTPOINTER( exists, int); \ + ACTION_RETURN_VALUE( MapCheckValue(self, key, exists) ); \ + } + +#define DEF_MAP_X_S( name, key_type, PARAM_KEY ) \ + _DEF_MAP( name , key_type , FString , PARAM_KEY , PARAM_STRING ) \ + DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGetString< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + FString out; \ + MapGetString(self, key, out); \ + ACTION_RETURN_STRING( out ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, GetIfExists, MapGetIfExistsString< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + FString out; \ + MapGetIfExistsString(self, key, out); \ + ACTION_RETURN_STRING( out ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name, CheckValue, MapCheckValueString< name >) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_KEY( key ); \ + PARAM_OUTPOINTER( exists, int); \ + FString out; \ + MapCheckValueString(self, key, exists, out); \ + ACTION_RETURN_STRING( out ); \ + } + +#define COMMA , + +#define _DEF_MAP_IT( map_name , name, key_type, value_type, PARAM_VALUE ) \ + typedef ZSMapIterator name; \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Init , MapIteratorInit< name COMMA map_name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_POINTER( other, map_name ); \ + ACTION_RETURN_BOOL( MapIteratorInit(self , other) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , ReInit , MapIteratorReInit< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_BOOL( MapIteratorReInit(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Valid , MapIteratorValid< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_BOOL( MapIteratorValid(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , Next , MapIteratorNext< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_BOOL( MapIteratorNext(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , SetValue , MapIteratorSetValue< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + PARAM_VALUE( value ); \ + MapIteratorSetValue(self, value); \ + return 0; \ + } +/* + DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_KEY( MapIteratorGetKey(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \ + } \ +*/ + +#define DEF_MAP_IT_I_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + _DEF_MAP_IT( map_name , name , uint32_t , value_type , PARAM_VALUE ) \ + DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_INT( MapIteratorGetKey(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \ + } + +#define DEF_MAP_IT_S_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + _DEF_MAP_IT( map_name , name , FString , value_type , PARAM_VALUE ) \ + DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKeyString< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + FString out; \ + MapIteratorGetKeyString(self , out); \ + ACTION_RETURN_STRING( out ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( name ); \ + ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \ + } + +#define DEF_MAP_IT_I_S() \ + _DEF_MAP_IT( FMap_I32_Str , FMapIterator_I32_Str , uint32_t , FString , PARAM_STRING ) \ + DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetKey , MapIteratorGetKey< FMapIterator_I32_Str > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \ + ACTION_RETURN_INT( MapIteratorGetKey(self) ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetValue , MapIteratorGetValueString< FMapIterator_I32_Str > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \ + FString out; \ + MapIteratorGetValueString(self , out); \ + ACTION_RETURN_STRING( out ); \ + } + +#define DEF_MAP_IT_S_S() \ + _DEF_MAP_IT( FMap_Str_Str , FMapIterator_Str_Str , FString , FString , PARAM_STRING ) \ + DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetKey , MapIteratorGetKeyString< FMapIterator_Str_Str > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \ + FString out; \ + MapIteratorGetKeyString(self , out); \ + ACTION_RETURN_STRING( out ); \ + } \ + DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetValue , MapIteratorGetValueString< FMapIterator_Str_Str > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \ + FString out; \ + MapIteratorGetValueString(self , out); \ + ACTION_RETURN_STRING( out ); \ + } + + + +#define DEFINE_MAP_AND_IT_I_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + DEF_MAP_X_X( FMap_ ## name , uint32_t , value_type , PARAM_INT , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + DEF_MAP_IT_I_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) + + +#define DEFINE_MAP_AND_IT_S_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + DEF_MAP_X_X( FMap_ ## name , FString , value_type , PARAM_STRING , PARAM_VALUE , ACTION_RETURN_VALUE ) \ + DEF_MAP_IT_S_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) + +#define DEFINE_MAP_AND_IT_I_S() \ + DEF_MAP_X_S( FMap_I32_Str , uint32_t , PARAM_INT ) \ + DEF_MAP_IT_I_S() + +#define DEFINE_MAP_AND_IT_S_S() \ + DEF_MAP_X_S( FMap_Str_Str , FString , PARAM_STRING ) \ + DEF_MAP_IT_S_S() + +DEFINE_MAP_AND_IT_I_X(I32_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_I_X(I32_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_I_X(I32_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_I_X(I32_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT); +DEFINE_MAP_AND_IT_I_X(I32_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT); +DEFINE_MAP_AND_IT_I_X(I32_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT); +DEFINE_MAP_AND_IT_I_X(I32_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER); +DEFINE_MAP_AND_IT_I_S(); + +DEFINE_MAP_AND_IT_S_X(Str_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_S_X(Str_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_S_X(Str_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT); +DEFINE_MAP_AND_IT_S_X(Str_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT); +DEFINE_MAP_AND_IT_S_X(Str_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT); +DEFINE_MAP_AND_IT_S_X(Str_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT); +DEFINE_MAP_AND_IT_S_X(Str_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER); +DEFINE_MAP_AND_IT_S_S(); \ No newline at end of file diff --git a/src/common/scripting/core/maps.h b/src/common/scripting/core/maps.h new file mode 100644 index 000000000..ed303537b --- /dev/null +++ b/src/common/scripting/core/maps.h @@ -0,0 +1,110 @@ +#pragma once + +#include +#include "tarray.h" +#include "refcounted.h" + +class ZSMapInfo : public RefCountedBase +{ +public: + void * self = nullptr; + int rev = 0; +}; + +struct ZSFMap : FMap { + RefCountedPtr info; +}; + +template +class ZSMap : public TMap +{ +public: + RefCountedPtr info; + ZSMap() : + TMap(), info(new ZSMapInfo) + { + info->self = this; + } + ~ZSMap() + { + info->self = nullptr; + } +}; + +template +struct ZSMapIterator +{ + RefCountedPtr info; + TMapIterator *it = nullptr; + typename ZSMap::Pair *p = nullptr; + + typedef KT KeyType; + typedef VT ValueType; + + int rev = 0; + + ~ZSMapIterator() + { + if(it) delete it; + } + + bool Valid() + { + return it && p && info.get() && info->self && info->rev == rev; + } + + bool ReInit() + { + if(info.get() && info->self) { + if(it) delete it; + it = new TMapIterator(*static_cast*>(info->self)); + rev = info->rev; + p = nullptr; + return true; + } + return false; + } + + bool Init(ZSMap &m) + { + info = m.info; + return ReInit(); + } + + bool Next() + { + if(it && info.get() && info->self && info->rev == rev) + { + p = nullptr; + return it->NextPair(p); + } + else + { + ThrowAbortException(X_FORMAT_ERROR,"MapIterator::Next called from invalid iterator"); + } + } + + VT& GetValue() + { + if(p && info.get() && info->self && info->rev == rev) + { + return p->Value; + } + else + { + ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetValue called from invalid iterator" : "MapIterator::GetValue called from invalid position"); + } + } + + const KT& GetKey() + { + if(p && info.get() && info->self && info->rev == rev) + { + return p->Key; + } + else + { + ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetKey called from invalid iterator" : "MapIterator::GetKey called from invalid position"); + } + } +}; \ No newline at end of file diff --git a/src/common/scripting/core/scopebarrier.h b/src/common/scripting/core/scopebarrier.h index fb931d223..b5eeae78f 100644 --- a/src/common/scripting/core/scopebarrier.h +++ b/src/common/scripting/core/scopebarrier.h @@ -46,7 +46,7 @@ struct FScopeBarrier // static int FlagsFromSide(int side); static EScopeFlags ObjectFlagsFromSide(int side); - + // used for errors static const char* StringFromSide(int side); diff --git a/src/common/scripting/core/symbols.cpp b/src/common/scripting/core/symbols.cpp index c6e38551f..d293cbbee 100644 --- a/src/common/scripting/core/symbols.cpp +++ b/src/common/scripting/core/symbols.cpp @@ -35,7 +35,7 @@ #include #include "dobject.h" -#include "templates.h" + #include "serializer.h" #include "types.h" #include "vm.h" @@ -137,7 +137,6 @@ PField::PField() { } - PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitvalue) : PSymbol(name), Offset(offset), Type(type), Flags(flags) { @@ -331,10 +330,12 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym) // //========================================================================== -PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align) +PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align, int fileno) { PField *field = Create(name, type, flags); + field->mDefFileNo = fileno; + // The new field is added to the end of this struct, alignment permitting. field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1); @@ -345,7 +346,7 @@ PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned // its fields. if (Align != nullptr) { - *Align = MAX(*Align, type->Align); + *Align = max(*Align, type->Align); } if (AddSymbol(field) == nullptr) @@ -365,10 +366,12 @@ PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned // //========================================================================== -PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue) +PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue, int fileno) { PField *field = Create(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue); + field->mDefFileNo = fileno; + if (AddSymbol(field) == nullptr) { // name is already in use field->Destroy(); diff --git a/src/common/scripting/core/symbols.h b/src/common/scripting/core/symbols.h index 38412c078..de5caaae9 100644 --- a/src/common/scripting/core/symbols.h +++ b/src/common/scripting/core/symbols.h @@ -78,6 +78,7 @@ public: uint32_t Flags; int BitValue; FString DeprecationMessage; + int mDefFileNo = 0; protected: PField(); }; @@ -212,8 +213,8 @@ struct PSymbolTable // a symbol with the same name is already in the table. This symbol is // not copied and will be freed when the symbol table is destroyed. PSymbol *AddSymbol (PSymbol *sym); - PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr); - PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue); + PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr, int fileno = 0); + PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue, int fileno = 0); bool ReadFields(FSerializer &ar, void *addr, const char *TypeName) const; void WriteFields(FSerializer &ar, const void *addr, const void *def = nullptr) const; @@ -272,4 +273,3 @@ struct AFuncDesc; struct FieldDesc; AFuncDesc *FindFunction(PContainerType *cls, const char * string); FieldDesc *FindField(PContainerType *cls, const char * string); -void SetImplicitArgs(TArray* args, TArray* argflags, TArray* argnames, PContainerType* cls, uint32_t funcflags, int useflags); diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 260aff106..6c40aa5f0 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -33,11 +33,14 @@ ** */ +#include + #include "vmintern.h" #include "s_soundinternal.h" #include "types.h" #include "printf.h" #include "textureid.h" +#include "maps.h" FTypeTable TypeTable; @@ -61,8 +64,15 @@ PPointer *TypeFont; PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; +PStruct* TypeVector4; +PStruct* TypeQuaternion; +PStruct* TypeFVector2; +PStruct* TypeFVector3; +PStruct* TypeFVector4; +PStruct* TypeFQuaternion; PStruct *TypeColorStruct; PStruct *TypeStringStruct; +PStruct* TypeQuaternionStruct; PPointer *TypeNullPtr; PPointer *TypeVoidPtr; @@ -176,7 +186,7 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray //========================================================================== // -// PType :: SetDefaultValue +// PType :: SetPointer* // //========================================================================== @@ -188,6 +198,10 @@ void PType::SetPointerArray(void *base, unsigned offset, TArray *stroffs { } +void PType::SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) +{ +} + //========================================================================== // // PType :: InitializeValue @@ -310,6 +324,7 @@ void PType::StaticInit() TypeVoidPtr = NewPointer(TypeVoid, false); 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); TypeFont = NewPointer(NewStruct("Font", nullptr, true)); #ifdef __BIG_ENDIAN__ TypeColorStruct->AddField(NAME_a, TypeUInt8); @@ -332,6 +347,7 @@ void PType::StaticInit() TypeVector2->moveOp = OP_MOVEV2; TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegCount = 2; + TypeVector2->isOrdered = true; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -345,7 +361,98 @@ void PType::StaticInit() TypeVector3->moveOp = OP_MOVEV3; TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegCount = 3; + TypeVector3->isOrdered = true; + TypeVector4 = new PStruct(NAME_Vector4, nullptr); + TypeVector4->AddField(NAME_X, TypeFloat64); + TypeVector4->AddField(NAME_Y, TypeFloat64); + TypeVector4->AddField(NAME_Z, TypeFloat64); + TypeVector4->AddField(NAME_W, TypeFloat64); + // allow accessing xyz as a vector3. This is not supposed to be serialized so it's marked transient + TypeVector4->Symbols.AddSymbol(Create(NAME_XYZ, TypeVector3, VARF_Transient, 0)); + TypeVector4->Symbols.AddSymbol(Create(NAME_XY, TypeVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeVector4, NAME_Struct); + TypeVector4->loadOp = OP_LV4; + TypeVector4->storeOp = OP_SV4; + TypeVector4->moveOp = OP_MOVEV4; + TypeVector4->RegType = REGT_FLOAT; + TypeVector4->RegCount = 4; + TypeVector4->isOrdered = true; + + + TypeFVector2 = new PStruct(NAME_FVector2, nullptr); + TypeFVector2->AddField(NAME_X, TypeFloat32); + TypeFVector2->AddField(NAME_Y, TypeFloat32); + TypeTable.AddType(TypeFVector2, NAME_Struct); + TypeFVector2->loadOp = OP_LFV2; + TypeFVector2->storeOp = OP_SFV2; + TypeFVector2->moveOp = OP_MOVEV2; + TypeFVector2->RegType = REGT_FLOAT; + TypeFVector2->RegCount = 2; + TypeFVector2->isOrdered = true; + + TypeFVector3 = new PStruct(NAME_FVector3, nullptr); + TypeFVector3->AddField(NAME_X, TypeFloat32); + TypeFVector3->AddField(NAME_Y, TypeFloat32); + TypeFVector3->AddField(NAME_Z, TypeFloat32); + // allow accessing xy as a vector2 + TypeFVector3->Symbols.AddSymbol(Create(NAME_XY, TypeFVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeFVector3, NAME_Struct); + TypeFVector3->loadOp = OP_LFV3; + TypeFVector3->storeOp = OP_SFV3; + TypeFVector3->moveOp = OP_MOVEV3; + TypeFVector3->RegType = REGT_FLOAT; + TypeFVector3->RegCount = 3; + TypeFVector3->isOrdered = true; + + TypeFVector4 = new PStruct(NAME_FVector4, nullptr); + TypeFVector4->AddField(NAME_X, TypeFloat32); + TypeFVector4->AddField(NAME_Y, TypeFloat32); + TypeFVector4->AddField(NAME_Z, TypeFloat32); + TypeFVector4->AddField(NAME_W, TypeFloat32); + // allow accessing xyz as a vector3 + TypeFVector4->Symbols.AddSymbol(Create(NAME_XYZ, TypeFVector3, VARF_Transient, 0)); + TypeFVector4->Symbols.AddSymbol(Create(NAME_XY, TypeFVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeFVector4, NAME_Struct); + TypeFVector4->loadOp = OP_LFV4; + TypeFVector4->storeOp = OP_SFV4; + TypeFVector4->moveOp = OP_MOVEV4; + TypeFVector4->RegType = REGT_FLOAT; + TypeFVector4->RegCount = 4; + TypeFVector4->isOrdered = true; + + + TypeQuaternion = new PStruct(NAME_Quat, nullptr); + TypeQuaternion->AddField(NAME_X, TypeFloat64); + TypeQuaternion->AddField(NAME_Y, TypeFloat64); + TypeQuaternion->AddField(NAME_Z, TypeFloat64); + TypeQuaternion->AddField(NAME_W, TypeFloat64); + // allow vector access. + TypeQuaternion->Symbols.AddSymbol(Create(NAME_XYZ, TypeVector3, VARF_Transient, 0)); + TypeQuaternion->Symbols.AddSymbol(Create(NAME_XY, TypeVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeQuaternion, NAME_Struct); + TypeQuaternion->loadOp = OP_LV4; + TypeQuaternion->storeOp = OP_SV4; + TypeQuaternion->moveOp = OP_MOVEV4; + TypeQuaternion->RegType = REGT_FLOAT; + TypeQuaternion->RegCount = 4; + TypeQuaternion->isOrdered = true; + + TypeFQuaternion = new PStruct(NAME_FQuat, nullptr); + TypeFQuaternion->AddField(NAME_X, TypeFloat32); + TypeFQuaternion->AddField(NAME_Y, TypeFloat32); + TypeFQuaternion->AddField(NAME_Z, TypeFloat32); + TypeFQuaternion->AddField(NAME_W, TypeFloat32); + // allow accessing xyz as a vector3 + TypeFQuaternion->Symbols.AddSymbol(Create(NAME_XYZ, TypeFVector3, VARF_Transient, 0)); + TypeFQuaternion->Symbols.AddSymbol(Create(NAME_XY, TypeFVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeFQuaternion, NAME_Struct); + TypeFQuaternion->loadOp = OP_LFV4; + TypeFQuaternion->storeOp = OP_SFV4; + TypeFQuaternion->moveOp = OP_MOVEV4; + TypeFQuaternion->RegType = REGT_FLOAT; + TypeFQuaternion->RegCount = 4; + TypeFQuaternion->isOrdered = true; Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); @@ -366,6 +473,12 @@ void PType::StaticInit() Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_State, TypeState)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector2, TypeVector2)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector3, TypeVector3)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector4, TypeVector4)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Quat, TypeQuaternion)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FVector2, TypeFVector2)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FVector3, TypeFVector3)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FVector4, TypeFVector4)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FQuat, TypeFQuaternion)); } @@ -410,7 +523,7 @@ bool PContainerType::IsMatch(intptr_t id1, intptr_t id2) const { const PTypeBase *outer = (const PTypeBase *)id1; FName name = (ENamedName)(intptr_t)id2; - + return Outer == outer && TypeName == name; } @@ -888,7 +1001,7 @@ void PFloat::SetValue(void *addr, double val) int PFloat::GetValueInt(void *addr) const { - return xs_ToInt(GetValueFloat(addr)); + return int(GetValueFloat(addr)); } //========================================================================== @@ -1245,7 +1358,7 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const } else { - *(FSoundID *)addr = FSoundID(cptr); + *(FSoundID *)addr = S_FindSound(cptr); return true; } } @@ -1702,7 +1815,7 @@ bool PArray::ReadValue(FSerializer &ar, const char *key, void *addr) const { bool readsomething = false; unsigned count = ar.ArraySize(); - unsigned loop = std::min(count, ElementCount); + unsigned loop = min(count, ElementCount); uint8_t *addrb = (uint8_t *)addr; for(unsigned i=0;i *special) void PArray::SetPointerArray(void *base, unsigned offset, TArray *special) { - if (ElementType->isStruct()) + if (ElementType->isStruct() || ElementType->isDynArray()) { for (unsigned int i = 0; i < ElementCount; ++i) { @@ -1765,6 +1878,23 @@ void PArray::SetPointerArray(void *base, unsigned offset, TArray *specia } } +//========================================================================== +// +// PArray :: SetPointerMap +// +//========================================================================== + +void PArray::SetPointerMap(void *base, unsigned offset, TArray> *special) +{ + if(ElementType->isStruct() || ElementType->isMap()) + { + for (unsigned int i = 0; i < ElementCount; ++i) + { + ElementType->SetPointerMap(base, offset + ElementSize * i, special); + } + } +} + //========================================================================== // // NewArray @@ -2096,12 +2226,89 @@ PDynArray *NewDynArray(PType *type) // //========================================================================== -PMap::PMap(PType *keytype, PType *valtype) -: KeyType(keytype), ValueType(valtype) +enum OverrideFunctionRetType { + OFN_RET_VOID, + OFN_RET_VAL, + OFN_RET_KEY, + OFN_RET_BOOL, +}; +enum OverrideFunctionArgType { + OFN_ARG_VOID, + OFN_ARG_KEY, + OFN_ARG_VAL, + OFN_ARG_KEY_VAL, +}; + +template +void CreateOverrideFunction(MT *self, FName name) +{ + auto Fn = Create(self->BackingType, name); + auto NativeFn = FindFunction(self->BackingType, name.GetChars()); + + assert(NativeFn); + assert(NativeFn->VMPointer); + + + TArray ret; + TArray args; + TArray argflags; + TArray argnames; + + if constexpr(RetType == OFN_RET_VAL) + { + ret.Push(self->ValueType); + } + else if constexpr(RetType == OFN_RET_KEY) + { + ret.Push(self->KeyType); + } + else if constexpr(RetType == OFN_RET_BOOL) + { + ret.Push(TypeBool); + } + + args.Push(NewPointer(self->BackingType)); + argnames.Push(NAME_self); + argflags.Push(VARF_Implicit | VARF_ReadOnly); + + if constexpr(ArgType == OFN_ARG_KEY) + { + args.Push(self->KeyType); + argflags.Push(0); + argnames.Push(NAME_Key); + } + else if constexpr(ArgType == OFN_ARG_VAL) + { + + args.Push(self->ValueType); + argflags.Push(0); + argnames.Push(NAME_Value); + } + else if constexpr(ArgType == OFN_ARG_KEY_VAL) + { + args.Push(self->KeyType); + args.Push(self->ValueType); + argflags.Push(0); + argflags.Push(0); + argnames.Push(NAME_Key); + argnames.Push(NAME_Value); + } + + Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native,SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM); + self->FnOverrides.Insert(name, Fn); +} + +PMap::PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class) +: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class) { mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); - Size = sizeof(FMap); - Align = alignof(FMap); + Size = sizeof(ZSFMap); + Align = alignof(ZSFMap); + CreateOverrideFunction(this, NAME_Get); + CreateOverrideFunction(this, NAME_CheckKey); + CreateOverrideFunction(this, NAME_Insert); + CreateOverrideFunction(this, NAME_InsertNew); + CreateOverrideFunction(this, NAME_Remove); } //========================================================================== @@ -2130,6 +2337,340 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = (intptr_t)ValueType; } +//========================================================================== +// +// PMap :: InitializeValue +// +//========================================================================== + +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; + }; +} + +void PMap::InitializeValue(void *addr, const void *def) const +{ + Construct(addr); +} + +//========================================================================== +// +// PMap :: DestroyValue +// +//========================================================================== + +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; + } +} + +//========================================================================== +// +// PMap :: SetDefaultValue +// +//========================================================================== + +void PMap::SetDefaultValue(void *base, unsigned offset, TArray *special) +{ + if (base != nullptr) + { + Construct(((uint8_t*)base)+offset); // is this needed? string/dynarray do this initialization if base != nullptr, but their initialization doesn't need to allocate + // it might lead to double allocations (and memory leakage) for Map if both base and special != nullptr + } + if (special != nullptr) + { + special->Push(std::make_pair(this, offset)); + } + else + { + I_Error("null special"); + } +} + +//========================================================================== +// +// PMap :: SetPointer +// +//========================================================================== + +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)); + } +} + +//========================================================================== +// +// PMap :: WriteValue +// +//========================================================================== + +template +static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m) +{ + TMapConstIterator it(*map); + const typename M::Pair * p; + while(it.NextPair(p)) + { + if constexpr(std::is_same_v) + { + m->ValueType->WriteValue(ar,p->Key.GetChars(),static_cast(&p->Value)); + } + else if constexpr(std::is_same_v) + { + FString key; + key.Format("%u",p->Key); + m->ValueType->WriteValue(ar,key.GetChars(),static_cast(&p->Value)); + } + //else unknown key type + } +} + +void PMap::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + if(ar.BeginObject(key)) + { + 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; + } + ar.EndObject(); + } +} + +//========================================================================== +// +// PMap :: ReadValue +// +//========================================================================== + + +template +static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m) +{ + const char * k; + while((k = ar.GetKey())) + { + typename M::ValueType * val; + if constexpr(std::is_same_v) + { + val = &map->InsertNew(k); + } + else if constexpr(std::is_same_v) + { + FString s(k); + if(!s.IsInt()) + { + ar.EndObject(); + return false; + } + val = &map->InsertNew(static_cast(s.ToULong())); + } + if (!m->ValueType->ReadValue(ar,nullptr,static_cast(val))) + { + ar.EndObject(); + return false; + } + } + ar.EndObject(); + return true; +} + + +bool PMap::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + DestroyValue(addr); + InitializeValue(addr, nullptr); + if(ar.BeginObject(key)) + { + 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); + } + } + return false; +} + //========================================================================== // // NewMap @@ -2139,16 +2680,325 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const // //========================================================================== -PMap *NewMap(PType *keytype, PType *valuetype) +int PMapBackingClass(PType *keytype, PType *valuetype, FString &backingName) { + int backingClass; + auto key_rtype = keytype->GetRegType(); + auto value_rtype = valuetype->GetRegType(); + if (key_rtype == REGT_INT) + { + if(keytype->Size != 4) + { + I_Error("Unsupported map requested"); + } + else + { + backingName += "I32_"; + backingClass = PMap::MAP_I32_I8; + } + } + else if (key_rtype == REGT_STRING) + { + backingName += "Str_"; + backingClass = PMap::MAP_STR_I8; + } + else + { + I_Error("Unsupported map requested"); + } + switch (valuetype->GetRegType()) + { + case REGT_INT: + backingName.AppendFormat("I%d", valuetype->Size * 8); + backingClass += (valuetype->Size >> 1); + break; + case REGT_FLOAT: + backingName.AppendFormat("F%d", valuetype->Size * 8); + backingClass += PMap::MAP_I32_F32 + (valuetype->Size == 8); + break; + case REGT_STRING: + backingName += "Str"; + backingClass += PMap::MAP_I32_STR; + break; + + case REGT_POINTER: + if (valuetype->isObjectPointer()) + { + backingName += "Obj"; + backingClass += PMap::MAP_I32_OBJ; + } + else + { + backingName += "Ptr"; + backingClass += PMap::MAP_I32_PTR; + } + break; + default: + I_Error("Unsupported map requested"); + break; + } + return backingClass; +} + +PMap *NewMap(PType *keyType, PType *valueType) { size_t bucket; - PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket); - if (maptype == nullptr) + PType *mapType = TypeTable.FindType(NAME_Map, (intptr_t)keyType, (intptr_t)valueType, &bucket); + if (mapType == nullptr) { - maptype = new PMap(keytype, valuetype); - TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket); + FString backingName = "Map_"; + int backingClass = PMapBackingClass(keyType, valueType, backingName); + + auto backing = NewStruct(backingName, nullptr, true); + mapType = new PMap(keyType, valueType, backing, backingClass); + TypeTable.AddType(mapType, NAME_Map, (intptr_t)keyType, (intptr_t)valueType, bucket); + } - return (PMap *)maptype; + return (PMap *)mapType; +} + +/* PMap *******************************************************************/ + +//========================================================================== +// +// PMap - Parameterized Constructor +// +//========================================================================== + +PMapIterator::PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class) + : KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class) +{ + mDescriptiveName.Format("MapIterator<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); + Size = sizeof(ZSFMap); + Align = alignof(ZSFMap); + CreateOverrideFunction(this, NAME_GetKey); + CreateOverrideFunction(this, NAME_GetValue); + CreateOverrideFunction(this, NAME_SetValue); +} + +//========================================================================== +// +// PMapIterator :: IsMatch +// +//========================================================================== + +bool PMapIterator::IsMatch(intptr_t id1, intptr_t id2) const +{ + const PType *keyty = (const PType *)id1; + const PType *valty = (const PType *)id2; + + return keyty == KeyType && valty == ValueType; +} + +//========================================================================== +// +// PMapIterator :: GetTypeIDs +// +//========================================================================== + +void PMapIterator::GetTypeIDs(intptr_t &id1, intptr_t &id2) const +{ + id1 = (intptr_t)KeyType; + id2 = (intptr_t)ValueType; +} + +//========================================================================== +// +// PMapIterator :: InitializeValue +// +//========================================================================== + +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; + }; +} + +void PMapIterator::InitializeValue(void *addr, const void *def) const +{ + Construct(addr); +} + +//========================================================================== +// +// PMapIterator :: DestroyValue +// +//========================================================================== + +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; + } +} + +//========================================================================== +// +// PMapIterator :: SetDefaultValue +// +//========================================================================== + +void PMapIterator::SetDefaultValue(void *base, unsigned offset, TArray *special) +{ + if (base != nullptr) + { + Construct(((uint8_t*)base)+offset); + } + if (special != nullptr) + { + special->Push(std::make_pair(this, offset)); + } + else + { + I_Error("null special"); + } +} + +//========================================================================== +// +// PMapIterator :: WriteValue +// +//========================================================================== + +void PMapIterator::WriteValue(FSerializer &ar, const char *key, const void *addr) const +{ + ar.BeginObject(key); + ar.EndObject(); +} + +//========================================================================== +// +// PMapIterator :: ReadValue +// +//========================================================================== + +bool PMapIterator::ReadValue(FSerializer &ar, const char *key, void *addr) const +{ + DestroyValue(addr); + InitializeValue(addr, nullptr); + ar.BeginObject(key); + ar.EndObject(); + return true; +} + +//========================================================================== +// +// NewMapIterator +// +// Returns a PMapIterator for the given key and value types, ensuring not to create +// duplicates. +// +//========================================================================== + +PMapIterator *NewMapIterator(PType *keyType, PType *valueType) +{ + size_t bucket; + PType *mapIteratorType = TypeTable.FindType(NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, &bucket); + if (mapIteratorType == nullptr) + { + FString backingName = "MapIterator_"; + int backingClass = PMapBackingClass(keyType, valueType, backingName); + + auto backing = NewStruct(backingName, nullptr, true); + mapIteratorType = new PMapIterator(keyType, valueType, backing, backingClass); + TypeTable.AddType(mapIteratorType, NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, bucket); + } + return (PMapIterator *)mapIteratorType; } /* PStruct ****************************************************************/ @@ -2159,12 +3009,13 @@ PMap *NewMap(PType *keytype, PType *valuetype) // //========================================================================== -PStruct::PStruct(FName name, PTypeBase *outer, bool isnative) +PStruct::PStruct(FName name, PTypeBase *outer, bool isnative, int fileno) : PContainerType(name, outer) { mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars()); Size = 0; isNative = isnative; + mDefFileNo = fileno; } //========================================================================== @@ -2227,6 +3078,26 @@ void PStruct::SetPointerArray(void *base, unsigned offset, TArray *speci } } +//========================================================================== +// +// PStruct :: SetPointerMap +// +//========================================================================== + +void PStruct::SetPointerMap(void *base, unsigned offset, TArray> *special) +{ + auto it = Symbols.GetIterator(); + PSymbolTable::MapType::Pair *pair; + while (it.NextPair(pair)) + { + auto field = dyn_cast(pair->Value); + if (field && !(field->Flags & VARF_Transient)) + { + field->Type->SetPointerMap(base, unsigned(offset + field->Offset), special); + } + } +} + //========================================================================== // // PStruct :: WriteValue @@ -2285,7 +3156,7 @@ PField *PStruct::AddField(FName name, PType *type, uint32_t flags) PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue) { - return Symbols.AddNativeField(name, type, address, flags, bitvalue); + return Symbols.AddNativeField(name, type, address, flags, bitvalue, mDefFileNo); } //========================================================================== @@ -2296,14 +3167,14 @@ PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_ // //========================================================================== -PStruct *NewStruct(FName name, PTypeBase *outer, bool native) +PStruct *NewStruct(FName name, PTypeBase *outer, bool native, int fileno) { size_t bucket; if (outer == nullptr) outer = Namespaces.GlobalNamespace; PType *stype = TypeTable.FindType(NAME_Struct, (intptr_t)outer, name.GetIndex(), &bucket); if (stype == nullptr) { - stype = new PStruct(name, outer, native); + stype = new PStruct(name, outer, native, fileno); TypeTable.AddType(stype, NAME_Struct, (intptr_t)outer, name.GetIndex(), bucket); } return static_cast(stype); @@ -2321,6 +3192,29 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native) PPrototype::PPrototype(const TArray &rettypes, const TArray &argtypes) : ArgumentTypes(argtypes), ReturnTypes(rettypes) { + for (auto& type: ArgumentTypes) + { + if (type == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } + } + + for (auto& type : ReturnTypes) + { + if (type == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } + } } //========================================================================== @@ -2378,7 +3272,7 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray // //========================================================================== -PClassType::PClassType(PClass *cls) +PClassType::PClassType(PClass *cls, int fileno) { assert(cls->VMType == nullptr); Descriptor = cls; @@ -2391,6 +3285,7 @@ PClassType::PClassType(PClass *cls) ScopeFlags = ParentType->ScopeFlags; } cls->VMType = this; + mDefFileNo = fileno; mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars()); } @@ -2402,7 +3297,7 @@ PClassType::PClassType(PClass *cls) PField *PClassType::AddField(FName name, PType *type, uint32_t flags) { - return Descriptor->AddField(name, type, flags); + return Descriptor->AddField(name, type, flags, mDefFileNo); } //========================================================================== @@ -2413,7 +3308,7 @@ PField *PClassType::AddField(FName name, PType *type, uint32_t flags) PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue) { - auto field = Symbols.AddNativeField(name, type, address, flags, bitvalue); + auto field = Symbols.AddNativeField(name, type, address, flags, bitvalue, mDefFileNo); if (field != nullptr) Descriptor->Fields.Push(field); return field; } @@ -2424,13 +3319,13 @@ PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint // //========================================================================== -PClassType *NewClassType(PClass *cls) +PClassType *NewClassType(PClass *cls, int fileno) { size_t bucket; PType *ptype = TypeTable.FindType(NAME_Object, 0, cls->TypeName.GetIndex(), &bucket); if (ptype == nullptr) { - ptype = new PClassType(cls); + ptype = new PClassType(cls, fileno); TypeTable.AddType(ptype, NAME_Object, 0, cls->TypeName.GetIndex(), bucket); } return static_cast(ptype); diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index ae423af9d..f4ac3447d 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -129,6 +129,7 @@ public: 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); // Initialize the value, if needed (e.g. strings) virtual void InitializeValue(void *addr, const void *def) const; @@ -200,6 +201,8 @@ public: bool isArray() const { return !!(Flags & TYPE_Array); } bool isStaticArray() const { return TypeTableType == NAME_StaticArray; } bool isDynArray() const { return TypeTableType == NAME_DynArray; } + bool isMap() const { return TypeTableType == NAME_Map; } + bool isMapIterator() const { return TypeTableType == NAME_MapIterator; } bool isStruct() const { return TypeTableType == NAME_Struct; } bool isClass() const { return TypeTableType == NAME_Object; } bool isPrototype() const { return TypeTableType == NAME_Prototype; } @@ -489,6 +492,7 @@ public: 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; }; class PStaticArray : public PArray @@ -521,25 +525,85 @@ public: class PMap : public PCompoundType { + void Construct(void * addr) const; public: - PMap(PType *keytype, PType *valtype); + PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class); PType *KeyType; PType *ValueType; + TMap FnOverrides; + + PStruct *BackingType; + + enum EBackingClass { + MAP_I32_I8, + MAP_I32_I16, + MAP_I32_I32, + MAP_I32_F32, + MAP_I32_F64, + MAP_I32_OBJ, + MAP_I32_PTR, + MAP_I32_STR, + + MAP_STR_I8, + MAP_STR_I16, + MAP_STR_I32, + MAP_STR_F32, + MAP_STR_F64, + MAP_STR_OBJ, + MAP_STR_PTR, + MAP_STR_STR, + } BackingClass; + virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + + 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 InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; + void SetPointerMap(void *base, unsigned offset, TArray> *ptrofs) override; +}; + + +class PMapIterator : public PCompoundType +{ + void Construct(void * addr) const; +public: + PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class); + + PType *KeyType; + PType *ValueType; + + TMap FnOverrides; + + PStruct *BackingType; + + PMap::EBackingClass BackingClass; + + virtual bool IsMatch(intptr_t id1, intptr_t id2) const; + virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; + + 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 InitializeValue(void *addr, const void *def) const override; + void DestroyValue(void *addr) const override; }; class PStruct : public PContainerType { public: - PStruct(FName name, PTypeBase *outer, bool isnative = false); + PStruct(FName name, PTypeBase *outer, bool isnative = false, int fileno = 0); bool isNative; + bool isOrdered = false; // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. VMFunction *mConstructor = nullptr; VMFunction *mDestructor = nullptr; + int mDefFileNo; PField *AddField(FName name, PType *type, uint32_t flags=0) override; PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override; @@ -549,6 +613,7 @@ public: 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; }; class PPrototype : public PCompoundType @@ -571,8 +636,9 @@ class PClassType : public PContainerType public: PClass *Descriptor; PClassType *ParentType; + int mDefFileNo; - PClassType(PClass *cls = nullptr); + PClassType(PClass *cls = nullptr, int fileno = 0); PField *AddField(FName name, PType *type, uint32_t flags = 0) override; PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override; }; @@ -585,6 +651,7 @@ inline PClass *PObjectPointer::PointedClass() const // Returns a type from the TypeTable. Will create one if it isn't present. PMap *NewMap(PType *keytype, PType *valuetype); +PMapIterator *NewMapIterator(PType *keytype, PType *valuetype); PArray *NewArray(PType *type, unsigned int count); PStaticArray *NewStaticArray(PType *type); PDynArray *NewDynArray(PType *type); @@ -592,9 +659,9 @@ PPointer *NewPointer(PType *type, bool isconst = false); PPointer *NewPointer(PClass *type, bool isconst = false); PClassPointer *NewClassPointer(PClass *restrict); PEnum *NewEnum(FName name, PTypeBase *outer); -PStruct *NewStruct(FName name, PTypeBase *outer, bool native = false); +PStruct *NewStruct(FName name, PTypeBase *outer, bool native = false, int fileno = 0); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); -PClassType *NewClassType(PClass *cls); +PClassType *NewClassType(PClass *cls, int fileno); // Built-in types ----------------------------------------------------------- @@ -612,10 +679,17 @@ extern PSound *TypeSound; extern PColor *TypeColor; extern PTextureID *TypeTextureID; extern PSpriteID *TypeSpriteID; -extern PStruct *TypeVector2; -extern PStruct *TypeVector3; +extern PStruct* TypeVector2; +extern PStruct* TypeVector3; +extern PStruct* TypeVector4; +extern PStruct* TypeFVector2; +extern PStruct* TypeFVector3; +extern PStruct* TypeFVector4; +extern PStruct* TypeQuaternion; +extern PStruct* TypeFQuaternion; extern PStruct *TypeColorStruct; extern PStruct *TypeStringStruct; +extern PStruct* TypeQuaternionStruct; extern PStatePointer *TypeState; extern PPointer *TypeFont; extern PStateLabel *TypeStateLabel; diff --git a/src/common/scripting/core/vmdisasm.cpp b/src/common/scripting/core/vmdisasm.cpp index b3dbece6e..433a2fd1a 100644 --- a/src/common/scripting/core/vmdisasm.cpp +++ b/src/common/scripting/core/vmdisasm.cpp @@ -33,7 +33,7 @@ #include "dobject.h" #include "c_console.h" -#include "templates.h" + #include "vmintern.h" #include "printf.h" @@ -265,7 +265,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func) { - VMFunction *callfunc; + VMFunction *callfunc = nullptr; const char *name; int col; int mode; @@ -526,7 +526,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction { printf_wrapper(out, ",%d\n", code[++i].i24); } - else if (code[i].op == OP_CALL_K) + else if (code[i].op == OP_CALL_K && callfunc) { printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars()); } @@ -639,6 +639,8 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const return col+printf_wrapper(out, "v%d.2", regnum); case REGT_FLOAT | REGT_MULTIREG3: return col+printf_wrapper(out, "v%d.3", regnum); + case REGT_FLOAT | REGT_MULTIREG4: + return col+printf_wrapper(out, "v%d.4", regnum); case REGT_INT | REGT_KONST: return col+print_reg(out, 0, regnum, MODE_KI, 0, func); case REGT_FLOAT | REGT_KONST: @@ -665,7 +667,6 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const default: return col+printf_wrapper(out, "$%d", arg); } - return col; } //========================================================================== @@ -677,7 +678,7 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen) { const char *marks = "======================================================="; - fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks); + fprintf(dump, "\n%.*s %s %.*s", max(3, 38 - labellen / 2), marks, label, max(3, 38 - labellen / 2), marks); fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n", sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam); VMDumpConstants(dump, sfunc); diff --git a/src/common/scripting/frontend/ast.cpp b/src/common/scripting/frontend/ast.cpp index cb29457e4..50e1c2e9f 100644 --- a/src/common/scripting/frontend/ast.cpp +++ b/src/common/scripting/frontend/ast.cpp @@ -39,7 +39,7 @@ #include "printf.h" class FLispString; -extern void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *); +using NodePrinterFunc = void (*)(FLispString &, const ZCC_TreeNode *); static const char *BuiltInTypeNames[] = { @@ -53,6 +53,7 @@ static const char *BuiltInTypeNames[] = "string", "vector2", "vector3", + "vector4", "name", "color", @@ -220,24 +221,11 @@ private: bool NeedSpace; }; -static void PrintNode(FLispString &out, ZCC_TreeNode *node) -{ - assert(TreeNodePrinter[NUM_AST_NODE_TYPES-1] != NULL); - if (node->NodeType >= 0 && node->NodeType < NUM_AST_NODE_TYPES) - { - TreeNodePrinter[node->NodeType](out, node); - } - else - { - out.Open("unknown-node-type"); - out.AddInt(node->NodeType); - out.Close(); - } -} +static void PrintNode(FLispString &out, const ZCC_TreeNode *node); -static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true, bool addbreaks=false) +static void PrintNodes(FLispString &out, const ZCC_TreeNode *node, bool newlist=true, bool addbreaks=false) { - ZCC_TreeNode *p; + const ZCC_TreeNode *p; if (node == NULL) { @@ -268,7 +256,7 @@ static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true, static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type) { - assert(ZCC_NUM_BUILT_IN_TYPES == countof(BuiltInTypeNames)); + static_assert(ZCC_NUM_BUILT_IN_TYPES == countof(BuiltInTypeNames)); if (unsigned(type) >= unsigned(ZCC_NUM_BUILT_IN_TYPES)) { char buf[30]; @@ -281,7 +269,7 @@ static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type) } } -static void PrintIdentifier(FLispString &out, ZCC_TreeNode *node) +static void PrintIdentifier(FLispString &out, const ZCC_TreeNode *node) { ZCC_Identifier *inode = (ZCC_Identifier *)node; out.Open("identifier"); @@ -316,7 +304,7 @@ static void PrintStringConst(FLispString &out, FString str) out.Add(outstr); } -static void PrintClass(FLispString &out, ZCC_TreeNode *node) +static void PrintClass(FLispString &out, const ZCC_TreeNode *node) { ZCC_Class *cnode = (ZCC_Class *)node; out.Break(); @@ -329,7 +317,7 @@ static void PrintClass(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStruct(FLispString &out, ZCC_TreeNode *node) +static void PrintStruct(FLispString &out, const ZCC_TreeNode *node) { ZCC_Struct *snode = (ZCC_Struct *)node; out.Break(); @@ -339,7 +327,7 @@ static void PrintStruct(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintProperty(FLispString &out, ZCC_TreeNode *node) +static void PrintProperty(FLispString &out, const ZCC_TreeNode *node) { ZCC_Property *snode = (ZCC_Property *)node; out.Break(); @@ -349,7 +337,7 @@ static void PrintProperty(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node) +static void PrintFlagDef(FLispString &out, const ZCC_TreeNode *node) { ZCC_FlagDef *snode = (ZCC_FlagDef *)node; out.Break(); @@ -360,7 +348,7 @@ static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node) +static void PrintStaticArrayState(FLispString &out, const ZCC_TreeNode *node) { auto *snode = (ZCC_StaticArrayStatement *)node; out.Break(); @@ -370,7 +358,7 @@ static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintEnum(FLispString &out, ZCC_TreeNode *node) +static void PrintEnum(FLispString &out, const ZCC_TreeNode *node) { ZCC_Enum *enode = (ZCC_Enum *)node; out.Break(); @@ -381,13 +369,13 @@ static void PrintEnum(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintEnumTerminator(FLispString &out, ZCC_TreeNode *node) +static void PrintEnumTerminator(FLispString &out, const ZCC_TreeNode *node) { out.Open("enum-term"); out.Close(); } -static void PrintStates(FLispString &out, ZCC_TreeNode *node) +static void PrintStates(FLispString &out, const ZCC_TreeNode *node) { ZCC_States *snode = (ZCC_States *)node; out.Break(); @@ -397,13 +385,13 @@ static void PrintStates(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStatePart(FLispString &out, ZCC_TreeNode *node) +static void PrintStatePart(FLispString &out, const ZCC_TreeNode *node) { out.Open("state-part"); out.Close(); } -static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node) +static void PrintStateLabel(FLispString &out, const ZCC_TreeNode *node) { ZCC_StateLabel *snode = (ZCC_StateLabel *)node; out.Open("state-label"); @@ -411,31 +399,31 @@ static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStateStop(FLispString &out, ZCC_TreeNode *node) +static void PrintStateStop(FLispString &out, const ZCC_TreeNode *node) { out.Open("state-stop"); out.Close(); } -static void PrintStateWait(FLispString &out, ZCC_TreeNode *node) +static void PrintStateWait(FLispString &out, const ZCC_TreeNode *node) { out.Open("state-wait"); out.Close(); } -static void PrintStateFail(FLispString &out, ZCC_TreeNode *node) +static void PrintStateFail(FLispString &out, const ZCC_TreeNode *node) { out.Open("state-fail"); out.Close(); } -static void PrintStateLoop(FLispString &out, ZCC_TreeNode *node) +static void PrintStateLoop(FLispString &out, const ZCC_TreeNode *node) { out.Open("state-loop"); out.Close(); } -static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node) +static void PrintStateGoto(FLispString &out, const ZCC_TreeNode *node) { ZCC_StateGoto *snode = (ZCC_StateGoto *)node; out.Open("state-goto"); @@ -445,7 +433,7 @@ static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStateLine(FLispString &out, ZCC_TreeNode *node) +static void PrintStateLine(FLispString &out, const ZCC_TreeNode *node) { ZCC_StateLine *snode = (ZCC_StateLine *)node; out.Open("state-line"); @@ -462,7 +450,7 @@ static void PrintStateLine(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintVarName(FLispString &out, ZCC_TreeNode *node) +static void PrintVarName(FLispString &out, const ZCC_TreeNode *node) { ZCC_VarName *vnode = (ZCC_VarName *)node; out.Open("var-name"); @@ -471,7 +459,7 @@ static void PrintVarName(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintVarInit(FLispString &out, ZCC_TreeNode *node) +static void PrintVarInit(FLispString &out, const ZCC_TreeNode *node) { ZCC_VarInit *vnode = (ZCC_VarInit *)node; out.Open("var-init"); @@ -482,7 +470,7 @@ static void PrintVarInit(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintType(FLispString &out, ZCC_TreeNode *node) +static void PrintType(FLispString &out, const ZCC_TreeNode *node) { ZCC_Type *tnode = (ZCC_Type *)node; out.Open("bad-type"); @@ -490,7 +478,7 @@ static void PrintType(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintBasicType(FLispString &out, ZCC_TreeNode *node) +static void PrintBasicType(FLispString &out, const ZCC_TreeNode *node) { ZCC_BasicType *tnode = (ZCC_BasicType *)node; out.Open("basic-type"); @@ -504,7 +492,7 @@ static void PrintBasicType(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintMapType(FLispString &out, ZCC_TreeNode *node) +static void PrintMapType(FLispString &out, const ZCC_TreeNode *node) { ZCC_MapType *tnode = (ZCC_MapType *)node; out.Open("map-type"); @@ -514,7 +502,17 @@ static void PrintMapType(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node) +static void PrintMapIteratorType(FLispString &out, const ZCC_TreeNode *node) +{ + ZCC_MapIteratorType *tnode = (ZCC_MapIteratorType *)node; + out.Open("map-iterator-type"); + PrintNodes(out, tnode->ArraySize); + PrintNodes(out, tnode->KeyType); + PrintNodes(out, tnode->ValueType); + out.Close(); +} + +static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node) { ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node; out.Open("dyn-array-type"); @@ -523,7 +521,7 @@ static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintClassType(FLispString &out, ZCC_TreeNode *node) +static void PrintClassType(FLispString &out, const ZCC_TreeNode *node) { ZCC_ClassType *tnode = (ZCC_ClassType *)node; out.Open("class-type"); @@ -547,14 +545,14 @@ static void OpenExprType(FLispString &out, EZCCExprType type) out.Open(buf); } -static void PrintExpression(FLispString &out, ZCC_TreeNode *node) +static void PrintExpression(FLispString &out, const ZCC_TreeNode *node) { ZCC_Expression *enode = (ZCC_Expression *)node; OpenExprType(out, enode->Operation); out.Close(); } -static void PrintExprID(FLispString &out, ZCC_TreeNode *node) +static void PrintExprID(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprID *enode = (ZCC_ExprID *)node; assert(enode->Operation == PEX_ID); @@ -563,7 +561,7 @@ static void PrintExprID(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node) +static void PrintExprTypeRef(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprTypeRef *enode = (ZCC_ExprTypeRef *)node; assert(enode->Operation == PEX_TypeRef); @@ -582,7 +580,7 @@ static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node) +static void PrintExprConstant(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprConstant *enode = (ZCC_ExprConstant *)node; assert(enode->Operation == PEX_ConstValue); @@ -610,7 +608,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node) +static void PrintExprFuncCall(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprFuncCall *enode = (ZCC_ExprFuncCall *)node; assert(enode->Operation == PEX_FuncCall); @@ -620,7 +618,7 @@ static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node) +static void PrintExprClassCast(FLispString &out, const ZCC_TreeNode *node) { ZCC_ClassCast *enode = (ZCC_ClassCast *)node; assert(enode->Operation == PEX_ClassCast); @@ -630,7 +628,7 @@ static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node) +static void PrintStaticArray(FLispString &out, const ZCC_TreeNode *node) { ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node; out.Open("static-array-stmt"); @@ -640,7 +638,7 @@ static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node) +static void PrintExprMemberAccess(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node; assert(enode->Operation == PEX_MemberAccess); @@ -650,7 +648,7 @@ static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node) +static void PrintExprUnary(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprUnary *enode = (ZCC_ExprUnary *)node; OpenExprType(out, enode->Operation); @@ -658,7 +656,7 @@ static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node) +static void PrintExprBinary(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprBinary *enode = (ZCC_ExprBinary *)node; OpenExprType(out, enode->Operation); @@ -667,7 +665,7 @@ static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node) +static void PrintExprTrinary(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExprTrinary *enode = (ZCC_ExprTrinary *)node; OpenExprType(out, enode->Operation); @@ -677,17 +675,18 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node) +static void PrintVectorInitializer(FLispString &out, const ZCC_TreeNode *node) { ZCC_VectorValue *enode = (ZCC_VectorValue *)node; OpenExprType(out, enode->Operation); PrintNodes(out, enode->X); PrintNodes(out, enode->Y); PrintNodes(out, enode->Z); + PrintNodes(out, enode->W); out.Close(); } -static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node) +static void PrintFuncParam(FLispString &out, const ZCC_TreeNode *node) { ZCC_FuncParm *pnode = (ZCC_FuncParm *)node; out.Break(); @@ -697,13 +696,13 @@ static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintStatement(FLispString &out, ZCC_TreeNode *node) +static void PrintStatement(FLispString &out, const ZCC_TreeNode *node) { out.Open("statement"); out.Close(); } -static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintCompoundStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_CompoundStmt *snode = (ZCC_CompoundStmt *)node; out.Break(); @@ -712,7 +711,7 @@ static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintDefault(FLispString &out, ZCC_TreeNode *node) +static void PrintDefault(FLispString &out, const ZCC_TreeNode *node) { ZCC_Default *snode = (ZCC_Default *)node; out.Break(); @@ -721,21 +720,21 @@ static void PrintDefault(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintContinueStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintContinueStmt(FLispString &out, const ZCC_TreeNode *node) { out.Break(); out.Open("continue-stmt"); out.Close(); } -static void PrintBreakStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintBreakStmt(FLispString &out, const ZCC_TreeNode *node) { out.Break(); out.Open("break-stmt"); out.Close(); } -static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintReturnStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_ReturnStmt *snode = (ZCC_ReturnStmt *)node; out.Break(); @@ -744,7 +743,7 @@ static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintExpressionStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_ExpressionStmt *snode = (ZCC_ExpressionStmt *)node; out.Break(); @@ -753,7 +752,7 @@ static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintIterationStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_IterationStmt *snode = (ZCC_IterationStmt *)node; out.Break(); @@ -768,7 +767,7 @@ static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintIfStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_IfStmt *snode = (ZCC_IfStmt *)node; out.Break(); @@ -781,7 +780,7 @@ static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintSwitchStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_SwitchStmt *snode = (ZCC_SwitchStmt *)node; out.Break(); @@ -792,7 +791,7 @@ static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintCaseStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintCaseStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_CaseStmt *snode = (ZCC_CaseStmt *)node; out.Break(); @@ -808,7 +807,7 @@ static void BadAssignOp(FLispString &out, int op) out.Add(buf, len); } -static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintAssignStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node; out.Open("assign-stmt"); @@ -817,7 +816,16 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintAssignDeclStmt(FLispString &out, const ZCC_TreeNode *node) +{ + ZCC_AssignDeclStmt *snode = (ZCC_AssignDeclStmt *)node; + out.Open("assign-stmt-decl"); + PrintNodes(out, snode->Dests); + PrintNodes(out, snode->Sources); + out.Close(); +} + +static void PrintLocalVarStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_LocalVarStmt *snode = (ZCC_LocalVarStmt *)node; out.Open("local-var-stmt"); @@ -826,7 +834,7 @@ static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node) +static void PrintFuncParamDecl(FLispString &out, const ZCC_TreeNode *node) { ZCC_FuncParamDecl *dnode = (ZCC_FuncParamDecl *)node; out.Break(); @@ -838,7 +846,7 @@ static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node) +static void PrintConstantDef(FLispString &out, const ZCC_TreeNode *node) { ZCC_ConstantDef *dnode = (ZCC_ConstantDef *)node; out.Break(); @@ -848,7 +856,7 @@ static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node) +static void PrintDeclarator(FLispString &out, const ZCC_TreeNode *node) { ZCC_Declarator *dnode = (ZCC_Declarator *)node; out.Break(); @@ -858,7 +866,7 @@ static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node) +static void PrintVarDeclarator(FLispString &out, const ZCC_TreeNode *node) { ZCC_VarDeclarator *dnode = (ZCC_VarDeclarator *)node; out.Break(); @@ -869,7 +877,7 @@ static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node) +static void PrintFuncDeclarator(FLispString &out, const ZCC_TreeNode *node) { ZCC_FuncDeclarator *dnode = (ZCC_FuncDeclarator *)node; out.Break(); @@ -883,7 +891,7 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node) +static void PrintDeclFlags(FLispString &out, const ZCC_TreeNode *node) { auto dnode = (ZCC_DeclFlags *)node; out.Break(); @@ -893,7 +901,7 @@ static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintFlagStmt(FLispString &out, const ZCC_TreeNode *node) { auto dnode = (ZCC_FlagStmt *)node; out.Break(); @@ -903,7 +911,7 @@ static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintPropertyStmt(FLispString &out, const ZCC_TreeNode *node) { auto dnode = (ZCC_PropertyStmt *)node; out.Break(); @@ -913,7 +921,7 @@ static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintMixinDef(FLispString &out, ZCC_TreeNode *node) +static void PrintMixinDef(FLispString &out, const ZCC_TreeNode *node) { ZCC_MixinDef *mdnode = (ZCC_MixinDef *)node; out.Break(); @@ -923,7 +931,7 @@ static void PrintMixinDef(FLispString &out, ZCC_TreeNode *node) out.Close(); } -static void PrintMixinStmt(FLispString &out, ZCC_TreeNode *node) +static void PrintMixinStmt(FLispString &out, const ZCC_TreeNode *node) { ZCC_MixinStmt *msnode = (ZCC_MixinStmt *)node; out.Break(); @@ -932,7 +940,20 @@ static void PrintMixinStmt(FLispString &out, ZCC_TreeNode *node) out.Close(); } -void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *) = +static void PrintArrayIterationStmt(FLispString &out, const ZCC_TreeNode *node) +{ + auto inode = (ZCC_ArrayIterationStmt *)node; + out.Break(); + out.Open("array-iteration-stmt"); + PrintVarName(out, inode->ItName); + out.Break(); + PrintNodes(out, inode->ItArray); + out.Break(); + PrintNodes(out, inode->LoopStatement); + out.Close(); +} + +static const NodePrinterFunc TreeNodePrinter[] = { PrintIdentifier, PrintClass, @@ -953,6 +974,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintType, PrintBasicType, PrintMapType, + PrintMapIteratorType, PrintDynArrayType, PrintClassType, PrintExpression, @@ -976,6 +998,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintSwitchStmt, PrintCaseStmt, PrintAssignStmt, + PrintAssignDeclStmt, PrintLocalVarStmt, PrintFuncParamDecl, PrintConstantDef, @@ -993,11 +1016,27 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode * PrintFlagDef, PrintMixinDef, PrintMixinStmt, + PrintArrayIterationStmt, }; -FString ZCC_PrintAST(ZCC_TreeNode *root) +FString ZCC_PrintAST(const ZCC_TreeNode *root) { FLispString out; PrintNodes(out, root); return out; } + +static void PrintNode(FLispString &out, const ZCC_TreeNode *node) +{ + static_assert(countof(TreeNodePrinter) == NUM_AST_NODE_TYPES, "All AST node types should have printers defined for them"); + if (node->NodeType >= 0 && node->NodeType < NUM_AST_NODE_TYPES) + { + TreeNodePrinter[node->NodeType](out, node); + } + else + { + out.Open("unknown-node-type"); + out.AddInt(node->NodeType); + out.Close(); + } +} diff --git a/src/common/scripting/frontend/zcc-parse.lemon b/src/common/scripting/frontend/zcc-parse.lemon index 6765defa1..1a9146f37 100644 --- a/src/common/scripting/frontend/zcc-parse.lemon +++ b/src/common/scripting/frontend/zcc-parse.lemon @@ -861,6 +861,7 @@ type_name1(X) ::= DOUBLE(T). { X.Int = ZCC_Float64; X.SourceLoc = T.SourceLoc //type_name1(X) ::= STRING(T). { X.Int = ZCC_String; X.SourceLoc = T.SourceLoc; } // [ZZ] it's handled elsewhere. this particular line only causes troubles in the form of String.Format being invalid. type_name1(X) ::= VECTOR2(T). { X.Int = ZCC_Vector2; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= VECTOR3(T). { X.Int = ZCC_Vector3; X.SourceLoc = T.SourceLoc; } +type_name1(X) ::= VECTOR4(T). { X.Int = ZCC_Vector4; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= NAME(T). { X.Int = ZCC_Name; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= SOUND(T). { X.Int = ZCC_Sound; X.SourceLoc = T.SourceLoc; } type_name1(X) ::= STATE(T). { X.Int = ZCC_State; X.SourceLoc = T.SourceLoc; } @@ -931,7 +932,7 @@ type_name(X) ::= DOT dottable_id(A). /* Type names can also be used as identifiers in contexts where type names * are not normally allowed. */ %fallback IDENTIFIER - SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 NAME MAP ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY. + SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 VECTOR4 NAME MAP MAPITERATOR ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY. /* Aggregate types */ %type aggregate_type {ZCC_Type *} @@ -943,7 +944,7 @@ type_name(X) ::= DOT dottable_id(A). %type array_size{ZCC_Expression *} %type array_size_expr{ZCC_Expression *} -aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* Hash table */ +aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMap */ { NEW_AST_NODE(MapType,map,T); map->KeyType = A; @@ -951,6 +952,14 @@ aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* H X = map; } +aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMapIterator */ +{ + NEW_AST_NODE(MapIteratorType,map_it,T); + map_it->KeyType = A; + map_it->ValueType = B; + X = map_it; +} + aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray */ { NEW_AST_NODE(DynArrayType,arr,T); @@ -1303,6 +1312,17 @@ primary(X) ::= SUPER(T). X = expr; } primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ } +primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) COMMA expr(D) RPAREN. [DOT] +{ + NEW_AST_NODE(VectorValue, expr, A); + expr->Operation = PEX_Vector; + expr->Type = TypeVector4; + expr->X = A; + expr->Y = B; + expr->Z = C; + expr->W = D; + XX = expr; +} primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] { NEW_AST_NODE(VectorValue, expr, A); @@ -1311,6 +1331,7 @@ primary(XX) ::= LPAREN expr(A) COMMA expr(B) COMMA expr(C) RPAREN. [DOT] expr->X = A; expr->Y = B; expr->Z = C; + expr->W = nullptr; XX = expr; } primary(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT] @@ -1321,6 +1342,7 @@ primary(XX) ::= LPAREN expr(A) COMMA expr(B) RPAREN. [DOT] expr->X = A; expr->Y = B; expr->Z = nullptr; + expr->W = nullptr; XX = expr; } primary(X) ::= LPAREN expr(A) RPAREN. @@ -1815,8 +1837,10 @@ statement(X) ::= compound_statement(A). { X = A; /*X-overwrites-A*/ } 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) ::= 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*/ } statement(X) ::= local_var(A) SEMICOLON. { X = A; /*X-overwrites-A*/ } statement(X) ::= error SEMICOLON. { X = NULL; } statement(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ } @@ -1972,6 +1996,17 @@ iteration_statement(X) ::= FOR(T) LPAREN for_init(IN) SEMICOLON opt_expr(EX) SEM X = wrap; } +%type array_iteration_statement{ZCC_Statement *} + +array_iteration_statement(X) ::= FOREACH(T) LPAREN variable_name(IN) COLON expr(EX) RPAREN statement(ST). +{ + NEW_AST_NODE(ArrayIterationStmt, iter, T); + iter->ItName = IN; + iter->ItArray = EX; + iter->LoopStatement = ST; + X = iter; +} + while_or_until(X) ::= WHILE(T). { X.Int = ZCC_WHILE; @@ -2064,6 +2099,17 @@ assign_statement(X) ::= LBRACKET expr_list(A) RBRACKET EQ expr(B). [EQ] X = stmt; } +%type assign_decl_statement{ZCC_AssignDeclStmt *} + +assign_decl_statement(X) ::= LET LBRACKET identifier_list(A) RBRACKET EQ expr(B). [EQ] +{ + NEW_AST_NODE(AssignDeclStmt,stmt,A); + stmt->AssignOp = ZCC_EQ; + stmt->Dests = A; + stmt->Sources = B; + X = stmt; +} + /*----- Local Variable Definition "Statements" -----*/ %type local_var{ZCC_LocalVarStmt *} diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 07c4fe346..ffba4c301 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -68,7 +68,7 @@ const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx) int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls) { - FCompileContext ctx(OutNamespace, cls, false); + FCompileContext ctx(OutNamespace, cls, false, mVersion); FxExpression *ex = new FxIntCast(ConvertNode(node), false); ex = ex->Resolve(ctx); if (ex == nullptr) return 0; @@ -82,7 +82,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls) FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls) { - FCompileContext ctx(OutNamespace, cls, false); + FCompileContext ctx(OutNamespace, cls, false, mVersion); FxExpression *ex = new FxStringCast(ConvertNode(node)); ex = ex->Resolve(ctx); if (ex == nullptr) return ""; @@ -475,7 +475,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, if (ast.TopNode != NULL) { ZCC_TreeNode *node = ast.TopNode; - PSymbolTreeNode *tnode; + PSymbolTreeNode *tnode = nullptr; // [pbeta] Anything that must be processed before classes, structs, etc. should go here. do @@ -606,7 +606,6 @@ PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbo else { auto sy = Create(name, node); - FString name; treenodes->AddSymbol(sy); return sy; } @@ -721,11 +720,11 @@ void ZCCCompiler::CreateStructTypes() } else if (s->strct->Flags & ZCC_Native) { - s->strct->Type = NewStruct(s->NodeName(), outer, true); + s->strct->Type = NewStruct(s->NodeName(), outer, true, AST.FileNo); } else { - s->strct->Type = NewStruct(s->NodeName(), outer); + s->strct->Type = NewStruct(s->NodeName(), outer, false, AST.FileNo); } if (s->strct->Flags & ZCC_Version) { @@ -833,7 +832,7 @@ void ZCCCompiler::CreateClassTypes() { DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars()); } - c->cls->Type = NewClassType(me); + c->cls->Type = NewClassType(me, AST.FileNo); me->SourceLumpName = *c->cls->SourceName; } else @@ -845,14 +844,14 @@ void ZCCCompiler::CreateClassTypes() { Error(c->cls, "Parent class %s of %s not accessible to ZScript version %d.%d.%d", parent->TypeName.GetChars(), c->NodeName().GetChars(), mVersion.major, mVersion.minor, mVersion.revision); } - auto newclass = parent->CreateDerivedClass(c->NodeName(), TentativeClass); + auto newclass = parent->CreateDerivedClass(c->NodeName(), TentativeClass, nullptr, AST.FileNo); if (newclass == nullptr) { Error(c->cls, "Class name %s already exists", c->NodeName().GetChars()); } else { - c->cls->Type = NewClassType(newclass); + c->cls->Type = NewClassType(newclass, AST.FileNo); DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->ClassType()->ParentClass->TypeName.GetChars()); } } @@ -865,7 +864,7 @@ void ZCCCompiler::CreateClassTypes() if (c->Type() == nullptr) { // create a placeholder so that the compiler can continue looking for errors. - c->cls->Type = NewClassType(parent->FindClassTentative(c->NodeName())); + c->cls->Type = NewClassType(parent->FindClassTentative(c->NodeName()), AST.FileNo); } if (c->cls->Flags & ZCC_Abstract) @@ -929,7 +928,7 @@ void ZCCCompiler::CreateClassTypes() { Error(c->cls, "Class %s has unknown base class %s", c->NodeName().GetChars(), FName(c->cls->ParentName->Id).GetChars()); // create a placeholder so that the compiler can continue looking for errors. - c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName())); + c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()), AST.FileNo); c->cls->Symbol = Create(c->NodeName(), c->Type()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); Classes.Push(c); @@ -945,7 +944,7 @@ void ZCCCompiler::CreateClassTypes() for (auto c : OrigClasses) { Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars()); - c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName())); + c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()), AST.FileNo); c->cls->Symbol = Create(c->NodeName(), c->Type()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); Classes.Push(c); @@ -1070,7 +1069,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) auto def = constant.node; auto val = def->Value; ExpVal &c = constant.constval; - + // This is for literal constants. if (val->NodeType == AST_ExprConstant) { @@ -1145,7 +1144,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) bool ZCCCompiler::CompileConstant(ZCC_ConstantWork *work) { - FCompileContext ctx(OutNamespace, work->cls, false); + FCompileContext ctx(OutNamespace, work->cls, false, mVersion); FxExpression *exp = ConvertNode(work->node->Value); try { @@ -1186,7 +1185,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work) ConvertNodeList(values, sas->Values); bool fail = false; - FCompileContext ctx(OutNamespace, work->Type(), false); + FCompileContext ctx(OutNamespace, work->Type(), false, mVersion); char *destmem = (char *)ClassDataAllocator.Alloc(values.Size() * ztype->Align); memset(destmem, 0, values.Size() * ztype->Align); @@ -1326,7 +1325,7 @@ void ZCCCompiler::CompileAllFields() { // Create copies of the arrays which can be altered auto Classes = this->Classes; - auto Structs = this->Structs; + auto Structs = OrderStructs(); TMap HasNativeChildren; // first step: Look for native classes with native children. @@ -1365,7 +1364,7 @@ void ZCCCompiler::CompileAllFields() for (unsigned i = 0; i < Classes.Size(); i++) { auto type = Classes[i]->ClassType(); - + if (type->Size == TentativeClass) { if (type->ParentClass->Size == TentativeClass) @@ -1529,7 +1528,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray ZCCCompiler::OrderStructs() +{ + TArray new_order; + + for (auto struct_def : Structs) + { + if (std::find(new_order.begin(), new_order.end(), struct_def) != new_order.end()) + { + continue; + } + AddStruct(new_order, struct_def); + } + return new_order; +} + +//========================================================================== +// +// ZCCCompiler :: AddStruct +// +// Adds a struct to the Structs array, preceded by all its dependant structs +// +//========================================================================== + +void ZCCCompiler::AddStruct(TArray &new_order, ZCC_StructWork *my_def) +{ + PStruct *my_type = static_cast(my_def->Type()); + if (my_type) + { + if (my_type->isOrdered) + { + return; + } + my_type->isOrdered = true; + } + + // Find all struct fields and add them before this one + for (const auto field : my_def->Fields) + { + PType *fieldtype = DetermineType(my_type, field, field->Names->Name, field->Type, true, true); + if (fieldtype->isStruct() && !static_cast(fieldtype)->isOrdered) + { + AddStruct(new_order, StructTypeToWork(static_cast(fieldtype))); + } + } + new_order.Push(my_def); +} + +//========================================================================== +// +// ZCCCompiler :: StructTypeToWork +// +// Find the ZCC_StructWork that corresponds to a PStruct +// +//========================================================================== + +ZCC_StructWork *ZCCCompiler::StructTypeToWork(const PStruct *type) const +{ + assert(type->isStruct()); + for (auto &def : Structs) + { + if (def->Type() == type) + { + return def; + } + } + assert(false && "Struct not found"); + return nullptr; +} + //========================================================================== // // ZCCCompiler :: FieldFlagsToString @@ -1714,6 +1790,10 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeVector3; break; + case ZCC_Vector4: + retval = TypeVector4; + break; + case ZCC_State: retval = TypeState; break; @@ -1737,7 +1817,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n { Error(field, "%s: @ not allowed for user scripts", name.GetChars()); } - retval = ResolveUserType(btype, outertype? &outertype->Symbols : nullptr, true); + retval = ResolveUserType(btype, btype->UserType, outertype? &outertype->Symbols : nullptr, true); break; case ZCC_UserType: @@ -1761,7 +1841,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n break; default: - retval = ResolveUserType(btype, outertype ? &outertype->Symbols : nullptr, false); + retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); break; } break; @@ -1773,16 +1853,96 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n } case AST_MapType: - if (allowarraytypes) + { + if(AST.ParseVersion < MakeVersion(4, 10, 0)) { - Error(field, "%s: Map types not implemented yet", name.GetChars()); - // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. - auto mtype = static_cast(ztype); - retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false)); + Error(field, "Map not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision); break; } - break; + // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. + auto mtype = static_cast(ztype); + + 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->Size != 4) + { + 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()) + { + case REGT_FLOAT: + case REGT_INT: + case REGT_STRING: + 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()); + 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; + } + case AST_MapIteratorType: + { + if(AST.ParseVersion < MakeVersion(4, 10, 0)) + { + Error(field, "MapIterator not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision); + break; + } + // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. + auto mtype = static_cast(ztype); + + 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->Size != 4) + { + 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()) + { + case REGT_FLOAT: + case REGT_INT: + case REGT_STRING: + 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()); + 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; + } case AST_DynArrayType: { auto atype = static_cast(ztype); @@ -1860,18 +2020,25 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n // // ZCCCompiler :: ResolveUserType // -// resolves a user type and returns a matching PType -// //========================================================================== -PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, bool nativetype) +/** +* Resolves a user type and returns a matching PType. +* +* @param type The tree node with the identifiers to look for. +* @param type The current identifier being looked for. This must be in type's UserType list. +* @param symt The symbol table to search in. If id is the first identifier and not found in symt, then OutNamespace will also be searched. +* @param nativetype Distinguishes between searching for a native type or a user type. +* @returns the PType found for this user type +*/ +PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *symt, bool nativetype) { // Check the symbol table for the identifier. PSymbol *sym = nullptr; - + // We first look in the current class and its parents, and then in the current namespace and its parents. - if (symt != nullptr) sym = symt->FindSymbol(type->UserType->Id, true); - if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(type->UserType->Id, true); + if (symt != nullptr) sym = symt->FindSymbol(id->Id, true); + if (sym == nullptr && type->UserType == id) sym = OutNamespace->Symbols.FindSymbol(id->Id, true); if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) { auto ptype = static_cast(sym)->Type; @@ -1881,6 +2048,21 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo return TypeError; } + if (id->SiblingNext != type->UserType) + { + assert(id->SiblingNext->NodeType == AST_Identifier); + ptype = ResolveUserType( + type, + static_cast(id->SiblingNext), + &ptype->Symbols, + nativetype + ); + if (ptype == TypeError) + { + return ptype; + } + } + if (ptype->isEnum()) { if (!nativetype) return TypeSInt32; // hack this to an integer until we can resolve the enum mess. @@ -1896,11 +2078,36 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo } if (!nativetype) return ptype; } - Error(type, "Unable to resolve %s%s as type.", nativetype? "@" : "", FName(type->UserType->Id).GetChars()); + Error(type, "Unable to resolve %s%s as a type.", nativetype? "@" : "", UserTypeName(type).GetChars()); return TypeError; } +//========================================================================== +// +// ZCCCompiler :: UserTypeName STATIC +// +// Returns the full name for a UserType node. +// +//========================================================================== + +FString ZCCCompiler::UserTypeName(ZCC_BasicType *type) +{ + FString out; + ZCC_Identifier *id = type->UserType; + + do + { + assert(id->NodeType == AST_Identifier); + if (out.Len() > 0) + { + out += '.'; + } + out += FName(id->Id).GetChars(); + } while ((id = static_cast(id->SiblingNext)) != type->UserType); + return out; +} + //========================================================================== // // ZCCCompiler :: ResolveArraySize @@ -1930,19 +2137,19 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, if (mVersion >= MakeVersion(3, 7, 2)) { TArray fixedIndices; - for (auto node : indices) + for (auto index : indices) { - fixedIndices.Insert (0, node); + fixedIndices.Insert (0, index); } indices = std::move(fixedIndices); } - FCompileContext ctx(OutNamespace, cls, false); - for (auto node : indices) + FCompileContext ctx(OutNamespace, cls, false, mVersion); + for (auto index : indices) { // There is no float->int casting here. - FxExpression *ex = ConvertNode(node); + FxExpression *ex = ConvertNode(index); ex = ex->Resolve(ctx); if (ex == nullptr) return TypeError; @@ -2027,7 +2234,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool do { auto type = DetermineType(c->Type(), f, f->Name, t, false, false); - if (type->isContainer() && type != TypeVector2 && type != TypeVector3) + if (type->isContainer() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) { // structs and classes only get passed by pointer. type = NewPointer(type); @@ -2037,6 +2244,22 @@ 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 == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } + else if (type == TypeFVector4) + { + type = TypeVector4; + } + else if (type == TypeFQuaternion) + { + type = TypeQuaternion; + } // TBD: disallow certain types? For now, let everything pass that isn't an array. rets.Push(type); t = static_cast(t->SiblingNext); @@ -2209,12 +2432,12 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool do { int elementcount = 1; - TypedVMValue vmval[3]; // default is REGT_NIL which means 'no default value' here. + TypedVMValue vmval[4]; // default is REGT_NIL which means 'no default value' here. if (p->Type != nullptr) { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; - if ((type->isStruct() && type != TypeVector2 && type != TypeVector3) || type->isDynArray()) + 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()) { // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly. type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); @@ -2223,18 +2446,26 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool else if (type->GetRegType() != REGT_NIL) { if (p->Flags & ZCC_Out) flags |= VARF_Out; - if (type == TypeVector2) + if (type == TypeVector2 || type == TypeFVector2) { elementcount = 2; } - else if (type == TypeVector3) + else if (type == TypeVector3 || type == TypeFVector3) { elementcount = 3; } + else if (type == TypeVector4 || type == TypeFVector4 || type == TypeQuaternion || type == TypeFQuaternion) + { + elementcount = 4; + } } - if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3) + if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) { - Error(p, "Invalid type %s for function parameter", type->DescriptiveName()); + // If it's TypeError, then an error was already given + if (type != TypeError) + { + Error(p, "Invalid type %s for function parameter", type->DescriptiveName()); + } } else if (p->Default != nullptr) { @@ -2245,7 +2476,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool flags |= VARF_Optional; hasoptionals = true; - + if ((varflags & VARF_Override) && !overridemsg) { // This is illegal, but in older compilers wasn't checked, so there it has to be demoted to a warning. @@ -2263,24 +2494,40 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); - FCompileContext ctx(OutNamespace, c->Type(), false); + FCompileContext ctx(OutNamespace, c->Type(), false, mVersion); x = x->Resolve(ctx); if (x != nullptr) { // Vectors need special treatment because they use more than one entry in the Defaults and do not report as actual constants - if (type == TypeVector2 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(2)) + if ((type == TypeVector2 || type == TypeFVector2) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(2)) { auto vx = static_cast(x); - vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); - vmval[1] = static_cast(vx->xyz[1])->GetValue().GetFloat(); + vmval[0] = static_cast(vx->xyzw[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyzw[1])->GetValue().GetFloat(); } - else if (type == TypeVector3 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(3)) + else if ((type == TypeVector3 || type == TypeFVector3) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(3)) { auto vx = static_cast(x); - vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); - vmval[1] = static_cast(vx->xyz[1])->GetValue().GetFloat(); - vmval[2] = static_cast(vx->xyz[2])->GetValue().GetFloat(); + vmval[0] = static_cast(vx->xyzw[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyzw[1])->GetValue().GetFloat(); + vmval[2] = static_cast(vx->xyzw[2])->GetValue().GetFloat(); + } + else if ((type == TypeVector4 || type == TypeFVector4) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(4)) + { + auto vx = static_cast(x); + vmval[0] = static_cast(vx->xyzw[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyzw[1])->GetValue().GetFloat(); + vmval[2] = static_cast(vx->xyzw[2])->GetValue().GetFloat(); + vmval[3] = static_cast(vx->xyzw[3])->GetValue().GetFloat(); + } + else if ((type == TypeQuaternion || type == TypeFQuaternion) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(4)) + { + auto vx = static_cast(x); + vmval[0] = static_cast(vx->xyzw[0])->GetValue().GetFloat(); + vmval[1] = static_cast(vx->xyzw[1])->GetValue().GetFloat(); + vmval[2] = static_cast(vx->xyzw[2])->GetValue().GetFloat(); + vmval[3] = static_cast(vx->xyzw[3])->GetValue().GetFloat(); } else if (!x->isConstant()) { @@ -2425,17 +2672,17 @@ 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 vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); // specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types. if (varflags & VARF_Override) { - if (vindex == -1) + if (virtindex == -1) { Error(f, "Attempt to override non-existent virtual function %s", FName(f->Name).GetChars()); } else { - auto oldfunc = clstype->Virtuals[vindex]; + auto oldfunc = clstype->Virtuals[virtindex]; if (parentfunc && parentfunc->mVersion > mVersion) { Error(f, "Attempt to override function %s which is incompatible with version %d.%d.%d", FName(f->Name).GetChars(), mVersion.major, mVersion.minor, mVersion.revision); @@ -2466,11 +2713,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->Variants[0].Flags |= VARF_ReadOnly; if (oldfunc->VarFlags & VARF_Protected) sym->Variants[0].Flags |= VARF_Protected; - - clstype->Virtuals[vindex] = sym->Variants[0].Implementation; - sym->Variants[0].Implementation->VirtualIndex = vindex; + + clstype->Virtuals[virtindex] = sym->Variants[0].Implementation; + sym->Variants[0].Implementation->VirtualIndex = virtindex; sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; - + // Defaults must be identical to parent class if (parentfunc->Variants[0].Implementation->DefaultArgs.Size() > 0) { @@ -2493,7 +2740,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else { - if (vindex != -1) + if (virtindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); } @@ -2507,8 +2754,8 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else if (forclass) { - int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); - if (vindex != -1) + int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); + if (virtindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); } @@ -2724,7 +2971,14 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) } else if (cnst->Type->isInt()) { - return new FxConstant(cnst->IntVal, *ast); + if (cnst->Type == TypeUInt32) + { + return new FxConstant((unsigned)cnst->IntVal, *ast); + } + else + { + return new FxConstant(cnst->IntVal, *ast); + } } else if (cnst->Type == TypeBool) { @@ -2896,7 +3150,8 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) auto xx = ConvertNode(vecini->X); auto yy = ConvertNode(vecini->Y); auto zz = ConvertNode(vecini->Z); - return new FxVectorValue(xx, yy, zz, *ast); + auto ww = ConvertNode(vecini->W); + return new FxVectorValue(xx, yy, zz, ww, *ast); } case AST_LocalVarStmt: @@ -3004,6 +3259,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) return new FxIfStatement(ConvertNode(iff->Condition), truePath, falsePath, *ast); } + case AST_ArrayIterationStmt: + { + 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 body = ConvertImplicitScopeNode(ast, iter->LoopStatement); + return new FxForEachLoop(iter->ItName->Name, itArray, itArray2, body, *ast); + + } + case AST_IterationStmt: { auto iter = static_cast(ast); @@ -3084,6 +3350,28 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute) return new FxMultiAssign(args, ConvertNode(ass->Sources), *ast); } + case AST_AssignDeclStmt: + { + auto ass = static_cast(ast); + FArgumentList args; + { + ZCC_TreeNode *n = ass->Dests; + if(n) do + { + args.Push(new FxIdentifier(static_cast(n)->Id,*n)); + n = n->SiblingNext; + } while(n != ass->Dests); + } + assert(ass->Sources->SiblingNext == ass->Sources); // right side should be a single function call - nothing else + if (ass->Sources->NodeType != AST_ExprFuncCall) + { + // don't let this through to the code generator. This node is only used to assign multiple returns of a function to more than one variable. + Error(ass, "Right side of multi-assignment must be a function call"); + return new FxNop(*ast); // allow compiler to continue looking for errors. + } + return new FxMultiAssignDecl(args, ConvertNode(ass->Sources), *ast); + } + default: break; } @@ -3113,7 +3401,7 @@ FxExpression *ZCCCompiler::ConvertImplicitScopeNode(ZCC_TreeNode *node, ZCC_Stat { return nullptr; } - + FxExpression *nestedExpr = ConvertNode(nested); assert(nullptr != nestedExpr); diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index ca19d8aff..b6f32018d 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -134,13 +134,17 @@ protected: FString FlagsToString(uint32_t flags); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize); - PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype); + PType *ResolveUserType(ZCC_BasicType *type, ZCC_Identifier *id, PSymbolTable *sym, bool nativetype); + static FString UserTypeName(ZCC_BasicType *type); + TArray OrderStructs(); + void AddStruct(TArray &new_order, ZCC_StructWork *struct_def); + ZCC_StructWork *StructTypeToWork(const PStruct *type) const; void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass); void InitFunctions(); virtual void InitDefaults(); - + TArray Constants; TArray Structs; TArray Classes; diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index e176c646e..cedeb53fb 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -40,19 +40,66 @@ #include "version.h" #include "zcc_parser.h" #include "zcc_compile.h" -#include "templates.h" + TArray Includes; TArray IncludeLocs; +static FString ResolveIncludePath(const FString &path,const FString &lumpname){ + if (path.IndexOf("./") == 0 || path.IndexOf("../") == 0) // relative path resolving + { + auto start = lumpname.LastIndexOf(":"); // find find separator between wad and path + + 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 + bool topLevelFile = start > end ; + + FString fullPath = topLevelFile ? FString {} : lumpname.Mid(start + 1, end - start - 1); // get path from lumpname (format 'wad:filepath/filename') + + if (start != -1) + { + FString relativePath = path; + if (relativePath.IndexOf("./") == 0) // strip initial marker + { + relativePath = relativePath.Mid(2); + } + + bool pathOk = true; + + while (relativePath.IndexOf("../") == 0) // go back one folder for each '..' + { + relativePath = relativePath.Mid(3); + auto slash_index = fullPath.LastIndexOf("/"); + if (slash_index != -1) { + fullPath = fullPath.Mid(0, slash_index); + } else { + pathOk = false; + break; + } + } + if (pathOk) // if '..' parsing was successful + { + return topLevelFile ? relativePath : fullPath + "/" + relativePath; + } + } + } + return path; +} + static FString ZCCTokenName(int terminal); void AddInclude(ZCC_ExprConstant *node) { assert(node->Type == TypeString); - if (Includes.Find(*node->StringVal) >= Includes.Size()) + + FScriptPosition pos(*node); + + FString path = ResolveIncludePath(*node->StringVal, pos.FileName.GetChars()); + + if (Includes.Find(path) >= Includes.Size()) { - Includes.Push(*node->StringVal); - IncludeLocs.Push(*node); + Includes.Push(path); + IncludeLocs.Push(pos); } } @@ -173,6 +220,7 @@ static void InitTokenMap() TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3); TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name); TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map); + TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator); TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array); TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include); TOKENDEF (TK_Void, ZCC_VOID); @@ -193,6 +241,7 @@ static void InitTokenMap() TOKENDEF (TK_Return, ZCC_RETURN); TOKENDEF (TK_Do, ZCC_DO); TOKENDEF (TK_For, ZCC_FOR); + TOKENDEF (TK_ForEach, ZCC_FOREACH); TOKENDEF (TK_While, ZCC_WHILE); TOKENDEF (TK_Until, ZCC_UNTIL); TOKENDEF (TK_If, ZCC_IF); @@ -358,6 +407,10 @@ 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) { InitTokenMap(); @@ -848,6 +901,19 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + case AST_MapIteratorType: + { + TreeNodeDeepCopy_Start(MapIteratorType); + + // ZCC_Type + copy->ArraySize = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList)); + // AST_MapIteratorType + copy->KeyType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList)); + copy->ValueType = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList)); + + break; + } + case AST_DynArrayType: { TreeNodeDeepCopy_Start(DynArrayType); @@ -1076,6 +1142,18 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + case AST_ArrayIterationStmt: + { + TreeNodeDeepCopy_Start(ArrayIterationStmt); + + // ZCC_ArrayIterationStmt + copy->ItName = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItName, true, copiedNodesList)); + copy->LoopStatement = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList)); + copy->ItArray = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->ItArray, true, copiedNodesList)); + + break; + } + case AST_IfStmt: { TreeNodeDeepCopy_Start(IfStmt); @@ -1121,6 +1199,18 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } + case AST_AssignDeclStmt: + { + TreeNodeDeepCopy_Start(AssignDeclStmt); + + // ZCC_AssignDeclStmt + copy->Dests = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Dests, true, copiedNodesList)); + copy->Sources = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Sources, true, copiedNodesList)); + copy->AssignOp = origCasted->AssignOp; + + break; + } + case AST_LocalVarStmt: { TreeNodeDeepCopy_Start(LocalVarStmt); @@ -1250,7 +1340,8 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c // ZCC_VectorValue copy->X = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->X, true, copiedNodesList)); copy->Y = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Y, true, copiedNodesList)); - copy->Z = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Z, true, copiedNodesList)); + copy->Z = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->Z, true, copiedNodesList)); + copy->W = static_cast(TreeNodeDeepCopy_Internal(ast, origCasted->W, true, copiedNodesList)); break; } @@ -1267,7 +1358,7 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c break; } - + case AST_ClassCast: { TreeNodeDeepCopy_Start(ClassCast); diff --git a/src/common/scripting/frontend/zcc_parser.h b/src/common/scripting/frontend/zcc_parser.h index 2d89d0d94..25a60d9ad 100644 --- a/src/common/scripting/frontend/zcc_parser.h +++ b/src/common/scripting/frontend/zcc_parser.h @@ -98,6 +98,7 @@ enum EZCCTreeNodeType AST_Type, AST_BasicType, AST_MapType, + AST_MapIteratorType, AST_DynArrayType, AST_ClassType, AST_Expression, @@ -121,6 +122,7 @@ enum EZCCTreeNodeType AST_SwitchStmt, AST_CaseStmt, AST_AssignStmt, + AST_AssignDeclStmt, AST_LocalVarStmt, AST_FuncParamDecl, AST_ConstantDef, @@ -138,6 +140,7 @@ enum EZCCTreeNodeType AST_FlagDef, AST_MixinDef, AST_MixinStmt, + AST_ArrayIterationStmt, NUM_AST_NODE_TYPES }; @@ -158,6 +161,7 @@ enum EZCCBuiltinType ZCC_String, ZCC_Vector2, ZCC_Vector3, + ZCC_Vector4, ZCC_Name, ZCC_Color, // special types for ZDoom. @@ -365,6 +369,12 @@ struct ZCC_MapType : ZCC_Type ZCC_Type *ValueType; }; +struct ZCC_MapIteratorType : ZCC_Type +{ + ZCC_Type *KeyType; + ZCC_Type *ValueType; +}; + struct ZCC_DynArrayType : ZCC_Type { ZCC_Type *ElementType; @@ -442,7 +452,7 @@ struct ZCC_ExprTrinary : ZCC_Expression struct ZCC_VectorValue : ZCC_Expression { - ZCC_Expression *X, *Y, *Z; + ZCC_Expression *X, *Y, *Z, *W; }; struct ZCC_Statement : ZCC_TreeNode @@ -491,6 +501,13 @@ struct ZCC_IterationStmt : ZCC_Statement enum { Start, End } CheckAt; }; +struct ZCC_ArrayIterationStmt : ZCC_Statement +{ + ZCC_VarName* ItName; + ZCC_Expression* ItArray; + ZCC_Statement* LoopStatement; +}; + struct ZCC_IfStmt : ZCC_Statement { ZCC_Expression *Condition; @@ -517,6 +534,13 @@ struct ZCC_AssignStmt : ZCC_Statement int AssignOp; }; +struct ZCC_AssignDeclStmt : ZCC_Statement +{ + ZCC_Identifier *Dests; + ZCC_Expression *Sources; + int AssignOp; +}; + struct ZCC_LocalVarStmt : ZCC_Statement { ZCC_Type *Type; @@ -592,7 +616,7 @@ struct ZCC_MixinStmt : ZCC_Statement ENamedName MixinName; }; -FString ZCC_PrintAST(ZCC_TreeNode *root); +FString ZCC_PrintAST(const ZCC_TreeNode *root); struct ZCC_AST @@ -604,6 +628,7 @@ struct ZCC_AST FMemArena SyntaxArena; struct ZCC_TreeNode *TopNode; VersionInfo ParseVersion; + int FileNo; }; struct ZCCParseState : public ZCC_AST diff --git a/src/common/scripting/interface/stringformat.cpp b/src/common/scripting/interface/stringformat.cpp index 4bfe34ff6..77ce54ed6 100644 --- a/src/common/scripting/interface/stringformat.cpp +++ b/src/common/scripting/interface/stringformat.cpp @@ -578,6 +578,34 @@ DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, StripRight, StringStripRight) return 0; } +static void StringStripLeft(FString* self, const FString& junk) +{ + if (junk.IsNotEmpty()) self->StripLeft(junk); + else self->StripLeft(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, StripLeft, StringStripLeft) +{ + PARAM_SELF_STRUCT_PROLOGUE(FString); + PARAM_STRING(junk); + StringStripLeft(self, junk); + return 0; +} + +static void StringStripLeftRight(FString* self, const FString& junk) +{ + if (junk.IsNotEmpty()) self->StripLeftRight(junk); + else self->StripLeftRight(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FStringStruct, StripLeftRight, StringStripLeftRight) +{ + PARAM_SELF_STRUCT_PROLOGUE(FString); + PARAM_STRING(junk); + StringStripLeftRight(self, junk); + return 0; +} + static void StringSplit(FString* self, TArray* tokens, const FString& delimiter, int keepEmpty) { self->Split(*tokens, delimiter, static_cast(keepEmpty)); diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 13f3e2558..a29a6b711 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -41,7 +41,7 @@ #include "c_cvars.h" #include "c_bind.h" #include "c_dispatch.h" -#include "templates.h" + #include "menu.h" #include "vm.h" #include "gstrings.h" @@ -80,7 +80,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, StatusbarToRealCoords, StatusbarTo if (numret > 1) ret[1].SetFloat(y); if (numret > 2) ret[2].SetFloat(w); if (numret > 3) ret[3].SetFloat(h); - return MIN(4, numret); + return min(4, numret); } void SBar_DrawTexture(DStatusBarCore* self, int 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) @@ -228,7 +228,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DStatusBarCore, TransformRect, SBar_TransformRect) if (numret > 1) ret[1].SetFloat(y); if (numret > 2) ret[2].SetFloat(w); if (numret > 3) ret[3].SetFloat(h); - return MIN(4, numret); + return min(4, numret); } static void SBar_Fill(DStatusBarCore* self, int color, double x, double y, double w, double h, int flags) @@ -437,7 +437,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, GetSize, GetTextureSize) x = GetTextureSize(texid, &y); if (numret > 0) ret[0].SetInt(x); if (numret > 1) ret[1].SetInt(y); - return MIN(numret, 2); + return min(numret, 2); } //========================================================================== @@ -522,11 +522,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, CheckRealHeight, CheckRealHeight) ACTION_RETURN_INT(CheckRealHeight(texid)); } -bool OkForLocalization(FTextureID texnum, const char* substitute); - static int OkForLocalization_(int index, const FString& substitute) { - return OkForLocalization(FSetTextureID(index), substitute); + return sysCallbacks.OkForLocalization? sysCallbacks.OkForLocalization(FSetTextureID(index), substitute) : false; } DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, OkForLocalization, OkForLocalization_) @@ -552,6 +550,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, UseGamePalette, UseGamePalette) ACTION_RETURN_INT(UseGamePalette(texid)); } +FCanvas* GetTextureCanvas(const FString& texturename); + +DEFINE_ACTION_FUNCTION(_TexMan, GetCanvas) +{ + PARAM_PROLOGUE; + PARAM_STRING(texturename); + ACTION_RETURN_POINTER(GetTextureCanvas(texturename)); +} + //===================================================================================== // // FFont exports @@ -710,6 +717,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetDefaultKerning, GetDefaultKerning) ACTION_RETURN_INT(self->GetDefaultKerning()); } +static double GetDisplayTopOffset(FFont* font, int c) +{ + auto texc = font->GetChar(c, CR_UNDEFINED, nullptr); + return texc ? texc->GetDisplayTopOffset() : 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetDisplayTopOffset, GetDisplayTopOffset) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_INT(code); + ACTION_RETURN_FLOAT(GetDisplayTopOffset(self, code)); +} + //========================================================================== // // file system @@ -749,6 +769,16 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLump) ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name, &startlump, 0 != ns) : -1); } +DEFINE_ACTION_FUNCTION(_Wads, FindLumpFullName) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + PARAM_INT(startlump); + PARAM_BOOL(noext); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); + ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLumpFullName(name, &startlump, noext) : -1); +} + DEFINE_ACTION_FUNCTION(_Wads, GetLumpName) { PARAM_PROLOGUE; @@ -941,7 +971,7 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, GetKeysForCommand) self->GetKeysForCommand(cmd.GetChars(), &k1, &k2); if (numret > 0) ret[0].SetInt(k1); if (numret > 1) ret[1].SetInt(k2); - return MIN(numret, 2); + return min(numret, 2); } DEFINE_ACTION_FUNCTION(FKeyBindings, GetAllKeysForCommand) @@ -989,7 +1019,7 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) } UnsafeExecutionScope scope(unsafe); - C_DoCommand(cmd); + AddCommandString(cmd); return 0; } @@ -1009,6 +1039,18 @@ DEFINE_ACTION_FUNCTION(_Console, Printf) return 0; } +DEFINE_ACTION_FUNCTION(_Console, PrintfEx) +{ + PARAM_PROLOGUE; + PARAM_INT(printlevel); + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + FString s = FStringFormat(VM_ARGS_NAMES,1); + + Printf(printlevel,"%s\n", s.GetChars()); + return 0; +} + static void StopAllSounds() { soundEngine->StopAllChannels(); @@ -1055,7 +1097,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_System, MusicEnabled, MusicEnabled) ACTION_RETURN_INT(MusicEnabled()); } -DEFINE_ACTION_FUNCTION_NATIVE(_System, GetTimeFrac, I_GetTimeFrac) +static double Jit_GetTimeFrac() // cannot use I_GetTimwfrac directly due to default arguments. +{ + return I_GetTimeFrac(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_System, GetTimeFrac, Jit_GetTimeFrac) { ACTION_RETURN_FLOAT(I_GetTimeFrac()); } @@ -1082,3 +1129,136 @@ DEFINE_FIELD(DStatusBarCore, drawClip); DEFINE_FIELD(DStatusBarCore, fullscreenOffsets); DEFINE_FIELD(DStatusBarCore, defaultScale); DEFINE_FIELD(DHUDFont, mFont); + +// +// Quaternion +void QuatFromAngles(double yaw, double pitch, double roll, DQuaternion* pquat) +{ + *pquat = DQuaternion::FromAngles(DAngle::fromDeg(yaw), DAngle::fromDeg(pitch), DAngle::fromDeg(roll)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, FromAngles, QuatFromAngles) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(yaw); + PARAM_FLOAT(pitch); + PARAM_FLOAT(roll); + + DQuaternion quat; + QuatFromAngles(yaw, pitch, roll, &quat); + ACTION_RETURN_QUAT(quat); +} + +void QuatAxisAngle(double x, double y, double z, double angleDeg, DQuaternion* pquat) +{ + auto axis = DVector3(x, y, z); + auto angle = DAngle::fromDeg(angleDeg); + *pquat = DQuaternion::AxisAngle(axis, angle); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, AxisAngle, QuatAxisAngle) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(angle); + + DQuaternion quat; + QuatAxisAngle(x, y, z, angle, &quat); + ACTION_RETURN_QUAT(quat); +} + +void QuatNLerp( + double ax, double ay, double az, double aw, + double bx, double by, double bz, double bw, + double t, + DQuaternion* pquat +) +{ + auto from = DQuaternion { ax, ay, az, aw }; + auto to = DQuaternion { bx, by, bz, bw }; + *pquat = DQuaternion::NLerp(from, to, t); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, NLerp, QuatNLerp) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(ax); + PARAM_FLOAT(ay); + PARAM_FLOAT(az); + PARAM_FLOAT(aw); + PARAM_FLOAT(bx); + PARAM_FLOAT(by); + PARAM_FLOAT(bz); + PARAM_FLOAT(bw); + PARAM_FLOAT(t); + + DQuaternion quat; + QuatNLerp(ax, ay, az, aw, bx, by, bz, bw, t, &quat); + ACTION_RETURN_QUAT(quat); +} + +void QuatSLerp( + double ax, double ay, double az, double aw, + double bx, double by, double bz, double bw, + double t, + DQuaternion* pquat +) +{ + auto from = DQuaternion { ax, ay, az, aw }; + auto to = DQuaternion { bx, by, bz, bw }; + *pquat = DQuaternion::SLerp(from, to, t); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, SLerp, QuatSLerp) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(ax); + PARAM_FLOAT(ay); + PARAM_FLOAT(az); + PARAM_FLOAT(aw); + PARAM_FLOAT(bx); + PARAM_FLOAT(by); + PARAM_FLOAT(bz); + PARAM_FLOAT(bw); + PARAM_FLOAT(t); + + DQuaternion quat; + QuatSLerp(ax, ay, az, aw, bx, by, bz, bw, t, &quat); + ACTION_RETURN_QUAT(quat); +} + +void QuatConjugate( + double x, double y, double z, double w, + DQuaternion* pquat +) +{ + *pquat = DQuaternion(x, y, z, w).Conjugate(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, Conjugate, QuatConjugate) +{ + PARAM_SELF_STRUCT_PROLOGUE(DQuaternion); + + DQuaternion quat; + QuatConjugate(self->X, self->Y, self->Z, self->W, &quat); + ACTION_RETURN_QUAT(quat); +} + +void QuatInverse( + double x, double y, double z, double w, + DQuaternion* pquat +) +{ + *pquat = DQuaternion(x, y, z, w).Inverse(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, Inverse, QuatInverse) +{ + PARAM_SELF_STRUCT_PROLOGUE(DQuaternion); + + DQuaternion quat; + QuatInverse(self->X, self->Y, self->Z, self->W, &quat); + ACTION_RETURN_QUAT(quat); +} diff --git a/src/common/scripting/jit/jit.cpp b/src/common/scripting/jit/jit.cpp index 9823a6029..13679d59a 100644 --- a/src/common/scripting/jit/jit.cpp +++ b/src/common/scripting/jit/jit.cpp @@ -6,6 +6,9 @@ extern PString *TypeString; extern PStruct *TypeVector2; extern PStruct *TypeVector3; +extern PStruct* TypeVector4; +extern PStruct* TypeQuaternion; +extern PStruct* TypeFQuaternion; static void OutputJitLog(const asmjit::StringLogger &logger); @@ -304,17 +307,24 @@ void JitCompiler::SetupSimpleFrame() { cc.mov(regA[rega++], x86::ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, a))); } - else if (type == TypeVector2) + else if (type == TypeVector2 || type == TypeFVector2) { cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); } - else if (type == TypeVector3) + else if (type == TypeVector3 || type == TypeFVector3) { cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); } + else if (type == TypeVector4 || type == TypeFVector4 || type == TypeQuaternion || type == TypeFQuaternion) + { + cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); + cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); + cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); + cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); + } else if (type == TypeFloat64) { cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); @@ -551,6 +561,20 @@ asmjit::X86Xmm JitCompiler::CheckRegF(int r0, int r1, int r2, int r3) } } +asmjit::X86Xmm JitCompiler::CheckRegF(int r0, int r1, int r2, int r3, int r4) +{ + if (r0 != r1 && r0 != r2 && r0 != r3 && r0 != r4) + { + return regF[r0]; + } + else + { + auto copy = newTempXmmSd(); + cc.movsd(copy, regF[r0]); + return copy; + } +} + asmjit::X86Gp JitCompiler::CheckRegS(int r0, int r1) { if (r0 != r1) diff --git a/src/common/scripting/jit/jit.h b/src/common/scripting/jit/jit.h index faaf65112..c4aa1fb27 100644 --- a/src/common/scripting/jit/jit.h +++ b/src/common/scripting/jit/jit.h @@ -5,4 +5,4 @@ JitFuncPtr JitCompile(VMScriptFunction *func); void JitDumpLog(FILE *file, VMScriptFunction *func); -FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames); +FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1); diff --git a/src/common/scripting/jit/jit_call.cpp b/src/common/scripting/jit/jit_call.cpp index ee35fc139..e6c1feb0b 100644 --- a/src/common/scripting/jit/jit_call.cpp +++ b/src/common/scripting/jit/jit_call.cpp @@ -182,6 +182,13 @@ int JitCompiler::StoreCallParams() } numparams += 2; break; + case REGT_FLOAT | REGT_MULTIREG4: + for (int j = 0; j < 4; j++) + { + cc.movsd(x86::qword_ptr(vmframe, offsetParams + (slot + j) * sizeof(VMValue) + myoffsetof(VMValue, f)), regF[bc + j]); + } + numparams += 3; + break; case REGT_FLOAT | REGT_ADDROF: cc.lea(stackPtr, x86::ptr(vmframe, offsetF + (int)(bc * sizeof(double)))); // When passing the address to a float we don't know if the receiving function will treat it as float, vec2 or vec3. @@ -256,6 +263,12 @@ void JitCompiler::LoadCallResult(int type, int regnum, bool addrof) cc.movsd(regF[regnum + 1], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 1) * sizeof(double))); cc.movsd(regF[regnum + 2], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 2) * sizeof(double))); } + else if (type & REGT_MULTIREG4) + { + cc.movsd(regF[regnum + 1], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 1) * sizeof(double))); + cc.movsd(regF[regnum + 2], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 2) * sizeof(double))); + cc.movsd(regF[regnum + 3], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 3) * sizeof(double))); + } break; case REGT_STRING: // We don't have to do anything in this case. String values are never moved to virtual registers. @@ -340,7 +353,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) I_Error("Unexpected register type for self pointer\n"); break; } - + cc.test(*reg, *reg); cc.jz(label); } @@ -408,6 +421,11 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) call->setArg(slot + j, regF[bc + j]); numparams += 2; break; + case REGT_FLOAT | REGT_MULTIREG4: + for (int j = 0; j < 4; j++) + call->setArg(slot + j, regF[bc + j]); + numparams += 3; + break; case REGT_FLOAT | REGT_KONST: tmp = newTempIntPtr(); tmp2 = newTempXmmSd(); @@ -550,6 +568,12 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) cc.movsd(regF[regnum + 1], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 1) * sizeof(double))); cc.movsd(regF[regnum + 2], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 2) * sizeof(double))); break; + case REGT_FLOAT | REGT_MULTIREG4: + cc.movsd(regF[regnum], asmjit::x86::qword_ptr(vmframe, offsetF + regnum * sizeof(double))); + cc.movsd(regF[regnum + 1], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 1) * sizeof(double))); + cc.movsd(regF[regnum + 2], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 2) * sizeof(double))); + cc.movsd(regF[regnum + 3], asmjit::x86::qword_ptr(vmframe, offsetF + (regnum + 3) * sizeof(double))); + break; case REGT_STRING: // We don't have to do anything in this case. String values are never moved to virtual registers. break; @@ -624,6 +648,13 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature() args.Push(TypeIdOf::kTypeId); key += "fff"; break; + case REGT_FLOAT | REGT_MULTIREG4: + args.Push(TypeIdOf::kTypeId); + args.Push(TypeIdOf::kTypeId); + args.Push(TypeIdOf::kTypeId); + args.Push(TypeIdOf::kTypeId); + key += "ffff"; + break; default: I_Error("Unknown REGT value passed to EmitPARAM\n"); diff --git a/src/common/scripting/jit/jit_flow.cpp b/src/common/scripting/jit/jit_flow.cpp index 8439481cf..3b5acd1ab 100644 --- a/src/common/scripting/jit/jit_flow.cpp +++ b/src/common/scripting/jit/jit_flow.cpp @@ -7,7 +7,7 @@ void JitCompiler::EmitTEST() cc.cmp(regD[A], BC); cc.jne(GetLabel(i + 2)); } - + void JitCompiler::EmitTESTN() { int bc = BC; @@ -110,7 +110,21 @@ void JitCompiler::EmitRET() if (regtype & REGT_KONST) { auto tmp = newTempInt64(); - if (regtype & REGT_MULTIREG3) + if (regtype & REGT_MULTIREG4) + { + cc.mov(tmp, (((int64_t*)konstf)[regnum])); + cc.mov(x86::qword_ptr(location), tmp); + + cc.mov(tmp, (((int64_t*)konstf)[regnum + 1])); + cc.mov(x86::qword_ptr(location, 8), tmp); + + cc.mov(tmp, (((int64_t*)konstf)[regnum + 2])); + cc.mov(x86::qword_ptr(location, 16), tmp); + + cc.mov(tmp, (((int64_t*)konstf)[regnum + 3])); + cc.mov(x86::qword_ptr(location, 24), tmp); + } + else if (regtype & REGT_MULTIREG3) { cc.mov(tmp, (((int64_t *)konstf)[regnum])); cc.mov(x86::qword_ptr(location), tmp); @@ -137,7 +151,14 @@ void JitCompiler::EmitRET() } else { - if (regtype & REGT_MULTIREG3) + if (regtype & REGT_MULTIREG4) + { + cc.movsd(x86::qword_ptr(location), regF[regnum]); + cc.movsd(x86::qword_ptr(location, 8), regF[regnum + 1]); + cc.movsd(x86::qword_ptr(location, 16), regF[regnum + 2]); + cc.movsd(x86::qword_ptr(location, 24), regF[regnum + 3]); + } + else if (regtype & REGT_MULTIREG3) { cc.movsd(x86::qword_ptr(location), regF[regnum]); cc.movsd(x86::qword_ptr(location, 8), regF[regnum + 1]); diff --git a/src/common/scripting/jit/jit_load.cpp b/src/common/scripting/jit/jit_load.cpp index 0881cfd21..60947084d 100644 --- a/src/common/scripting/jit/jit_load.cpp +++ b/src/common/scripting/jit/jit_load.cpp @@ -325,6 +325,106 @@ void JitCompiler::EmitLV3_R() cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); } +void JitCompiler::EmitLV4() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); + cc.movsd(regF[A + 3], asmjit::x86::qword_ptr(tmp, 24)); +} + +void JitCompiler::EmitLV4_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); + cc.movsd(regF[A + 3], asmjit::x86::qword_ptr(tmp, 24)); +} + +void JitCompiler::EmitLFV2() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); +} + +void JitCompiler::EmitLFV2_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); +} + +void JitCompiler::EmitLFV3() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 8)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); +} + +void JitCompiler::EmitLFV3_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 8)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); +} + +void JitCompiler::EmitLFV4() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 8)); + cc.movss(regF[A + 3], asmjit::x86::qword_ptr(tmp, 12)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); + cc.cvtss2sd(regF[A + 3], regF[A + 3]); +} + +void JitCompiler::EmitLFV4_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 8)); + cc.movss(regF[A + 3], asmjit::x86::qword_ptr(tmp, 12)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); + cc.cvtss2sd(regF[A + 3], regF[A + 3]); +} + static void SetString(FString *to, char **from) { *to = *from; diff --git a/src/common/scripting/jit/jit_math.cpp b/src/common/scripting/jit/jit_math.cpp index d2fb45c7d..24328b9d3 100644 --- a/src/common/scripting/jit/jit_math.cpp +++ b/src/common/scripting/jit/jit_math.cpp @@ -902,7 +902,7 @@ void JitCompiler::EmitMINF_RK() cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); cc.minpd(regF[A], rb); // minsd requires SSE 4.1 } - + void JitCompiler::EmitMAXF_RR() { auto rc = CheckRegF(C, A); @@ -919,7 +919,7 @@ void JitCompiler::EmitMAXF_RK() cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp)); cc.maxpd(regF[A], rb); // maxsd requires SSE 4.1 } - + void JitCompiler::EmitATAN2() { auto result = newResultXmmSd(); @@ -1441,12 +1441,227 @@ void JitCompiler::EmitEQV3_R() EmitVectorComparison<3> (check, fail, success); }); } - + void JitCompiler::EmitEQV3_K() { I_Error("EQV3_K is not used."); } +///////////////////////////////////////////////////////////////////////////// +// Vector math. (4D/Quaternion) + +void JitCompiler::EmitNEGV4() +{ + auto mask = cc.newDoubleConst(asmjit::kConstScopeLocal, -0.0); + auto maskXmm = newTempXmmSd(); + cc.movsd(maskXmm, mask); + cc.movsd(regF[A], regF[B]); + cc.xorpd(regF[A], maskXmm); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.xorpd(regF[A + 1], maskXmm); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.xorpd(regF[A + 2], maskXmm); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.xorpd(regF[A + 3], maskXmm); +} + +void JitCompiler::EmitADDV4_RR() +{ + auto rc0 = CheckRegF(C, A); + auto rc1 = CheckRegF(C + 1, A + 1); + auto rc2 = CheckRegF(C + 2, A + 2); + auto rc3 = CheckRegF(C + 3, A + 3); + cc.movsd(regF[A], regF[B]); + cc.addsd(regF[A], rc0); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.addsd(regF[A + 1], rc1); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.addsd(regF[A + 2], rc2); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.addsd(regF[A + 3], rc3); +} + +void JitCompiler::EmitSUBV4_RR() +{ + auto rc0 = CheckRegF(C, A); + auto rc1 = CheckRegF(C + 1, A + 1); + auto rc2 = CheckRegF(C + 2, A + 2); + auto rc3 = CheckRegF(C + 3, A + 3); + cc.movsd(regF[A], regF[B]); + cc.subsd(regF[A], rc0); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.subsd(regF[A + 1], rc1); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.subsd(regF[A + 2], rc2); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.subsd(regF[A + 3], rc3); +} + +void JitCompiler::EmitDOTV4_RR() +{ + auto rb1 = CheckRegF(B + 1, A); + auto rb2 = CheckRegF(B + 2, A); + auto rb3 = CheckRegF(B + 3, A); + auto rc0 = CheckRegF(C, A); + auto rc1 = CheckRegF(C + 1, A); + auto rc2 = CheckRegF(C + 2, A); + auto rc3 = CheckRegF(C + 3, A); + auto tmp = newTempXmmSd(); + cc.movsd(regF[A], regF[B]); + cc.mulsd(regF[A], rc0); + cc.movsd(tmp, rb1); + cc.mulsd(tmp, rc1); + cc.addsd(regF[A], tmp); + cc.movsd(tmp, rb2); + cc.mulsd(tmp, rc2); + cc.addsd(regF[A], tmp); + cc.movsd(tmp, rb3); + cc.mulsd(tmp, rc3); + cc.addsd(regF[A], tmp); +} + +void JitCompiler::EmitMULVF4_RR() +{ + auto rc = CheckRegF(C, A, A + 1, A + 2, A + 3); + cc.movsd(regF[A], regF[B]); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.mulsd(regF[A], rc); + cc.mulsd(regF[A + 1], rc); + cc.mulsd(regF[A + 2], rc); + cc.mulsd(regF[A + 3], rc); +} + +void JitCompiler::EmitMULVF4_RK() +{ + auto tmp = newTempIntPtr(); + cc.movsd(regF[A], regF[B]); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.mov(tmp, asmjit::imm_ptr(&konstf[C])); + cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.mulsd(regF[A + 1], asmjit::x86::qword_ptr(tmp)); + cc.mulsd(regF[A + 2], asmjit::x86::qword_ptr(tmp)); + cc.mulsd(regF[A + 3], asmjit::x86::qword_ptr(tmp)); +} + +void JitCompiler::EmitDIVVF4_RR() +{ + auto rc = CheckRegF(C, A, A + 1, A + 2, A + 3); + cc.movsd(regF[A], regF[B]); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.divsd(regF[A], rc); + cc.divsd(regF[A + 1], rc); + cc.divsd(regF[A + 2], rc); + cc.divsd(regF[A + 3], rc); +} + +void JitCompiler::EmitDIVVF4_RK() +{ + auto tmp = newTempIntPtr(); + cc.movsd(regF[A], regF[B]); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.movsd(regF[A + 3], regF[B + 3]); + cc.mov(tmp, asmjit::imm_ptr(&konstf[C])); + cc.divsd(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.divsd(regF[A + 1], asmjit::x86::qword_ptr(tmp)); + cc.divsd(regF[A + 2], asmjit::x86::qword_ptr(tmp)); + cc.divsd(regF[A + 3], asmjit::x86::qword_ptr(tmp)); +} + +void JitCompiler::EmitLENV4() +{ + auto rb1 = CheckRegF(B + 1, A); + auto rb2 = CheckRegF(B + 2, A); + auto rb3 = CheckRegF(B + 3, A); + auto tmp = newTempXmmSd(); + cc.movsd(regF[A], regF[B]); + cc.mulsd(regF[A], regF[B]); + cc.movsd(tmp, rb1); + cc.mulsd(tmp, rb1); + cc.addsd(regF[A], tmp); + cc.movsd(tmp, rb2); + cc.mulsd(tmp, rb2); + cc.addsd(regF[A], tmp); + cc.movsd(tmp, rb3); + cc.mulsd(tmp, rb3); + cc.addsd(regF[A], tmp); + CallSqrt(regF[A], regF[A]); +} + +void JitCompiler::EmitEQV4_R() +{ + EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { + EmitVectorComparison<4> (check, fail, success); + }); +} + +void JitCompiler::EmitEQV4_K() +{ + I_Error("EQV4_K is not used."); +} + +// Quaternion ops +void FuncMULQQ(void *result, double ax, double ay, double az, double aw, double bx, double by, double bz, double bw) +{ + *reinterpret_cast(result) = DQuaternion(ax, ay, az, aw) * DQuaternion(bx, by, bz, bw); +} + +void FuncMULQV3(void *result, double ax, double ay, double az, double aw, double bx, double by, double bz) +{ + *reinterpret_cast(result) = DQuaternion(ax, ay, az, aw) * DVector3(bx, by, bz); +} + +void JitCompiler::EmitMULQQ_RR() +{ + auto stack = GetTemporaryVectorStackStorage(); + auto tmp = newTempIntPtr(); + cc.lea(tmp, stack); + + auto call = CreateCall(FuncMULQQ); + call->setArg(0, tmp); + call->setArg(1, regF[B + 0]); + call->setArg(2, regF[B + 1]); + call->setArg(3, regF[B + 2]); + call->setArg(4, regF[B + 3]); + call->setArg(5, regF[C + 0]); + call->setArg(6, regF[C + 1]); + call->setArg(7, regF[C + 2]); + call->setArg(8, regF[C + 3]); + + cc.movsd(regF[A + 0], asmjit::x86::qword_ptr(tmp, 0)); + cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); + cc.movsd(regF[A + 3], asmjit::x86::qword_ptr(tmp, 24)); +} + +void JitCompiler::EmitMULQV3_RR() +{ + auto stack = GetTemporaryVectorStackStorage(); + auto tmp = newTempIntPtr(); + cc.lea(tmp, stack); + + auto call = CreateCall(FuncMULQV3); + call->setArg(0, tmp); + call->setArg(1, regF[B + 0]); + call->setArg(2, regF[B + 1]); + call->setArg(3, regF[B + 2]); + call->setArg(4, regF[B + 3]); + call->setArg(5, regF[C + 0]); + call->setArg(6, regF[C + 1]); + call->setArg(7, regF[C + 2]); + + cc.movsd(regF[A + 0], asmjit::x86::qword_ptr(tmp, 0)); + cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); +} + + ///////////////////////////////////////////////////////////////////////////// // Pointer math. diff --git a/src/common/scripting/jit/jit_move.cpp b/src/common/scripting/jit/jit_move.cpp index 63f6158e3..840a6487c 100644 --- a/src/common/scripting/jit/jit_move.cpp +++ b/src/common/scripting/jit/jit_move.cpp @@ -39,11 +39,20 @@ void JitCompiler::EmitMOVEV3() cc.movsd(regF[A + 2], regF[B + 2]); } +void JitCompiler::EmitMOVEV4() +{ + cc.movsd(regF[A], regF[B]); + cc.movsd(regF[A + 1], regF[B + 1]); + cc.movsd(regF[A + 2], regF[B + 2]); + cc.movsd(regF[A + 3], regF[B + 3]); +} + static void CastI2S(FString *a, int b) { a->Format("%d", b); } static void CastU2S(FString *a, int b) { a->Format("%u", b); } static void CastF2S(FString *a, double b) { a->Format("%.5f", b); } static void CastV22S(FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); } static void CastV32S(FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); } +static void CastV42S(FString *a, double b, double b1, double b2, double b3) { a->Format("(%.5f, %.5f, %.5f, %.5f)", b, b1, b2, b3); } static void CastP2S(FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); } static int CastS2I(FString *b) { return (int)b->ToLong(); } static double CastS2F(FString *b) { return b->ToDouble(); } @@ -51,8 +60,8 @@ static int CastS2N(FString *b) { return b->Len() == 0 ? NAME_None : FName(*b).Ge 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 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 FSoundID(*b); } -static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(b); } +static int CastS2So(FString *b) { return S_FindSound(*b).index(); } +static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(FSoundID::fromInt(b)); } static void CastSID2S(FString* a, unsigned int b) { VM_CastSpriteIDToString(a, b); } static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetGameTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); } @@ -109,6 +118,14 @@ void JitCompiler::EmitCAST() call->setArg(2, regF[B + 1]); call->setArg(3, regF[B + 2]); break; + case CAST_V42S: + call = CreateCall(CastV42S); + call->setArg(0, regS[A]); + call->setArg(1, regF[B]); + call->setArg(2, regF[B + 1]); + call->setArg(3, regF[B + 2]); + call->setArg(4, regF[B + 3]); + break; case CAST_P2S: call = CreateCall(CastP2S); call->setArg(0, regS[A]); diff --git a/src/common/scripting/jit/jit_runtime.cpp b/src/common/scripting/jit/jit_runtime.cpp index b0a9dc488..89672b940 100644 --- a/src/common/scripting/jit/jit_runtime.cpp +++ b/src/common/scripting/jit/jit_runtime.cpp @@ -5,6 +5,7 @@ #ifdef WIN32 #include +#include #else #include #include @@ -56,7 +57,7 @@ static void *AllocJitMemory(size_t size) } else { - const size_t bytesToAllocate = std::max(size_t(1024 * 1024), size); + const size_t bytesToAllocate = max(size_t(1024 * 1024), size); size_t allocatedSize = 0; void *p = OSUtils::allocVirtualMemory(bytesToAllocate, &allocatedSize, OSUtils::kVMWritable | OSUtils::kVMExecutable); if (!p) @@ -403,7 +404,7 @@ static void WriteCIE(TArray &stream, const TArray &cieInstruct unsigned int lengthPos = stream.Size(); WriteUInt32(stream, 0); // Length WriteUInt32(stream, 0); // CIE ID - + WriteUInt8(stream, 1); // CIE Version WriteUInt8(stream, 'z'); WriteUInt8(stream, 'R'); // fde encoding @@ -428,7 +429,7 @@ static void WriteFDE(TArray &stream, const TArray &fdeInstruct WriteUInt32(stream, 0); // Length uint32_t offsetToCIE = stream.Size() - cieLocation; WriteUInt32(stream, offsetToCIE); - + functionStart = stream.Size(); WriteUInt64(stream, 0); // func start WriteUInt64(stream, 0); // func size @@ -499,7 +500,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & // // The CFI_Parser::decodeFDE parser on the other side.. // https://github.com/llvm-mirror/libunwind/blob/master/src/DwarfParser.hpp - + // Asmjit -> DWARF register id int dwarfRegId[16]; dwarfRegId[X86Gp::kIdAx] = 0; @@ -520,7 +521,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & dwarfRegId[X86Gp::kIdR15] = 15; int dwarfRegRAId = 16; int dwarfRegXmmId = 17; - + TArray cieInstructions; TArray fdeInstructions; @@ -529,7 +530,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & WriteDefineCFA(cieInstructions, dwarfRegId[X86Gp::kIdSp], stackOffset); WriteRegisterStackLocation(cieInstructions, returnAddressReg, stackOffset); - + FuncFrameLayout layout; Error error = layout.init(func->getDetail(), func->getFrameInfo()); if (error != kErrorOk) @@ -702,7 +703,7 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler) uint64_t length64 = *((uint64_t *)(entry + 4)); if (length64 == 0) break; - + uint64_t offset = *((uint64_t *)(entry + 12)); if (offset != 0) { @@ -803,7 +804,7 @@ static int CaptureStackTrace(int max_frames, void **out_frames) #elif defined(WIN32) // JIT isn't supported here, so just do nothing. - return 0;//return RtlCaptureStackBackTrace(0, MIN(max_frames, 32), out_frames, nullptr); + return 0;//return RtlCaptureStackBackTrace(0, min(max_frames, 32), out_frames, nullptr); #else return backtrace(out_frames, max_frames); #endif @@ -813,8 +814,16 @@ static int CaptureStackTrace(int max_frames, void **out_frames) class NativeSymbolResolver { public: - NativeSymbolResolver() { SymInitialize(GetCurrentProcess(), nullptr, TRUE); } - ~NativeSymbolResolver() { SymCleanup(GetCurrentProcess()); } + NativeSymbolResolver() + { + SymInitialize(GetCurrentProcess(), nullptr, TRUE); + GetModuleInformation(GetCurrentProcess(), GetModuleHandle(0), &moduleInfo, sizeof(MODULEINFO)); + } + + ~NativeSymbolResolver() + { + SymCleanup(GetCurrentProcess()); + } FString GetName(void *frame) { @@ -830,11 +839,14 @@ public: BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, symbol64); if (result) { + if ((DWORD64)frame < (DWORD64)moduleInfo.lpBaseOfDll || (DWORD64)frame >= ((DWORD64)moduleInfo.lpBaseOfDll + moduleInfo.SizeOfImage)) + return s; // Ignore anything not from the exe itself + IMAGEHLP_LINE64 line64; - DWORD displacement = 0; + DWORD displacement1 = 0; memset(&line64, 0, sizeof(IMAGEHLP_LINE64)); line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, &line64); + result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement1, &line64); if (result) { s.Format("Called from %s at %s, line %d\n", symbol64->Name, line64.FileName, (int)line64.LineNumber); @@ -847,6 +859,8 @@ public: return s; } + + MODULEINFO moduleInfo = {}; }; #else class NativeSymbolResolver @@ -952,7 +966,7 @@ FString JitGetStackFrameName(NativeSymbolResolver *nativeSymbols, void *pc) return nativeSymbols ? nativeSymbols->GetName(pc) : FString(); } -FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames) +FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames) { void *frames[32]; int numframes = CaptureStackTrace(32, frames); @@ -961,10 +975,18 @@ FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames) if (includeNativeFrames) nativeSymbols.reset(new NativeSymbolResolver()); + int total = 0; FString s; for (int i = framesToSkip + 1; i < numframes; i++) { - s += JitGetStackFrameName(nativeSymbols.get(), frames[i]); + FString name = JitGetStackFrameName(nativeSymbols.get(), frames[i]); + if (!name.IsEmpty()) + { + s += name; + total++; + if (maxFrames != -1 && maxFrames == total) + break; + } } return s; } diff --git a/src/common/scripting/jit/jit_store.cpp b/src/common/scripting/jit/jit_store.cpp index 6dc1a45a9..49464691e 100644 --- a/src/common/scripting/jit/jit_store.cpp +++ b/src/common/scripting/jit/jit_store.cpp @@ -161,6 +161,122 @@ void JitCompiler::EmitSV3_R() cc.movsd(asmjit::x86::qword_ptr(tmp, 16), regF[B + 2]); } +void JitCompiler::EmitSV4() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + cc.movsd(asmjit::x86::qword_ptr(tmp), regF[B]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 8), regF[B + 1]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 16), regF[B + 2]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 24), regF[B + 3]); +} + +void JitCompiler::EmitSV4_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + cc.movsd(asmjit::x86::qword_ptr(tmp), regF[B]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 8), regF[B + 1]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 16), regF[B + 2]); + cc.movsd(asmjit::x86::qword_ptr(tmp, 24), regF[B + 3]); +} + +void JitCompiler::EmitSFV2() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + +void JitCompiler::EmitSFV2_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + +void JitCompiler::EmitSFV3() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 8), tmpF); +} + +void JitCompiler::EmitSFV3_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 8), tmpF); +} + +void JitCompiler::EmitSFV4() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 8), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 3]); + cc.movss(asmjit::x86::qword_ptr(tmp, 12), tmpF); +} + +void JitCompiler::EmitSFV4_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 8), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 3]); + cc.movss(asmjit::x86::qword_ptr(tmp, 12), tmpF); +} + void JitCompiler::EmitSBIT() { EmitNullPointerThrow(A, X_WRITE_NIL); diff --git a/src/common/scripting/jit/jitintern.h b/src/common/scripting/jit/jitintern.h index ac3d8acf5..aaf8d70a6 100644 --- a/src/common/scripting/jit/jitintern.h +++ b/src/common/scripting/jit/jitintern.h @@ -186,7 +186,13 @@ private: asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)) { return cc.call(asmjit::imm_ptr(reinterpret_cast(static_cast(func))), asmjit::FuncSignature6()); } template - asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)) { return cc.call(asmjit::imm_ptr(reinterpret_cast(static_cast(func))), asmjit::FuncSignature7()); } + asmjit::CCFuncCall* CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)) { return cc.call(asmjit::imm_ptr(reinterpret_cast(static_cast(func))), asmjit::FuncSignature7()); } + + template + asmjit::CCFuncCall* CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)) { return cc.call(asmjit::imm_ptr(reinterpret_cast(static_cast(func))), asmjit::FuncSignature8()); } + + template + asmjit::CCFuncCall* CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9)) { return cc.call(asmjit::imm_ptr(reinterpret_cast(static_cast(func))), asmjit::FuncSignature9()); } FString regname; size_t tmpPosInt32, tmpPosInt64, tmpPosIntPtr, tmpPosXmmSd, tmpPosXmmSs, tmpPosXmmPd, resultPosInt32, resultPosIntPtr, resultPosXmmSd; @@ -241,6 +247,7 @@ private: asmjit::X86Xmm CheckRegF(int r0, int r1); asmjit::X86Xmm CheckRegF(int r0, int r1, int r2); asmjit::X86Xmm CheckRegF(int r0, int r1, int r2, int r3); + asmjit::X86Xmm CheckRegF(int r0, int r1, int r2, int r3, int r4); asmjit::X86Gp CheckRegS(int r0, int r1); asmjit::X86Gp CheckRegA(int r0, int r1); @@ -304,6 +311,19 @@ private: TArray labels; + // Get temporary storage enough for DVector4 which is required by operation such as MULQQ and MULQV3 + bool vectorStackAllocated = false; + asmjit::X86Mem vectorStack; + asmjit::X86Mem GetTemporaryVectorStackStorage() + { + if (!vectorStackAllocated) + { + vectorStack = cc.newStack(sizeof(DVector4), alignof(DVector4), "tmpDVector4"); + vectorStackAllocated = true; + } + return vectorStack; + } + const VMOP *pc; VM_UBYTE op; }; diff --git a/src/common/scripting/vm/vm.h b/src/common/scripting/vm/vm.h index d0a34a975..3766e9d31 100644 --- a/src/common/scripting/vm/vm.h +++ b/src/common/scripting/vm/vm.h @@ -39,6 +39,7 @@ #include "autosegs.h" #include "zstring.h" #include "vectors.h" +#include "quaternion.h" #include "cmdlib.h" #include "engineerrors.h" #include "memarena.h" @@ -80,8 +81,9 @@ enum REGT_KONST = 4, REGT_MULTIREG2 = 8, REGT_MULTIREG3 = 16, // (e.g. a vector) - REGT_MULTIREG = 24, + REGT_MULTIREG = 8 | 16 | 64, REGT_ADDROF = 32, // used with PARAM: pass address of this register + REGT_MULTIREG4 = 64, REGT_NIL = 128 // parameter was omitted }; @@ -110,8 +112,8 @@ public: }; // This must be a separate function because the VC compiler would otherwise allocate memory on the stack for every separate instance of the exception object that may get thrown. -void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...); -void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...); +[[noreturn]] void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...); +[[noreturn]] void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...); void ClearGlobalVMStack(); @@ -130,8 +132,32 @@ struct VMReturn assert(RegType == REGT_FLOAT); *(double *)Location = val; } + void SetVector4(const double val[4]) + { + assert(RegType == (REGT_FLOAT|REGT_MULTIREG4)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + ((double *)Location)[2] = val[2]; + ((double *)Location)[3] = val[3]; + } + void SetVector4(const DVector4 &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG4)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + ((double *)Location)[2] = val[2]; + ((double *)Location)[3] = val[3]; + } + void SetQuaternion(const DQuaternion &val) + { + assert(RegType == (REGT_FLOAT | REGT_MULTIREG4)); + ((double *)Location)[0] = val[0]; + ((double *)Location)[1] = val[1]; + ((double *)Location)[2] = val[2]; + ((double *)Location)[3] = val[3]; + } void SetVector(const double val[3]) - { + { assert(RegType == (REGT_FLOAT|REGT_MULTIREG3)); ((double *)Location)[0] = val[0]; ((double *)Location)[1] = val[1]; @@ -189,6 +215,11 @@ struct VMReturn Location = loc; RegType = REGT_FLOAT | REGT_MULTIREG2; } + void Vec3At(DVector3 *loc) + { + Location = loc; + RegType = REGT_FLOAT | REGT_MULTIREG3; + } void StringAt(FString *loc) { Location = loc; @@ -203,6 +234,7 @@ struct VMReturn VMReturn(int *loc) { IntAt(loc); } VMReturn(double *loc) { FloatAt(loc); } VMReturn(DVector2 *loc) { Vec2At(loc); } + VMReturn(DVector3 *loc) { Vec3At(loc); } VMReturn(FString *loc) { StringAt(loc); } VMReturn(void **loc) { PointerAt(loc); } }; @@ -315,6 +347,10 @@ struct VMValue { i = v; } + VMValue(unsigned int v) + { + i = v; + } VMValue(double v) { f = v; @@ -492,6 +528,7 @@ inline int VMCallAction(VMFunction *func, VMValue *params, int numparams, VMRetu // Use these to collect the parameters in a native function. // variable name at position

+[[noreturn]] void NullParam(const char *varname); #ifndef NDEBUG @@ -508,10 +545,11 @@ bool AssertObject(void * ob); #define PARAM_UINT_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); unsigned x = param[p].i; #define PARAM_BOOL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); bool x = !!param[p].i; #define PARAM_NAME_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FName x = ENamedName(param[p].i); -#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FSoundID x = param[p].i; -#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); PalEntry x; x.d = param[p].i; +#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FSoundID x = FSoundID::fromInt(param[p].i); +#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); PalEntry x = param[p].i; #define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); double x = param[p].f; -#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); DAngle x = param[p].f; +#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); DAngle x = DAngle::fromDeg(param[p].f); +#define PARAM_FANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); FAngle x = FAngle::fromDeg(param[p].f); #define PARAM_STRING_VAL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); FString x = param[p].s(); #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); const FString &x = param[p].s(); #define PARAM_STATELABEL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); int x = param[p].i; @@ -538,6 +576,7 @@ bool AssertObject(void * ob); #define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x) #define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x) #define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x) +#define PARAM_FANGLE(x) ++paramnum; PARAM_FANGLE_AT(paramnum,x) #define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x) #define PARAM_STRING_VAL(x) ++paramnum; PARAM_STRING_VAL_AT(paramnum,x) #define PARAM_STATELABEL(x) ++paramnum; PARAM_STATELABEL_AT(paramnum,x) @@ -599,7 +638,8 @@ struct DirectNativeDesc 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); } - #undef TP + 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 void ValidateType() { static_assert(native_is_valid::value, "Argument type is not valid as a direct native parameter or return type"); } @@ -708,6 +748,13 @@ struct AFuncDesc extern FieldDesc const *const VMGlobal_##name##_HookPtr; \ MSVC_FSEG FieldDesc const *const VMGlobal_##name##_HookPtr GCC_FSEG = &VMGlobal_##name; +#define DEFINE_GLOBAL_UNSIZED(name) \ + static const FieldDesc VMGlobal_##name = { "", #name, (size_t)&name, ~0u, 0 }; \ + extern FieldDesc const *const VMGlobal_##name##_HookPtr; \ + MSVC_FSEG FieldDesc const *const VMGlobal_##name##_HookPtr GCC_FSEG = &VMGlobal_##name; + + + class AActor; @@ -717,6 +764,8 @@ class AActor; #define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) #define ACTION_RETURN_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(u); return 1; } return 0; } while(0) #define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_VEC4(v) do { DVector4 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector4(u); return 1; } return 0; } while(0) +#define ACTION_RETURN_QUAT(v) do { DQuaternion u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetQuaternion(u); return 1; } return 0; } while(0) #define ACTION_RETURN_INT(v) do { int u = v; if (numret > 0) { assert(ret != NULL); ret->SetInt(u); return 1; } return 0; } while(0) #define ACTION_RETURN_BOOL(v) ACTION_RETURN_INT(v) #define ACTION_RETURN_STRING(v) do { FString u = v; if (numret > 0) { assert(ret != NULL); ret->SetString(u); return 1; } return 0; } while(0) diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h index defbcdf6d..6716509da 100644 --- a/src/common/scripting/vm/vmexec.h +++ b/src/common/scripting/vm/vmexec.h @@ -263,44 +263,126 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) GETADDR(PB,RC,X_READ_NIL); reg.a[a] = *(void **)ptr; NEXTOP; - OP(LV2): + OP(LV2) : + ASSERTF(a + 1); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + } + NEXTOP; + OP(LV2_R) : + ASSERTF(a + 1); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + } + NEXTOP; + OP(LV3) : + ASSERTF(a + 2); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + reg.f[a+2] = v[2]; + } + NEXTOP; + OP(LV3_R) : + ASSERTF(a + 2); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + reg.f[a+2] = v[2]; + } + NEXTOP; + OP(LV4) : + ASSERTF(a + 3); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + reg.f[a + 2] = v[2]; + reg.f[a + 3] = v[3]; + } + NEXTOP; + OP(LV4_R) : + ASSERTF(a + 3); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + reg.f[a + 2] = v[2]; + reg.f[a + 3] = v[3]; + } + NEXTOP; + OP(LFV2): ASSERTF(a+1); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; } NEXTOP; - OP(LV2_R): + OP(LFV2_R): ASSERTF(a+1); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; } NEXTOP; - OP(LV3): + OP(LFV3): ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; } NEXTOP; - OP(LV3_R): + OP(LFV3_R): ASSERTF(a+2); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; } NEXTOP; + OP(LFV4) : + ASSERTF(a + 3); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (float*)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + reg.f[a+2] = v[2]; + reg.f[a+3] = v[3]; + } + NEXTOP; + OP(LFV4_R) : + ASSERTF(a + 3); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (float*)ptr; + reg.f[a] = v[0]; + reg.f[a+1] = v[1]; + reg.f[a+2] = v[2]; + reg.f[a+3] = v[3]; + } + NEXTOP; OP(LBIT): ASSERTD(a); ASSERTA(B); GETADDR(PB,0,X_READ_NIL); @@ -430,6 +512,88 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) v[2] = reg.f[B+2]; } NEXTOP; + OP(SV4): + ASSERTA(a); ASSERTF(B+3); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; + v[3] = reg.f[B+3]; + } + NEXTOP; + OP(SV4_R): + ASSERTA(a); ASSERTF(B+3); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (double *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; + v[3] = reg.f[B+3]; + } + NEXTOP; + OP(SFV2): + ASSERTA(a); ASSERTF(B+1); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + } + NEXTOP; + OP(SFV2_R): + ASSERTA(a); ASSERTF(B+1); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + } + NEXTOP; + OP(SFV3): + ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + v[2] = (float)reg.f[B+2]; + } + NEXTOP; + OP(SFV3_R): + ASSERTA(a); ASSERTF(B+2); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + v[2] = (float)reg.f[B+2]; + } + NEXTOP; + OP(SFV4): + ASSERTA(a); ASSERTF(B+3); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + v[2] = (float)reg.f[B+2]; + v[3] = (float)reg.f[B+3]; + } + NEXTOP; + OP(SFV4_R): + ASSERTA(a); ASSERTF(B+3); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = (float)reg.f[B]; + v[1] = (float)reg.f[B+1]; + v[2] = (float)reg.f[B+2]; + v[3] = (float)reg.f[B+3]; + } + NEXTOP; OP(SBIT): ASSERTA(a); ASSERTD(B); GETADDR(PA,0,X_WRITE_NIL); @@ -479,6 +643,16 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) reg.f[a + 2] = reg.f[b + 2]; NEXTOP; } + OP(MOVEV4) : + { + ASSERTF(a); ASSERTF(B); + b = B; + reg.f[a] = reg.f[b]; + reg.f[a + 1] = reg.f[b + 1]; + reg.f[a + 2] = reg.f[b + 2]; + reg.f[a + 3] = reg.f[b + 3]; + NEXTOP; + } OP(DYNCAST_R) : ASSERTA(a); ASSERTA(B); ASSERTA(C); b = B; @@ -515,7 +689,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) DoCast(reg, f, a, B, C); } NEXTOP; - + OP(CASTB): if (C == CASTB_I) { @@ -538,7 +712,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) reg.d[a] = reg.s[B].Len() > 0; } NEXTOP; - + OP(TEST): ASSERTD(a); if (reg.d[a] != BC) @@ -637,10 +811,23 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) ::new(param + 2) VMValue(reg.f[b + 2]); f->NumParam += 2; break; + case REGT_FLOAT | REGT_MULTIREG4: + assert(b < f->NumRegF - 3); + assert(f->NumParam < sfunc->MaxParam - 2); + ::new(param) VMValue(reg.f[b]); + ::new(param + 1) VMValue(reg.f[b + 1]); + ::new(param + 2) VMValue(reg.f[b + 2]); + ::new(param + 3) VMValue(reg.f[b + 3]); + f->NumParam += 3; + break; case REGT_FLOAT | REGT_ADDROF: assert(b < f->NumRegF); ::new(param) VMValue(®.f[b]); break; + case REGT_FLOAT | REGT_MULTIREG2 | REGT_ADDROF: + case REGT_FLOAT | REGT_MULTIREG3 | REGT_ADDROF: + case REGT_FLOAT | REGT_MULTIREG4 | REGT_ADDROF: + I_Error("REGT_ADDROF not implemented for vectors\n"); case REGT_FLOAT | REGT_KONST: assert(b < sfunc->NumKonstF); ::new(param) VMValue(konstf[b]); @@ -692,7 +879,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) { VMFunction *call = (VMFunction *)ptr; VMReturn returns[MAX_RETURNS]; - int numret; + int numret1; b = B; FillReturns(reg, f, returns, pc+1, C); @@ -701,7 +888,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) try { VMCycles[0].Unclock(); - numret = static_cast(call)->NativeCall(VM_INVOKE(reg.param + f->NumParam - b, b, returns, C, call->RegTypes)); + numret1 = static_cast(call)->NativeCall(VM_INVOKE(reg.param + f->NumParam - b, b, returns, C, call->RegTypes)); VMCycles[0].Clock(); } catch (CVMAbortException &err) @@ -714,10 +901,10 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) } else { - auto sfunc = static_cast(call); - numret = sfunc->ScriptCall(sfunc, reg.param + f->NumParam - b, b, returns, C); + auto sfunc1 = static_cast(call); + numret1 = sfunc1->ScriptCall(sfunc1, reg.param + f->NumParam - b, b, returns, C); } - assert(numret == C && "Number of parameters returned differs from what was expected by the caller"); + assert(numret1 == C && "Number of parameters returned differs from what was expected by the caller"); f->NumParam -= B; pc += C; // Skip RESULTs } @@ -852,37 +1039,37 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) ASSERTD(a); ASSERTS(B); reg.d[a] = (int)reg.s[B].Len(); NEXTOP; - + OP(CMPS): // String comparison is a fairly expensive operation, so I've // chosen to conserve a few opcodes by condensing all the // string comparisons into a single one. { - const FString *b, *c; + const FString *b1, *c1; int test, method; bool cmp; if (a & CMP_BK) { ASSERTKS(B); - b = &konsts[B]; + b1 = &konsts[B]; } else { ASSERTS(B); - b = ®.s[B]; + b1 = ®.s[B]; } if (a & CMP_CK) { ASSERTKS(C); - c = &konsts[C]; + c1 = &konsts[C]; } else { ASSERTS(C); - c = ®.s[C]; + c1 = ®.s[C]; } - test = (a & CMP_APPROX) ? b->CompareNoCase(*c) : b->Compare(*c); + test = (a & CMP_APPROX) ? b1->CompareNoCase(*c1) : b1->Compare(*c1); method = a & CMP_METHOD_MASK; if (method == CMP_EQ) { @@ -1302,12 +1489,10 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) ASSERTF(a); ASSERTF(B); ASSERTKF(C); fb = reg.f[B]; fc = konstf[C]; goto Do_MODF; - NEXTOP; OP(MODF_KR): ASSERTF(a); ASSERTKF(B); ASSERTF(C); fb = konstf[B]; fc = reg.f[C]; goto Do_MODF; - NEXTOP; OP(POWF_RR): ASSERTF(a); ASSERTF(B); ASSERTF(C); @@ -1349,7 +1534,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) fb = reg.f[B]; reg.f[a] = (C == FLOP_ABS) ? fabs(fb) : (C == FLOP_NEG) ? -fb : DoFLOP(C, fb); NEXTOP; - + OP(EQF_R): ASSERTF(B); ASSERTF(C); if (a & CMP_APPROX) @@ -1616,6 +1801,112 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) fcp = &konstf[C]; goto Do_EQV3; + OP(NEGV4): + ASSERTF(a+3); ASSERTF(B+3); + reg.f[a] = -reg.f[B]; + reg.f[a+1] = -reg.f[B+1]; + reg.f[a+2] = -reg.f[B+2]; + reg.f[a+3] = -reg.f[B+3]; + NEXTOP; + + OP(ADDV4_RR): + ASSERTF(a+3); ASSERTF(B+3); ASSERTF(C+3); + fcp = ®.f[C]; + fbp = ®.f[B]; + reg.f[a] = fbp[0] + fcp[0]; + reg.f[a+1] = fbp[1] + fcp[1]; + reg.f[a+2] = fbp[2] + fcp[2]; + reg.f[a+3] = fbp[3] + fcp[3]; + NEXTOP; + + OP(SUBV4_RR): + ASSERTF(a+3); ASSERTF(B+3); ASSERTF(C+3); + fbp = ®.f[B]; + fcp = ®.f[C]; + reg.f[a] = fbp[0] - fcp[0]; + reg.f[a+1] = fbp[1] - fcp[1]; + reg.f[a+2] = fbp[2] - fcp[2]; + reg.f[a+3] = fbp[3] - fcp[3]; + NEXTOP; + + OP(DOTV4_RR): + ASSERTF(a); ASSERTF(B+3); ASSERTF(C+3); + reg.f[a] = reg.f[B] * reg.f[C] + reg.f[B+1] * reg.f[C+1] + reg.f[B+2] * reg.f[C+2] + reg.f[B+3] * reg.f[C+3]; + NEXTOP; + + OP(MULVF4_RR): + ASSERTF(a+3); ASSERTF(B+3); ASSERTF(C); + fc = reg.f[C]; + fbp = ®.f[B]; + Do_MULV4: + reg.f[a] = fbp[0] * fc; + reg.f[a+1] = fbp[1] * fc; + reg.f[a+2] = fbp[2] * fc; + reg.f[a+3] = fbp[3] * fc; + NEXTOP; + OP(MULVF4_RK): + ASSERTF(a+3); ASSERTF(B+3); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_MULV4; + + OP(DIVVF4_RR): + ASSERTF(a+3); ASSERTF(B+3); ASSERTF(C); + fc = reg.f[C]; + fbp = ®.f[B]; + Do_DIVV4: + reg.f[a] = fbp[0] / fc; + reg.f[a+1] = fbp[1] / fc; + reg.f[a+2] = fbp[2] / fc; + reg.f[a+3] = fbp[3] / fc; + NEXTOP; + OP(DIVVF4_RK): + ASSERTF(a+3); ASSERTF(B+3); ASSERTKF(C); + fc = konstf[C]; + fbp = ®.f[B]; + goto Do_DIVV4; + + OP(LENV4): + ASSERTF(a); ASSERTF(B+3); + reg.f[a] = g_sqrt(reg.f[B] * reg.f[B] + reg.f[B+1] * reg.f[B+1] + reg.f[B+2] * reg.f[B+2]+ reg.f[B+3] * reg.f[B+3]); + NEXTOP; + + OP(EQV4_R): + ASSERTF(B+3); ASSERTF(C+3); + fcp = ®.f[C]; + Do_EQV4: + if (a & CMP_APPROX) + { + CMPJMP(fabs(reg.f[B ] - fcp[0]) < VM_EPSILON && + fabs(reg.f[B+1] - fcp[1]) < VM_EPSILON && + fabs(reg.f[B+2] - fcp[2]) < VM_EPSILON && + fabs(reg.f[B+3] - fcp[3]) < VM_EPSILON); + } + else + { + CMPJMP(reg.f[B] == fcp[0] && reg.f[B+1] == fcp[1] && reg.f[B+2] == fcp[2] && reg.f[B+3] == fcp[3]); + } + NEXTOP; + OP(EQV4_K): + ASSERTF(B+3); ASSERTKF(C+3); + fcp = &konstf[C]; + goto Do_EQV4; + OP(MULQV3_RR): + ASSERTF(a + 2); ASSERTF(B + 3); ASSERTF(C + 2); + { + const DQuaternion& q = reinterpret_cast(reg.f[B]); + const DVector3& v = reinterpret_cast(reg.f[C]); + reinterpret_cast(reg.f[A]) = q * v; + } + NEXTOP; + OP(MULQQ_RR): + ASSERTF(a + 3); ASSERTF(B + 3); ASSERTF(C + 3); + { + const DQuaternion& q1 = reinterpret_cast(reg.f[B]); + const DQuaternion& q2 = reinterpret_cast(reg.f[C]); + reinterpret_cast(reg.f[A]) = q1 * q2; + } + NEXTOP; OP(ADDA_RR): ASSERTA(a); ASSERTA(B); ASSERTD(C); c = reg.d[C]; @@ -1712,7 +2003,6 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) // PrintParameters(reg.param + f->NumParam - B, B); throw; } - return 0; } static double DoFLOP(int flop, double v) @@ -1836,12 +2126,12 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c case CAST_S2So: ASSERTD(a); ASSERTS(b); - reg.d[a] = FSoundID(reg.s[b]); + reg.d[a] = S_FindSound(reg.s[b]).index(); break; case CAST_So2S: ASSERTS(a); ASSERTD(b); - reg.s[a] = soundEngine->GetSoundName(reg.d[b]); + reg.s[a] = soundEngine->GetSoundName(FSoundID::fromInt(reg.d[b])); break; case CAST_SID2S: @@ -1955,7 +2245,11 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_ assert(regnum < frame->NumRegF); src = ®.f[regnum]; } - if (regtype & REGT_MULTIREG3) + if (regtype & REGT_MULTIREG4) + { + ret->SetVector4((double*)src); + } + else if (regtype & REGT_MULTIREG3) { ret->SetVector((double *)src); } diff --git a/src/common/scripting/vm/vmframe.cpp b/src/common/scripting/vm/vmframe.cpp index 4b50f9b21..a2c972820 100644 --- a/src/common/scripting/vm/vmframe.cpp +++ b/src/common/scripting/vm/vmframe.cpp @@ -37,7 +37,7 @@ #include "v_text.h" #include "stats.h" #include "c_dispatch.h" -#include "templates.h" + #include "vmintern.h" #include "types.h" #include "jit.h" @@ -56,7 +56,7 @@ CUSTOM_CVAR(Bool, vm_jit, true, CVAR_NOINITCALL) } #else CVAR(Bool, vm_jit, false, CVAR_NOINITCALL|CVAR_NOSET) -FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames) { return FString(); } +FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames) { return FString(); } void JitRelease() {} #endif @@ -682,22 +682,20 @@ void CVMAbortException::MaybePrintMessage() auto m = GetMessage(); if (m != nullptr) { - Printf(TEXTCOLOR_RED); - Printf("%s\n", m); + Printf(PRINT_NONOTIFY | PRINT_BOLD, TEXTCOLOR_RED "%s\n", m); SetMessage(""); } } -void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...) +[[noreturn]] void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...) { va_list ap; va_start(ap, moreinfo); throw CVMAbortException(reason, moreinfo, ap); - va_end(ap); } -void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...) +[[noreturn]] void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...) { va_list ap; va_start(ap, moreinfo); @@ -706,7 +704,6 @@ void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(line)); throw err; - va_end(ap); } DEFINE_ACTION_FUNCTION(DObject, ThrowAbortException) @@ -714,10 +711,9 @@ DEFINE_ACTION_FUNCTION(DObject, ThrowAbortException) PARAM_PROLOGUE; FString s = FStringFormat(VM_ARGS_NAMES); ThrowAbortException(X_OTHER, s.GetChars()); - return 0; } -void NullParam(const char *varname) +[[noreturn]] void NullParam(const char *varname) { ThrowAbortException(X_READ_NIL, "In function parameter %s", varname); } @@ -746,7 +742,7 @@ ADD_STAT(VM) for (auto d : VMCycles) { added += d.TimeMS(); - peak = MAX(peak, d.TimeMS()); + peak = max(peak, d.TimeMS()); } for (auto d : VMCalls) addedc += d; memmove(&VMCycles[1], &VMCycles[0], 9 * sizeof(cycle_t)); diff --git a/src/common/scripting/vm/vmintern.h b/src/common/scripting/vm/vmintern.h index b93f3e6ef..9a3e2d401 100644 --- a/src/common/scripting/vm/vmintern.h +++ b/src/common/scripting/vm/vmintern.h @@ -126,6 +126,7 @@ enum CAST_So2S, CAST_V22S, CAST_V32S, + CAST_V42S, CAST_SID2S, CAST_TID2S, diff --git a/src/common/scripting/vm/vmops.h b/src/common/scripting/vm/vmops.h index 82b3cabc4..1782e78b7 100644 --- a/src/common/scripting/vm/vmops.h +++ b/src/common/scripting/vm/vmops.h @@ -51,8 +51,16 @@ xx(LV2, lv2, RVRPKI, LV2_R, 4, REGT_INT) // load vector2 xx(LV2_R, lv2, RVRPRI, NOP, 0, 0) xx(LV3, lv3, RVRPKI, LV3_R, 4, REGT_INT) // load vector3 xx(LV3_R, lv3, RVRPRI, NOP, 0, 0) +xx(LV4, lv4, RVRPKI, LV4_R, 4, REGT_INT) // load vector4 +xx(LV4_R, lv4, RVRPRI, NOP, 0, 0) xx(LCS, lcs, RSRPKI, LCS_R, 4, REGT_INT) // load string from char ptr. xx(LCS_R, lcs, RSRPRI, NOP, 0, 0) +xx(LFV2, lfv2, RVRPKI, LFV2_R, 4, REGT_INT) // load fvector2 +xx(LFV2_R, lfv2, RVRPRI, NOP, 0, 0) +xx(LFV3, lfv3, RVRPKI, LFV3_R, 4, REGT_INT) // load fvector3 +xx(LFV3_R, lfv3, RVRPRI, NOP, 0, 0) +xx(LFV4, lfv4, RVRPKI, LFV4_R, 4, REGT_INT) // load fvector4 +xx(LFV4_R, lfv4, RVRPRI, NOP, 0, 0) xx(LBIT, lbit, RIRPI8, NOP, 0, 0) // rA = !!(*rB & C) -- *rB is a byte @@ -77,6 +85,14 @@ xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT) // store vector2 xx(SV2_R, sv2, RPRVRI, NOP, 0, 0) xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT) // store vector3 xx(SV3_R, sv3, RPRVRI, NOP, 0, 0) +xx(SV4, sv4, RPRVKI, SV4_R, 4, REGT_INT) // store vector4 +xx(SV4_R, sv4, RPRVRI, NOP, 0, 0) +xx(SFV2, sfv2, RPRVKI, SFV2_R, 4, REGT_INT) // store fvector2 +xx(SFV2_R, sfv2, RPRVRI, NOP, 0, 0) +xx(SFV3, sfv3, RPRVKI, SFV3_R, 4, REGT_INT) // store fvector3 +xx(SFV3_R, sfv3, RPRVRI, NOP, 0, 0) +xx(SFV4, sfv4, RPRVKI, SFV4_R, 4, REGT_INT) // store fvector4 +xx(SFV4_R, sfv4, RPRVRI, NOP, 0, 0) xx(SBIT, sbit, RPRII8, NOP, 0, 0) // *rA |= C if rB is true, *rA &= ~C otherwise @@ -87,6 +103,7 @@ xx(MOVES, mov, RSRS, NOP, 0, 0) // sA = sB xx(MOVEA, mov, RPRP, NOP, 0, 0) // aA = aB xx(MOVEV2, mov2, RFRF, NOP, 0, 0) // fA = fB (2 elements) xx(MOVEV3, mov3, RFRF, NOP, 0, 0) // fA = fB (3 elements) +xx(MOVEV4, mov4, RFRF, NOP, 0, 0) // fA = fB (4 elements) xx(CAST, cast, CAST, NOP, 0, 0) // xA = xB, conversion specified by C xx(CASTB, castb, CAST, NOP, 0, 0) // xA = !!xB, type specified by C xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0) // aA = dyn_cast(aB); @@ -248,6 +265,23 @@ xx(LENV3, lenv3, RFRV, NOP, 0, 0) // fA = vB.Length xx(EQV3_R, beqv3, CVRR, NOP, 0, 0) // if ((vB == vkC) != A) then pc++ (inexact if A & 33) xx(EQV3_K, beqv3, CVRK, NOP, 0, 0) // this will never be used. +// Vector math (4D) +xx(NEGV4, negv4, RVRV, NOP, 0, 0) // vA = -vB +xx(ADDV4_RR, addv4, RVRVRV, NOP, 0, 0) // vA = vB + vkC +xx(SUBV4_RR, subv4, RVRVRV, NOP, 0, 0) // vA = vkB - vkC +xx(DOTV4_RR, dotv4, RVRVRV, NOP, 0, 0) // va = vB dot vkC +xx(MULVF4_RR, mulv4, RVRVRF, NOP, 0, 0) // vA = vkB * fkC +xx(MULVF4_RK, mulv4, RVRVKF, MULVF4_RR, 4, REGT_FLOAT) +xx(DIVVF4_RR, divv4, RVRVRF, NOP, 0, 0) // vA = vkB / fkC +xx(DIVVF4_RK, divv4, RVRVKF, DIVVF4_RR, 4, REGT_FLOAT) +xx(LENV4, lenv4, RFRV, NOP, 0, 0) // fA = vB.Length +xx(EQV4_R, beqv4, CVRR, NOP, 0, 0) // if ((vB == vkC) != A) then pc++ (inexact if A & 33) +xx(EQV4_K, beqv4, CVRK, NOP, 0, 0) // this will never be used. + +// Quaternion math +xx(MULQQ_RR, mulqq, RVRVRV, NOP, 0, 0) // qA = qB * qC +xx(MULQV3_RR, mulqv3, RVRVRV, NOP, 0, 0) // qA = qB * vC + // Pointer math. xx(ADDA_RR, add, RPRPRI, NOP, 0, 0) // pA = pB + dkC xx(ADDA_RK, add, RPRPKI, ADDA_RR,4, REGT_INT) diff --git a/src/common/startscreen/endoom.cpp b/src/common/startscreen/endoom.cpp new file mode 100644 index 000000000..0fff948c0 --- /dev/null +++ b/src/common/startscreen/endoom.cpp @@ -0,0 +1,200 @@ + +/* +** endoom.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** Copyright 2006-2022 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. +**--------------------------------------------------------------------------- +** +*/ + +// HEADER FILES ------------------------------------------------------------ + +#include "startscreen.h" +#include "cmdlib.h" + +#include "i_system.h" +#include "gstrings.h" +#include "filesystem.h" +#include "m_argv.h" +#include "engineerrors.h" +#include "s_music.h" +#include "printf.h" +#include "startupinfo.h" +#include "i_interface.h" +#include "texturemanager.h" +#include "c_cvars.h" +#include "i_time.h" +#include "g_input.h" +#include "d_eventbase.h" + +// MACROS ------------------------------------------------------------------ + +// How many ms elapse between blinking text flips. On a standard VGA +// adapter, the characters are on for 16 frames and then off for another 16. +// The number here therefore corresponds roughly to the blink rate on a +// 60 Hz display. +#define BLINK_PERIOD 267 + + +// TYPES ------------------------------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +CUSTOM_CVAR(Int, showendoom, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + if (self < 0) self = 0; + else if (self > 2) self=2; +} + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +class FEndoomScreen : public FStartScreen +{ + uint64_t lastUpdateTime; + bool blinkstate = false; + bool blinking = true; + uint8_t endoom_screen[4000]; + +public: + FEndoomScreen(int); + void Update(); +}; + + +//========================================================================== +// +// FHereticStartScreen Constructor +// +// Shows the Heretic startup screen. If the screen doesn't appear to be +// valid, it returns a failure code in hr. +// +// The loading screen is an 80x25 text screen with character data and +// attributes intermixed, which means it must be exactly 4000 bytes long. +// +//========================================================================== + +FEndoomScreen::FEndoomScreen(int loading_lump) + : FStartScreen(0) +{ + fileSystem.ReadFile(loading_lump, endoom_screen); + + // Draw the loading screen to a bitmap. + 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}); + lastUpdateTime = I_msTime(); + + // Does this screen need blinking? + for (int i = 0; i < 80*25; ++i) + { + if (endoom_screen[1+i*2] & 0x80) + { + blinking = true; + break; + } + } +} + +void FEndoomScreen::Update() +{ + if (blinking && I_msTime() > lastUpdateTime + BLINK_PERIOD) + { + lastUpdateTime = I_msTime(); + UpdateTextBlink (StartupBitmap, endoom_screen, blinkstate); + blinkstate = !blinkstate; + StartupTexture->CleanHardwareData(); + Render(true); + } +} + + +//========================================================================== +// +// ST_Endoom +// +// Shows an ENDOOM text screen +// +//========================================================================== + +int RunEndoom() +{ + if (showendoom == 0 || endoomName.Len() == 0) + { + return 0; + } + + int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true); + + if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) + { + return 0; + } + + if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2) + { + // showendoom==2 means to show only lumps from PWADs. + return 0; + } + + S_StopMusic(true); + auto endoom = new FEndoomScreen(endoom_lump); + endoom->Render(true); + + while(true) + { + I_GetEvent(); + endoom->Update(); + while (eventtail != eventhead) + { + event_t *ev = &events[eventtail]; + eventtail = (eventtail + 1) & (MAXEVENTS - 1); + + if (ev->type == EV_KeyDown || ev->type == EV_KeyUp) + { + return 0; + } + if (ev->type == EV_GUI_Event && (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_LButtonDown || ev->subtype == EV_GUI_RButtonDown || ev->subtype == EV_GUI_MButtonDown)) + { + return 0; + } + } + } + return 0; +} + +[[noreturn]] +void ST_Endoom() +{ + int code = RunEndoom(); + throw CExitEvent(code); +} diff --git a/src/common/startscreen/startscreen.cpp b/src/common/startscreen/startscreen.cpp new file mode 100644 index 000000000..660561fd2 --- /dev/null +++ b/src/common/startscreen/startscreen.cpp @@ -0,0 +1,715 @@ +/* +** st_start.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** Copyright 2006-2022 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 "startscreen.h" +#include "filesystem.h" +#include "palutil.h" +#include "v_font.h" +#include "i_interface.h" +#include "startupinfo.h" +#include "m_argv.h" +#include "engineerrors.h" +#include "utf8.h" +#include "gstrings.h" +#include "printf.h" +#include "i_time.h" +#include "v_video.h" +#include "v_draw.h" +#include "g_input.h" +#include "texturemanager.h" + +// Text mode color values +enum{ + LO = 85, + MD = 170, + HI = 255, +}; + +const RgbQuad TextModePalette[16] = +{ + { 0, 0, 0, 255 }, // 0 black + { MD, 0, 0, 255 }, // 1 blue + { 0, MD, 0, 255 }, // 2 green + { MD, MD, 0, 255 }, // 3 cyan + { 0, 0, MD, 255 }, // 4 red + { MD, 0, MD, 255 }, // 5 magenta + { 0, LO, MD, 255 }, // 6 brown + { MD, MD, MD, 255 }, // 7 light gray + + { LO, LO, LO, 255 }, // 8 dark gray + { HI, LO, LO, 255 }, // 9 light blue + { LO, HI, LO, 255 }, // A light green + { HI, HI, LO, 255 }, // B light cyan + { LO, LO, HI, 255 }, // C light red + { HI, LO, HI, 255 }, // D light magenta + { LO, HI, HI, 255 }, // E yellow + { HI, HI, HI, 255 }, // F white +}; + +static const uint16_t IBM437ToUnicode[] = { + 0x0000, //#NULL + 0x263a, //#START OF HEADING + 0x263B, //#START OF TEXT + 0x2665, //#END OF TEXT + 0x2666, //#END OF TRANSMISSION + 0x2663, //#ENQUIRY + 0x2660, //#ACKNOWLEDGE + 0x2022, //#BELL + 0x25d8, //#BACKSPACE + 0x25cb, //#HORIZONTAL TABULATION + 0x25d9, //#LINE FEED + 0x2642, //#VERTICAL TABULATION + 0x2640, //#FORM FEED + 0x266a, //#CARRIAGE RETURN + 0x266b, //#SHIFT OUT + 0x263c, //#SHIFT IN + 0x25ba, //#DATA LINK ESCAPE + 0x25c4, //#DEVICE CONTROL ONE + 0x2195, //#DEVICE CONTROL TWO + 0x203c, //#DEVICE CONTROL THREE + 0x00b6, //#DEVICE CONTROL FOUR + 0x00a7, //#NEGATIVE ACKNOWLEDGE + 0x25ac, //#SYNCHRONOUS IDLE + 0x21ab, //#END OF TRANSMISSION BLOCK + 0x2191, //#CANCEL + 0x2193, //#END OF MEDIUM + 0x2192, //#SUBSTITUTE + 0x2190, //#ESCAPE + 0x221f, //#FILE SEPARATOR + 0x2194, //#GROUP SEPARATOR + 0x25b2, //#RECORD SEPARATOR + 0x25bc, //#UNIT SEPARATOR + 0x0020, //#SPACE + 0x0021, //#EXCLAMATION MARK + 0x0022, //#QUOTATION MARK + 0x0023, //#NUMBER SIGN + 0x0024, //#DOLLAR SIGN + 0x0025, //#PERCENT SIGN + 0x0026, //#AMPERSAND + 0x0027, //#APOSTROPHE + 0x0028, //#LEFT PARENTHESIS + 0x0029, //#RIGHT PARENTHESIS + 0x002a, //#ASTERISK + 0x002b, //#PLUS SIGN + 0x002c, //#COMMA + 0x002d, //#HYPHEN-MINUS + 0x002e, //#FULL STOP + 0x002f, //#SOLIDUS + 0x0030, //#DIGIT ZERO + 0x0031, //#DIGIT ONE + 0x0032, //#DIGIT TWO + 0x0033, //#DIGIT THREE + 0x0034, //#DIGIT FOUR + 0x0035, //#DIGIT FIVE + 0x0036, //#DIGIT SIX + 0x0037, //#DIGIT SEVEN + 0x0038, //#DIGIT EIGHT + 0x0039, //#DIGIT NINE + 0x003a, //#COLON + 0x003b, //#SEMICOLON + 0x003c, //#LESS-THAN SIGN + 0x003d, //#EQUALS SIGN + 0x003e, //#GREATER-THAN SIGN + 0x003f, //#QUESTION MARK + 0x0040, //#COMMERCIAL AT + 0x0041, //#LATIN CAPITAL LETTER A + 0x0042, //#LATIN CAPITAL LETTER B + 0x0043, //#LATIN CAPITAL LETTER C + 0x0044, //#LATIN CAPITAL LETTER D + 0x0045, //#LATIN CAPITAL LETTER E + 0x0046, //#LATIN CAPITAL LETTER F + 0x0047, //#LATIN CAPITAL LETTER G + 0x0048, //#LATIN CAPITAL LETTER H + 0x0049, //#LATIN CAPITAL LETTER I + 0x004a, //#LATIN CAPITAL LETTER J + 0x004b, //#LATIN CAPITAL LETTER K + 0x004c, //#LATIN CAPITAL LETTER L + 0x004d, //#LATIN CAPITAL LETTER M + 0x004e, //#LATIN CAPITAL LETTER N + 0x004f, //#LATIN CAPITAL LETTER O + 0x0050, //#LATIN CAPITAL LETTER P + 0x0051, //#LATIN CAPITAL LETTER Q + 0x0052, //#LATIN CAPITAL LETTER R + 0x0053, //#LATIN CAPITAL LETTER S + 0x0054, //#LATIN CAPITAL LETTER T + 0x0055, //#LATIN CAPITAL LETTER U + 0x0056, //#LATIN CAPITAL LETTER V + 0x0057, //#LATIN CAPITAL LETTER W + 0x0058, //#LATIN CAPITAL LETTER X + 0x0059, //#LATIN CAPITAL LETTER Y + 0x005a, //#LATIN CAPITAL LETTER Z + 0x005b, //#LEFT SQUARE BRACKET + 0x005c, //#REVERSE SOLIDUS + 0x005d, //#RIGHT SQUARE BRACKET + 0x005e, //#CIRCUMFLEX ACCENT + 0x005f, //#LOW LINE + 0x0060, //#GRAVE ACCENT + 0x0061, //#LATIN SMALL LETTER A + 0x0062, //#LATIN SMALL LETTER B + 0x0063, //#LATIN SMALL LETTER C + 0x0064, //#LATIN SMALL LETTER D + 0x0065, //#LATIN SMALL LETTER E + 0x0066, //#LATIN SMALL LETTER F + 0x0067, //#LATIN SMALL LETTER G + 0x0068, //#LATIN SMALL LETTER H + 0x0069, //#LATIN SMALL LETTER I + 0x006a, //#LATIN SMALL LETTER J + 0x006b, //#LATIN SMALL LETTER K + 0x006c, //#LATIN SMALL LETTER L + 0x006d, //#LATIN SMALL LETTER M + 0x006e, //#LATIN SMALL LETTER N + 0x006f, //#LATIN SMALL LETTER O + 0x0070, //#LATIN SMALL LETTER P + 0x0071, //#LATIN SMALL LETTER Q + 0x0072, //#LATIN SMALL LETTER R + 0x0073, //#LATIN SMALL LETTER S + 0x0074, //#LATIN SMALL LETTER T + 0x0075, //#LATIN SMALL LETTER U + 0x0076, //#LATIN SMALL LETTER V + 0x0077, //#LATIN SMALL LETTER W + 0x0078, //#LATIN SMALL LETTER X + 0x0079, //#LATIN SMALL LETTER Y + 0x007a, //#LATIN SMALL LETTER Z + 0x007b, //#LEFT CURLY BRACKET + 0x007c, //#VERTICAL LINE + 0x007d, //#RIGHT CURLY BRACKET + 0x007e, //#TILDE + 0x2302, //#DELETE + 0x00c7, //#LATIN CAPITAL LETTER C WITH CEDILLA + 0x00fc, //#LATIN SMALL LETTER U WITH DIAERESIS + 0x00e9, //#LATIN SMALL LETTER E WITH ACUTE + 0x00e2, //#LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4, //#LATIN SMALL LETTER A WITH DIAERESIS + 0x00e0, //#LATIN SMALL LETTER A WITH GRAVE + 0x00e5, //#LATIN SMALL LETTER A WITH RING ABOVE + 0x00e7, //#LATIN SMALL LETTER C WITH CEDILLA + 0x00ea, //#LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb, //#LATIN SMALL LETTER E WITH DIAERESIS + 0x00e8, //#LATIN SMALL LETTER E WITH GRAVE + 0x00ef, //#LATIN SMALL LETTER I WITH DIAERESIS + 0x00ee, //#LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ec, //#LATIN SMALL LETTER I WITH GRAVE + 0x00c4, //#LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5, //#LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c9, //#LATIN CAPITAL LETTER E WITH ACUTE + 0x00e6, //#LATIN SMALL LIGATURE AE + 0x00c6, //#LATIN CAPITAL LIGATURE AE + 0x00f4, //#LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6, //#LATIN SMALL LETTER O WITH DIAERESIS + 0x00f2, //#LATIN SMALL LETTER O WITH GRAVE + 0x00fb, //#LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00f9, //#LATIN SMALL LETTER U WITH GRAVE + 0x00ff, //#LATIN SMALL LETTER Y WITH DIAERESIS + 0x00d6, //#LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc, //#LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00a2, //#CENT SIGN + 0x00a3, //#POUND SIGN + 0x00a5, //#YEN SIGN + 0x20a7, //#PESETA SIGN + 0x0192, //#LATIN SMALL LETTER F WITH HOOK + 0x00e1, //#LATIN SMALL LETTER A WITH ACUTE + 0x00ed, //#LATIN SMALL LETTER I WITH ACUTE + 0x00f3, //#LATIN SMALL LETTER O WITH ACUTE + 0x00fa, //#LATIN SMALL LETTER U WITH ACUTE + 0x00f1, //#LATIN SMALL LETTER N WITH TILDE + 0x00d1, //#LATIN CAPITAL LETTER N WITH TILDE + 0x00aa, //#FEMININE ORDINAL INDICATOR + 0x00ba, //#MASCULINE ORDINAL INDICATOR + 0x00bf, //#INVERTED QUESTION MARK + 0x2310, //#REVERSED NOT SIGN + 0x00ac, //#NOT SIGN + 0x00bd, //#VULGAR FRACTION ONE HALF + 0x00bc, //#VULGAR FRACTION ONE QUARTER + 0x00a1, //#INVERTED EXCLAMATION MARK + 0x00ab, //#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bb, //#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x2591, //#LIGHT SHADE + 0x2592, //#MEDIUM SHADE + 0x2593, //#DARK SHADE + 0x2502, //#BOX DRAWINGS LIGHT VERTICAL + 0x2524, //#BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x2561, //#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562, //#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2556, //#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2555, //#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2563, //#BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2551, //#BOX DRAWINGS DOUBLE VERTICAL + 0x2557, //#BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255d, //#BOX DRAWINGS DOUBLE UP AND LEFT + 0x255c, //#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255b, //#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x2510, //#BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514, //#BOX DRAWINGS LIGHT UP AND RIGHT + 0x2534, //#BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x252c, //#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x251c, //#BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2500, //#BOX DRAWINGS LIGHT HORIZONTAL + 0x253c, //#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x255e, //#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f, //#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x255a, //#BOX DRAWINGS DOUBLE UP AND RIGHT + 0x2554, //#BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2569, //#BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x2566, //#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2560, //#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2550, //#BOX DRAWINGS DOUBLE HORIZONTAL + 0x256c, //#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2567, //#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568, //#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2564, //#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565, //#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2559, //#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x2558, //#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2552, //#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553, //#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x256b, //#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256a, //#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x2518, //#BOX DRAWINGS LIGHT UP AND LEFT + 0x250c, //#BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2588, //#FULL BLOCK + 0x2584, //#LOWER HALF BLOCK + 0x258c, //#LEFT HALF BLOCK + 0x2590, //#RIGHT HALF BLOCK + 0x2580, //#UPPER HALF BLOCK + 0x03b1, //#GREEK SMALL LETTER ALPHA + 0x00df, //#LATIN SMALL LETTER SHARP S + 0x0393, //#GREEK CAPITAL LETTER GAMMA + 0x03c0, //#GREEK SMALL LETTER PI + 0x03a3, //#GREEK CAPITAL LETTER SIGMA + 0x03c3, //#GREEK SMALL LETTER SIGMA + 0x00b5, //#MICRO SIGN + 0x03c4, //#GREEK SMALL LETTER TAU + 0x03a6, //#GREEK CAPITAL LETTER PHI + 0x0398, //#GREEK CAPITAL LETTER THETA + 0x03a9, //#GREEK CAPITAL LETTER OMEGA + 0x03b4, //#GREEK SMALL LETTER DELTA + 0x221e, //#INFINITY + 0x03c6, //#GREEK SMALL LETTER PHI + 0x03b5, //#GREEK SMALL LETTER EPSILON + 0x2229, //#INTERSECTION + 0x2261, //#IDENTICAL TO + 0x00b1, //#PLUS-MINUS SIGN + 0x2265, //#GREATER-THAN OR EQUAL TO + 0x2264, //#LESS-THAN OR EQUAL TO + 0x2320, //#TOP HALF INTEGRAL + 0x2321, //#BOTTOM HALF INTEGRAL + 0x00f7, //#DIVISION SIGN + 0x2248, //#ALMOST EQUAL TO + 0x00b0, //#DEGREE SIGN + 0x2219, //#BULLET OPERATOR + 0x00b7, //#MIDDLE DOT + 0x221a, //#SQUARE ROOT + 0x207f, //#SUPERSCRIPT LATIN SMALL LETTER N + 0x00b2, //#SUPERSCRIPT TWO + 0x25a0, //#BLACK SQUARE + 0x00a0, //#NO-BREAK SPACE +}; + +FStartScreen* CreateHexenStartScreen(int max_progress); +FStartScreen* CreateHereticStartScreen(int max_progress); +FStartScreen* CreateStrifeStartScreen(int max_progress); +FStartScreen* CreateGenericStartScreen(int max_progress); + + +FStartScreen* GetGameStartScreen(int max_progress) +{ + if (!Args->CheckParm("-nostartup")) + { + try + { + if (GameStartupInfo.Type == FStartupInfo::HexenStartup) + { + return CreateHexenStartScreen(max_progress); + } + else if (GameStartupInfo.Type == FStartupInfo::HereticStartup) + { + return CreateHereticStartScreen(max_progress); + } + else if (GameStartupInfo.Type == FStartupInfo::StrifeStartup) + { + return CreateStrifeStartScreen(max_progress); + } + } + catch(const CRecoverableError& err) + { + Printf("Error creating start screen: %s\n", err.what()); + // fall through to the generic startup screen + } + //return CreateGenericStartScreen(max_progress); + } + return nullptr; +} + +//========================================================================== +// +// ST_Util_ClearBlock +// +//========================================================================== + +void FStartScreen::ClearBlock(FBitmap& bitmap_info, RgbQuad fill, int x, int y, int bytewidth, int height) +{ + int destpitch = bitmap_info.GetWidth(); + auto dest = (RgbQuad*)(bitmap_info.GetPixels()) + x + y * destpitch; + + while (height > 0) + { + for(int i = 0; i < bytewidth; i++) + { + dest[i] = fill; + } + dest += destpitch; + height--; + } +} + +//========================================================================== +// +// ST_Util_DrawTextScreen +// +// Draws the text screen to the bitmap. The bitmap must be the proper size +// for the font. +// +//========================================================================== + +void FStartScreen::DrawTextScreen(FBitmap& bitmap_info, const uint8_t* text_screen) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + DrawChar(bitmap_info, x, y, IBM437ToUnicode[text_screen[0]], text_screen[1]); + text_screen += 2; + } + } +} + +//========================================================================== +// +// ST_Util_DrawChar +// +// Draws a character on the bitmap. X and Y specify the character cell, +// and fg and bg are 4-bit colors. +// +//========================================================================== +uint8_t* GetHexChar(int codepoint); + +int FStartScreen::DrawChar(FBitmap& screen, double x, double y, unsigned charnum, RgbQuad fg, RgbQuad bg) +{ + if (x < 0 || y < 0 || y >= screen.GetHeight() - 16) return 1; + static const uint8_t space[17] = { 16 }; + const RgbQuad color_array[4] = { bg, fg }; + const uint8_t* src = GetHexChar(charnum); + if (!src) src = space; + int size = (*src++) == 32? 2 : 1; + if (x > (screen.GetWidth() >> 3) - size) return size; + int pitch = screen.GetWidth(); + RgbQuad* dest = (RgbQuad*)screen.GetPixels() + int(x * 8) + int(y * 16) * pitch; + + for (y = 0; y <16; ++y) + { + uint8_t srcbyte = *src++; + + dest[0] = color_array[(srcbyte >> 7) & 1]; + dest[1] = color_array[(srcbyte >> 6) & 1]; + dest[2] = color_array[(srcbyte >> 5) & 1]; + dest[3] = color_array[(srcbyte >> 4) & 1]; + dest[4] = color_array[(srcbyte >> 3) & 1]; + dest[5] = color_array[(srcbyte >> 2) & 1]; + dest[6] = color_array[(srcbyte >> 1) & 1]; + dest[7] = color_array[(srcbyte) & 1]; + if (size == 16) + { + srcbyte = *src++; + + dest[8] = color_array[(srcbyte >> 7) & 1]; + dest[9] = color_array[(srcbyte >> 6) & 1]; + dest[10] = color_array[(srcbyte >> 5) & 1]; + dest[11] = color_array[(srcbyte >> 4) & 1]; + dest[12] = color_array[(srcbyte >> 3) & 1]; + dest[13] = color_array[(srcbyte >> 2) & 1]; + dest[14] = color_array[(srcbyte >> 1) & 1]; + dest[15] = color_array[(srcbyte) & 1]; + } + dest += pitch; + } + return size; +} + +int FStartScreen::DrawChar(FBitmap& screen, double x, double y, unsigned charnum, uint8_t attrib) +{ + const uint8_t bg = (attrib & 0x70) >> 4; + const uint8_t fg = attrib & 0x0F; + auto bgc = TextModePalette[bg], fgc = TextModePalette[fg]; + return DrawChar(screen, x, y, charnum, fgc, bgc); +} + +int FStartScreen::DrawString(FBitmap& screen, double x, double y, const char* text, RgbQuad fg, RgbQuad bg) +{ + double oldx = x; + auto str = (const uint8_t*)text; + while (auto chr = GetCharFromString(str)) + { + x += DrawChar(screen, x, y, chr, fg, bg); + } + return int(x - oldx); +} + +//========================================================================== +// +// SizeOfText +// +// returns width in pixels +// +//========================================================================== + +int FStartScreen::SizeOfText(const char* text) +{ + int len = 0; + const uint8_t* utext = (uint8_t*)text; + while(auto code = GetCharFromString(utext)) + { + const uint8_t* src = GetHexChar(code); + if (src && *src == 32) len += 2; + else len ++; + } + return len; +} + +//========================================================================== +// +// ST_Util_UpdateTextBlink +// +// Draws the parts of the text screen that blink to the bitmap. The bitmap +// must be the proper size for the font. +// +//========================================================================== + +void FStartScreen::UpdateTextBlink(FBitmap& bitmap_info, const uint8_t* text_screen, bool on) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + if (text_screen[1] & 0x80) + { + DrawChar(bitmap_info, x, y, on ? IBM437ToUnicode[text_screen[0]] : ' ', text_screen[1]); + } + text_screen += 2; + } + } +} + +//========================================================================== +// +// ST_Sound +// +// plays a sound on the start screen +// +//========================================================================== + +void FStartScreen::ST_Sound(const char* sndname) +{ + if (sysCallbacks.PlayStartupSound) + sysCallbacks.PlayStartupSound(sndname); +} + +//========================================================================== +// +// CreateHeader +// +// creates a bitmap for the title header +// +//========================================================================== + +void FStartScreen::CreateHeader() +{ + HeaderBitmap.Create(StartupBitmap.GetWidth() * Scale, 2 * 16); + RgbQuad bcolor, fcolor; + bcolor.rgbRed = RPART(GameStartupInfo.BkColor); + bcolor.rgbGreen = GPART(GameStartupInfo.BkColor); + bcolor.rgbBlue = BPART(GameStartupInfo.BkColor); + bcolor.rgbReserved = 255; + fcolor.rgbRed = RPART(GameStartupInfo.FgColor); + fcolor.rgbGreen = GPART(GameStartupInfo.FgColor); + 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); + NetBitmap.Create(StartupBitmap.GetWidth() * Scale, 16); +} + +//========================================================================== +// +// DrawNetStatus +// +// Draws network status into the last line of the startup screen. +// +//========================================================================== + +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); + char of[10]; + mysnprintf(of, 10, "%d/%d", found, total); + int siz = SizeOfText(of); + DrawString(NetBitmap, (NetBitmap.GetWidth() >> 3) - siz, 0, of, gray, black); +} + +//========================================================================== +// +// NetInit +// +// sets network status message +// +//========================================================================== + +bool FStartScreen::NetInit(const char* message, int numplayers) +{ + NetMaxPos = numplayers; + NetCurPos = 0; + NetMessageString.Format("%s %s", message, GStrings("TXT_NET_PRESSESC")); + NetProgress(1); // You always know about yourself + return true; +} + +//========================================================================== +// +// Progress +// +// advances the progress bar +// +//========================================================================== + +bool FStartScreen::DoProgress(int advance) +{ + CurPos = min(CurPos + advance, MaxPos); + return true; +} + +void FStartScreen::DoNetProgress(int count) +{ + if (count == 0) + { + NetCurPos++; + } + else if (count > 0) + { + NetCurPos = count; + } + NetTexture->CleanHardwareData(); +} + +bool FStartScreen::Progress(int advance) +{ + bool done = DoProgress(advance); + Render(); + return done; +} + +void FStartScreen::NetProgress(int count) +{ + DoNetProgress(count); + Render(); +} + +void FStartScreen::Render(bool force) +{ + 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) + { + screen->FrameTime = nowtime; + screen->BeginFrame(); + twod->ClearClipRect(); + I_GetEvent(); + ValidateTexture(); + float displaywidth; + float displayheight; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + + // At this point the shader for untextured rendering has not been loaded yet, so we got to clear the screen by rendering a texture with black color. + DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, StartupTexture->GetDisplayWidth(), DTA_VirtualHeightF, StartupTexture->GetDisplayHeight(), DTA_KeepRatio, true, DTA_Color, PalEntry(255,0,0,0), TAG_END); + + if (HeaderTexture) + { + displaywidth = HeaderTexture->GetDisplayWidth(); + displayheight = HeaderTexture->GetDisplayHeight() + StartupTexture->GetDisplayHeight(); + DrawTexture(twod, HeaderTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END); + DrawTexture(twod, StartupTexture, 0, 32, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END); + if (NetMaxPos >= 0) DrawTexture(twod, NetTexture, 0, displayheight - 16, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END); + } + else + { + displaywidth = StartupTexture->GetDisplayWidth(); + displayheight = StartupTexture->GetDisplayHeight(); + DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END); + } + + twod->End(); + screen->Update(); + twod->OnFrameDone(); + } +} + +FImageSource* CreateStartScreenTexture(FBitmap& srcdata); + +void FStartScreen::ValidateTexture() +{ + if (StartupTexture == nullptr) + { + auto imgsource = CreateStartScreenTexture(StartupBitmap); + StartupTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override); + StartupTexture->SetScale(1.f / Scale, 1.f / Scale); + } + if (HeaderTexture == nullptr && HeaderBitmap.GetWidth() > 0) + { + auto imgsource = CreateStartScreenTexture(HeaderBitmap); + HeaderTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override); + } + if (NetTexture == nullptr && NetBitmap.GetWidth() > 0) + { + auto imgsource = CreateStartScreenTexture(NetBitmap); + NetTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override); + } +} + diff --git a/src/common/startscreen/startscreen.h b/src/common/startscreen/startscreen.h new file mode 100644 index 000000000..afac6c759 --- /dev/null +++ b/src/common/startscreen/startscreen.h @@ -0,0 +1,106 @@ +#pragma once +/* +** st_start.h +** Interface for the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 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. +**--------------------------------------------------------------------------- +** +#pragma once +** The startup screen interface is based on a mix of Heretic and Hexen. +** Actual implementation is system-specific. +*/ +#include +#include +#include "bitmap.h" +#include "zstring.h" + +class FGameTexture; + +struct RgbQuad +{ + uint8_t rgbBlue; + uint8_t rgbGreen; + uint8_t rgbRed; + uint8_t rgbReserved; +}; + + +extern const RgbQuad TextModePalette[16]; + +class FStartScreen +{ +protected: + int CurPos = 0; + int MaxPos; + int Scale = 1; + int NetMaxPos = -1; + int NetCurPos = 0; + FBitmap StartupBitmap; + FBitmap HeaderBitmap; + FBitmap NetBitmap; + FString NetMessageString; + FGameTexture* StartupTexture = nullptr; + FGameTexture* HeaderTexture = nullptr; + FGameTexture* NetTexture = nullptr; +public: + FStartScreen(int maxp) { MaxPos = maxp; } + virtual ~FStartScreen() = default; + void Render(bool force = false); + bool Progress(int); + void NetProgress(int count); + virtual void LoadingStatus(const char *message, int colors) {} + virtual void AppendStatusLine(const char *status) {} + virtual bool NetInit(const char* message, int numplayers); + virtual void NetDone() {} + virtual void NetTick() {} + FBitmap& GetBitmap() { return StartupBitmap; } + int GetScale() const { return Scale; } + + +protected: + void ClearBlock(FBitmap& bitmap_info, RgbQuad fill, int x, int y, int bytewidth, int height); + FBitmap AllocTextBitmap(); + void DrawTextScreen(FBitmap& bitmap_info, const uint8_t* text_screen); + int DrawChar(FBitmap& screen, double x, double y, unsigned charnum, uint8_t attrib); + int DrawChar(FBitmap& screen, double x, double y, unsigned charnum, RgbQuad fg, RgbQuad bg); + int DrawString(FBitmap& screen, double x, double y, const char* text, RgbQuad fg, RgbQuad bg); + void UpdateTextBlink(FBitmap& bitmap_info, const uint8_t* text_screen, bool on); + void ST_Sound(const char* sndname); + int SizeOfText(const char* text); + void CreateHeader(); + void DrawNetStatus(int found, int total); + void ValidateTexture(); + virtual bool DoProgress(int); + virtual void DoNetProgress(int count); +}; + +FStartScreen* GetGameStartScreen(int max_progress); + +[[noreturn]] +void ST_Endoom(); diff --git a/src/common/startscreen/startscreen_generic.cpp b/src/common/startscreen/startscreen_generic.cpp new file mode 100644 index 000000000..c2af0bd50 --- /dev/null +++ b/src/common/startscreen/startscreen_generic.cpp @@ -0,0 +1,127 @@ +/* +** st_start.cpp +** Generic startup screen +** +**--------------------------------------------------------------------------- +** Copyright 2022 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 "startscreen.h" +#include "filesystem.h" +#include "printf.h" +#include "startupinfo.h" +#include "image.h" +#include "texturemanager.h" + +// Hexen startup screen +#define ST_PROGRESS_X 64 // Start of notches x screen pos. +#define ST_PROGRESS_Y 441 // Start of notches y screen pos. + + +class FGenericStartScreen : public FStartScreen +{ + FBitmap Background; + int NotchPos = 0; + +public: + FGenericStartScreen(int max_progress); + + bool DoProgress(int) override; +}; + + +//========================================================================== +// +// FGenericStartScreen Constructor +// +// Shows the Hexen startup screen. If the screen doesn't appear to be +// valid, it sets hr for a failure. +// +// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a +// 16 entry (48 byte) VGA palette. +// +//========================================================================== + +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); + + StartupBitmap.Create(640, 480); + ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640, 480); + // This also needs to work if the lump turns out to be unusable. + if (startup_lump != -1) + { + auto iBackground = FImageSource::GetImage(startup_lump, false); + 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); + else + StartupBitmap.Blit(0, 0, Background, 640, 480); + + } + } + CreateHeader(); +} + +//========================================================================== +// +// FGenericStartScreen :: Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +bool FGenericStartScreen::DoProgress(int advance) +{ + int notch_pos; + + if (CurPos < MaxPos) + { + RgbQuad bcolor = { 128, 0, 0, 255 }; // todo: make configurable + int numnotches = 512; + notch_pos = ((CurPos + 1) * 512) / MaxPos; + if (notch_pos != NotchPos) + { // Time to draw another notch. + ClearBlock(StartupBitmap, bcolor, ST_PROGRESS_X, ST_PROGRESS_Y, notch_pos, 16); + NotchPos = notch_pos; + StartupTexture->CleanHardwareData(true); + } + } + return FStartScreen::DoProgress(advance); +} + + +FStartScreen* CreateGenericStartScreen(int max_progress) +{ + return new FGenericStartScreen(max_progress); +} diff --git a/src/common/startscreen/startscreen_heretic.cpp b/src/common/startscreen/startscreen_heretic.cpp new file mode 100644 index 000000000..6829436f9 --- /dev/null +++ b/src/common/startscreen/startscreen_heretic.cpp @@ -0,0 +1,181 @@ +/* +** st_start.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** Copyright 2006-2022 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 "startscreen.h" +#include "filesystem.h" +#include "printf.h" +#include "texturemanager.h" + + +// Heretic startup screen +#define HERETIC_MINOR_VERSION '3' // Since we're based on Heretic 1.3 +#define THERM_X 14 +#define THERM_Y 14 +#define THERM_LEN 51 +#define THERM_COLOR 0xA // light green + + +class FHereticStartScreen : public FStartScreen +{ + int NotchPos; + int ThermX, ThermY, ThermWidth, ThermHeight; + int HMsgY, SMsgX; +public: + FHereticStartScreen(int max_progress); + + bool DoProgress(int) override; + void LoadingStatus(const char *message, int colors) override; + void AppendStatusLine(const char *status) override; +}; + + +//========================================================================== +// +// FHereticStartScreen Constructor +// +// Shows the Heretic startup screen. If the screen doesn't appear to be +// valid, it returns a failure code in hr. +// +// The loading screen is an 80x25 text screen with character data and +// attributes intermixed, which means it must be exactly 4000 bytes long. +// +//========================================================================== + +FHereticStartScreen::FHereticStartScreen(int max_progress) + : FStartScreen(max_progress) +{ + int loading_lump = fileSystem.CheckNumForName("LOADING"); + uint8_t loading_screen[4000]; + + if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000) + { + I_Error("'LOADING' not found"); + } + + fileSystem.ReadFile(loading_lump, loading_screen); + + // Slap the Heretic minor version on the loading screen. Heretic + // did this inside the executable rather than coming with modified + // LOADING screens, so we need to do the same. + loading_screen[2 * 160 + 49 * 2] = HERETIC_MINOR_VERSION; + + // Draw the loading screen to a bitmap. + StartupBitmap.Create(80 * 8, 25 * 16); + DrawTextScreen(StartupBitmap, loading_screen); + + ThermX = THERM_X * 8; + ThermY = THERM_Y * 16; + ThermWidth = THERM_LEN * 8 - 4; + ThermHeight = 16; + HMsgY = 7; + SMsgX = 1; + NotchPos = 0; + CreateHeader(); +} + +//========================================================================== +// +// FHereticStartScreen::Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +bool FHereticStartScreen::DoProgress(int advance) +{ + if (CurPos < MaxPos) + { + int notch_pos = ((CurPos + 1) * ThermWidth) / MaxPos; + if (notch_pos != NotchPos && !(notch_pos & 3)) + { // Time to draw another notch. + int left = NotchPos + ThermX; + int top = ThermY; + int right = notch_pos + ThermX; + int bottom = top + ThermHeight; + ClearBlock(StartupBitmap, TextModePalette[THERM_COLOR], left, top, right - left, bottom - top); + NotchPos = notch_pos; + StartupTexture->CleanHardwareData(true); + } + } + return FStartScreen::DoProgress(advance); +} + +//========================================================================== +// +// FHereticStartScreen :: LoadingStatus +// +// Prints text in the center box of the startup screen. +// +//========================================================================== + +void FHereticStartScreen::LoadingStatus(const char* message, int colors) +{ + int x; + + for (x = 0; message[x] != '\0'; ++x) + { + DrawChar(StartupBitmap, 17 + x, HMsgY, message[x], colors); + } + HMsgY++; + StartupTexture->CleanHardwareData(true); + Render(); +} + +//========================================================================== +// +// FHereticStartScreen :: AppendStatusLine +// +// Appends text to Heretic's status line. +// +//========================================================================== + +void FHereticStartScreen::AppendStatusLine(const char* status) +{ + int x; + + for (x = 0; status[x] != '\0'; ++x) + { + DrawChar(StartupBitmap, SMsgX + x, 24, status[x], 0x1f); + } + SMsgX += x; + StartupTexture->CleanHardwareData(true); + Render(); +} + + +FStartScreen* CreateHereticStartScreen(int max_progress) +{ + return new FHereticStartScreen(max_progress); +} diff --git a/src/common/startscreen/startscreen_hexen.cpp b/src/common/startscreen/startscreen_hexen.cpp new file mode 100644 index 000000000..6eef73599 --- /dev/null +++ b/src/common/startscreen/startscreen_hexen.cpp @@ -0,0 +1,212 @@ +/* +** st_start.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** Copyright 2006-2022 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 "startscreen.h" +#include "filesystem.h" +#include "printf.h" +#include "startupinfo.h" +#include "s_music.h" +#include "image.h" +#include "texturemanager.h" + +// Hexen startup screen +#define ST_PROGRESS_X 64 // Start of notches x screen pos. +#define ST_PROGRESS_Y 441 // Start of notches y screen pos. + +#define ST_NETPROGRESS_X 288 +#define ST_NETPROGRESS_Y 32 + +class FHexenStartScreen : public FStartScreen +{ + // Hexen's notch graphics, converted to chunky pixels. + FBitmap Background; + FBitmap NotchBits; + FBitmap NetNotchBits; + int NotchPos = 0; + +public: + FHexenStartScreen(int max_progress); + + bool DoProgress(int) override; + void DoNetProgress(int count) override; + void NetDone() override; +}; + + +//========================================================================== +// +// FHexenStartScreen Constructor +// +// Shows the Hexen startup screen. If the screen doesn't appear to be +// valid, it sets hr for a failure. +// +// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a +// 16 entry (48 byte) VGA palette. +// +//========================================================================== + +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); + + // 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"); + if (netnotch_lump == -1)netnotch_lump = fileSystem.CheckNumForName("NETNOTCH"); + if (notch_lump == -1)notch_lump = fileSystem.CheckNumForName("NOTCH"); + + + if (startup_lump < 0 || netnotch_lump < 0 || notch_lump < 0) + { + I_Error("Start screen assets missing"); + } + + auto iBackground = FImageSource::GetImage(startup_lump, false); + auto iNetNotchBits = FImageSource::GetImage(netnotch_lump, false); + auto iNotchBits = FImageSource::GetImage(notch_lump, false); + if (!iBackground || !iNetNotchBits || !iNotchBits || iBackground->GetWidth() != 640 || iBackground->GetHeight() != 480) + { + I_Error("Start screen assets missing"); + } + NetNotchBits = iNetNotchBits->GetCachedBitmap(nullptr, FImageSource::normal); + NotchBits = iNotchBits->GetCachedBitmap(nullptr, FImageSource::normal); + Background = iBackground->GetCachedBitmap(nullptr, FImageSource::normal); + + StartupBitmap.Create(640, 480); + StartupBitmap.Blit(0, 0, Background, 640, 480); + + // Fill in the bitmap data. Convert to chunky, because I can't figure out + // if Windows actually supports planar images or not, despite the presence + // of biPlanes in the BITMAPINFOHEADER. + + + if (!batchrun) + { + if (GameStartupInfo.Song.IsNotEmpty()) + { + S_ChangeMusic(GameStartupInfo.Song.GetChars(), true, true); + } + else + { + S_ChangeMusic("orb", true, true); + } + } + CreateHeader(); +} + +//========================================================================== +// +// FHexenStartScreen :: Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +bool FHexenStartScreen::DoProgress(int advance) +{ + int notch_pos, x, y; + + if (CurPos <= MaxPos) + { + int numnotches = (16 * 32) / NotchBits.GetWidth(); + notch_pos = ((CurPos + 1) * numnotches) / MaxPos; + if (notch_pos != NotchPos) + { // Time to draw another notch. + for (; NotchPos < notch_pos; NotchPos++) + { + x = ST_PROGRESS_X + NotchBits.GetWidth() * NotchPos; + y = ST_PROGRESS_Y; + StartupBitmap.Blit(x, y, NotchBits); + } + StartupTexture->CleanHardwareData(true); + ST_Sound("StartupTick"); + } + } + return FStartScreen::DoProgress(advance); +} + +//========================================================================== +// +// FHexenStartScreen :: NetProgress +// +// Draws the red net noches in addition to the normal progress bar. +// +//========================================================================== + +void FHexenStartScreen::DoNetProgress(int count) +{ + int oldpos = NetCurPos; + int x, y; + + FStartScreen::NetProgress(count); + + if (NetMaxPos != 0 && NetCurPos > oldpos) + { + int numnotches = (4 * 8) / NetNotchBits.GetWidth(); + int notch_pos = (NetCurPos * numnotches) / NetMaxPos; + + for (; oldpos < NetCurPos && oldpos < numnotches; ++oldpos) + { + x = ST_NETPROGRESS_X + NetNotchBits.GetWidth() * oldpos; + y = ST_NETPROGRESS_Y; + StartupBitmap.Blit(x, y, NetNotchBits); + } + ST_Sound("misc/netnotch"); + StartupTexture->CleanHardwareData(true); + } +} + +//========================================================================== +// +// FHexenStartScreen :: NetDone +// +// Aside from the standard processing, also plays a sound. +// +//========================================================================== + +void FHexenStartScreen::NetDone() +{ + ST_Sound("PickupWeapon"); + FStartScreen::NetDone(); +} + + +FStartScreen* CreateHexenStartScreen(int max_progress) +{ + return new FHexenStartScreen(max_progress); +} diff --git a/src/common/startscreen/startscreen_strife.cpp b/src/common/startscreen/startscreen_strife.cpp new file mode 100644 index 000000000..6587443b8 --- /dev/null +++ b/src/common/startscreen/startscreen_strife.cpp @@ -0,0 +1,202 @@ +/* +** st_start.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** Copyright 2006-2022 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 "startscreen.h" +#include "filesystem.h" +#include "printf.h" +#include "image.h" +#include "textures.h" +#include "palettecontainer.h" + +// Strife startup screen +#define PEASANT_INDEX 0 +#define LASER_INDEX 4 +#define BOT_INDEX 6 + +#define ST_LASERSPACE_X 60 +#define ST_LASERSPACE_Y 156 +#define ST_LASERSPACE_WIDTH 200 +#define ST_LASER_WIDTH 16 +#define ST_LASER_HEIGHT 16 + +#define ST_BOT_X 14 +#define ST_BOT_Y 138 +#define ST_BOT_WIDTH 48 +#define ST_BOT_HEIGHT 48 + +#define ST_PEASANT_X 262 +#define ST_PEASANT_Y 136 +#define ST_PEASANT_WIDTH 32 +#define ST_PEASANT_HEIGHT 64 + +static const char* StrifeStartupPicNames[] = +{ + "STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1", + "STRTLZ1", "STRTLZ2", + "STRTBOT", + "STARTUP0" +}; + + + +class FStrifeStartScreen : public FStartScreen +{ +public: + FStrifeStartScreen(int max_progress); + + bool DoProgress(int) override; +protected: + void DrawStuff(int old_laser, int new_laser); + + FBitmap StartupPics[4+2+1+1]; + int NotchPos = 0; +}; + + +//========================================================================== +// +// FStrifeStartScreen Constructor +// +// Shows the Strife startup screen. If the screen doesn't appear to be +// valid, it returns a failure code in hr. +// +// The startup background is a raw 320x200 image, however Strife only +// actually uses 95 rows from it, starting at row 57. The rest of the image +// is discarded. (What a shame.) +// +// The peasants are raw 32x64 images. The laser dots are raw 16x16 images. +// The bot is a raw 48x48 image. All use the standard PLAYPAL. +// +//========================================================================== + +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. + for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i) + { + int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics); + if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); + + if (lumpnum >= 0) + { + auto lumpr1 = FImageSource::GetImage(lumpnum, false); + if (lumpr1) StartupPics[i] = lumpr1->GetCachedBitmap(nullptr, FImageSource::normal); + } + } + if (StartupPics[7].GetWidth() != 320 || StartupPics[7].GetHeight() != 200) + { + I_Error("bad startscreen assets"); + } + + // Make the startup image appear. + DrawStuff(0, 0); + Scale = 2; + CreateHeader(); +} + +//========================================================================== +// +// FStrifeStartScreen :: Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +bool FStrifeStartScreen::DoProgress(int advance) +{ + int notch_pos; + + if (CurPos < MaxPos) + { + notch_pos = ((CurPos + 1) * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos; + if (notch_pos != NotchPos && !(notch_pos & 1)) + { // Time to update. + DrawStuff(NotchPos, notch_pos); + NotchPos = notch_pos; + StartupTexture->CleanHardwareData(true); + } + } + return FStartScreen::DoProgress(advance); +} + +//========================================================================== +// +// FStrifeStartScreen :: DrawStuff +// +// Draws all the moving parts of Strife's startup screen. If you're +// running off a slow drive, it can look kind of good. Otherwise, it +// borders on crazy insane fast. +// +//========================================================================== + +void FStrifeStartScreen::DrawStuff(int old_laser, int new_laser) +{ + int y; + + // Clear old laser + StartupBitmap.Blit(0, 0, StartupPics[7]); + + // Draw new laser + auto& lp = StartupPics[LASER_INDEX + (new_laser & 1)]; + StartupBitmap.Blit(ST_LASERSPACE_X + new_laser, ST_LASERSPACE_Y, lp); + + // The bot jumps up and down like crazy. + y = max(0, (new_laser >> 1) % 5 - 2); + + StartupBitmap.Blit(ST_BOT_X, ST_BOT_Y + y, StartupPics[BOT_INDEX]); + + // The peasant desperately runs in place, trying to get away from the laser. + // Yet, despite all his limb flailing, he never manages to get anywhere. + auto& pp = StartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)]; + StartupBitmap.Blit(ST_PEASANT_X, ST_PEASANT_Y, pp); +} + + +FStartScreen* CreateStrifeStartScreen(int max_progress) +{ + return new FStrifeStartScreen(max_progress); +} diff --git a/src/common/statusbar/base_sbar.cpp b/src/common/statusbar/base_sbar.cpp index e63c21fb2..b1fb2d79a 100644 --- a/src/common/statusbar/base_sbar.cpp +++ b/src/common/statusbar/base_sbar.cpp @@ -35,7 +35,7 @@ #include -#include "templates.h" + #include "base_sbar.h" #include "printf.h" #include "v_draw.h" @@ -46,6 +46,8 @@ #include "utf8.h" #include "v_text.h" #include "vm.h" +#include "i_interface.h" +#include "r_videoscale.h" FGameTexture* CrosshairImage; static int CrosshairNum; @@ -59,9 +61,19 @@ CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE); CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE); CVARD(Float, crosshairscale, 0.5, CVAR_ARCHIVE, "changes the size of the crosshair"); CVAR(Bool, crosshairgrow, false, CVAR_ARCHIVE); -EXTERN_CVAR(Bool, vid_fps) -EXTERN_CVAR(Float, hud_scalefactor) +CUSTOM_CVARD(Float, hud_scalefactor, 1.f, CVAR_ARCHIVE, "changes the hud scale") +{ + if (self < 0.36f) self = 0.36f; + else if (self > 1) self = 1; + else if (sysCallbacks.HudScaleChanged) sysCallbacks.HudScaleChanged(); +} + +CUSTOM_CVARD(Bool, hud_aspectscale, true, CVAR_ARCHIVE, "enables aspect ratio correction for the status bar") +{ + if (sysCallbacks.HudScaleChanged) sysCallbacks.HudScaleChanged(); +} + void ST_LoadCrosshair(int num, bool alwaysload) { @@ -113,7 +125,7 @@ void ST_UnloadCrosshair() // //--------------------------------------------------------------------------- -void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale) +void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale, DAngle angle) { uint32_t color; double size; @@ -196,6 +208,7 @@ void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale) xpos, ypos, DTA_DestWidth, w, DTA_DestHeight, h, + DTA_Rotate, angle.Degrees(), DTA_AlphaChannel, true, DTA_FillColor, color & 0xFFFFFF, TAG_DONE); @@ -293,11 +306,11 @@ static void ST_CalcCleanFacs(int designwidth, int designheight, int realwidth, i } // Use whichever pair of cwidth/cheight or width/height that produces less difference // between CleanXfac and CleanYfac. - cx1 = MAX(cwidth / designwidth, 1); - cy1 = MAX(cheight / designheight, 1); - cx2 = MAX(realwidth / designwidth, 1); - cy2 = MAX(realheight / designheight, 1); - if (abs(cx1 - cy1) <= abs(cx2 - cy2) || MAX(cx1, cx2) >= 4) + cx1 = max(cwidth / designwidth, 1); + cy1 = max(cheight / designheight, 1); + cx2 = max(realwidth / designwidth, 1); + cy2 = max(realheight / designheight, 1); + if (abs(cx1 - cy1) <= abs(cx2 - cy2) || max(cx1, cx2) >= 4) { // e.g. 640x360 looks better with this. *cleanx = cx1; *cleany = cy1; @@ -353,10 +366,14 @@ void DStatusBarCore::SetScale() int vert = VerticalResolution; double refaspect = horz / double(vert); double screenaspect = w / double(h); + double aspectscale = 1.0; + + double ViewportAspect = ViewportPixelAspect(); if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400)) { - refaspect = 1.333; + refaspect = (4. / 3.); + if (!hud_aspectscale) aspectscale = 1 / 1.2; } if (screenaspect < refaspect) @@ -370,14 +387,14 @@ void DStatusBarCore::SetScale() refw = h * refaspect; } refw *= hud_scalefactor; - refh *= hud_scalefactor; + refh *= hud_scalefactor * aspectscale / ViewportAspect; - int sby = VerticalResolution - RelTop; + int sby = vert - int(RelTop * hud_scalefactor * aspectscale / ViewportAspect); // Use full pixels for destination size. ST_X = xs_CRoundToInt((w - refw) / 2); ST_Y = xs_CRoundToInt(h - refh); - SBarTop = Scale(sby, h, VerticalResolution); + SBarTop = Scale(sby, h, vert); SBarScale.X = refw / horz; SBarScale.Y = refh / vert; } @@ -467,7 +484,7 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag double texheight = tex->GetDisplayHeight() * scaleY; double texleftoffs = tex->GetDisplayLeftOffset() * scaleY; double textopoffs = tex->GetDisplayTopOffset() * scaleY; - double boxleftoffs, boxtopoffs; + double boxleftoffs = 0, boxtopoffs = 0; if (boxwidth > 0 || boxheight > 0) { @@ -489,7 +506,7 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag if (boxwidth <= 0 || (boxheight > 0 && scale2 < scale1)) scale1 = scale2; } - else scale1 = MIN(scale1, scale2); + else scale1 = min(scale1, scale2); boxwidth = texwidth * scale1; boxheight = texheight * scale1; @@ -565,9 +582,6 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } - // move stuff in the top right corner a bit down if the fps counter is on. - if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; - DVector2 Scale = GetHUDScale(); x *= Scale.X; @@ -618,8 +632,6 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag { double texwidth = tex->GetDisplayWidth() * scaleX; double texheight = tex->GetDisplayHeight() * scaleY; - double texleftoffs = tex->GetDisplayLeftOffset() * scaleY; - double textopoffs = tex->GetDisplayTopOffset() * scaleY; // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) @@ -661,9 +673,6 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } - // move stuff in the top right corner a bit down if the fps counter is on. - if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; - x *= Scale.X; y *= Scale.Y; scaleX *= Scale.X; @@ -741,9 +750,6 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break; case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } - - // move stuff in the top right corner a bit down if the fps counter is on. - if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; } else { @@ -754,7 +760,7 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d { if (ch == ' ') { - x += monospaced ? spacing : font->GetSpaceWidth() + spacing; + x += (monospaced ? spacing : font->GetSpaceWidth() + spacing) * scaleX; continue; } else if (ch == TEXTCOLOR_ESCAPE) @@ -774,7 +780,7 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d width += font->GetDefaultKerning(); if (!monospaced) //If we are monospaced lets use the offset - x += (c->GetDisplayLeftOffset() + 1); //ignore x offsets since we adapt to character size + x += (c->GetDisplayLeftOffset() * scaleX + 1); //ignore x offsets since we adapt to character size double rx, ry, rw, rh; rx = x + drawOffset.X; @@ -825,12 +831,12 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d DTA_LegacyRenderStyle, ERenderStyle(style), TAG_DONE); - dx = monospaced - ? spacing - : width + spacing - (c->GetDisplayLeftOffset() + 1); - // Take text scale into account - x += dx * scaleX; + dx = monospaced + ? spacing * scaleX + : (double(width) + spacing - c->GetDisplayLeftOffset()) * scaleX - 1; + + x += dx; } } @@ -906,9 +912,6 @@ void DStatusBarCore::TransformRect(double& x, double& y, double& w, double& h, i case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break; } - // move stuff in the top right corner a bit down if the fps counter is on. - if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; - DVector2 Scale = GetHUDScale(); x *= Scale.X; diff --git a/src/common/statusbar/base_sbar.h b/src/common/statusbar/base_sbar.h index 9b1204412..f095ab80d 100644 --- a/src/common/statusbar/base_sbar.h +++ b/src/common/statusbar/base_sbar.h @@ -10,7 +10,7 @@ class FFont; extern FGameTexture* CrosshairImage; void ST_LoadCrosshair(int num, bool alwaysload); void ST_UnloadCrosshair(); -void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale); +void ST_DrawCrosshair(int phealth, double xpos, double ypos, double scale, DAngle angle = nullAngle); enum DI_Flags @@ -131,7 +131,7 @@ class DStatusBarCore : public DObject DECLARE_CLASS(DStatusBarCore, DObject) protected: - + public: diff --git a/src/common/textures/animlib.cpp b/src/common/textures/animlib.cpp index c712ae2bf..e42386bd9 100644 --- a/src/common/textures/animlib.cpp +++ b/src/common/textures/animlib.cpp @@ -44,38 +44,38 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) { - // curlpnum is initialized to 0xffff, obviously - size_t i = anim->curlpnum & ~0xffff; - size_t const nLps = anim->lpheader->nLps; - bool j = true; + // curlpnum is initialized to 0xffff, obviously + size_t i = anim->curlpnum & ~0xffff; + size_t const nLps = anim->lpheader->nLps; + bool j = true; - if (framenumber < anim->currentframe) - i = 0, j = false; + if (framenumber < anim->currentframe) + i = 0, j = false; - // this scans the last used page and higher first and then scans the - // previously accessed pages afterwards if it doesn't find anything - do - { - for (; i < nLps; ++i) - { - lp_descriptor & lp = anim->LpArray[i]; - if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) - return (uint16_t)i; - } + // this scans the last used page and higher first and then scans the + // previously accessed pages afterwards if it doesn't find anything + do + { + for (; i < nLps; ++i) + { + lp_descriptor & lp = anim->LpArray[i]; + if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) + return (uint16_t)i; + } - if (j && i == nLps) - { - // handle out of order pages... I don't think any Duke .ANM files - // have them, but they're part of the file spec - i = 0, j = false; - continue; - } + if (j && i == nLps) + { + // handle out of order pages... I don't think any Duke .ANM files + // have them, but they're part of the file spec + i = 0, j = false; + continue; + } - break; - } - while (1); + break; + } + while (1); - return (uint16_t)i; + return (uint16_t)i; } @@ -88,13 +88,13 @@ static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepointer) { - if (anim->curlpnum == pagenumber) - return; + if (anim->curlpnum == pagenumber) + return; - anim->curlpnum = pagenumber; - anim->curlp = &anim->LpArray[pagenumber]; - *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + - sizeof(lp_descriptor) + sizeof(uint16_t)); + anim->curlpnum = pagenumber; + anim->curlp = &anim->LpArray[pagenumber]; + *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + + sizeof(lp_descriptor) + sizeof(uint16_t)); } @@ -114,63 +114,63 @@ static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepo static void decodeframe(uint8_t * srcP, uint8_t * dstP) { - do - { - { - /* short op */ - uint8_t count = *srcP++; + do + { + { + /* short op */ + uint8_t count = *srcP++; - if (!count) /* short RLE */ - { - uint8_t color = *(srcP+1); - count = *(uint8_t *)srcP; - srcP += sizeof(int16_t); - memset(dstP, color, count); - dstP += count; - continue; - } - else if ((count & 0x80) == 0) /* short copy */ - { - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - continue; - } - else if ((count &= ~0x80) > 0) /* short skip */ - { - dstP += count; - continue; - } - } + if (!count) /* short RLE */ + { + uint8_t color = *(srcP+1); + count = *(uint8_t *)srcP; + srcP += sizeof(int16_t); + memset(dstP, color, count); + dstP += count; + continue; + } + else if ((count & 0x80) == 0) /* short copy */ + { + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + continue; + } + else if ((count &= ~0x80) > 0) /* short skip */ + { + dstP += count; + continue; + } + } - { - /* long op */ - uint16_t count = LittleShort((uint16_t)GetShort(srcP)); - srcP += sizeof(int16_t); + { + /* long op */ + uint16_t count = LittleShort((uint16_t)GetShort(srcP)); + srcP += sizeof(int16_t); - if (!count) /* stop sign */ - return; - else if ((count & 0x8000) == 0) /* long skip */ - { - dstP += count; - continue; - } - else if ((count &= ~0x8000) & 0x4000) /* long RLE */ - { - uint8_t color = *srcP++; - count &= ~0x4000; - memset(dstP, color, count); - dstP += count; - continue; - } + if (!count) /* stop sign */ + return; + else if ((count & 0x8000) == 0) /* long skip */ + { + dstP += count; + continue; + } + else if ((count &= ~0x8000) & 0x4000) /* long RLE */ + { + uint8_t color = *srcP++; + count &= ~0x4000; + memset(dstP, color, count); + dstP += count; + continue; + } - /* long copy */ - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - } - } - while (1); + /* long copy */ + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + } + } + while (1); } @@ -183,23 +183,23 @@ static void decodeframe(uint8_t * srcP, uint8_t * dstP) static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointer) { - uint16_t offset = 0; - uint16_t frame = framenumber - anim->curlp->baseRecord; + uint16_t offset = 0; + uint16_t frame = framenumber - anim->curlp->baseRecord; - while (frame--) offset += LittleShort(pagepointer[frame]); + while (frame--) offset += LittleShort(pagepointer[frame]); if (offset >= anim->curlp->nBytes) return; - uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; + uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; - if ((ppointer-4)[1]) - { - uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); - ppointer += temp + (temp & 1); - } + if ((ppointer-4)[1]) + { + uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); + ppointer += temp + (temp & 1); + } - decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); + decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); } @@ -212,79 +212,79 @@ static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointe static inline void drawframe(anim_t *anim, uint16_t framenumber) { - loadpage(anim, findpage(anim, framenumber), &anim->thepage); - renderframe(anim, framenumber, anim->thepage); + loadpage(anim, findpage(anim, framenumber), &anim->thepage); + renderframe(anim, framenumber, anim->thepage); } // is the file size, for consistency checking. int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) { - if (memcmp(buffer, "LPF ", 4)) return -1; + if (memcmp(buffer, "LPF ", 4)) return -1; - length -= sizeof(lpfileheader)+128+768; - if (length < 0) - return -1; + length -= sizeof(lpfileheader)+128+768; + if (length < 0) + return -1; - anim->curlpnum = 0xffff; - anim->currentframe = -1; + anim->curlpnum = 0xffff; + anim->currentframe = -1; - // this just modifies the data in-place instead of copying it elsewhere now - lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); + // this just modifies the data in-place instead of copying it elsewhere now + lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); - lpheader.id = LittleLong(lpheader.id); - lpheader.maxLps = LittleShort(lpheader.maxLps); - lpheader.nLps = LittleShort(lpheader.nLps); - lpheader.nRecords = LittleLong(lpheader.nRecords); - lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); - lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); - lpheader.contentType = LittleLong(lpheader.contentType); - lpheader.width = LittleShort(lpheader.width); - lpheader.height = LittleShort(lpheader.height); - lpheader.nFrames = LittleLong(lpheader.nFrames); - lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); + lpheader.id = LittleLong(lpheader.id); + lpheader.maxLps = LittleShort(lpheader.maxLps); + lpheader.nLps = LittleShort(lpheader.nLps); + lpheader.nRecords = LittleLong(lpheader.nRecords); + lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); + lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); + lpheader.contentType = LittleLong(lpheader.contentType); + lpheader.width = LittleShort(lpheader.width); + lpheader.height = LittleShort(lpheader.height); + lpheader.nFrames = LittleLong(lpheader.nFrames); + lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); - length -= lpheader.nLps * sizeof(lp_descriptor); - if (length < 0) - return -2; + length -= lpheader.nLps * sizeof(lp_descriptor); + if (length < 0) + return -2; - buffer += sizeof(lpfileheader)+128; + buffer += sizeof(lpfileheader)+128; - // load the color palette - for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) - { - pal[2] = buffer[0]; - pal[1] = buffer[1]; - pal[0] = buffer[2]; - } + // load the color palette + for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) + { + pal[2] = buffer[0]; + pal[1] = buffer[1]; + pal[0] = buffer[2]; + } - // set up large page descriptors - anim->LpArray = (lp_descriptor *)buffer; + // set up large page descriptors + anim->LpArray = (lp_descriptor *)buffer; - // theoretically we should be able to play files with more than 256 frames now - // assuming the utilities to create them can make them that way - for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) - { - lp->baseRecord = LittleShort(lp->baseRecord); - lp->nRecords = LittleShort(lp->nRecords); - lp->nBytes = LittleShort(lp->nBytes); - } - return ANIM_NumFrames(anim) <= 0 ? -1 : 0; + // theoretically we should be able to play files with more than 256 frames now + // assuming the utilities to create them can make them that way + for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) + { + lp->baseRecord = LittleShort(lp->baseRecord); + lp->nRecords = LittleShort(lp->nRecords); + lp->nBytes = LittleShort(lp->nBytes); + } + return ANIM_NumFrames(anim) <= 0 ? -1 : 0; } uint8_t * ANIM_DrawFrame(anim_t *anim, int32_t framenumber) { - uint32_t cnt = anim->currentframe; + uint32_t cnt = anim->currentframe; - // handle first play and looping or rewinding - if (cnt > (uint32_t)framenumber) - cnt = 0; + // handle first play and looping or rewinding + if (cnt > (uint32_t)framenumber) + cnt = 0; - do drawframe(anim, cnt++); - while (cnt < (uint32_t)framenumber); + do drawframe(anim, cnt++); + while (cnt < (uint32_t)framenumber); - anim->currentframe = framenumber; - return anim->imagebuffer; + anim->currentframe = framenumber; + return anim->imagebuffer; } diff --git a/src/common/textures/animlib.h b/src/common/textures/animlib.h index dd9415aa4..23d0d89da 100644 --- a/src/common/textures/animlib.h +++ b/src/common/textures/animlib.h @@ -45,37 +45,37 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) struct lpfileheader { - uint32_t id; /* 4 uint8_tacter ID == "LPF " */ - uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ - uint16_t nLps; /* # largePages in this file. */ - uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ - uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ - uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ - uint32_t contentType; /* 4 character ID == "ANIM" */ - uint16_t width; /* Width of screen in pixels. */ - uint16_t height; /* Height of screen in pixels. */ - uint8_t variant; /* 0==ANIM. */ - uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ - uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ - uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ - uint8_t pixelType; /* 0==256 color. */ - uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ - uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ - uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ - uint8_t recordTypes[32]; /* Not yet implemented. */ - uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ - uint16_t framesPerSecond; /* Number of frames to play per second. */ - uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ + uint32_t id; /* 4 uint8_tacter ID == "LPF " */ + uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ + uint16_t nLps; /* # largePages in this file. */ + uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ + uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ + uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ + uint32_t contentType; /* 4 character ID == "ANIM" */ + uint16_t width; /* Width of screen in pixels. */ + uint16_t height; /* Height of screen in pixels. */ + uint8_t variant; /* 0==ANIM. */ + uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ + uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ + uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ + uint8_t pixelType; /* 0==256 color. */ + uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ + uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ + uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ + uint8_t recordTypes[32]; /* Not yet implemented. */ + uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ + uint16_t framesPerSecond; /* Number of frames to play per second. */ + uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ }; // this is the format of a large page structure struct lp_descriptor { - uint16_t baseRecord; // Number of first record in this large page. - uint16_t nRecords; // Number of records in lp. - // bit 15 of "nRecords" == "has continuation from previous lp". - // bit 14 of "nRecords" == "final record continues on next lp". - uint16_t nBytes; // Total number of bytes of contents, excluding header. + uint16_t baseRecord; // Number of first record in this large page. + uint16_t nRecords; // Number of records in lp. + // bit 15 of "nRecords" == "has continuation from previous lp". + // bit 14 of "nRecords" == "final record continues on next lp". + uint16_t nBytes; // Total number of bytes of contents, excluding header. }; #pragma pack(pop) @@ -84,16 +84,16 @@ struct lp_descriptor struct anim_t { - uint16_t framecount; // current frame of anim - lpfileheader * lpheader; // file header will be loaded into this structure - lp_descriptor * LpArray; // arrays of large page structs used to find frames - uint16_t curlpnum; // initialize to an invalid Large page number - 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; - uint8_t pal[768]; - int32_t currentframe; + uint16_t framecount; // current frame of anim + lpfileheader * lpheader; // file header will be loaded into this structure + lp_descriptor * LpArray; // arrays of large page structs used to find frames + uint16_t curlpnum; // initialize to an invalid Large page number + 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; + uint8_t pal[768]; + int32_t currentframe; }; //**************************************************************************** @@ -116,7 +116,7 @@ int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length); inline int32_t ANIM_NumFrames(anim_t* anim) { - return anim->lpheader->nRecords; + return anim->lpheader->nRecords; } //**************************************************************************** @@ -138,7 +138,7 @@ uint8_t * ANIM_DrawFrame(anim_t* anim, int32_t framenumber); inline uint8_t* ANIM_GetPalette(anim_t* anim) { - return anim->pal; + return anim->pal; } #endif diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index 8f8add3f7..a3be03079 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -34,7 +34,7 @@ #include "animtexture.h" #include "bitmap.h" #include "texturemanager.h" -#include "templates.h" + //========================================================================== // @@ -44,42 +44,42 @@ void AnimTexture::SetFrameSize(int format, int width, int height) { - pixelformat = format; - FTexture::SetSize(width, height); - Image.Resize(width * height * (format == Paletted ? 1 : 3)); - memset(Image.Data(), 0, Image.Size()); + pixelformat = format; + FTexture::SetSize(width, height); + Image.Resize(width * height * (format == Paletted ? 1 : 3)); + memset(Image.Data(), 0, Image.Size()); } void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) { - if (palette) memcpy(Palette, palette, 768); - if (data_) - { - if (pixelformat == YUV) - { - auto spix = (const uint8_t*)data_; - auto dpix = Image.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; + if (palette) memcpy(Palette, palette, 768); + if (data_) + { + if (pixelformat == YUV) + { + auto spix = (const uint8_t*)data_; + auto dpix = Image.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); + 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; + 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); - } - } - else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); - } + 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); + } + } + else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); + } } //=========================================================================== @@ -90,37 +90,37 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) { - FBitmap bmp; + FBitmap bmp; - bmp.Create(Width, Height); + 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; + 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; } //========================================================================== @@ -131,36 +131,36 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) AnimTextures::AnimTextures() { - active = 1; - tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); - tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); + active = 1; + tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); + tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); } AnimTextures::~AnimTextures() { - Clean(); + Clean(); } void AnimTextures::Clean() { - if (tex[0]) tex[0]->CleanHardwareData(true); - if (tex[1]) tex[1]->CleanHardwareData(true); - tex[0] = tex[1] = nullptr; + if (tex[0]) tex[0]->CleanHardwareData(true); + if (tex[1]) tex[1]->CleanHardwareData(true); + tex[0] = tex[1] = nullptr; } void AnimTextures::SetSize(int format, int width, int height) { - static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); - static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); - tex[0]->SetSize(width, height); - tex[1]->SetSize(width, height); - tex[0]->CleanHardwareData(); - tex[1]->CleanHardwareData(); + static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); + static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); + tex[0]->SetSize(width, height); + tex[1]->SetSize(width, height); + tex[0]->CleanHardwareData(); + tex[1]->CleanHardwareData(); } void AnimTextures::SetFrame(const uint8_t* palette, const void* data) { - active ^= 1; - static_cast(tex[active]->GetTexture())->SetFrame(palette, data); - tex[active]->CleanHardwareData(); + active ^= 1; + static_cast(tex[active]->GetTexture())->SetFrame(palette, data); + tex[active]->CleanHardwareData(); } diff --git a/src/common/textures/bitmap.cpp b/src/common/textures/bitmap.cpp index 2e9a32883..b685b0325 100644 --- a/src/common/textures/bitmap.cpp +++ b/src/common/textures/bitmap.cpp @@ -68,7 +68,6 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn int i; int fac; uint8_t r,g,b; - int gray; int a; switch(inf? inf->blend : BLEND_NONE) @@ -98,7 +97,7 @@ void iCopyColors(uint8_t *pout, const uint8_t *pin, int count, int step, FCopyIn if (TBlend::ProcessAlpha0() || a) { int gray = TSrc::Gray(pin)>>4; - + TBlend::OpC(pout[TDest::RED], IcePalette[gray][0], a, inf); TBlend::OpC(pout[TDest::GREEN], IcePalette[gray][1], a, inf); TBlend::OpC(pout[TDest::BLUE], IcePalette[gray][2], a, inf); @@ -119,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) { - gray = clamp(TSrc::Gray(pin),0,255); + int gray = clamp(TSrc::Gray(pin),0,255); PalEntry pe = cm->GrayscaleToColor[gray]; TBlend::OpC(pout[TDest::RED], pe.r , a, inf); @@ -140,7 +139,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) { - gray = TSrc::Gray(pin); + int gray = TSrc::Gray(pin); r = (TSrc::R(pin)*(31-fac) + gray*fac)/31; g = (TSrc::G(pin)*(31-fac) + gray*fac)/31; b = (TSrc::B(pin)*(31-fac) + gray*fac)/31; @@ -210,13 +209,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step, iCopyColors, \ iCopyColors, \ iCopyColors, \ + iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors \ } -static const CopyFunc copyfuncs[][11]={ +static const CopyFunc copyfuncs[][12]={ COPY_FUNCS(bCopy), COPY_FUNCS(bBlend), COPY_FUNCS(bAdd), @@ -332,7 +332,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, srcwidth = cr->x + cr->width - originx; if (srcwidth<=0) return false; } - + if (originy < cr->y) { int skip = cr->y - originy; @@ -403,7 +403,6 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const uint8_t *patch, i } } - template void iCopyPaletted(uint8_t *buffer, const uint8_t * patch, int srcwidth, int srcheight, int Pitch, int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf) diff --git a/src/common/textures/bitmap.h b/src/common/textures/bitmap.h index 36d520771..ae5ede88f 100644 --- a/src/common/textures/bitmap.h +++ b/src/common/textures/bitmap.h @@ -37,7 +37,7 @@ #define __BITMAP_H__ #include "basics.h" -#include "templates.h" + #include "palentry.h" struct FCopyInfo; @@ -65,6 +65,7 @@ enum ColorType CF_IA, CF_CMYK, CF_YCbCr, + CF_YCCK, CF_BGR, CF_BGRA, CF_I16, @@ -156,7 +157,7 @@ public: } } - + ~FBitmap() { Destroy(); @@ -326,6 +327,15 @@ struct cYCbCr static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; } }; +struct cYCCK +{ + static __forceinline unsigned char R(const unsigned char* p) { auto myR = cYCbCr::R(p); return p[3] - ((myR * p[3]) >> 8); } + static __forceinline unsigned char G(const unsigned char* p) { auto myG = cYCbCr::G(p); return p[3] - ((myG * p[3]) >> 8); } + static __forceinline unsigned char B(const unsigned char* p) { auto myB = cYCbCr::B(p); return p[3] - ((myB * p[3]) >> 8); } + 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; } +}; + struct cBGR { static __forceinline unsigned char R(const unsigned char * p) { return p[2]; } @@ -460,7 +470,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 = max(s,d); } static __forceinline bool ProcessAlpha0() { return false; } }; @@ -473,21 +483,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 = 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 = 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 = 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 aa65dc693..eeea41a89 100644 --- a/src/common/textures/formats/anmtexture.cpp +++ b/src/common/textures/formats/anmtexture.cpp @@ -51,7 +51,7 @@ class FAnmTexture : public FImageSource public: FAnmTexture (int lumpnum, int w, int h); void ReadFrame(uint8_t *buffer, uint8_t *palette); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap *bmp, int conversion) override; }; @@ -66,7 +66,8 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) { file.Seek(0, FileReader::SeekSet); char check[4]; - file.Read(check, 4); + auto num = file.Read(check, 4); + if (num < 4) return nullptr; if (memcmp(check, "LPF ", 4)) return nullptr; file.Seek(0, FileReader::SeekSet); auto buffer = file.ReadPadded(1); @@ -81,7 +82,7 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) { return new FAnmTexture(lumpnum, 320, 200); } - + return nullptr; } @@ -126,13 +127,13 @@ void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette) // //========================================================================== -TArray FAnmTexture::CreatePalettedPixels(int conversion) +PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion) { - TArray pixels(Width*Height, true); + PalettedPixels pixels(Width*Height); uint8_t buffer[64000]; uint8_t palette[768]; uint8_t remap[256]; - + ReadFrame(buffer, palette); for(int i=0;i<256;i++) { @@ -153,7 +154,7 @@ int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion) uint8_t buffer[64000]; uint8_t palette[768]; ReadFrame(buffer, palette); - + auto dpix = bmp->GetPixels(); for (int i = 0; i < Width * Height; i++) { diff --git a/src/common/textures/formats/automaptexture.cpp b/src/common/textures/formats/automaptexture.cpp index 4135f4908..c253650fd 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); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; @@ -89,13 +89,13 @@ FAutomapTexture::FAutomapTexture (int lumpnum) // //========================================================================== -TArray FAutomapTexture::CreatePalettedPixels(int conversion) +PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion) { int x, y; FileData data = fileSystem.ReadFile (SourceLump); const uint8_t *indata = (const uint8_t *)data.GetMem(); - TArray Pixels(Width * Height, true); + PalettedPixels Pixels(Width * Height); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); for (x = 0; x < Width; ++x) diff --git a/src/common/textures/formats/buildtexture.cpp b/src/common/textures/formats/buildtexture.cpp index 44648a51c..f8d8a7b6a 100644 --- a/src/common/textures/formats/buildtexture.cpp +++ b/src/common/textures/formats/buildtexture.cpp @@ -55,9 +55,9 @@ FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8 TopOffset = top; } -TArray FBuildTexture::CreatePalettedPixels(int conversion) +PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion) { - TArray Pixels(Width * Height, true); + PalettedPixels Pixels(Width * Height); FRemapTable *Remap = Translation; for (int i = 0; i < Width*Height; i++) { diff --git a/src/common/textures/formats/ddstexture.cpp b/src/common/textures/formats/ddstexture.cpp index 3a88fcdd1..8a3d0ba74 100644 --- a/src/common/textures/formats/ddstexture.cpp +++ b/src/common/textures/formats/ddstexture.cpp @@ -163,7 +163,7 @@ class FDDSTexture : public FImageSource public: FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; protected: uint32_t Format; @@ -371,11 +371,11 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift // //========================================================================== -TArray FDDSTexture::CreatePalettedPixels(int conversion) +PalettedPixels FDDSTexture::CreatePalettedPixels(int conversion) { auto lump = fileSystem.OpenFileReader (SourceLump); - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet); diff --git a/src/common/textures/formats/emptytexture.cpp b/src/common/textures/formats/emptytexture.cpp index bcbd682e0..74e8fe1cb 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); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; //========================================================================== @@ -94,10 +94,10 @@ FEmptyTexture::FEmptyTexture (int lumpnum) // //========================================================================== -TArray FEmptyTexture::CreatePalettedPixels(int conversion) +PalettedPixels FEmptyTexture::CreatePalettedPixels(int conversion) { - TArray Pixel(1, true); - Pixel[0] = 0; + static uint8_t p; + PalettedPixels Pixel(&p, 1); return Pixel; } diff --git a/src/common/textures/formats/flattexture.cpp b/src/common/textures/formats/flattexture.cpp index 20c5d052a..a01016a36 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); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; @@ -102,10 +102,10 @@ FFlatTexture::FFlatTexture (int lumpnum) // //========================================================================== -TArray FFlatTexture::CreatePalettedPixels(int conversion) +PalettedPixels FFlatTexture::CreatePalettedPixels(int conversion) { auto lump = fileSystem.OpenFileReader (SourceLump); - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); auto numread = lump.Read (Pixels.Data(), Width*Height); if (numread < Width*Height) { diff --git a/src/common/textures/formats/fontchars.cpp b/src/common/textures/formats/fontchars.cpp index 44a72ca6e..add4f1f74 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 // //========================================================================== -TArray FFontChar2::CreatePalettedPixels(int) +PalettedPixels FFontChar2::CreatePalettedPixels(int) { auto lump = fileSystem.OpenFileReader(SourceLump); int destSize = Width * Height; @@ -96,7 +96,7 @@ TArray FFontChar2::CreatePalettedPixels(int) } } - TArray Pixels(destSize, true); + PalettedPixels Pixels(destSize); int runlen = 0, setlen = 0; uint8_t setval = 0; // Shut up, GCC! @@ -113,7 +113,7 @@ TArray FFontChar2::CreatePalettedPixels(int) if (runlen != 0) { uint8_t color = lump.ReadUInt8(); - color = MIN(color, max); + color = min(color, max); *dest_p = color; dest_p += dest_adv; x--; @@ -137,7 +137,7 @@ TArray FFontChar2::CreatePalettedPixels(int) { uint8_t color = lump.ReadUInt8(); setlen = (-code) + 1; - setval = MIN(color, max); + setval = min(color, max); } } } diff --git a/src/common/textures/formats/fontchars.h b/src/common/textures/formats/fontchars.h index 79baf4a2b..45c678566 100644 --- a/src/common/textures/formats/fontchars.h +++ b/src/common/textures/formats/fontchars.h @@ -6,7 +6,7 @@ class FFontChar2 : public FImageSource public: FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap* bmp, int conversion); void SetSourceRemap(const PalEntry* sourceremap) diff --git a/src/common/textures/formats/imgztexture.cpp b/src/common/textures/formats/imgztexture.cpp index 5c2e041ac..733d20f84 100644 --- a/src/common/textures/formats/imgztexture.cpp +++ b/src/common/textures/formats/imgztexture.cpp @@ -66,7 +66,7 @@ class FIMGZTexture : public FImageSource public: FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap *bmp, int conversion) override; }; @@ -118,7 +118,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 // //========================================================================== -TArray FIMGZTexture::CreatePalettedPixels(int conversion) +PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion) { FileData lump = fileSystem.ReadFile (SourceLump); const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); @@ -128,7 +128,7 @@ TArray FIMGZTexture::CreatePalettedPixels(int conversion) int dest_adv = Height; int dest_rew = Width * Height - 1; - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); dest_p = Pixels.Data(); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance, isalpha); diff --git a/src/common/textures/formats/jpegtexture.cpp b/src/common/textures/formats/jpegtexture.cpp index e07f4425d..b1e5163b3 100644 --- a/src/common/textures/formats/jpegtexture.cpp +++ b/src/common/textures/formats/jpegtexture.cpp @@ -185,7 +185,7 @@ public: FJPEGTexture (int lumpnum, int width, int height); int CopyPixels(FBitmap *bmp, int conversion) override; - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; //========================================================================== @@ -259,7 +259,7 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) // //========================================================================== -TArray FJPEGTexture::CreatePalettedPixels(int conversion) +PalettedPixels FJPEGTexture::CreatePalettedPixels(int conversion) { auto lump = fileSystem.OpenFileReader (SourceLump); JSAMPLE *buff = NULL; @@ -267,7 +267,7 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; - TArray Pixels(Width * Height, true); + PalettedPixels Pixels(Width * Height); memset (Pixels.Data(), 0xBA, Width * Height); cinfo.err = jpeg_std_error(&jerr); @@ -282,6 +282,7 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) 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))) { @@ -296,7 +297,7 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) while (cinfo.output_scanline < cinfo.output_height) { - int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); + jpeg_read_scanlines(&cinfo, &buff, 1); uint8_t *in = buff; uint8_t *out = Pixels.Data() + y; switch (cinfo.out_color_space) @@ -350,6 +351,24 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) } 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. @@ -402,6 +421,7 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) 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))) { @@ -439,6 +459,11 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) 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); diff --git a/src/common/textures/formats/md5check.cpp b/src/common/textures/formats/md5check.cpp index 96e14b2f3..120371a8e 100644 --- a/src/common/textures/formats/md5check.cpp +++ b/src/common/textures/formats/md5check.cpp @@ -219,10 +219,10 @@ void makeMD5(const void *buffer, unsigned length, char *md5out) bool checkPatchForAlpha(const void *buffer, uint32_t length) { if (length > 10164) return false; // shortcut for anything too large - + char md5[33]; bool done = false; - + for(int i=0; alphapatches[i].length > 0; i++) { if (alphapatches[i].length == (int)length) // length check diff --git a/src/common/textures/formats/multipatchtexture.cpp b/src/common/textures/formats/multipatchtexture.cpp index e131b9024..17c0a7b28 100644 --- a/src/common/textures/formats/multipatchtexture.cpp +++ b/src/common/textures/formats/multipatchtexture.cpp @@ -201,13 +201,13 @@ void FMultiPatchTexture::CopyToBlock(uint8_t *dest, int dwidth, int dheight, FIm // //========================================================================== -TArray FMultiPatchTexture::CreatePalettedPixels(int conversion) +PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion) { int numpix = Width * Height; uint8_t blendwork[256]; bool buildrgb = bComplex; - TArray Pixels(numpix, true); + PalettedPixels Pixels(numpix); memset (Pixels.Data(), 0, numpix); if (conversion == luminance) diff --git a/src/common/textures/formats/multipatchtexture.h b/src/common/textures/formats/multipatchtexture.h index 48223ec5e..4b92aad4f 100644 --- a/src/common/textures/formats/multipatchtexture.h +++ b/src/common/textures/formats/multipatchtexture.h @@ -75,7 +75,7 @@ protected: // The getters must optionally redirect if it's a simple one-patch texture. int CopyPixels(FBitmap *bmp, int conversion) override; - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) 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; @@ -120,6 +120,7 @@ struct BuildInfo bool bComplex = false; bool textual = false; bool bNoDecals = false; + bool bNoTrim = false; int LeftOffset[2] = {}; int TopOffset[2] = {}; FGameTexture *texture = nullptr; diff --git a/src/common/textures/formats/patchtexture.cpp b/src/common/textures/formats/patchtexture.cpp index f1f65291d..2fe36efe7 100644 --- a/src/common/textures/formats/patchtexture.cpp +++ b/src/common/textures/formats/patchtexture.cpp @@ -61,7 +61,7 @@ class FPatchTexture : public FImageSource bool isalpha = false; public: FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool isalphatex); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap *bmp, int conversion) override; bool SupportRemap0() override { return !badflag; } void DetectBadPatches(); @@ -76,15 +76,15 @@ public: static bool CheckIfPatch(FileReader & file, bool &isalpha) { if (file.GetLength() < 13) return false; // minimum length of a valid Doom patch - + file.Seek(0, FileReader::SeekSet); auto data = file.Read(file.GetLength()); - + const patch_t *foo = (const patch_t *)data.Data(); - + int height = LittleShort(foo->height); int width = LittleShort(foo->width); - + if (height > 0 && height <= 2048 && width > 0 && width <= 2048 && width < file.GetLength()/4) { // The dimensions seem like they might be valid for a patch, so @@ -93,7 +93,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) // and none of them must point past the end of the patch. bool gapAtStart = true; int x; - + for (x = 0; x < width; ++x) { uint32_t ofs = LittleLong(foo->columnofs[x]); @@ -166,7 +166,7 @@ FPatchTexture::FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool is // //========================================================================== -TArray FPatchTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion) { uint8_t *remap, remaptable[256]; int numspans; @@ -189,7 +189,7 @@ TArray FPatchTexture::CreatePalettedPixels(int conversion) if (badflag) { - TArray Pixels(Width * Height, true); + PalettedPixels Pixels(Width * Height); uint8_t *out; // Draw the image to the buffer @@ -210,7 +210,7 @@ TArray FPatchTexture::CreatePalettedPixels(int conversion) numspans = Width; - TArray Pixels(numpix, true); + PalettedPixels Pixels(numpix); memset (Pixels.Data(), 0, numpix); // Draw the image to the buffer diff --git a/src/common/textures/formats/pcxtexture.cpp b/src/common/textures/formats/pcxtexture.cpp index 89d05e427..60e2f4aba 100644 --- a/src/common/textures/formats/pcxtexture.cpp +++ b/src/common/textures/formats/pcxtexture.cpp @@ -91,7 +91,7 @@ protected: void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; @@ -344,7 +344,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr // //========================================================================== -TArray FPCXTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion) { uint8_t PaletteMap[256]; PCXHeader header; @@ -355,7 +355,7 @@ TArray FPCXTexture::CreatePalettedPixels(int conversion) lump.Read(&header, sizeof(header)); bitcount = header.bitsPerPixel * header.numColorPlanes; - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); bool alphatex = conversion == luminance; if (bitcount < 24) @@ -383,7 +383,7 @@ TArray FPCXTexture::CreatePalettedPixels(int conversion) else if (bitcount == 8) { lump.Seek(-769, FileReader::SeekEnd); - uint8_t c = lump.ReadUInt8(); + lump.ReadUInt8(); //if (c !=0x0c) memcpy(PaletteMap, GrayMap, 256); // Fallback for files without palette //else for(int i=0;i<256;i++) @@ -402,7 +402,7 @@ TArray FPCXTexture::CreatePalettedPixels(int conversion) } else { - TArray newpix(Width*Height, true); + PalettedPixels newpix(Width*Height); ImageHelpers::FlipNonSquareBlockRemap (newpix.Data(), Pixels.Data(), Width, Height, Width, PaletteMap); return newpix; } diff --git a/src/common/textures/formats/pngtexture.cpp b/src/common/textures/formats/pngtexture.cpp index 294e218aa..f9e39fc8c 100644 --- a/src/common/textures/formats/pngtexture.cpp +++ b/src/common/textures/formats/pngtexture.cpp @@ -35,7 +35,7 @@ */ #include "files.h" -#include "templates.h" + #include "m_png.h" #include "bitmap.h" #include "imagehelpers.h" @@ -56,7 +56,7 @@ 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; - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; protected: void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap); @@ -244,7 +244,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height, break; case MAKE_ID('P','L','T','E'): - PaletteSize = MIN (len / 3, 256); + PaletteSize = min (len / 3, 256); StartOfPalette = (uint32_t)lump.Tell(); lump.Seek(len, FileReader::SeekCur); break; @@ -411,7 +411,7 @@ void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap) // //========================================================================== -TArray FPNGTexture::CreatePalettedPixels(int conversion) +PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion) { FileReader *lump; FileReader lfr; @@ -419,7 +419,7 @@ TArray FPNGTexture::CreatePalettedPixels(int conversion) lfr = fileSystem.OpenFileReader(SourceLump); lump = 𝔩 - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); if (StartOfIDAT == 0) { memset (Pixels.Data(), 0x99, Width*Height); @@ -456,7 +456,7 @@ TArray FPNGTexture::CreatePalettedPixels(int conversion) } else { - TArray newpix(Width*Height, true); + PalettedPixels newpix(Width*Height); if (conversion != luminance) { if (!PaletteMap) SetupPalette(lfr); @@ -684,7 +684,7 @@ public: virtual FBitmap GetBgraBitmap(const PalEntry *remap, int *trans) override; protected: - + FileReader fr; uint8_t ColorType; int PaletteSize; @@ -703,7 +703,7 @@ FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) { return nullptr; } - + // Savegame images can only be either 8 bit paletted or 24 bit RGB auto &data = png->File; int width = data.ReadInt32BE(); @@ -713,7 +713,7 @@ FGameTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) uint8_t compression = data.ReadUInt8(); uint8_t filter = data.ReadUInt8(); uint8_t interlace = data.ReadUInt8(); - + // Reject anything that cannot be put into a savegame picture by GZDoom itself. if (compression != 0 || filter != 0 || interlace > 0 || bitdepth != 8 || (colortype != 2 && colortype != 3)) return nullptr; else return MakeGameTexture(new FPNGFileTexture (png->File, width, height, colortype), nullptr, ETextureType::Override); @@ -748,9 +748,9 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) PalEntry pe[256]; uint32_t len, id; int pixwidth = Width * (ColorType == 2? 3:1); - + FileReader *lump = &fr; - + bmp.Create(Width, Height); lump->Seek(33, FileReader::SeekSet); lump->Read(&len, 4); @@ -762,7 +762,7 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) lump->Seek (len, FileReader::SeekCur); else { - PaletteSize = std::min (len / 3, 256); + PaletteSize = min (len / 3, 256); for(int i = 0; i < PaletteSize; i++) { pe[i].r = lump->ReadUInt8(); @@ -779,12 +779,12 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) auto StartOfIDAT = (uint32_t)lump->Tell() - 8; TArray Pixels(pixwidth * Height); - + lump->Seek (StartOfIDAT, FileReader::SeekSet); lump->Read(&len, 4); lump->Read(&id, 4); M_ReadIDAT (*lump, Pixels.Data(), Width, Height, pixwidth, 8, ColorType, 0, BigLong((unsigned int)len)); - + if (ColorType == 3) { bmp.CopyPixelData(0, 0, Pixels.Data(), Width, Height, 1, Width, 0, pe); @@ -794,4 +794,4 @@ FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) bmp.CopyPixelDataRGB(0, 0, Pixels.Data(), Width, Height, 3, pixwidth, 0, CF_RGB); } return bmp; -} +} \ No newline at end of file diff --git a/src/common/textures/formats/rawpagetexture.cpp b/src/common/textures/formats/rawpagetexture.cpp index 38fca7a67..19d3f4587 100644 --- a/src/common/textures/formats/rawpagetexture.cpp +++ b/src/common/textures/formats/rawpagetexture.cpp @@ -51,7 +51,7 @@ class FRawPageTexture : public FImageSource int mPaletteLump = -1; public: FRawPageTexture (int lumpnum); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap *bmp, int conversion) override; }; @@ -62,9 +62,9 @@ public: // //========================================================================== -static bool CheckIfRaw(FileReader & data) +bool CheckIfRaw(FileReader & data, unsigned desiredsize) { - if (data.GetLength() != 64000) return false; + if (data.GetLength() != desiredsize) return false; // This is probably a raw page graphic, but do some checking to be sure patch_t *foo; @@ -73,7 +73,7 @@ static bool CheckIfRaw(FileReader & data) 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); @@ -94,7 +94,7 @@ static bool CheckIfRaw(FileReader & data) { gapAtStart = false; } - else if (ofs >= 64000-1) // Need one byte for an empty column + else if (ofs >= desiredsize-1) // Need one byte for an empty column { return true; } @@ -102,7 +102,7 @@ static bool CheckIfRaw(FileReader & data) { // Ensure this column does not extend beyond the end of the patch const uint8_t *foo2 = (const uint8_t *)foo; - while (ofs < 64000) + while (ofs < desiredsize) { if (foo2[ofs] == 255) { @@ -110,7 +110,7 @@ static bool CheckIfRaw(FileReader & data) } ofs += foo2[ofs+1] + 4; } - if (ofs >= 64000) + if (ofs >= desiredsize) { return true; } @@ -136,7 +136,7 @@ static bool CheckIfRaw(FileReader & data) FImageSource *RawPageImage_TryCreate(FileReader & file, int lumpnum) { - if (!CheckIfRaw(file)) return nullptr; + if (!CheckIfRaw(file, 64000)) return nullptr; return new FRawPageTexture(lumpnum); } @@ -170,14 +170,14 @@ FRawPageTexture::FRawPageTexture (int lumpnum) // //========================================================================== -TArray FRawPageTexture::CreatePalettedPixels(int conversion) +PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion) { FileData lump = fileSystem.ReadFile (SourceLump); const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *source_p = source; uint8_t *dest_p; - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); dest_p = Pixels.Data(); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); diff --git a/src/common/textures/formats/shadertexture.cpp b/src/common/textures/formats/shadertexture.cpp index 6bde2b677..ce5952fc2 100644 --- a/src/common/textures/formats/shadertexture.cpp +++ b/src/common/textures/formats/shadertexture.cpp @@ -98,9 +98,9 @@ public: } } - TArray CreatePalettedPixels(int conversion) override + PalettedPixels CreatePalettedPixels(int conversion) override { - TArray Pix(512, true); + PalettedPixels Pix(512); if (conversion == luminance) { memcpy(Pix.Data(), Pixels, 512); diff --git a/src/common/textures/formats/startscreentexture.cpp b/src/common/textures/formats/startscreentexture.cpp new file mode 100644 index 000000000..85710d42f --- /dev/null +++ b/src/common/textures/formats/startscreentexture.cpp @@ -0,0 +1,81 @@ +/* +** startscreentexture.cpp +** Texture class to create a texture from the start screen's imagé +** +**--------------------------------------------------------------------------- +** Copyright 2004-2006 Randy Heit +** 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 "files.h" +#include "bitmap.h" +#include "textures.h" +#include "imagehelpers.h" +#include "image.h" +#include "startscreen.h" + + +//========================================================================== +// +// +// +//========================================================================== + +class FStartScreenTexture : public FImageSource +{ + FBitmap& info; // This must remain constant for the lifetime of this texture + +public: + FStartScreenTexture(FBitmap& srcdata) + : FImageSource(-1), info(srcdata) + { + Width = srcdata.GetWidth(); + Height = srcdata.GetHeight(); + bUseGamePalette = false; + } + int CopyPixels(FBitmap* bmp, int conversion) + { + bmp->Blit(0, 0, info); + return 0; + } +}; + +//========================================================================== +// +// +// +//========================================================================== + +FImageSource *CreateStartScreenTexture(FBitmap& srcdata) +{ + return new FStartScreenTexture(srcdata); +} + + diff --git a/src/common/textures/formats/startuptexture.cpp b/src/common/textures/formats/startuptexture.cpp new file mode 100644 index 000000000..8a2a1e602 --- /dev/null +++ b/src/common/textures/formats/startuptexture.cpp @@ -0,0 +1,381 @@ + +/* +** startuptexture.cpp +** Texture class for Hexen's startup screen +** +**--------------------------------------------------------------------------- +** Copyright 2022 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 "files.h" +#include "filesystem.h" +#include "bitmap.h" +#include "imagehelpers.h" +#include "image.h" + +#define ST_NOTCH_WIDTH 16 +#define ST_NOTCH_HEIGHT 23 + +#define ST_NETNOTCH_WIDTH 4 +#define ST_NETNOTCH_HEIGHT 16 + +struct StrifeStartupInfo +{ + char name[9]; + uint8_t width, height; +}; + +static StrifeStartupInfo StrifeRawPics[] = +{ + { "STRTPA1", 32, 64}, + { "STRTPB1", 32, 64}, + { "STRTPC1", 32, 64}, + { "STRTPD1", 32, 64}, + { "STRTLZ1", 16, 16}, + { "STRTLZ2", 16, 16}, + { "STRTBOT", 48, 48} +}; + +// there is only one palette for all these images. +static uint8_t startuppalette8[16]; +static uint32_t startuppalette32[16]; + +//========================================================================== +// +// +// +//========================================================================== + +class FStartupTexture : public FImageSource +{ +public: + FStartupTexture (int lumpnum); + PalettedPixels CreatePalettedPixels(int conversion) override; + int CopyPixels(FBitmap *bmp, int conversion) 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; +}; + +class FStrifeStartupTexture : public FImageSource +{ +public: + FStrifeStartupTexture (int lumpnum, int w, int h); + PalettedPixels CreatePalettedPixels(int conversion) override; +}; + +class FStrifeStartupBackground : public FImageSource +{ +public: + FStrifeStartupBackground (int lumpnum); + PalettedPixels CreatePalettedPixels(int conversion) override; +}; + +//========================================================================== +// +// Use the same function as raw textures to eliminate Doom patches +// +//========================================================================== + +bool CheckIfRaw(FileReader & data, unsigned desiredsize); + +//========================================================================== +// +// loads all raw images for Hexen's and Strife's startup screens +// +//========================================================================== + +FImageSource *StartupPageImage_TryCreate(FileReader & file, int lumpnum) +{ + if (fileSystem.CheckFileName(lumpnum, "STARTUP")) + { + if (!CheckIfRaw(file, 153648)) return nullptr; + return new FStartupTexture(lumpnum); + } + if (fileSystem.CheckFileName(lumpnum, "NOTCH")) + { + if (!CheckIfRaw(file, ST_NOTCH_WIDTH * ST_NOTCH_HEIGHT / 2)) return nullptr; + return new FNotchTexture(lumpnum, ST_NOTCH_WIDTH, ST_NOTCH_HEIGHT); + } + if (fileSystem.CheckFileName(lumpnum, "NETNOTCH")) + { + if (!CheckIfRaw(file, ST_NETNOTCH_WIDTH * ST_NETNOTCH_HEIGHT / 2)) return nullptr; + return new FNotchTexture(lumpnum, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT); + } + if (fileSystem.CheckFileName(lumpnum, "STARTUP0")) + { + if (!CheckIfRaw(file, 64000)) return nullptr; + return new FStrifeStartupBackground(lumpnum); + } + for(auto& sst : StrifeRawPics) + { + if (fileSystem.CheckFileName(lumpnum, sst.name)) + { + if (!CheckIfRaw(file, sst.width * sst.height)) return nullptr; + return new FStrifeStartupTexture(lumpnum, sst.width, sst.height); + } + } + return nullptr; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FStartupTexture::FStartupTexture (int lumpnum) +: FImageSource(lumpnum) +{ + Width = 640; + Height = 480; + bUseGamePalette = false; + + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + + // Initialize the bitmap palette. + // the palette is static so that the notches can share it. + // Note that if the STARTUP image gets replaced, the notches will be all black unless they get replaced as well! + for (int i = 0; i < 16; ++i) + { + PalEntry pe; + pe.r = source[i * 3 + 0]; + pe.g = source[i * 3 + 1]; + pe.b = source[i * 3 + 2]; + pe.a = 63; + // Convert from 6-bit per component to 8-bit per component. + pe.d= (pe.d << 2) | ((pe.d >> 4) & 0x03030303); + startuppalette8[i] = ColorMatcher.Pick(pe); + startuppalette32[i] = pe; + } +} + +//========================================================================== +// +// PlanarToChunky +// +// Convert a 4-bpp planar image to chunky pixels. +// +//========================================================================== + +template +void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int height) +{ + int y, x; + const uint8_t* src1, * src2, * src3, * src4; + size_t plane_size = width / 8 * height; + + src1 = src; + src2 = src1 + plane_size; + src3 = src2 + plane_size; + src4 = src3 + plane_size; + + for (y = height; y > 0; --y) + { + for (x = width; x > 0; x -= 8) + { + dest[0] = remap[((*src4 & 0x80) | ((*src3 & 0x80) >> 1) | ((*src2 & 0x80) >> 2) | ((*src1 & 0x80) >> 3)) >> 4]; + dest[1] = remap[((*src4 & 0x40) >> 3) | ((*src3 & 0x40) >> 4) | ((*src2 & 0x40) >> 5) | ((*src1 & 0x40) >> 6)]; + dest[2] = remap[(((*src4 & 0x20) << 2) | ((*src3 & 0x20) << 1) | ((*src2 & 0x20)) | ((*src1 & 0x20) >> 1)) >> 4]; + dest[3] = remap[((*src4 & 0x10) >> 1) | ((*src3 & 0x10) >> 2) | ((*src2 & 0x10) >> 3) | ((*src1 & 0x10) >> 4)]; + dest[4] = remap[(((*src4 & 0x08) << 4) | ((*src3 & 0x08) << 3) | ((*src2 & 0x08) << 2) | ((*src1 & 0x08) << 1)) >> 4]; + dest[5] = remap[((*src4 & 0x04) << 1) | ((*src3 & 0x04)) | ((*src2 & 0x04) >> 1) | ((*src1 & 0x04) >> 2)]; + dest[6] = remap[(((*src4 & 0x02) << 6) | ((*src3 & 0x02) << 5) | ((*src2 & 0x02) << 4) | ((*src1 & 0x02) << 3)) >> 4]; + dest[7] = remap[((*src4 & 0x01) << 3) | ((*src3 & 0x01) << 2) | ((*src2 & 0x01) << 1) | ((*src1 & 0x01))]; + dest += 8; + src1 += 1; + src2 += 1; + src3 += 1; + src4 += 1; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); + + + TArray Work(Width*Height, true); + PalettedPixels Pixels(Width*Height); + PlanarToChunky(Work.Data(), source + 48, startuppalette8, Width, Height); + ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap); + return Pixels; +} + +//========================================================================== +// +// +// +//========================================================================== + +int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height); + return 0; +} + +//========================================================================== +// +// +// +//========================================================================== + +FNotchTexture::FNotchTexture (int lumpnum, int width, int height) +: FImageSource(lumpnum) +{ + Width = width; + Height = height; + bUseGamePalette = false; +} + +//========================================================================== +// +// +// +//========================================================================== + +PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); + + TArray Work(Width*Height, true); + PalettedPixels Pixels(Width*Height); + for(int i=0; i * Width * Height / 2; i++) + { + Work[i * 2] = startuppalette8[source[i] >> 4]; + Work[i * 2 + 1] = startuppalette8[source[i] & 15]; + } + ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap); + return Pixels; +} + +//========================================================================== +// +// +// +//========================================================================== + +int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + + auto Work = (uint32_t*)bmp->GetPixels(); + for(int i = 0; i < Width * Height / 2; i++) + { + Work[i * 2] = startuppalette32[source[i] >> 4]; + Work[i * 2 + 1] = startuppalette32[source[i] & 15]; + } + return 0; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h) +: FImageSource(lumpnum) +{ + Width = w; + Height = h; +} + +//========================================================================== +// +// +// +//========================================================================== + +PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion) +{ + FileData lump = fileSystem.ReadFile (SourceLump); + const uint8_t *source = (const uint8_t *)lump.GetMem(); + PalettedPixels Pixels(Width*Height); + const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); + ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source, Width, Height, Width, remap); + return Pixels; +} + +//========================================================================== +// +// +// +//========================================================================== + +FStrifeStartupBackground::FStrifeStartupBackground (int lumpnum) +: FImageSource(lumpnum) +{ + Width = 320; + Height = 200; +} + +//========================================================================== +// +// this image is very messy but let's prepare it just like Strife does +// so that the screen can be replaced with a whole image. +// +//========================================================================== + +PalettedPixels FStrifeStartupBackground::CreatePalettedPixels(int conversion) +{ + TArray source(64000, true); + memset(source.Data(), 0xF0, 64000); + auto lumpr = fileSystem.OpenFileReader(SourceLump); + lumpr.Seek(57 * 320, FileReader::SeekSet); + lumpr.Read(source.Data() + 41 * 320, 95 * 320); + + PalettedPixels Pixels(Width*Height); + const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); + ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source.Data(), Width, Height, Width, remap); + return Pixels; +} diff --git a/src/common/textures/formats/stb_image.h b/src/common/textures/formats/stb_image.h index 196dfd5cc..44117802a 100644 --- a/src/common/textures/formats/stb_image.h +++ b/src/common/textures/formats/stb_image.h @@ -1198,7 +1198,7 @@ static FILE *stbi__fopen(char const *filename, char const *mode) wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) return 0; - + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) return 0; @@ -1302,7 +1302,7 @@ STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int * unsigned char *result; 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 ); @@ -6522,7 +6522,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i g->color_table = (stbi_uc *) g->pal; } else return stbi__errpuc("missing color table", "Corrupt GIF"); - + o = stbi__process_gif_raster(s, g); if (!o) return NULL; @@ -6608,7 +6608,7 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, *y = g.h; ++layers; stride = g.w * g.h * 4; - + if (out) { out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); if (delays) { diff --git a/src/common/textures/formats/stbtexture.cpp b/src/common/textures/formats/stbtexture.cpp index bce080c62..e8d9fe2a0 100644 --- a/src/common/textures/formats/stbtexture.cpp +++ b/src/common/textures/formats/stbtexture.cpp @@ -43,7 +43,7 @@ #define STBI_NO_HDR #define STBI_NO_PNM #include "stb_image.h" - + #include "files.h" #include "filesystem.h" @@ -67,7 +67,7 @@ class FStbTexture : public FImageSource public: FStbTexture (int lumpnum, int w, int h); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap *bmp, int conversion) override; }; @@ -92,7 +92,7 @@ FImageSource *StbImage_TryCreate(FileReader & file, int lumpnum) { return new FStbTexture(lumpnum, x, y); } - + return nullptr; } @@ -117,7 +117,7 @@ FStbTexture::FStbTexture (int lumpnum, int w, int h) // //========================================================================== -TArray FStbTexture::CreatePalettedPixels(int conversion) +PalettedPixels FStbTexture::CreatePalettedPixels(int conversion) { FBitmap bitmap; bitmap.Create(Width, Height); @@ -128,7 +128,7 @@ TArray FStbTexture::CreatePalettedPixels(int conversion) int dest_adv = Height; int dest_rew = Width * Height - 1; - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); dest_p = Pixels.Data(); bool doalpha = conversion == luminance; diff --git a/src/common/textures/formats/tgatexture.cpp b/src/common/textures/formats/tgatexture.cpp index 80c7b04a8..932eeeaf1 100644 --- a/src/common/textures/formats/tgatexture.cpp +++ b/src/common/textures/formats/tgatexture.cpp @@ -35,7 +35,7 @@ #include "files.h" #include "filesystem.h" -#include "templates.h" + #include "bitmap.h" #include "imagehelpers.h" #include "image.h" @@ -57,7 +57,7 @@ struct TGAHeader int16_t cm_first; int16_t cm_length; uint8_t cm_size; - + int16_t x_origin; int16_t y_origin; int16_t width; @@ -83,7 +83,7 @@ public: protected: void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; }; //========================================================================== @@ -97,12 +97,12 @@ FImageSource *TGAImage_TryCreate(FileReader & file, int lumpnum) TGAHeader hdr; if (file.GetLength() < (long)sizeof(hdr)) return NULL; - + file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); - + // Not much that can be done here because TGA does not have a proper // header to be identified with. if (hdr.has_cm != 0 && hdr.has_cm != 1) return NULL; @@ -145,7 +145,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe { uint8_t data[4]; int Size = Width * Height; - + while (Size > 0) { uint8_t b = lump.ReadUInt8(); @@ -153,7 +153,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe { b&=~128; lump.Read(data, bytesperpixel); - for (int i=MIN(Size, (b+1)); i>0; i--) + for (int i=min(Size, (b+1)); i>0; i--) { buffer[0] = data[0]; if (bytesperpixel>=2) buffer[1] = data[1]; @@ -164,7 +164,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe } else { - lump.Read(buffer, MIN(Size, (b+1))*bytesperpixel); + lump.Read(buffer, min(Size, (b+1))*bytesperpixel); buffer += (b+1)*bytesperpixel; } Size -= b+1; @@ -177,7 +177,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe // //========================================================================== -TArray FTGATexture::CreatePalettedPixels(int conversion) +PalettedPixels FTGATexture::CreatePalettedPixels(int conversion) { uint8_t PaletteMap[256]; auto lump = fileSystem.OpenFileReader (SourceLump); @@ -185,10 +185,10 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) uint16_t w; uint8_t r,g,b,a; - TArray Pixels(Width*Height, true); + PalettedPixels Pixels(Width*Height); lump.Read(&hdr, sizeof(hdr)); lump.Seek(hdr.id_len, FileReader::SeekCur); - + hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); hdr.cm_first = LittleShort(hdr.cm_first); @@ -209,14 +209,14 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) b = (w & 0x7C00) >> 7; a = 255; break; - + case 24: b = lump.ReadUInt8(); g = lump.ReadUInt8(); r = lump.ReadUInt8(); a=255; break; - + case 32: b = lump.ReadUInt8(); g = lump.ReadUInt8(); @@ -224,7 +224,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) a = lump.ReadUInt8(); if ((hdr.img_desc&15)!=8) a=255; break; - + default: // should never happen r=g=b=a=0; break; @@ -232,10 +232,10 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) PaletteMap[i] = ImageHelpers::RGBToPalettePrecise(conversion == luminance, r, g, b, a); } } - + int Size = Width * Height * (hdr.bpp>>3); TArray buffer(Size, true); - + if (hdr.img_type < 4) // uncompressed { lump.Read(buffer.Data(), Size); @@ -244,7 +244,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) { ReadCompressed(lump, buffer.Data(), hdr.bpp>>3); } - + uint8_t * ptr = buffer.Data(); int step_x = (hdr.bpp>>3); int Pitch = Width * step_x; @@ -293,7 +293,7 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) } } break; - + case 24: for(int y=0;y FTGATexture::CreatePalettedPixels(int conversion) } } break; - + case 32: if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel { @@ -332,12 +332,12 @@ TArray FTGATexture::CreatePalettedPixels(int conversion) } } break; - + default: break; } break; - + case 3: // Grayscale { auto remap = ImageHelpers::GetRemap(conversion == luminance, true); @@ -395,7 +395,7 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) lump.Read(&hdr, sizeof(hdr)); lump.Seek(hdr.id_len, FileReader::SeekCur); - + hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); hdr.cm_first = LittleShort(hdr.cm_first); @@ -440,10 +440,10 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) pe[i] = PalEntry(a, r, g, b); } } - + int Size = Width * Height * (hdr.bpp>>3); TArray sbuffer(Size); - + if (hdr.img_type < 4) // uncompressed { lump.Read(sbuffer.Data(), Size); @@ -452,7 +452,7 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) { ReadCompressed(lump, sbuffer.Data(), hdr.bpp>>3); } - + uint8_t * ptr = sbuffer.Data(); int step_x = (hdr.bpp>>3); int Pitch = Width * step_x; @@ -483,11 +483,11 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) case 16: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_RGB555); break; - + case 24: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_BGR); break; - + case 32: if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel { @@ -499,12 +499,12 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) transval = -1; } break; - + default: break; } break; - + case 3: // Grayscale switch (hdr.bpp) { @@ -512,11 +512,11 @@ int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // gray map bmp->CopyPixelData(0, 0, ptr, Width, Height, step_x, Pitch, 0, pe); break; - + case 16: bmp->CopyPixelDataRGB(0, 0, ptr, Width, Height, step_x, Pitch, 0, CF_I16); break; - + default: break; } diff --git a/src/common/textures/gametexture.cpp b/src/common/textures/gametexture.cpp index 29d1ee2dd..be4063213 100644 --- a/src/common/textures/gametexture.cpp +++ b/src/common/textures/gametexture.cpp @@ -37,7 +37,7 @@ #include "printf.h" #include "files.h" #include "filesystem.h" -#include "templates.h" + #include "textures.h" #include "bitmap.h" #include "colormatcher.h" @@ -96,8 +96,11 @@ void FGameTexture::Setup(FTexture *wrap) FGameTexture::~FGameTexture() { - FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump()); - if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr); + if (Base != nullptr) + { + FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump()); + if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr); + } if (SoftwareTexture != nullptr) { delete SoftwareTexture; @@ -137,16 +140,27 @@ void FGameTexture::AddAutoMaterials() const char* path; RefCountedPtr FGameTexture::* pointer; }; + struct AutoTextureSearchPath2 + { + const char* path; + RefCountedPtr FMaterialLayers::* pointer; + }; static AutoTextureSearchPath autosearchpaths[] = { { "brightmaps/", &FGameTexture::Brightmap }, // For backwards compatibility, only for short names { "materials/brightmaps/", &FGameTexture::Brightmap }, - { "materials/normalmaps/", &FGameTexture::Normal }, - { "materials/specular/", &FGameTexture::Specular }, - { "materials/metallic/", &FGameTexture::Metallic }, - { "materials/roughness/", &FGameTexture::Roughness }, - { "materials/ao/", &FGameTexture::AmbientOcclusion } + }; + + static AutoTextureSearchPath2 autosearchpaths2[] = + { + { "materials/detailmaps/", &FMaterialLayers::Detailmap }, + { "materials/glowmaps/", &FMaterialLayers::Glowmap }, + { "materials/normalmaps/", &FMaterialLayers::Normal }, + { "materials/specular/", &FMaterialLayers::Specular }, + { "materials/metallic/", &FMaterialLayers::Metallic }, + { "materials/roughness/", &FMaterialLayers::Roughness }, + { "materials/ao/", &FMaterialLayers::AmbientOcclusion } }; if (flags & GTexf_AutoMaterialsAdded) return; // do this only once @@ -178,6 +192,24 @@ void FGameTexture::AddAutoMaterials() } } } + for (size_t i = 0; i < countof(autosearchpaths2); i++) + { + auto& layer = autosearchpaths2[i]; + 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); + if (lump != -1) + { + auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); + if (bmtex != nullptr) + { + if (this->Layers == nullptr) this->Layers = std::make_unique(); + this->Layers.get()->* (layer.pointer) = bmtex->GetTexture(); + } + } + } + } flags |= GTexf_AutoMaterialsAdded; } @@ -280,7 +312,7 @@ bool FGameTexture::ShouldExpandSprite() expandSprite = false; return false; } - if (Glowmap != NULL && (Base->GetWidth() != Glowmap->GetWidth() || Base->GetHeight() != Glowmap->GetHeight())) + if (Layers && Layers->Glowmap != NULL && (Base->GetWidth() != Layers->Glowmap->GetWidth() || Base->GetHeight() != Layers->Glowmap->GetHeight())) { // same restriction for the glow map expandSprite = false; @@ -311,7 +343,7 @@ void FGameTexture::SetupSpriteData() if (i == 1 && ShouldExpandSprite()) { - spi.mTrimResult = Base->TrimBorders(spi.trim); // get the trim size before adding the empty frame + spi.mTrimResult = Base->TrimBorders(spi.trim) && !GetNoTrimming(); // get the trim size before adding the empty frame spi.spriteWidth += 2; spi.spriteHeight += 2; } diff --git a/src/common/textures/gametexture.h b/src/common/textures/gametexture.h index e9851fbe3..3eb3740a9 100644 --- a/src/common/textures/gametexture.h +++ b/src/common/textures/gametexture.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "vectors.h" #include "floatrect.h" #include "refcounted.h" @@ -59,6 +60,20 @@ enum EGameTexFlags GTexf_BrightmapChecked = 128, // Check for a colormap-based brightmap was already done. GTexf_AutoMaterialsAdded = 256, // AddAutoMaterials has been called on this texture. GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font. + GTexf_NoTrim = 1024, // Don't perform trimming on this texture. + GTexf_Seen = 2048, // Set to true when the texture is being used for rendering. Must be cleared manually if the check is needed. +}; + +struct FMaterialLayers +{ + RefCountedPtr Detailmap; + RefCountedPtr Glowmap; + RefCountedPtr Normal; // Normal map texture + RefCountedPtr Specular; // Specular light texture for the diffuse+normal+specular light model + RefCountedPtr Metallic; // Metalness texture for the physically based rendering (PBR) light model + 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 }; // Refactoring helper to allow piece by piece adjustment of the API @@ -70,14 +85,7 @@ class FGameTexture // Material layers. These are shared so reference counting is used. RefCountedPtr Base; RefCountedPtr Brightmap; - RefCountedPtr Detailmap; - RefCountedPtr Glowmap; - RefCountedPtr Normal; // Normal map texture - RefCountedPtr Specular; // Specular light texture for the diffuse+normal+specular light model - RefCountedPtr Metallic; // Metalness texture for the physically based rendering (PBR) light model - 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 + std::unique_ptr Layers; FString Name; FTextureID id; @@ -136,8 +144,12 @@ public: void SetSpriteRect(); ETextureType GetUseType() const { return UseType; } - void SetUpscaleFlag(int what) { shouldUpscaleFlag = what; } - int GetUpscaleFlag() { return shouldUpscaleFlag == 1; } + void SetUpscaleFlag(int what, bool manual = false) + { + if ((shouldUpscaleFlag & 2) && !manual) return; // if set manually this may not be reset. + shouldUpscaleFlag = what | (manual? 2 : 0); + } + int GetUpscaleFlag() { return shouldUpscaleFlag & 1; } FTexture* GetTexture() { return Base.get(); } int GetSourceLump() const { return Base->GetSourceLump(); } @@ -155,6 +167,8 @@ public: bool expandSprites() { return expandSprite == -1? ShouldExpandSprite() : !!expandSprite; } bool useWorldPanning() const { return !!(flags & GTexf_WorldPanning); } void SetWorldPanning(bool on) { if (on) flags |= GTexf_WorldPanning; else flags &= ~GTexf_WorldPanning; } + void SetNoTrimming(bool on) { if (on) flags |= GTexf_NoTrim; else flags &= ~GTexf_NoTrim; } + bool GetNoTrimming() { return !!(flags & GTexf_NoTrim); } bool allowNoDecals() const { return !!(flags & GTexf_NoDecals); } void SetNoDecals(bool on) { if (on) flags |= GTexf_NoDecals; else flags &= ~GTexf_NoDecals; } void SetOffsetsNotForFont() { flags |= GTexf_OffsetsNotForFont; } @@ -172,6 +186,13 @@ public: void SetRotations(int rot) { Rotations = int16_t(rot); } void SetSkyOffset(int offs) { SkyOffset = offs; } int GetSkyOffset() const { return SkyOffset; } + void setSeen() { flags |= GTexf_Seen; } + bool isSeen(bool reset) + { + int v = flags & GTexf_Seen; + if (reset) flags &= ~GTexf_Seen; + return v; + } ISoftwareTexture* GetSoftwareTexture() { @@ -197,14 +218,25 @@ public: if (lay.Glossiness > -1000) Glossiness = lay.Glossiness; if (lay.SpecularLevel > -1000) SpecularLevel = lay.SpecularLevel; if (lay.Brightmap) Brightmap = lay.Brightmap->GetTexture(); - if (lay.Normal) Normal = lay.Normal->GetTexture(); - if (lay.Specular) Specular = lay.Specular->GetTexture(); - if (lay.Metallic) Metallic = lay.Metallic->GetTexture(); - if (lay.Roughness) Roughness = lay.Roughness->GetTexture(); - if (lay.AmbientOcclusion) AmbientOcclusion = lay.AmbientOcclusion->GetTexture(); - for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++) + + bool needlayers = (lay.Normal || lay.Specular || lay.Metallic || lay.Roughness || lay.AmbientOcclusion); + for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES && !needlayers; i++) { - if (lay.CustomShaderTextures[i]) CustomShaderTextures[i] = lay.CustomShaderTextures[i]->GetTexture(); + if (lay.CustomShaderTextures[i]) needlayers = true; + } + if (needlayers) + { + Layers = std::make_unique(); + + if (lay.Normal) Layers->Normal = lay.Normal->GetTexture(); + if (lay.Specular) Layers->Specular = lay.Specular->GetTexture(); + if (lay.Metallic) Layers->Metallic = lay.Metallic->GetTexture(); + if (lay.Roughness) Layers->Roughness = lay.Roughness->GetTexture(); + 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(); + } } } float GetGlossiness() const { return Glossiness; } @@ -299,13 +331,20 @@ public: void GetLayers(TArray& layers) { layers.Clear(); - for (auto tex : { Base.get(), Brightmap.get(), Detailmap.get(), Glowmap.get(), Normal.get(), Specular.get(), Metallic.get(), Roughness.get(), AmbientOcclusion.get() }) + for (auto tex : { Base.get(), Brightmap.get() }) { if (tex != nullptr) layers.Push(tex); } - for (auto& tex : CustomShaderTextures) + if (Layers) { - if (tex != nullptr) layers.Push(tex.get()); + for (auto tex : { Layers->Detailmap.get(), Layers->Glowmap.get(), Layers->Normal.get(), Layers->Specular.get(), Layers->Metallic.get(), Layers->Roughness.get(), Layers->AmbientOcclusion.get() }) + { + if (tex != nullptr) layers.Push(tex); + } + for (auto& tex : Layers->CustomShaderTextures) + { + if (tex != nullptr) layers.Push(tex.get()); + } } } @@ -328,28 +367,59 @@ public: } FTexture* GetGlowmap() { - return Glowmap.get(); + if (!Layers) return nullptr; + return Layers->Glowmap.get(); } FTexture* GetDetailmap() { - return Detailmap.get(); + if (!Layers) return nullptr; + return Layers->Detailmap.get(); + } + FTexture* GetNormalmap() + { + if (!Layers) return nullptr; + return Layers->Normal.get(); + } + FTexture* GetSpecularmap() + { + if (!Layers) return nullptr; + return Layers->Specular.get(); + } + FTexture* GetMetallic() + { + if (!Layers) return nullptr; + return Layers->Metallic.get(); + } + FTexture* GetRoughness() + { + if (!Layers) return nullptr; + return Layers->Roughness.get(); + } + FTexture* GetAmbientOcclusion() + { + if (!Layers) return nullptr; + return Layers->AmbientOcclusion.get(); } void SetGlowmap(FTexture *T) { - Glowmap = T; + if (!Layers) Layers = std::make_unique(); + Layers->Glowmap = T; } void SetDetailmap(FTexture* T) { - Detailmap = T; + if (!Layers) Layers = std::make_unique(); + Layers->Detailmap = T; } void SetNormalmap(FTexture* T) { - Normal = T; + if (!Layers) Layers = std::make_unique(); + Layers->Normal = T; } void SetSpecularmap(FTexture* T) { - Specular = T; + if (!Layers) Layers = std::make_unique(); + Layers->Specular = T; } }; diff --git a/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp b/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp index 7ce8a1621..5d22e1348 100644 --- a/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp +++ b/src/common/textures/hires/hqnx_asm/hq4x_asm.cpp @@ -272,9 +272,9 @@ bool Diff(const unsigned int rgb1, const unsigned int rgb2) { return false; } - + static const hq_vec THRESHOLD = 0x00300706; - + const hq_vec yuv1 = RGBtoYUV[rgb1]; const hq_vec yuv2 = RGBtoYUV[rgb2]; diff --git a/src/common/textures/hires/hqresize.cpp b/src/common/textures/hires/hqresize.cpp index 16b2b4b13..9a6c42aa2 100644 --- a/src/common/textures/hires/hqresize.cpp +++ b/src/common/textures/hires/hqresize.cpp @@ -375,7 +375,7 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t* outHeight = N *inHeight; unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - + const int thresholdWidth = gl_texture_hqresize_mt_width; const int thresholdHeight = gl_texture_hqresize_mt_height; diff --git a/src/common/textures/hires/xbr/xbrz_old.h b/src/common/textures/hires/xbr/xbrz_old.h index 9a46f2a97..10e60dcfc 100644 --- a/src/common/textures/hires/xbr/xbrz_old.h +++ b/src/common/textures/hires/xbr/xbrz_old.h @@ -47,7 +47,7 @@ http://board.byuu.org/viewtopic.php?f=10&t=2248 THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap! - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only - + */ void scale(size_t factor, //valid range: 2 - 5 const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, diff --git a/src/common/textures/hw_ihwtexture.cpp b/src/common/textures/hw_ihwtexture.cpp index aebf387d4..296bfd40d 100644 --- a/src/common/textures/hw_ihwtexture.cpp +++ b/src/common/textures/hw_ihwtexture.cpp @@ -34,7 +34,7 @@ */ #include "hw_ihwtexture.h" -#include "templates.h" +#include "basics.h" #include "tarray.h" #include "xs_Float.h" @@ -67,8 +67,8 @@ static void ResampleBoxPrecalc(TArray& boxes, int oldDim) const int src_p = int(dst * scale_factor_1); BoxPrecalc& precalc = boxes[dst]; - precalc.boxStart = clamp(int(src_p - scale_factor_1 / 2.0 + 1), 0, oldDim - 1); - precalc.boxEnd = clamp(MAX(precalc.boxStart + 1, int(src_p + scale_factor_2)), 0, oldDim - 1); + precalc.boxStart = std::clamp(int(src_p - scale_factor_1 / 2.0 + 1), 0, oldDim - 1); + precalc.boxEnd = std::clamp(std::max(precalc.boxStart + 1, int(src_p + scale_factor_2)), 0, oldDim - 1); } } diff --git a/src/common/textures/hw_material.cpp b/src/common/textures/hw_material.cpp index 944e311d1..2517c098e 100644 --- a/src/common/textures/hw_material.cpp +++ b/src/common/textures/hw_material.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, @@ -30,7 +30,7 @@ #include "v_video.h" -CVAR(Bool, gl_customshader, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL); +CVAR(Bool, gl_customshader, true, 0); static IHardwareTexture* (*layercallback)(int layer, int translation); @@ -79,17 +79,17 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) mShaderIndex = tx->isWarped(); // This picks SHADER_Warp1 or SHADER_Warp2 } // Note that the material takes no ownership of the texture! - else if (tx->Normal.get() && tx->Specular.get()) + else if (tx->Layers && tx->Layers->Normal.get() && tx->Layers->Specular.get()) { - for (auto &texture : { tx->Normal.get(), tx->Specular.get() }) + for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Specular.get() }) { mTextureLayers.Push({ texture, 0, -1 }); } mShaderIndex = SHADER_Specular; } - else if (tx->Normal.get() && tx->Metallic.get() && tx->Roughness.get() && tx->AmbientOcclusion.get()) + else if (tx->Layers && tx->Layers->Normal.get() && tx->Layers->Metallic.get() && tx->Layers->Roughness.get() && tx->Layers->AmbientOcclusion.get()) { - for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() }) + for (auto &texture : { tx->Layers->Normal.get(), tx->Layers->Metallic.get(), tx->Layers->Roughness.get(), tx->Layers->AmbientOcclusion.get() }) { mTextureLayers.Push({ texture, 0, -1 }); } @@ -108,18 +108,18 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) { mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); } - if (tx->Detailmap.get()) + if (tx->Layers && tx->Layers->Detailmap.get()) { - mTextureLayers.Push({ tx->Detailmap.get(), 0, CLAMP_NONE }); + mTextureLayers.Push({ tx->Layers->Detailmap.get(), 0, CLAMP_NONE }); mLayerFlags |= TEXF_Detailmap; } else { mTextureLayers.Push({ placeholder->GetTexture(), 0, -1 }); } - if (tx->Glowmap.get()) + if (tx->Layers && tx->Layers->Glowmap.get()) { - mTextureLayers.Push({ tx->Glowmap.get(), scaleflags, -1 }); + mTextureLayers.Push({ tx->Layers->Glowmap.get(), scaleflags, -1 }); mLayerFlags |= TEXF_Glowmap; } else @@ -135,10 +135,13 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) const UserShaderDesc& usershader = usershaders[index - FIRST_USER_SHADER]; if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material { - for (auto& texture : tx->CustomShaderTextures) + if (tx->Layers) { - if (texture == nullptr) continue; - mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. + for (auto& texture : tx->Layers->CustomShaderTextures) + { + if (texture == nullptr) continue; + mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. + } } mShaderIndex = index; } diff --git a/src/common/textures/hw_texcontainer.h b/src/common/textures/hw_texcontainer.h index 91afa526f..a4ff33f93 100644 --- a/src/common/textures/hw_texcontainer.h +++ b/src/common/textures/hw_texcontainer.h @@ -58,7 +58,7 @@ private: TranslatedTexture hwDefTex[4]; TArray hwTex_Translated; - + TranslatedTexture * GetTexID(int translation, int scaleflags) { // Allow negative indices to pass through unchanged. @@ -108,13 +108,13 @@ public: hwDefTex[1].Delete(); hwTex_Translated.Clear(); } - + IHardwareTexture * GetHardwareTexture(int translation, int scaleflags) { auto tt = GetTexID(translation, scaleflags); return tt->hwTexture; } - + void AddHardwareTexture(int translation, int scaleflags, IHardwareTexture *tex) { auto tt = GetTexID(translation, scaleflags); @@ -170,6 +170,6 @@ public: for (auto & t : hwTex_Translated) if (t.hwTexture) callback(t.hwTexture); } - + }; diff --git a/src/common/textures/image.cpp b/src/common/textures/image.cpp index 73d6f5227..b32634948 100644 --- a/src/common/textures/image.cpp +++ b/src/common/textures/image.cpp @@ -48,7 +48,7 @@ static PrecacheInfo precacheInfo; struct PrecacheDataPaletted { - TArray Pixels; + PalettedPixels Pixels; int RefCount; int ImageID; }; @@ -71,9 +71,9 @@ TArray precacheDataRgba; // //=========================================================================== -TArray FImageSource::CreatePalettedPixels(int conversion) +PalettedPixels FImageSource::CreatePalettedPixels(int conversion) { - TArray Pixels(Width * Height, true); + PalettedPixels Pixels(Width * Height); memset(Pixels.Data(), 0, Width * Height); return Pixels; } @@ -82,10 +82,6 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) { PalettedPixels ret; - FString name; - fileSystem.GetFileShortName(name, SourceLump); - - std::pair *info = nullptr; auto imageID = ImageID; // Do we have this image in the cache? @@ -103,8 +99,7 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) else if (cache->Pixels.Size() > 0) { //Printf("returning contents of %s, refcount = %d\n", name.GetChars(), cache->RefCount); - ret.PixelStore = std::move(cache->Pixels); - ret.Pixels.Set(ret.PixelStore.Data(), ret.PixelStore.Size()); + ret = std::move(cache->Pixels); precacheDataPaletted.Delete(index); } else @@ -120,8 +115,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()); - ret.PixelStore = CreatePalettedPixels(conversion); - ret.Pixels.Set(ret.PixelStore.Data(), ret.PixelStore.Size()); + return CreatePalettedPixels(conversion); } else { @@ -175,6 +169,7 @@ int FImageSource::CopyPixels(FBitmap *bmp, int conversion) { if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. PalEntry *palette = GPalette.BaseColors; + auto ppix = CreatePalettedPixels(conversion); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr); return 0; @@ -182,7 +177,7 @@ int FImageSource::CopyPixels(FBitmap *bmp, int conversion) int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) { - auto ppix = CreatePalettedPixels(false); + auto ppix = CreatePalettedPixels(normal); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, remap, nullptr); return 0; } @@ -196,14 +191,10 @@ int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans) { FBitmap ret; - - FString name; + int trans = -1; - fileSystem.GetFileShortName(name, SourceLump); - - std::pair *info = nullptr; auto imageID = ImageID; - + if (remap != nullptr) { // Remapped images are never run through the cache because they would complicate matters too much for very little gain. @@ -220,7 +211,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int if (index < precacheDataRgba.Size()) { auto cache = &precacheDataRgba[index]; - + trans = cache->TransInfo; if (cache->RefCount > 1) { @@ -258,7 +249,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int //Printf("creating cached entry for %s, refcount = %d\n", name.GetChars(), info->first); // This is the first time it gets accessed and needs to be placed in the cache. PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)]; - + pdr->ImageID = imageID; pdr->RefCount = info->first - 1; info->first = 0; @@ -337,6 +328,7 @@ FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum); FImageSource *PatchImage_TryCreate(FileReader &, int lumpnum); FImageSource *EmptyImage_TryCreate(FileReader &, int lumpnum); FImageSource *AutomapImage_TryCreate(FileReader &, int lumpnum); +FImageSource *StartupPageImage_TryCreate(FileReader &, int lumpnum); // Examines the lump contents to decide what type of texture to create, @@ -352,6 +344,7 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat) { StbImage_TryCreate, false }, { TGAImage_TryCreate, false }, { AnmImage_TryCreate, false }, + { StartupPageImage_TryCreate, false }, { RawPageImage_TryCreate, false }, { FlatImage_TryCreate, true }, // flat detection is not reliable, so only consider this for real flats. { PatchImage_TryCreate, false }, diff --git a/src/common/textures/image.h b/src/common/textures/image.h index 6ddd34bc2..5be852549 100644 --- a/src/common/textures/image.h +++ b/src/common/textures/image.h @@ -26,10 +26,30 @@ struct PalettedPixels private: TArray PixelStore; +public: + PalettedPixels() = default; + PalettedPixels(unsigned size) + { + PixelStore.Resize(size); + Pixels.Set(PixelStore.Data(), PixelStore.Size()); + } + PalettedPixels(uint8_t* data, unsigned size) + { + Pixels.Set(data, size); + } bool ownsPixels() const { return Pixels.Data() == PixelStore.Data(); } + uint8_t* Data() const { return Pixels.Data(); } + unsigned Size() const { return Pixels.Size(); } + + uint8_t& operator[] (size_t index) const + { + assert(index < Size()); + return Pixels[index]; + } + }; // This represents a naked image. It has no high level logic attached to it. @@ -51,8 +71,7 @@ protected: // 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 TArray CreatePalettedPixels(int conversion); - virtual int CopyPixels(FBitmap *bmp, int conversion); // This will always ignore 'luminance'. + virtual PalettedPixels CreatePalettedPixels(int conversion); int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap); @@ -60,7 +79,7 @@ public: virtual bool SupportRemap0() { return false; } // Unfortunate hackery that's needed for Hexen's skies. Only the image can know about the needed parameters virtual bool IsRawCompatible() { return true; } // Same thing for mid texture compatibility handling. Can only be determined by looking at the composition data which is private to the image. - void CopySize(FImageSource &other) + void CopySize(FImageSource &other) noexcept { Width = other.Width; Height = other.Height; @@ -71,13 +90,14 @@ public: // Images are statically allocated and freed in bulk. None of the subclasses may hold any destructible data. void *operator new(size_t block) { return ImageArena.Alloc(block); } + void* operator new(size_t block, void* mem) { return mem; } void operator delete(void *block) {} bool bMasked = true; // Image (might) have holes (Assume true unless proven otherwise!) int8_t bTranslucent = -1; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check) int GetId() const { return ImageID; } - + // '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 @@ -86,8 +106,8 @@ public: // 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); - - // Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format. + virtual int CopyPixels(FBitmap* bmp, int conversion); + FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr); static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; } @@ -102,25 +122,25 @@ public: luminance = 1, noremap0 = 2 }; - - FImageSource(int sourcelump = -1) : SourceLump(sourcelump) { ImageID = ++NextID; } - virtual ~FImageSource() {} - + + FImageSource(int sourcelump = -1) noexcept : SourceLump(sourcelump) { ImageID = ++NextID; } + virtual ~FImageSource() = default; + int GetWidth() const { return Width; } - + int GetHeight() const { return Height; } - + std::pair GetSize() const { return std::make_pair(Width, Height); } - + std::pair GetOffsets() const { return std::make_pair(LeftOffset, TopOffset); @@ -131,12 +151,12 @@ public: LeftOffset = x; TopOffset = y; } - + int LumpNum() const { return SourceLump; } - + bool UseGamePalette() const { return bUseGamePalette; @@ -160,7 +180,7 @@ 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); - TArray CreatePalettedPixels(int conversion) override; + PalettedPixels CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap* bmp, int conversion) override; protected: diff --git a/src/common/textures/imagehelpers.h b/src/common/textures/imagehelpers.h index 8923f92db..a25187ef2 100644 --- a/src/common/textures/imagehelpers.h +++ b/src/common/textures/imagehelpers.h @@ -58,7 +58,7 @@ namespace ImageHelpers return srcisgrayscale ? GPalette.GrayMap : GPalette.Remap; } } - + inline uint8_t RGBToPalettePrecise(bool wantluminance, int r, int g, int b, int a = 255) { if (wantluminance) @@ -70,7 +70,7 @@ namespace ImageHelpers return ColorMatcher.Pick(r, g, b); } } - + inline uint8_t RGBToPalette(bool wantluminance, int r, int g, int b, int a = 255) { if (wantluminance) @@ -83,19 +83,19 @@ namespace ImageHelpers return a < 128? 0 : RGB256k.RGB[r >> 2][g >> 2][b >> 2]; } } - + inline uint8_t RGBToPalette(bool wantluminance, PalEntry pe, bool hasalpha = true) { return RGBToPalette(wantluminance, pe.r, pe.g, pe.b, hasalpha? pe.a : 255); } - + //========================================================================== // // Converts a texture between row-major and column-major format // by flipping it about the X=Y axis. // //========================================================================== - + template void FlipSquareBlock (T *block, int x) { @@ -109,7 +109,7 @@ namespace ImageHelpers } } } - + inline void FlipSquareBlockRemap (uint8_t *block, int x, const uint8_t *remap) { for (int i = 0; i < x; ++i) @@ -124,7 +124,7 @@ namespace ImageHelpers } } } - + template void FlipNonSquareBlock (T *dst, const T *src, int x, int y, int srcpitch) { @@ -136,7 +136,7 @@ namespace ImageHelpers } } } - + inline void FlipNonSquareBlockRemap (uint8_t *dst, const uint8_t *src, int x, int y, int srcpitch, const uint8_t *remap) { for (int i = 0; i < x; ++i) diff --git a/src/common/textures/imagetexture.cpp b/src/common/textures/imagetexture.cpp index 5ec15c7b5..d94ff8002 100644 --- a/src/common/textures/imagetexture.cpp +++ b/src/common/textures/imagetexture.cpp @@ -35,7 +35,7 @@ #include "files.h" #include "filesystem.h" -#include "templates.h" + #include "bitmap.h" #include "image.h" #include "textures.h" @@ -90,7 +90,7 @@ FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans) TArray FImageTexture::Get8BitPixels(bool alpha) { - return mImage->GetPalettedPixels(alpha? alpha : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); + return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); } //=========================================================================== diff --git a/src/common/textures/m_png.cpp b/src/common/textures/m_png.cpp index e58742da4..8467a5d42 100644 --- a/src/common/textures/m_png.cpp +++ b/src/common/textures/m_png.cpp @@ -246,7 +246,7 @@ bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text) { struct { uint32_t len, id; char key[80]; } head; int len = (int)strlen (text); - int keylen = std::min ((int)strlen (keyword), 79); + int keylen = min ((int)strlen (keyword), 79); uint32_t crc; head.len = BigLong(len + keylen + 1); @@ -329,7 +329,7 @@ char *M_GetPNGText (PNGHandle *png, const char *keyword) if (strncmp (keyword, png->TextChunks[i], 80) == 0) { // Woo! A match was found! - keylen = std::min (80, strlen (keyword) + 1); + keylen = min (80, strlen (keyword) + 1); textlen = strlen (png->TextChunks[i] + keylen) + 1; char *str = new char[textlen]; strcpy (str, png->TextChunks[i] + keylen); @@ -351,7 +351,7 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf if (strncmp (keyword, png->TextChunks[i], 80) == 0) { // Woo! A match was found! - keylen = std::min (80, strlen (keyword) + 1); + keylen = min (80, strlen (keyword) + 1); strncpy (buffer, png->TextChunks[i] + keylen, buffsize); return true; } @@ -566,7 +566,7 @@ bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int p if (stream.avail_in == 0 && chunklen > 0) { stream.next_in = chunkbuffer; - stream.avail_in = (uInt)file.Read (chunkbuffer, std::min(chunklen,sizeof(chunkbuffer))); + stream.avail_in = (uInt)file.Read (chunkbuffer, min(chunklen,sizeof(chunkbuffer))); chunklen -= stream.avail_in; } diff --git a/src/common/textures/multipatchtexturebuilder.cpp b/src/common/textures/multipatchtexturebuilder.cpp index 000af17e2..2a8b77fea 100644 --- a/src/common/textures/multipatchtexturebuilder.cpp +++ b/src/common/textures/multipatchtexturebuilder.cpp @@ -144,6 +144,7 @@ void FMultipatchTextureBuilder::MakeTexture(BuildInfo &buildinfo, ETextureType u buildinfo.texture->SetScale((float)buildinfo.Scale.X, (float)buildinfo.Scale.Y); buildinfo.texture->SetWorldPanning(buildinfo.bWorldPanning); buildinfo.texture->SetNoDecals(buildinfo.bNoDecals); + buildinfo.texture->SetNoTrimming(buildinfo.bNoTrim); TexMan.AddGameTexture(buildinfo.texture); } @@ -295,12 +296,12 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi // Catalog the patches these textures use so we know which // textures they represent. patchlookup.Resize(numpatches); - for (uint32_t i = 0; i < numpatches; ++i) + for (uint32_t ii = 0; ii < numpatches; ++ii) { char pname[9]; pnames.Read(pname, 8); pname[8] = '\0'; - patchlookup[i].Name = pname; + patchlookup[ii].Name = pname; } } @@ -572,7 +573,7 @@ void FMultipatchTextureBuilder::ParsePatch(FScanner &sc, BuildInfo &info, TexPar else if (sc.Compare("alpha")) { sc.MustGetFloat(); - part.Alpha = clamp(int(sc.Float * BLENDUNIT), 0, BLENDUNIT); + part.Alpha = clamp(int(sc.Float * +BLENDUNIT), 0, BLENDUNIT); // bComplex is not set because it is only needed when the style is not OP_COPY. } else if (sc.Compare("style")) @@ -611,7 +612,7 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType, BuildInfo &buildinfo = BuiltTextures[BuiltTextures.Reserve(1)]; bool bSilent = false; - + buildinfo.textual = true; sc.SetCMode(true); sc.MustGetString(); @@ -669,6 +670,10 @@ void FMultipatchTextureBuilder::ParseTexture(FScanner &sc, ETextureType UseType, { buildinfo.bNoDecals = true; } + else if (sc.Compare("NoTrim")) + { + buildinfo.bNoTrim = true; + } else if (sc.Compare("Patch")) { TexPartBuild part; @@ -777,12 +782,12 @@ void FMultipatchTextureBuilder::ResolvePatches(BuildInfo &buildinfo) { TArray list; TexMan.ListTextures(buildinfo.Inits[i].TexName, list, true); - for (int i = list.Size() - 1; i >= 0; i--) + for (int ii = list.Size() - 1; ii >= 0; ii--) { - auto gtex = TexMan.GetGameTexture(list[i]); + auto gtex = TexMan.GetGameTexture(list[ii]); if (gtex && gtex != buildinfo.texture && gtex->GetTexture() && gtex->GetTexture()->GetImage() && !dynamic_cast(gtex->GetTexture()->GetImage())) { - texno = list[i]; + texno = list[ii]; break; } } @@ -853,7 +858,6 @@ void FMultipatchTextureBuilder::ResolveAllPatches() ResolvePatches(bi); } // Now try to resolve the images. We only can do this at the end when all multipatch textures are set up. - int i = 0; // reverse the list so that the Delete operation in the loop below deletes at the end. // For normal sized lists this is of no real concern, but Total Chaos has over 250000 textures where this becomes a performance issue. diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index 6d24f1154..db922a7b5 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -37,7 +37,7 @@ #include "printf.h" #include "files.h" #include "filesystem.h" -#include "templates.h" + #include "textures.h" #include "bitmap.h" #include "colormatcher.h" @@ -97,7 +97,7 @@ FBitmap FTexture::GetBgraBitmap(const PalEntry* remap, int* ptrans) int FTexture::CheckRealHeight() { auto pixels = Get8BitPixels(false); - + for(int h = GetHeight()-1; h>= 0; h--) { for(int w = 0; w < GetWidth(); w++) @@ -387,7 +387,7 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags) FContentIdBuilder builder; builder.id = 0; builder.imageID = GetImage()->GetId(); - builder.translation = MAX(0, translation); + builder.translation = max(0, translation); builder.expand = exx; result.mContentId = builder.id; } diff --git a/src/common/textures/textureid.h b/src/common/textures/textureid.h index c7a6355cc..e30b4e86a 100644 --- a/src/common/textures/textureid.h +++ b/src/common/textures/textureid.h @@ -35,7 +35,7 @@ public: void SetNull() { texnum = 0; } bool operator ==(const FTextureID &other) const { return texnum == other.texnum; } bool operator !=(const FTextureID &other) const { return texnum != other.texnum; } - FTextureID operator +(int offset) throw(); + FTextureID operator +(int offset) const noexcept(true); int GetIndex() const { return texnum; } // Use this only if you absolutely need the index! void SetIndex(int index) { texnum = index; } // Use this only if you absolutely need the index! diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index c4fcfd841..94aa40de1 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -37,7 +37,7 @@ #include "filesystem.h" #include "printf.h" #include "c_cvars.h" -#include "templates.h" + #include "gstrings.h" #include "textures.h" #include "texturemanager.h" @@ -86,11 +86,11 @@ FTextureManager::~FTextureManager () void FTextureManager::DeleteAll() { - FImageSource::ClearImages(); for (unsigned int i = 0; i < Textures.Size(); ++i) { delete Textures[i].Texture; } + FImageSource::ClearImages(); Textures.Clear(); Translation.Clear(); FirstTextureForFile.Clear(); @@ -186,6 +186,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset // The name matches, so check the texture type if (usetype == ETextureType::Any) { + if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures. // All NULL textures should actually return 0 if (texUseType == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0; if (texUseType == ETextureType::SkinGraphic && !(flags & TEXMAN_AllowSkins)) return 0; @@ -229,13 +230,14 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset // Never return the index of NULL textures. if (firstfound != -1) { + if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures. if (firsttype == ETextureType::Null) return FTextureID(0); if (firsttype == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0); return FTextureID(firstfound); } } - + if (!(flags & TEXMAN_ShortNameOnly)) { // We intentionally only look for textures in subdirectories. @@ -376,18 +378,18 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut if (*substitute == '$') substitute = GStrings.GetString(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. - + // Modes 2, 3 and 4 must not replace localized textures. int localizedTex = ResolveLocalizedTexture(texnum.GetIndex()); if (localizedTex != texnum.GetIndex()) return true; // Do not substitute a localized variant of the graphics patch. - + // For mode 4 we are done now. if (locmode == 4) return false; - + // Mode 2 and 3 must reject any text replacement from the default language tables. if ((langtable & MAKE_ID(255,0,0,0)) == MAKE_ID('*', 0, 0, 0)) return true; // Do not substitute if the string comes from the default table. if (locmode == 2) return false; - + // Mode 3 must also reject substitutions for non-IWAD content. int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->GetSourceLump()); if (file > fileSystem.GetMaxIwadNum()) return true; @@ -426,7 +428,7 @@ FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohas hash = -1; } - TextureHash hasher = { texture, -1, -1, -1, hash }; + TextureDescriptor hasher = { texture, -1, -1, -1, hash }; int trans = Textures.Push (hasher); Translation.Push (trans); if (bucket >= 0) HashFirst[bucket] = trans; @@ -717,7 +719,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build sc.String[8]=0; tlist.Clear(); - int amount = ListTextures(sc.String, tlist); + ListTextures(sc.String, tlist); FName texname = sc.String; sc.MustGetString(); @@ -771,7 +773,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build else if (sc.Compare("define")) // define a new "fake" texture { sc.GetString(); - + FString base = ExtractFileBase(sc.String, false); if (!base.IsEmpty()) { @@ -811,6 +813,22 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build } //else Printf("Unable to define hires texture '%s'\n", tex->Name); } + else if (sc.Compare("notrim")) + { + sc.MustGetString(); + + FTextureID id = TexMan.CheckForTexture(sc.String, ETextureType::Sprite); + if (id.isValid()) + { + FGameTexture *tex = TexMan.GetGameTexture(id); + + if (tex) tex->SetNoTrimming(true); + else sc.ScriptError("NoTrim: %s not found", sc.String); + } + else + sc.ScriptError("NoTrim: %s is not a sprite", sc.String); + + } else if (sc.Compare("texture")) { build.ParseTexture(sc, ETextureType::Override, lump); @@ -919,7 +937,6 @@ void FTextureManager::LoadTextureX(int wadnum, FMultipatchTextureBuilder &build) void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build) { int firsttexture = Textures.Size(); - int lumpcount = fileSystem.GetNumEntries(); bool iwad = wadnum >= fileSystem.GetIwadNum() && wadnum <= fileSystem.GetMaxIwadNum(); FirstTextureForFile.Push(firsttexture); @@ -1135,7 +1152,7 @@ void FTextureManager::AddLocalizedVariants() uint32_t langid = MAKE_ID(lang[0], lang[1], lang[2], 0); uint64_t comboid = (uint64_t(langid) << 32) | origTex.GetIndex(); LocalizedTextures.Insert(comboid, tex.GetIndex()); - Textures[origTex.GetIndex()].HasLocalization = true; + Textures[origTex.GetIndex()].Flags |= TEXFLAG_HASLOCALIZATION; } else { @@ -1168,30 +1185,39 @@ void FTextureManager::AddLocalizedVariants() // //========================================================================== FGameTexture *CreateShaderTexture(bool, bool); -void InitBuildTiles(); FImageSource* CreateEmptyTexture(); -void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&)) +void FTextureManager::Init() { - progressFunc = progressFunc_; DeleteAll(); - //if (BuildTileFiles.Size() == 0) CountBuildTiles (); + // Add all the static content auto nulltex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Null); AddGameTexture(nulltex); // This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture. auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Override); emptytex->SetSize(1, 1); - AddGameTexture(emptytex); + AddGameTexture(emptytex); + // some special textures used in the game. AddGameTexture(CreateShaderTexture(false, false)); AddGameTexture(CreateShaderTexture(false, true)); AddGameTexture(CreateShaderTexture(true, false)); AddGameTexture(CreateShaderTexture(true, true)); // Add two animtexture entries so that movie playback can call functions using texture IDs. - AddGameTexture(MakeGameTexture(new AnimTexture(), "AnimTextureFrame1", ETextureType::Override)); - AddGameTexture(MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override)); + auto mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame1", ETextureType::Override); + mt->SetUpscaleFlag(false, true); + AddGameTexture(mt); + mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override); + mt->SetUpscaleFlag(false, true); + AddGameTexture(mt); +} + +void FTextureManager::AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&), void (*customtexturehandler)()) +{ + progressFunc = progressFunc_; + //if (BuildTileFiles.Size() == 0) CountBuildTiles (); int wadcnt = fileSystem.GetNumWads(); @@ -1204,9 +1230,9 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI build.ResolveAllPatches(); // Add one marker so that the last WAD is easier to handle and treat - // Build tiles as a completely separate block. + // custom textures as a completely separate block. FirstTextureForFile.Push(Textures.Size()); - InitBuildTiles (); + if (customtexturehandler) customtexturehandler(); FirstTextureForFile.Push(Textures.Size()); DefaultTexture = CheckForTexture ("-NOFLAT-", ETextureType::Override, 0); @@ -1276,11 +1302,12 @@ void FTextureManager::InitPalettedVersions() // //========================================================================== -FTextureID FTextureManager::GetRawTexture(FTextureID texid) +FTextureID FTextureManager::GetRawTexture(FTextureID texid, bool dontlookup) { int texidx = texid.GetIndex(); if ((unsigned)texidx >= Textures.Size()) return texid; - if (Textures[texidx].FrontSkyLayer != -1) return FSetTextureID(Textures[texidx].FrontSkyLayer); + if (Textures[texidx].RawTexture != -1) return FSetTextureID(Textures[texidx].RawTexture); + if (dontlookup) return texid; // Reject anything that cannot have been a front layer for the sky in original Hexen, i.e. it needs to be an unscaled wall texture only using Doom patches. auto tex = Textures[texidx].Texture; @@ -1383,7 +1410,7 @@ int FTextureManager::ResolveLocalizedTexture(int tex) int FTextureManager::GuesstimateNumTextures () { int numtex = 0; - + for(int i = fileSystem.GetNumEntries()-1; i>=0; i--) { int space = fileSystem.GetFileNamespace(i); @@ -1460,7 +1487,7 @@ int FTextureManager::CountLumpTextures (int lumpnum) if (lumpnum >= 0) { auto file = fileSystem.OpenFileReader (lumpnum); - uint32_t numtex = file.ReadUInt32();; + uint32_t numtex = file.ReadUInt32(); return int(numtex) >= 0 ? numtex : 0; } @@ -1576,11 +1603,28 @@ void FTextureManager::SetTranslation(FTextureID fromtexnum, FTextureID totexnum) // //----------------------------------------------------------------------------- -void FTextureManager::AddAlias(const char* name, FGameTexture* tex) +void FTextureManager::AddAlias(const char* name, int texindex) { - FTextureID id = tex->GetID(); - if (tex != Textures[id.GetIndex()].Texture || !tex->isValid()) return; // Whatever got passed in here was not valid, so ignore the alias. - aliases.Insert(name, id.GetIndex()); + if (texindex < 0 || texindex >= NumTextures()) return; // Whatever got passed in here was not valid, so ignore the alias. + aliases.Insert(name, texindex); +} + +void FTextureManager::Listaliases() +{ + decltype(aliases)::Iterator it(aliases); + decltype(aliases)::Pair* pair; + + TArray list; + while (it.NextPair(pair)) + { + auto tex = GetGameTexture(pair->Value); + list.Push(FStringf("%s -> %s%s", pair->Key.GetChars(), tex ? tex->GetName().GetChars() : "(null)", ((tex && tex->GetUseType() == ETextureType::Null) ? ", null" : ""))); + } + std::sort(list.begin(), list.end(), [](const FString& l, const FString& r) { return l.CompareNoCase(r) < 0; }); + for (auto& s : list) + { + Printf("%s\n", s.GetChars()); + } } //========================================================================== @@ -1590,7 +1634,7 @@ void FTextureManager::AddAlias(const char* name, FGameTexture* tex) // //========================================================================== -FTextureID FTextureID::operator +(int offset) throw() +FTextureID FTextureID::operator +(int offset) const noexcept(true) { if (!isValid()) return *this; if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1); @@ -1602,3 +1646,7 @@ CCMD(flushtextures) TexMan.FlushAll(); } +CCMD(listtexturealiases) +{ + TexMan.Listaliases(); +} diff --git a/src/common/textures/texturemanager.h b/src/common/textures/texturemanager.h index 076ee1769..575e838ea 100644 --- a/src/common/textures/texturemanager.h +++ b/src/common/textures/texturemanager.h @@ -21,54 +21,54 @@ class FTextureManager public: FTextureManager (); ~FTextureManager (); - + private: int ResolveLocalizedTexture(int texnum); - int ResolveTextureIndex(int texnum, bool animate, bool localize) + int ResolveTextureIndex(int texnum, bool animate) const { if ((unsigned)texnum >= Textures.Size()) return -1; if (animate) texnum = Translation[texnum]; - if (localize && Textures[texnum].HasLocalization) texnum = ResolveLocalizedTexture(texnum); + //if (localize && Textures[texnum].Flags & TEXFLAG_HASLOCALIZATION) texnum = ResolveLocalizedTexture(texnum); return texnum; } - FGameTexture *InternalGetTexture(int texnum, bool animate, bool localize) + FGameTexture *InternalGetTexture(int texnum, bool animate) const { - texnum = ResolveTextureIndex(texnum, animate, localize); + texnum = ResolveTextureIndex(texnum, animate); if (texnum == -1) return nullptr; return Textures[texnum].Texture; } -public: - FTextureID ResolveTextureIndex(FTextureID texid, bool animate, bool localize) + FTextureID ResolveTextureIndex(FTextureID texid, bool animate) const { - return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate, localize)); + return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate)); } +public: // This only gets used in UI code so we do not need PALVERS handling. FGameTexture* GetGameTextureByName(const char *name, bool animate = false, int flags = 0) { FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch, flags); - return InternalGetTexture(texnum.GetIndex(), animate, true); + return InternalGetTexture(texnum.GetIndex(), animate); } - FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false) + FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false) const { - return InternalGetTexture(texnum.GetIndex(), animate, true); + return InternalGetTexture(texnum.GetIndex(), animate); } - - FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true) + + FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true) const { - auto texid = ResolveTextureIndex(texnum.GetIndex(), animate, true); + auto texid = ResolveTextureIndex(texnum.GetIndex(), animate); if (texid == -1) return nullptr; if (allowsubstitute && Textures[texid].Paletted > 0) texid = Textures[texid].Paletted; return Textures[texid].Texture; } - FGameTexture* GameByIndex(int i, bool animate = false) + FGameTexture* GameByIndex(int i, bool animate = false) const { - return InternalGetTexture(i, animate, true); + return InternalGetTexture(i, animate); } FGameTexture* FindGameTexture(const char* texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny); @@ -76,8 +76,17 @@ public: bool OkForLocalization(FTextureID texnum, const char *substitute, int locnum); void FlushAll(); + void Listaliases(); FTextureID GetFrontSkyLayer(FTextureID); - FTextureID GetRawTexture(FTextureID); + FTextureID GetRawTexture(FTextureID tex, bool dontlookup = false); + void SetRawTexture(FTextureID texid) + { + int texidx = texid.GetIndex(); + if ((unsigned)texidx < Textures.Size()) + { + Textures[texidx].RawTexture = texidx; + } + } enum @@ -91,6 +100,7 @@ public: TEXMAN_Localize = 64, TEXMAN_ForceLookup = 128, TEXMAN_NoAlias = 256, + TEXMAN_ReturnAll = 512, }; enum @@ -123,7 +133,8 @@ public: void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build); void AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build); - void Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo &)); + void Init(); + void AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&), void (*customtexturehandler)() = nullptr); void DeleteAll(); void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free); @@ -145,7 +156,11 @@ public: tmanips.Remove(cname); } - void AddAlias(const char* name, FGameTexture* tex); + void AddAlias(const char* name, int texindex); + void AddAlias(const char* name, FTextureID texindex) + { + AddAlias(name, texindex.GetIndex()); + } private: @@ -164,6 +179,10 @@ public: BuildTileData.Reserve(1); return BuildTileData.Last(); } + TArray>& GetBuildTileDataStore() + { + return BuildTileData; + } FGameTexture* GameTexture(FTextureID id) { return Textures[id.GetIndex()].Texture; } void SetTranslation(FTextureID fromtexnum, FTextureID totexnum); @@ -171,20 +190,29 @@ public: private: void InitPalettedVersions(); - + // Switches - struct TextureHash + struct TextureDescriptor { FGameTexture* Texture; int Paletted; // redirection to paletted variant int FrontSkyLayer; // and front sky layer, int RawTexture; int HashNext; - bool HasLocalization; + uint64_t Flags; }; + + enum : uint64_t + { + TEXFLAG_HASLOCALIZATION = 1, + }; +public: + constexpr static int TEXFLAG_FIRSTUSER = 65536; // this leaves 16 flags to the texture manager and 48 flags to the user +private: + enum { HASH_END = -1, HASH_SIZE = 1027 }; - TArray Textures; + TArray Textures; TMap LocalizedTextures; int HashFirst[HASH_SIZE]; FTextureID DefaultTexture; diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index a24dba5fa..da2c7a167 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -249,10 +249,10 @@ public: int GetWidth() { return Width; } int GetHeight() { return Height; } - + 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; } - + 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); @@ -302,6 +302,8 @@ public: friend class FTextureManager; }; +class FCanvas; +extern TArray AllCanvases; // A texture that can be drawn to. @@ -317,8 +319,22 @@ public: aspectRatio = (float)width / height; } + ~FCanvasTexture() + { + if (Canvas) + { + AllCanvases.Delete(AllCanvases.Find(Canvas)); + Canvas = nullptr; + } + } + void NeedUpdate() { bNeedsUpdate = true; } void SetUpdated(bool rendertype) { bNeedsUpdate = false; bFirstUpdate = false; bLastUpdateType = rendertype; } + bool CheckNeedsUpdate() const { return bNeedsUpdate; } + + void SetAspectRatio(double aspectScale, bool useTextureRatio) { aspectRatio = (float)aspectScale * (useTextureRatio? ((float)Width / Height) : 1); } + + FCanvas* Canvas = nullptr; protected: diff --git a/src/common/thirdparty/base64.h b/src/common/thirdparty/base64.h index f98e031fa..1f1bde61c 100644 --- a/src/common/thirdparty/base64.h +++ b/src/common/thirdparty/base64.h @@ -6,6 +6,8 @@ #ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A +#include "tarray.h" + TArray base64_encode(unsigned char const* bytes_to_encode, size_t in_len); void base64_decode(void* memory, size_t len, const char* encoded_string); diff --git a/src/common/thirdparty/gain_analysis.cpp b/src/common/thirdparty/gain_analysis.cpp index 23d618d27..2f92e2128 100644 --- a/src/common/thirdparty/gain_analysis.cpp +++ b/src/common/thirdparty/gain_analysis.cpp @@ -111,41 +111,41 @@ #endif static const Float_t ABYule[][2 * YULE_ORDER + 1] = { - {(const Float_t) 0.006471345933032, (const Float_t) -7.22103125152679, (const Float_t) -0.02567678242161, (const Float_t) 24.7034187975904, (const Float_t) 0.049805860704367, (const Float_t) -52.6825833623896, (const Float_t) -0.05823001743528, (const Float_t) 77.4825736677539, (const Float_t) 0.040611847441914, (const Float_t) -82.0074753444205, (const Float_t) -0.010912036887501, (const Float_t) 63.1566097101925, (const Float_t) -0.00901635868667, (const Float_t) -34.889569769245, (const Float_t) 0.012448886238123, (const Float_t) 13.2126852760198, (const Float_t) -0.007206683749426, (const Float_t) -3.09445623301669, (const Float_t) 0.002167156433951, (const Float_t) 0.340344741393305, (const Float_t) -0.000261819276949}, - {(const Float_t) 0.015415414474287, (const Float_t) -7.19001570087017, (const Float_t) -0.07691359399407, (const Float_t) 24.4109412087159, (const Float_t) 0.196677418516518, (const Float_t) -51.6306373580801, (const Float_t) -0.338855114128061, (const Float_t) 75.3978476863163, (const Float_t) 0.430094579594561, (const Float_t) -79.4164552507386, (const Float_t) -0.415015413747894, (const Float_t) 61.0373661948115, (const Float_t) 0.304942508151101, (const Float_t) -33.7446462547014, (const Float_t) -0.166191795926663, (const Float_t) 12.8168791146274, (const Float_t) 0.063198189938739, (const Float_t) -3.01332198541437, (const Float_t) -0.015003978694525, (const Float_t) 0.223619893831468, (const Float_t) 0.001748085184539}, - {(const Float_t) 0.021776466467053, (const Float_t) -5.74819833657784, (const Float_t) -0.062376961003801, (const Float_t) 16.246507961894, (const Float_t) 0.107731165328514, (const Float_t) -29.9691822642542, (const Float_t) -0.150994515142316, (const Float_t) 40.027597579378, (const Float_t) 0.170334807313632, (const Float_t) -40.3209196052655, (const Float_t) -0.157984942890531, (const Float_t) 30.8542077487718, (const Float_t) 0.121639833268721, (const Float_t) -17.5965138737281, (const Float_t) -0.074094040816409, (const Float_t) 7.10690214103873, (const Float_t) 0.031282852041061, (const Float_t) -1.82175564515191, (const Float_t) -0.00755421235941, (const Float_t) 0.223619893831468, (const Float_t) 0.00117925454213}, - {(const Float_t) 0.03857599435200, (const Float_t) -3.84664617118067, (const Float_t) -0.02160367184185, (const Float_t) 7.81501653005538, (const Float_t) -0.00123395316851, (const Float_t) -11.34170355132042, (const Float_t) -0.00009291677959, (const Float_t) 13.05504219327545, (const Float_t) -0.01655260341619, (const Float_t) -12.28759895145294, (const Float_t) 0.02161526843274, (const Float_t) 9.48293806319790, (const Float_t) -0.02074045215285, (const Float_t) -5.87257861775999, (const Float_t) 0.00594298065125, (const Float_t) 2.75465861874613, (const Float_t) 0.00306428023191, (const Float_t) -0.86984376593551, (const Float_t) 0.00012025322027, (const Float_t) 0.13919314567432, (const Float_t) 0.00288463683916}, - {(const Float_t) 0.05418656406430, (const Float_t) -3.47845948550071, (const Float_t) -0.02911007808948, (const Float_t) 6.36317777566148, (const Float_t) -0.00848709379851, (const Float_t) -8.54751527471874, (const Float_t) -0.00851165645469, (const Float_t) 9.47693607801280, (const Float_t) -0.00834990904936, (const Float_t) -8.81498681370155, (const Float_t) 0.02245293253339, (const Float_t) 6.85401540936998, (const Float_t) -0.02596338512915, (const Float_t) -4.39470996079559, (const Float_t) 0.01624864962975, (const Float_t) 2.19611684890774, (const Float_t) -0.00240879051584, (const Float_t) -0.75104302451432, (const Float_t) 0.00674613682247, (const Float_t) 0.13149317958808, (const Float_t) -0.00187763777362}, - {(const Float_t) 0.15457299681924, (const Float_t) -2.37898834973084, (const Float_t) -0.09331049056315, (const Float_t) 2.84868151156327, (const Float_t) -0.06247880153653, (const Float_t) -2.64577170229825, (const Float_t) 0.02163541888798, (const Float_t) 2.23697657451713, (const Float_t) -0.05588393329856, (const Float_t) -1.67148153367602, (const Float_t) 0.04781476674921, (const Float_t) 1.00595954808547, (const Float_t) 0.00222312597743, (const Float_t) -0.45953458054983, (const Float_t) 0.03174092540049, (const Float_t) 0.16378164858596, (const Float_t) -0.01390589421898, (const Float_t) -0.05032077717131, (const Float_t) 0.00651420667831, (const Float_t) 0.02347897407020, (const Float_t) -0.00881362733839}, - {(const Float_t) 0.30296907319327, (const Float_t) -1.61273165137247, (const Float_t) -0.22613988682123, (const Float_t) 1.07977492259970, (const Float_t) -0.08587323730772, (const Float_t) -0.25656257754070, (const Float_t) 0.03282930172664, (const Float_t) -0.16276719120440, (const Float_t) -0.00915702933434, (const Float_t) -0.22638893773906, (const Float_t) -0.02364141202522, (const Float_t) 0.39120800788284, (const Float_t) -0.00584456039913, (const Float_t) -0.22138138954925, (const Float_t) 0.06276101321749, (const Float_t) 0.04500235387352, (const Float_t) -0.00000828086748, (const Float_t) 0.02005851806501, (const Float_t) 0.00205861885564, (const Float_t) 0.00302439095741, (const Float_t) -0.02950134983287}, - {(const Float_t) 0.33642304856132, (const Float_t) -1.49858979367799, (const Float_t) -0.25572241425570, (const Float_t) 0.87350271418188, (const Float_t) -0.11828570177555, (const Float_t) 0.12205022308084, (const Float_t) 0.11921148675203, (const Float_t) -0.80774944671438, (const Float_t) -0.07834489609479, (const Float_t) 0.47854794562326, (const Float_t) -0.00469977914380, (const Float_t) -0.12453458140019, (const Float_t) -0.00589500224440, (const Float_t) -0.04067510197014, (const Float_t) 0.05724228140351, (const Float_t) 0.08333755284107, (const Float_t) 0.00832043980773, (const Float_t) -0.04237348025746, (const Float_t) -0.01635381384540, (const Float_t) 0.02977207319925, (const Float_t) -0.01760176568150}, - {(const Float_t) 0.44915256608450, (const Float_t) -0.62820619233671, (const Float_t) -0.14351757464547, (const Float_t) 0.29661783706366, (const Float_t) -0.22784394429749, (const Float_t) -0.37256372942400, (const Float_t) -0.01419140100551, (const Float_t) 0.00213767857124, (const Float_t) 0.04078262797139, (const Float_t) -0.42029820170918, (const Float_t) -0.12398163381748, (const Float_t) 0.22199650564824, (const Float_t) 0.04097565135648, (const Float_t) 0.00613424350682, (const Float_t) 0.10478503600251, (const Float_t) 0.06747620744683, (const Float_t) -0.01863887810927, (const Float_t) 0.05784820375801, (const Float_t) -0.03193428438915, (const Float_t) 0.03222754072173, (const Float_t) 0.00541907748707}, - {(const Float_t) 0.56619470757641, (const Float_t) -1.04800335126349, (const Float_t) -0.75464456939302, (const Float_t) 0.29156311971249, (const Float_t) 0.16242137742230, (const Float_t) -0.26806001042947, (const Float_t) 0.16744243493672, (const Float_t) 0.00819999645858, (const Float_t) -0.18901604199609, (const Float_t) 0.45054734505008, (const Float_t) 0.30931782841830, (const Float_t) -0.33032403314006, (const Float_t) -0.27562961986224, (const Float_t) 0.06739368333110, (const Float_t) 0.00647310677246, (const Float_t) -0.04784254229033, (const Float_t) 0.08647503780351, (const Float_t) 0.01639907836189, (const Float_t) -0.03788984554840, (const Float_t) 0.01807364323573, (const Float_t) -0.00588215443421}, - {(const Float_t) 0.58100494960553, (const Float_t) -0.51035327095184, (const Float_t) -0.53174909058578, (const Float_t) -0.31863563325245, (const Float_t) -0.14289799034253, (const Float_t) -0.20256413484477, (const Float_t) 0.17520704835522, (const Float_t) 0.14728154134330, (const Float_t) 0.02377945217615, (const Float_t) 0.38952639978999, (const Float_t) 0.15558449135573, (const Float_t) -0.23313271880868, (const Float_t) -0.25344790059353, (const Float_t) -0.05246019024463, (const Float_t) 0.01628462406333, (const Float_t) -0.02505961724053, (const Float_t) 0.06920467763959, (const Float_t) 0.02442357316099, (const Float_t) -0.03721611395801, (const Float_t) 0.01818801111503, (const Float_t) -0.00749618797172}, - {(const Float_t) 0.53648789255105, (const Float_t) -0.25049871956020, (const Float_t) -0.42163034350696, (const Float_t) -0.43193942311114, (const Float_t) -0.00275953611929, (const Float_t) -0.03424681017675, (const Float_t) 0.04267842219415, (const Float_t) -0.04678328784242, (const Float_t) -0.10214864179676, (const Float_t) 0.26408300200955, (const Float_t) 0.14590772289388, (const Float_t) 0.15113130533216, (const Float_t) -0.02459864859345, (const Float_t) -0.17556493366449, (const Float_t) -0.11202315195388, (const Float_t) -0.18823009262115, (const Float_t) -0.04060034127000, (const Float_t) 0.05477720428674, (const Float_t) 0.04788665548180, (const Float_t) 0.04704409688120, (const Float_t) -0.02217936801134}, + {(Float_t) 0.006471345933032, (Float_t) -7.22103125152679, (Float_t) -0.02567678242161, (Float_t) 24.7034187975904, (Float_t) 0.049805860704367, (Float_t) -52.6825833623896, (Float_t) -0.05823001743528, (Float_t) 77.4825736677539, (Float_t) 0.040611847441914, (Float_t) -82.0074753444205, (Float_t) -0.010912036887501, (Float_t) 63.1566097101925, (Float_t) -0.00901635868667, (Float_t) -34.889569769245, (Float_t) 0.012448886238123, (Float_t) 13.2126852760198, (Float_t) -0.007206683749426, (Float_t) -3.09445623301669, (Float_t) 0.002167156433951, (Float_t) 0.340344741393305, (Float_t) -0.000261819276949}, + {(Float_t) 0.015415414474287, (Float_t) -7.19001570087017, (Float_t) -0.07691359399407, (Float_t) 24.4109412087159, (Float_t) 0.196677418516518, (Float_t) -51.6306373580801, (Float_t) -0.338855114128061, (Float_t) 75.3978476863163, (Float_t) 0.430094579594561, (Float_t) -79.4164552507386, (Float_t) -0.415015413747894, (Float_t) 61.0373661948115, (Float_t) 0.304942508151101, (Float_t) -33.7446462547014, (Float_t) -0.166191795926663, (Float_t) 12.8168791146274, (Float_t) 0.063198189938739, (Float_t) -3.01332198541437, (Float_t) -0.015003978694525, (Float_t) 0.223619893831468, (Float_t) 0.001748085184539}, + {(Float_t) 0.021776466467053, (Float_t) -5.74819833657784, (Float_t) -0.062376961003801, (Float_t) 16.246507961894, (Float_t) 0.107731165328514, (Float_t) -29.9691822642542, (Float_t) -0.150994515142316, (Float_t) 40.027597579378, (Float_t) 0.170334807313632, (Float_t) -40.3209196052655, (Float_t) -0.157984942890531, (Float_t) 30.8542077487718, (Float_t) 0.121639833268721, (Float_t) -17.5965138737281, (Float_t) -0.074094040816409, (Float_t) 7.10690214103873, (Float_t) 0.031282852041061, (Float_t) -1.82175564515191, (Float_t) -0.00755421235941, (Float_t) 0.223619893831468, (Float_t) 0.00117925454213}, + {(Float_t) 0.03857599435200, (Float_t) -3.84664617118067, (Float_t) -0.02160367184185, (Float_t) 7.81501653005538, (Float_t) -0.00123395316851, (Float_t) -11.34170355132042, (Float_t) -0.00009291677959, (Float_t) 13.05504219327545, (Float_t) -0.01655260341619, (Float_t) -12.28759895145294, (Float_t) 0.02161526843274, (Float_t) 9.48293806319790, (Float_t) -0.02074045215285, (Float_t) -5.87257861775999, (Float_t) 0.00594298065125, (Float_t) 2.75465861874613, (Float_t) 0.00306428023191, (Float_t) -0.86984376593551, (Float_t) 0.00012025322027, (Float_t) 0.13919314567432, (Float_t) 0.00288463683916}, + {(Float_t) 0.05418656406430, (Float_t) -3.47845948550071, (Float_t) -0.02911007808948, (Float_t) 6.36317777566148, (Float_t) -0.00848709379851, (Float_t) -8.54751527471874, (Float_t) -0.00851165645469, (Float_t) 9.47693607801280, (Float_t) -0.00834990904936, (Float_t) -8.81498681370155, (Float_t) 0.02245293253339, (Float_t) 6.85401540936998, (Float_t) -0.02596338512915, (Float_t) -4.39470996079559, (Float_t) 0.01624864962975, (Float_t) 2.19611684890774, (Float_t) -0.00240879051584, (Float_t) -0.75104302451432, (Float_t) 0.00674613682247, (Float_t) 0.13149317958808, (Float_t) -0.00187763777362}, + {(Float_t) 0.15457299681924, (Float_t) -2.37898834973084, (Float_t) -0.09331049056315, (Float_t) 2.84868151156327, (Float_t) -0.06247880153653, (Float_t) -2.64577170229825, (Float_t) 0.02163541888798, (Float_t) 2.23697657451713, (Float_t) -0.05588393329856, (Float_t) -1.67148153367602, (Float_t) 0.04781476674921, (Float_t) 1.00595954808547, (Float_t) 0.00222312597743, (Float_t) -0.45953458054983, (Float_t) 0.03174092540049, (Float_t) 0.16378164858596, (Float_t) -0.01390589421898, (Float_t) -0.05032077717131, (Float_t) 0.00651420667831, (Float_t) 0.02347897407020, (Float_t) -0.00881362733839}, + {(Float_t) 0.30296907319327, (Float_t) -1.61273165137247, (Float_t) -0.22613988682123, (Float_t) 1.07977492259970, (Float_t) -0.08587323730772, (Float_t) -0.25656257754070, (Float_t) 0.03282930172664, (Float_t) -0.16276719120440, (Float_t) -0.00915702933434, (Float_t) -0.22638893773906, (Float_t) -0.02364141202522, (Float_t) 0.39120800788284, (Float_t) -0.00584456039913, (Float_t) -0.22138138954925, (Float_t) 0.06276101321749, (Float_t) 0.04500235387352, (Float_t) -0.00000828086748, (Float_t) 0.02005851806501, (Float_t) 0.00205861885564, (Float_t) 0.00302439095741, (Float_t) -0.02950134983287}, + {(Float_t) 0.33642304856132, (Float_t) -1.49858979367799, (Float_t) -0.25572241425570, (Float_t) 0.87350271418188, (Float_t) -0.11828570177555, (Float_t) 0.12205022308084, (Float_t) 0.11921148675203, (Float_t) -0.80774944671438, (Float_t) -0.07834489609479, (Float_t) 0.47854794562326, (Float_t) -0.00469977914380, (Float_t) -0.12453458140019, (Float_t) -0.00589500224440, (Float_t) -0.04067510197014, (Float_t) 0.05724228140351, (Float_t) 0.08333755284107, (Float_t) 0.00832043980773, (Float_t) -0.04237348025746, (Float_t) -0.01635381384540, (Float_t) 0.02977207319925, (Float_t) -0.01760176568150}, + {(Float_t) 0.44915256608450, (Float_t) -0.62820619233671, (Float_t) -0.14351757464547, (Float_t) 0.29661783706366, (Float_t) -0.22784394429749, (Float_t) -0.37256372942400, (Float_t) -0.01419140100551, (Float_t) 0.00213767857124, (Float_t) 0.04078262797139, (Float_t) -0.42029820170918, (Float_t) -0.12398163381748, (Float_t) 0.22199650564824, (Float_t) 0.04097565135648, (Float_t) 0.00613424350682, (Float_t) 0.10478503600251, (Float_t) 0.06747620744683, (Float_t) -0.01863887810927, (Float_t) 0.05784820375801, (Float_t) -0.03193428438915, (Float_t) 0.03222754072173, (Float_t) 0.00541907748707}, + {(Float_t) 0.56619470757641, (Float_t) -1.04800335126349, (Float_t) -0.75464456939302, (Float_t) 0.29156311971249, (Float_t) 0.16242137742230, (Float_t) -0.26806001042947, (Float_t) 0.16744243493672, (Float_t) 0.00819999645858, (Float_t) -0.18901604199609, (Float_t) 0.45054734505008, (Float_t) 0.30931782841830, (Float_t) -0.33032403314006, (Float_t) -0.27562961986224, (Float_t) 0.06739368333110, (Float_t) 0.00647310677246, (Float_t) -0.04784254229033, (Float_t) 0.08647503780351, (Float_t) 0.01639907836189, (Float_t) -0.03788984554840, (Float_t) 0.01807364323573, (Float_t) -0.00588215443421}, + {(Float_t) 0.58100494960553, (Float_t) -0.51035327095184, (Float_t) -0.53174909058578, (Float_t) -0.31863563325245, (Float_t) -0.14289799034253, (Float_t) -0.20256413484477, (Float_t) 0.17520704835522, (Float_t) 0.14728154134330, (Float_t) 0.02377945217615, (Float_t) 0.38952639978999, (Float_t) 0.15558449135573, (Float_t) -0.23313271880868, (Float_t) -0.25344790059353, (Float_t) -0.05246019024463, (Float_t) 0.01628462406333, (Float_t) -0.02505961724053, (Float_t) 0.06920467763959, (Float_t) 0.02442357316099, (Float_t) -0.03721611395801, (Float_t) 0.01818801111503, (Float_t) -0.00749618797172}, + {(Float_t) 0.53648789255105, (Float_t) -0.25049871956020, (Float_t) -0.42163034350696, (Float_t) -0.43193942311114, (Float_t) -0.00275953611929, (Float_t) -0.03424681017675, (Float_t) 0.04267842219415, (Float_t) -0.04678328784242, (Float_t) -0.10214864179676, (Float_t) 0.26408300200955, (Float_t) 0.14590772289388, (Float_t) 0.15113130533216, (Float_t) -0.02459864859345, (Float_t) -0.17556493366449, (Float_t) -0.11202315195388, (Float_t) -0.18823009262115, (Float_t) -0.04060034127000, (Float_t) 0.05477720428674, (Float_t) 0.04788665548180, (Float_t) 0.04704409688120, (Float_t) -0.02217936801134}, - {(const Float_t) 0.38524531015142, (const Float_t) -1.29708918404534, (const Float_t) -0.27682212062067, (const Float_t) 0.90399339674203, (const Float_t)-0.09980181488805, (const Float_t) -0.29613799017877, (const Float_t) 0.09951486755646, (const Float_t)-0.42326645916207, (const Float_t) -0.08934020156622, (const Float_t) 0.37934887402200, (const Float_t) -0.00322369330199, (const Float_t) -0.37919795944938, (const Float_t) -0.00110329090689, (const Float_t) 0.23410283284785, (const Float_t) 0.03784509844682, (const Float_t) -0.03892971758879, (const Float_t) 0.01683906213303, (const Float_t) 0.00403009552351, (const Float_t) -0.01147039862572, (const Float_t) 0.03640166626278, (const Float_t) -0.01941767987192 }, - {(const Float_t)0.08717879977844, (const Float_t)-2.62816311472146, (const Float_t)-0.01000374016172, (const Float_t)3.53734535817992, (const Float_t)-0.06265852122368, (const Float_t)-3.81003448678921, (const Float_t)-0.01119328800950, (const Float_t)3.91291636730132, (const Float_t)-0.00114279372960, (const Float_t)-3.53518605896288, (const Float_t)0.02081333954769, (const Float_t)2.71356866157873, (const Float_t)-0.01603261863207, (const Float_t)-1.86723311846592, (const Float_t)0.01936763028546, (const Float_t)1.12075382367659, (const Float_t)0.00760044736442, (const Float_t)-0.48574086886890, (const Float_t)-0.00303979112271, (const Float_t)0.11330544663849, (const Float_t)-0.00075088605788 }, + {(Float_t) 0.38524531015142, (Float_t) -1.29708918404534, (Float_t) -0.27682212062067, (Float_t) 0.90399339674203, (Float_t)-0.09980181488805, (Float_t) -0.29613799017877, (Float_t) 0.09951486755646, (Float_t)-0.42326645916207, (Float_t) -0.08934020156622, (Float_t) 0.37934887402200, (Float_t) -0.00322369330199, (Float_t) -0.37919795944938, (Float_t) -0.00110329090689, (Float_t) 0.23410283284785, (Float_t) 0.03784509844682, (Float_t) -0.03892971758879, (Float_t) 0.01683906213303, (Float_t) 0.00403009552351, (Float_t) -0.01147039862572, (Float_t) 0.03640166626278, (Float_t) -0.01941767987192 }, + {(Float_t)0.08717879977844, (Float_t)-2.62816311472146, (Float_t)-0.01000374016172, (Float_t)3.53734535817992, (Float_t)-0.06265852122368, (Float_t)-3.81003448678921, (Float_t)-0.01119328800950, (Float_t)3.91291636730132, (Float_t)-0.00114279372960, (Float_t)-3.53518605896288, (Float_t)0.02081333954769, (Float_t)2.71356866157873, (Float_t)-0.01603261863207, (Float_t)-1.86723311846592, (Float_t)0.01936763028546, (Float_t)1.12075382367659, (Float_t)0.00760044736442, (Float_t)-0.48574086886890, (Float_t)-0.00303979112271, (Float_t)0.11330544663849, (Float_t)-0.00075088605788 }, }; static const Float_t ABButter[][2 * BUTTER_ORDER + 1] = { - {(const Float_t) 0.99308203517541, (const Float_t) -1.98611621154089, (const Float_t) -1.98616407035082, (const Float_t) 0.986211929160751, (const Float_t) 0.99308203517541}, - {(const Float_t) 0.992472550461293, (const Float_t) -1.98488843762334, (const Float_t) -1.98494510092258, (const Float_t) 0.979389350028798, (const Float_t) 0.992472550461293}, - {(const Float_t) 0.989641019334721, (const Float_t) -1.97917472731008, (const Float_t) -1.97928203866944, (const Float_t) 0.979389350028798, (const Float_t) 0.989641019334721}, - {(const Float_t) 0.98621192462708, (const Float_t) -1.97223372919527, (const Float_t) -1.97242384925416, (const Float_t) 0.97261396931306, (const Float_t) 0.98621192462708}, - {(const Float_t) 0.98500175787242, (const Float_t) -1.96977855582618, (const Float_t) -1.97000351574484, (const Float_t) 0.97022847566350, (const Float_t) 0.98500175787242}, - {(const Float_t) 0.97938932735214, (const Float_t) -1.95835380975398, (const Float_t) -1.95877865470428, (const Float_t) 0.95920349965459, (const Float_t) 0.97938932735214}, - {(const Float_t) 0.97531843204928, (const Float_t) -1.95002759149878, (const Float_t) -1.95063686409857, (const Float_t) 0.95124613669835, (const Float_t) 0.97531843204928}, - {(const Float_t) 0.97316523498161, (const Float_t) -1.94561023566527, (const Float_t) -1.94633046996323, (const Float_t) 0.94705070426118, (const Float_t) 0.97316523498161}, - {(const Float_t) 0.96454515552826, (const Float_t) -1.92783286977036, (const Float_t) -1.92909031105652, (const Float_t) 0.93034775234268, (const Float_t) 0.96454515552826}, - {(const Float_t) 0.96009142950541, (const Float_t) -1.91858953033784, (const Float_t) -1.92018285901082, (const Float_t) 0.92177618768381, (const Float_t) 0.96009142950541}, - {(const Float_t) 0.95856916599601, (const Float_t) -1.91542108074780, (const Float_t) -1.91713833199203, (const Float_t) 0.91885558323625, (const Float_t) 0.95856916599601}, - {(const Float_t) 0.94597685600279, (const Float_t) -1.88903307939452, (const Float_t) -1.89195371200558, (const Float_t) 0.89487434461664, (const Float_t) 0.94597685600279}, + {(Float_t) 0.99308203517541, (Float_t) -1.98611621154089, (Float_t) -1.98616407035082, (Float_t) 0.986211929160751, (Float_t) 0.99308203517541}, + {(Float_t) 0.992472550461293, (Float_t) -1.98488843762334, (Float_t) -1.98494510092258, (Float_t) 0.979389350028798, (Float_t) 0.992472550461293}, + {(Float_t) 0.989641019334721, (Float_t) -1.97917472731008, (Float_t) -1.97928203866944, (Float_t) 0.979389350028798, (Float_t) 0.989641019334721}, + {(Float_t) 0.98621192462708, (Float_t) -1.97223372919527, (Float_t) -1.97242384925416, (Float_t) 0.97261396931306, (Float_t) 0.98621192462708}, + {(Float_t) 0.98500175787242, (Float_t) -1.96977855582618, (Float_t) -1.97000351574484, (Float_t) 0.97022847566350, (Float_t) 0.98500175787242}, + {(Float_t) 0.97938932735214, (Float_t) -1.95835380975398, (Float_t) -1.95877865470428, (Float_t) 0.95920349965459, (Float_t) 0.97938932735214}, + {(Float_t) 0.97531843204928, (Float_t) -1.95002759149878, (Float_t) -1.95063686409857, (Float_t) 0.95124613669835, (Float_t) 0.97531843204928}, + {(Float_t) 0.97316523498161, (Float_t) -1.94561023566527, (Float_t) -1.94633046996323, (Float_t) 0.94705070426118, (Float_t) 0.97316523498161}, + {(Float_t) 0.96454515552826, (Float_t) -1.92783286977036, (Float_t) -1.92909031105652, (Float_t) 0.93034775234268, (Float_t) 0.96454515552826}, + {(Float_t) 0.96009142950541, (Float_t) -1.91858953033784, (Float_t) -1.92018285901082, (Float_t) 0.92177618768381, (Float_t) 0.96009142950541}, + {(Float_t) 0.95856916599601, (Float_t) -1.91542108074780, (Float_t) -1.91713833199203, (Float_t) 0.91885558323625, (Float_t) 0.95856916599601}, + {(Float_t) 0.94597685600279, (Float_t) -1.88903307939452, (Float_t) -1.89195371200558, (Float_t) 0.89487434461664, (Float_t) 0.94597685600279}, - {(const Float_t)0.96535326815829, (const Float_t)-1.92950577983524, (const Float_t)-1.93070653631658, (const Float_t)0.93190729279793, (const Float_t)0.96535326815829 }, - {(const Float_t)0.98252400815195, (const Float_t)-1.96474258269041, (const Float_t)-1.96504801630391, (const Float_t)0.96535344991740, (const Float_t)0.98252400815195 }, + {(Float_t)0.96535326815829, (Float_t)-1.92950577983524, (Float_t)-1.93070653631658, (Float_t)0.93190729279793, (Float_t)0.96535326815829 }, + {(Float_t)0.98252400815195, (Float_t)-1.96474258269041, (Float_t)-1.96504801630391, (Float_t)0.96535344991740, (Float_t)0.98252400815195 }, }; diff --git a/src/common/thirdparty/libsmackerdec/COPYING b/src/common/thirdparty/libsmackerdec/COPYING new file mode 100644 index 000000000..00b4fedfe --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/common/thirdparty/libsmackerdec/include/BitReader.h b/src/common/thirdparty/libsmackerdec/include/BitReader.h new file mode 100644 index 000000000..1bf12b2ca --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/include/BitReader.h @@ -0,0 +1,50 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#ifndef _SmackerBitReader_h_ +#define _SmackerBitReader_h_ + +#include +#include "FileStream.h" +#include "tarray.h" + +namespace SmackerCommon { + +class BitReader +{ + public: + BitReader(const uint8_t *data, uint32_t size) : bitData(data), totalSize(size) { } + ~BitReader() = default; + uint32_t GetBit(); + uint32_t GetBits(uint32_t n); + void SkipBits(uint32_t n); + + uint32_t GetSize(); + uint32_t GetPosition(); + + private: + const uint8_t *bitData = nullptr; + uint32_t totalSize = 0; + uint32_t currentOffset = 0; + uint32_t bytesRead = 0; +}; + +} // close namespace SmackerCommon + +#endif diff --git a/src/common/thirdparty/libsmackerdec/include/FileStream.h b/src/common/thirdparty/libsmackerdec/include/FileStream.h new file mode 100644 index 000000000..034ccb733 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/include/FileStream.h @@ -0,0 +1,63 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#ifndef _SmackerFileStream_h_ +#define _SmackerFileStream_h_ + +#include +#include "files.h" + +namespace SmackerCommon { + +class FileStream +{ + public: + + bool Open(const char *fileName); + bool Is_Open() { return file.isOpen(); } + void Close() { file.Close(); } + + int32_t ReadBytes(uint8_t *data, uint32_t nBytes) + { + return (uint32_t)file.Read(data, static_cast(nBytes)); + } + + uint64_t ReadUint64LE() { return file.ReadUInt64(); } + uint32_t ReadUint32LE() { return file.ReadUInt32(); } + uint16_t ReadUint16LE() { return file.ReadUInt16(); } + uint8_t ReadByte() { return file.ReadInt8(); } + + + enum SeekDirection{ + kSeekCurrent = SEEK_CUR, + kSeekStart = SEEK_SET, + kSeekEnd = SEEK_END + }; + + int32_t Seek(int32_t offset, SeekDirection dir = kSeekStart) { return (int)file.Seek(offset, (FileReader::ESeek) dir); } + int32_t Skip(int32_t offset) { return (int)Seek(offset, kSeekCurrent); } + int32_t GetPosition() { return (int)file.Tell(); } + + private: + FileReader file; +}; + +} // close namespace SmackerCommon + +#endif diff --git a/src/common/thirdparty/libsmackerdec/include/HuffmanVLC.h b/src/common/thirdparty/libsmackerdec/include/HuffmanVLC.h new file mode 100644 index 000000000..668249317 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/include/HuffmanVLC.h @@ -0,0 +1,43 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#ifndef _SmackerHuffmanVLC_h_ +#define _SmackerHuffmanVLC_h_ + +#include +#include "BitReader.h" +#include + +namespace SmackerCommon { + +struct VLC +{ + uint32_t symbol; + uint32_t code; +}; + +typedef std::vector< std::vector > VLCtable; + +uint16_t VLC_GetCodeBits(BitReader &bits, VLCtable &table); +void VLC_InitTable (VLCtable &table, uint32_t maxLength, uint32_t size, int *lengths, uint32_t *bits); +uint32_t VLC_GetSize (VLCtable &table); + +} // close namespace SmackerCommon + +#endif diff --git a/src/common/thirdparty/libsmackerdec/include/LogError.h b/src/common/thirdparty/libsmackerdec/include/LogError.h new file mode 100644 index 000000000..b5b8b5f36 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/include/LogError.h @@ -0,0 +1,31 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#ifndef _SmackerLogError_h_ +#define _SmackerLogError_h_ + +//#include + +namespace SmackerCommon { + +//void LogError(const std::string &error); + +} // close namespace SmackerCommon + +#endif \ No newline at end of file diff --git a/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h b/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h new file mode 100644 index 000000000..e9a8b1e27 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h @@ -0,0 +1,185 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +/* This code is based on smacker.c from the FFmpeg project which can be obtained from http://www.ffmpeg.org/ + * below is the license from smacker.c + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Smacker decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _SmackerDecoder_h_ +#define _SmackerDecoder_h_ + +#include +#include "FileStream.h" +#include "BitReader.h" +#include +#include +#include +#include + +// exportable interface +struct SmackerHandle +{ + bool isValid; + int instanceIndex; +}; + +struct SmackerAudioInfo +{ + uint32_t sampleRate; + uint8_t nChannels; + + uint32_t idealBufferSize; +}; + +SmackerHandle Smacker_Open (const char *fileName); +void Smacker_Close (SmackerHandle &handle); +uint32_t Smacker_GetNumAudioTracks (SmackerHandle &handle); +SmackerAudioInfo Smacker_GetAudioTrackDetails (SmackerHandle &handle, uint32_t trackIndex); +uint32_t Smacker_GetAudioData (SmackerHandle &handle, uint32_t trackIndex, int16_t *data); +void Smacker_DisableAudioTrack (SmackerHandle &handle, uint32_t trackIndex); +uint32_t Smacker_GetNumFrames (SmackerHandle &handle); +void Smacker_GetFrameSize (SmackerHandle &handle, uint32_t &width, uint32_t &height); +uint32_t Smacker_GetCurrentFrameNum (SmackerHandle &handle); +uint32_t Smacker_GetNextFrame (SmackerHandle &handle); +float Smacker_GetFrameRate (SmackerHandle &handle); +void Smacker_GetPalette (SmackerHandle &handle, uint8_t *palette); +void Smacker_GetFrame (SmackerHandle &handle, uint8_t *frame); +void Smacker_GotoFrame (SmackerHandle &handle, uint32_t frameNum); + +const int kMaxAudioTracks = 7; + +// forward declare +struct HuffContext; +struct DBCtx; + +struct SmackerPacket +{ + size_t size = 0; + std::unique_ptr data; +}; + +struct SmackerAudioTrack +{ + uint32_t sizeInBytes; + uint32_t flags; + uint32_t sampleRate; + uint8_t nChannels; + uint8_t bitsPerSample; +// int compressionType; + + uint8_t *buffer; + uint32_t bufferSize; + + uint32_t bytesReadThisFrame; + std::deque packetData; +}; + +class SmackerDecoder +{ + public: + uint32_t frameWidth; + uint32_t frameHeight; + + SmackerDecoder(); + ~SmackerDecoder(); + + bool Open(const char *fileName); + void GetPalette(uint8_t *palette); + void GetFrame(uint8_t *frame); + + uint32_t GetNumAudioTracks(); + SmackerAudioInfo GetAudioTrackDetails(uint32_t trackIndex); + uint32_t GetAudioData(uint32_t trackIndex, int16_t *audioBuffer); + void DisableAudioTrack(uint32_t trackIndex); + uint32_t GetNumFrames(); + uint32_t GetCurrentFrameNum(); + float GetFrameRate(); + void GetNextFrame(); + void GotoFrame(uint32_t frameNum); + + private: + SmackerCommon::FileStream file; + char signature[4]; + std::mutex fileMutex; + + // video related members + uint32_t nFrames; + uint32_t fps; // frames per second + + uint8_t palette[768]; + uint8_t *picture; + + bool isVer4; + + uint32_t currentReadFrame; + std::vector packetData; + + std::deque framePacketData; + SmackerAudioTrack audioTracks[kMaxAudioTracks]; + + uint32_t treeSize; + uint32_t mMapSize, MClrSize, fullSize, typeSize; + + std::vector mmap_tbl; + std::vector mclr_tbl; + std::vector full_tbl; + std::vector type_tbl; + + int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; + + std::vector frameSizes; + std::vector frameFlags; + + uint32_t currentFrame; + int32_t nextPos; + int32_t firstFrameFilePos; + + bool DecodeHeaderTrees(); + int DecodeHeaderTree(SmackerCommon::BitReader &bits, std::vector &recodes, int *last, int size); + int DecodeTree(SmackerCommon::BitReader &bits, HuffContext *hc, uint32_t prefix, int length); + int DecodeBigTree(SmackerCommon::BitReader &bits, HuffContext *hc, DBCtx *ctx); + int GetCode(SmackerCommon::BitReader &bits, std::vector &recode, int *last); + int ReadPacket(); + int DecodeFrame(const uint8_t *dataPtr, uint32_t frameSize); + void GetFrameSize(uint32_t &width, uint32_t &height); + int DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAudioTrack &track); +}; + +#endif diff --git a/src/common/thirdparty/libsmackerdec/src/BitReader.cpp b/src/common/thirdparty/libsmackerdec/src/BitReader.cpp new file mode 100644 index 000000000..604848ec6 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/src/BitReader.cpp @@ -0,0 +1,71 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#include "BitReader.h" +#include + +namespace SmackerCommon { + +uint32_t BitReader::GetSize() +{ + return totalSize * 8; +} + +uint32_t BitReader::GetPosition() +{ + return currentOffset; +} + +uint32_t BitReader::GetBit() +{ + uint32_t ret = (bitData[currentOffset>>3]>>(currentOffset&7))&1; + currentOffset++; + return ret; +} + +uint32_t BitReader::GetBits(uint32_t n) +{ + uint32_t ret = 0; + + int bitsTodo = n; + + uint32_t theShift = 0; + + while (bitsTodo) + { + uint32_t bit = GetBit(); + bit <<= theShift; + + theShift++; + + ret |= bit; + + bitsTodo--; + } + + return ret; +} + +void BitReader::SkipBits(uint32_t n) +{ + GetBits(n); +} + +} // close namespace SmackerCommon + diff --git a/src/common/thirdparty/libsmackerdec/src/FileStream.cpp b/src/common/thirdparty/libsmackerdec/src/FileStream.cpp new file mode 100644 index 000000000..454143ff1 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/src/FileStream.cpp @@ -0,0 +1,40 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#include "FileStream.h" +#include "filesystem.h" +#include +#include "cmdlib.h" + +namespace SmackerCommon { + +bool FileStream::Open(const char *fileName) +{ + FString fixedname = fileName; + FixPathSeperator(fixedname); + file = fileSystem.OpenFileReader(fixedname); + if (!file.isOpen()) + { + // log error + return false; + } + return true; +} + +} // close namespace SmackerCommon diff --git a/src/common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp b/src/common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp new file mode 100644 index 000000000..400e622f8 --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp @@ -0,0 +1,71 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#include + +namespace SmackerCommon { + +uint16_t VLC_GetCodeBits(BitReader &bits, VLCtable &table) +{ + uint32_t codeBits = 0; + + // search each length array + for (uint32_t i = 0; i < table.size(); i++) + { + // get and add a new bit to codeBits + uint32_t theBit = bits.GetBit() << i; + codeBits |= theBit; + + // search for a code match + for (uint32_t j = 0; j < table[i].size(); j++) + { + if (codeBits == table[i][j].code) + { + return table[i][j].symbol; + } + } + } + + // shouldn't get here.. + return 0; +} + +void VLC_InitTable(VLCtable &table, uint32_t maxLength, uint32_t size, int *lengths, uint32_t *bits) +{ + table.resize(maxLength); + + for (uint32_t i = 0; i < size; i++) + { + VLC newCode; + newCode.symbol = i; + newCode.code = bits[i]; + + uint32_t codeLength = lengths[i]; + + if (codeLength) + table[codeLength - 1].push_back(newCode); + } +} + +uint32_t VLC_GetSize(VLCtable &table) +{ + return uint32_t(table.size()); +} + +} // close namespace SmackerCommon diff --git a/src/common/thirdparty/libsmackerdec/src/LogError.cpp b/src/common/thirdparty/libsmackerdec/src/LogError.cpp new file mode 100644 index 000000000..46a45bb0a --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/src/LogError.cpp @@ -0,0 +1,33 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +#include "LogError.h" + +namespace SmackerCommon { + +#if 0 +static std::string LastError; + +void LogError(const std::string &error) +{ + LastError = error; +} +#endif + +} // close namespace SmackerCommon diff --git a/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp b/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp new file mode 100644 index 000000000..ff69f3b2c --- /dev/null +++ b/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp @@ -0,0 +1,1255 @@ +/* + * libsmackerdec - Smacker video decoder + * Copyright (C) 2011 Barry Duncan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +/* This code is heavily based on smacker.c from the FFmpeg project which can be obtained from http://www.ffmpeg.org/ + * below is the license from smacker.c + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Smacker decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "SmackerDecoder.h" +#include "HuffmanVLC.h" +#include "LogError.h" +#include "printf.h" +#include "limits.h" +#include +#include +#include + +std::vector classInstances; + +SmackerHandle Smacker_Open(const char* fileName) +{ + SmackerHandle newHandle; + newHandle.isValid = false; + newHandle.instanceIndex = -1; + + SmackerDecoder *newDecoder = new SmackerDecoder(); + if (!newDecoder->Open(fileName)) + { + delete newDecoder; + return newHandle; + } + + // add instance to global instance vector + classInstances.push_back(newDecoder); + + // get a handle ID + newHandle.instanceIndex = int(classInstances.size()) - 1; + + // loaded ok, make handle valid + newHandle.isValid = true; + + return newHandle; +} + +void Smacker_Close(SmackerHandle &handle) +{ + if (!classInstances.at(handle.instanceIndex)) + { + // invalid handle + return; + } + + // close bink decoder + delete classInstances[handle.instanceIndex]; + classInstances[handle.instanceIndex] = 0; + + handle.instanceIndex = -1; + handle.isValid = false; +} + +uint32_t Smacker_GetNumAudioTracks(SmackerHandle &handle) +{ + return classInstances[handle.instanceIndex]->GetNumAudioTracks(); +} + +SmackerAudioInfo Smacker_GetAudioTrackDetails(SmackerHandle &handle, uint32_t trackIndex) +{ + return classInstances[handle.instanceIndex]->GetAudioTrackDetails(trackIndex); +} + +/* Get a frame's worth of audio data. + * + * 'data' needs to be a pointer to allocated memory that this function will fill. + * You can find the size (in bytes) to make this buffer by calling Bink_GetAudioTrackDetails() + * and checking the 'idealBufferSize' member in the returned AudioInfo struct + */ +uint32_t Smacker_GetAudioData(SmackerHandle &handle, uint32_t trackIndex, int16_t *data) +{ + return classInstances[handle.instanceIndex]->GetAudioData(trackIndex, data); +} + +/* Disables an audio track if it's enabled. + * + * When getting video or audio data, encoded data is stored for other tracks so + * they can be read and decoded later. This function prevents a build-up of + * encoded audio data for the specified track if such data isn't going to be + * decoded and read by the caller. + */ +void Smacker_DisableAudioTrack(SmackerHandle &handle, uint32_t trackIndex) +{ + classInstances[handle.instanceIndex]->DisableAudioTrack(trackIndex); +} + +uint32_t Smacker_GetNumFrames(SmackerHandle &handle) +{ + return classInstances[handle.instanceIndex]->GetNumFrames(); +} + +void Smacker_GetFrameSize(SmackerHandle &handle, uint32_t &width, uint32_t &height) +{ + width = classInstances[handle.instanceIndex]->frameWidth; + height = classInstances[handle.instanceIndex]->frameHeight; +} + +uint32_t Smacker_GetCurrentFrameNum(SmackerHandle &handle) +{ + return classInstances[handle.instanceIndex]->GetCurrentFrameNum(); +} + +uint32_t Smacker_GetNextFrame(SmackerHandle &handle) +{ + SmackerDecoder *decoder = classInstances[handle.instanceIndex]; + + uint32_t frameIndex = decoder->GetCurrentFrameNum(); + + decoder->GetNextFrame(); + + return frameIndex; +} + +float Smacker_GetFrameRate(SmackerHandle &handle) +{ + return classInstances[handle.instanceIndex]->GetFrameRate(); +} + +void Smacker_GetPalette(SmackerHandle &handle, uint8_t *palette) +{ + classInstances[handle.instanceIndex]->GetPalette(palette); +} + +void Smacker_GetFrame(SmackerHandle &handle, uint8_t *frame) +{ + classInstances[handle.instanceIndex]->GetFrame(frame); +} + +void Smacker_GotoFrame(SmackerHandle &handle, uint32_t frameNum) +{ + classInstances[handle.instanceIndex]->GotoFrame(frameNum); +} + +SmackerDecoder::SmackerDecoder() +{ + isVer4 = false; + currentReadFrame = 0; + currentFrame = 0; + picture = 0; + nextPos = 0; + + for (int i = 0; i < kMaxAudioTracks; i++) + { + audioTracks[i].buffer = 0; + } +} + +SmackerDecoder::~SmackerDecoder() +{ + for (int i = 0; i < kMaxAudioTracks; i++) + { + delete[] audioTracks[i].buffer; + } + + delete[] picture; +} + +// from bswap.h +static /*av_always_inline av_const*/ uint16_t av_bswap16(uint16_t x) +{ + x= (x>>8) | (x<<8); + return x; +} + +/* possible runs of blocks */ +static const int block_runs[64] = { + 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, 128, 256, 512, 1024, 2048 }; + +enum SmkBlockTypes { + SMK_BLK_MONO = 0, + SMK_BLK_FULL = 1, + SMK_BLK_SKIP = 2, + SMK_BLK_FILL = 3 }; + +/* palette used in Smacker */ +static const uint8_t smk_pal[64] = { + 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, + 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, + 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, + 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D, + 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E, + 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE, + 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF, + 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF +}; + +enum SAudFlags { + SMK_AUD_PACKED = 0x80000000, + SMK_AUD_PRESENT = 0x40000000, + SMK_AUD_16BITS = 0x20000000, + SMK_AUD_STEREO = 0x10000000, + SMK_AUD_BINKAUD = 0x08000000, + SMK_AUD_USEDCT = 0x04000000 +}; + +const int kSMKpal = 0x01; +const int kFlagRingFrame = 0x01; + +const int kTreeBits = 9; +const int kSMKnode = 0x80000000; + +const char *kSMK2iD = "SMK2"; +const char *kSMK4iD = "SMK4"; + + +/** + * Context used for code reconstructing + */ +typedef struct HuffContext { + int length = 0; + int maxlength = 0; + int current = 0; + + std::vector bits; + std::vector lengths; + std::vector values; + +} HuffContext; + +/* common parameters used for decode_bigtree */ +typedef struct DBCtx { + SmackerCommon::VLCtable v1; + SmackerCommon::VLCtable v2; + std::vector recode1, recode2; + int escapes[3]; + int *last; + int lcur; +} DBCtx; + + +static void last_reset(std::vector &recode, int *last) { + recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; +} + +/* get code and update history */ +int SmackerDecoder::GetCode(SmackerCommon::BitReader &bits, std::vector &recode, int *last) +{ + int *table = &recode[0]; + + int v, b; + + b = bits.GetPosition(); + + while (*table & kSMKnode) + { + if (bits.GetBit()) + table += (*table) & (~kSMKnode); + table++; + } + v = *table; + b = bits.GetPosition() - b; + + if (v != recode[last[0]]) { + recode[last[2]] = recode[last[1]]; + recode[last[1]] = recode[last[0]]; + recode[last[0]] = v; + } + return v; +} + +bool SmackerDecoder::Open(const char *fileName) +{ + // open the file (read only) + file.Open(fileName); + if (!file.Is_Open()) + { + Printf("SmackerDecoder::Open() - Can't open file %s\n", fileName); + return false; + } + + // check the file signature + file.ReadBytes((uint8_t*)signature, 4); + if (memcmp(signature, kSMK2iD, 4) != 0 + && memcmp(signature, kSMK4iD, 4) != 0) + { + Printf("SmackerDecoder::Open() - Unknown Smacker signature\n"); + return false; + } + + if (!memcmp(signature, kSMK4iD, 4)) { + isVer4 = true; + } + + frameWidth = file.ReadUint32LE(); + frameHeight = file.ReadUint32LE(); + nFrames = file.ReadUint32LE(); + + picture = new uint8_t[frameWidth * frameHeight]; + + int32_t frameRate = file.ReadUint32LE(); + + if (frameRate > 0) + fps = 1000 / frameRate; + else if (frameRate < 0) + fps = 100000 / (-frameRate); + else + fps = 10; + + uint32_t flags = file.ReadUint32LE(); + + if (flags & kFlagRingFrame) { + nFrames++; + } + + for (int i = 0; i < kMaxAudioTracks; i++) { + audioTracks[i].sizeInBytes = file.ReadUint32LE(); + } + + treeSize = file.ReadUint32LE(); + mMapSize = file.ReadUint32LE(); + MClrSize = file.ReadUint32LE(); + fullSize = file.ReadUint32LE(); + typeSize = file.ReadUint32LE(); + + for (int i = 0; i < kMaxAudioTracks; i++) { + audioTracks[i].flags = file.ReadUint32LE(); + } + + // skip pad + file.Skip(4); + + if (nFrames > 0xFFFFFF) + { + Printf("SmackerDecoder::Open() - Too many frames\n"); + return false; + } + + frameSizes.resize(nFrames); + frameFlags.resize(nFrames); + + // read frame info + for (uint32_t i = 0; i < nFrames; i++) { + frameSizes[i] = file.ReadUint32LE(); + } + for (uint32_t i = 0; i < nFrames; i++) { + frameFlags[i] = file.ReadByte(); + } + + auto maxFrameSize = std::max_element(frameSizes.begin(), frameSizes.end()); + if (maxFrameSize != frameSizes.end()) + packetData.reserve(*maxFrameSize); + + // handle possible audio streams + for (int i = 0; i < kMaxAudioTracks; i++) + { + audioTracks[i].buffer = 0; + audioTracks[i].bufferSize = 0; + audioTracks[i].bytesReadThisFrame = 0; + + // Disable non-consecutive enabled tracks. Not sure how to otherwise report + // them properly for Smacker_GetNumAudioTracks. + if (i > 0 && !(audioTracks[i-1].flags & SMK_AUD_PRESENT)) + audioTracks[i].flags &= ~SMK_AUD_PRESENT; + + if (audioTracks[i].flags & 0xFFFFFF) + { +/* + if (audioTracks[i].flags & SMK_AUD_BINKAUD) { + audioTracks[i].compressionType = SMK_AUD_BINKAUD; + } else if (audioTracks[i].flags & SMK_AUD_USEDCT) { + audioTracks[i].compressionType = SMK_AUD_USEDCT; + } else if (audioTracks[i].flags & SMK_AUD_PACKED){ + ast[i]->codec->codec_id = CODEC_ID_SMACKAUDIO; + ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A'); + } else { + ast[i]->codec->codec_id = CODEC_ID_PCM_U8; + } +*/ + audioTracks[i].nChannels = (audioTracks[i].flags & SMK_AUD_STEREO) ? 2 : 1; + audioTracks[i].sampleRate = audioTracks[i].flags & 0xFFFFFF; + audioTracks[i].bitsPerSample = (audioTracks[i].flags & SMK_AUD_16BITS) ? 16 : 8; + } + } + + memset(palette, 0, 768); + + DecodeHeaderTrees(); + + // set nextPos to where we are now, as next data is frame 1 + nextPos = file.GetPosition(); + firstFrameFilePos = nextPos; + + // determine max buffer sizes for audio tracks +// file.Seek(nextPos, SmackerCommon::FileStream::kSeekStart); + + uint8_t frameFlag = frameFlags[0]; + + // skip over palette + if (frameFlag & kSMKpal) + { + uint32_t size = file.ReadByte(); + size = size * 4 - 1; + file.Skip(size); + } + + frameFlag >>= 1; + + for (int i = 0; i < kMaxAudioTracks; i++) + { + if (frameFlag & 1) + { + uint32_t size = file.ReadUint32LE(); + uint32_t unpackedSize = file.ReadUint32LE(); + + // If the track isn't 16-bit, double the buffer size for converting 8-bit to 16-bit. + if (!(audioTracks[i].flags & SMK_AUD_16BITS)) + unpackedSize *= 2; + + audioTracks[i].bufferSize = unpackedSize; + audioTracks[i].buffer = new uint8_t[unpackedSize]; + + // skip size + file.Skip(size - 8); + } + frameFlag >>= 1; + } + + return true; +} + +// static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) +int SmackerDecoder::DecodeTree(SmackerCommon::BitReader &bits, HuffContext *hc, uint32_t prefix, int length) +{ + if (!bits.GetBit()) // Leaf + { + if (hc->current >= 256){ + Printf("SmackerDecoder::DecodeTree() - Tree size exceeded\n"); + return -1; + } + if (length){ + hc->bits[hc->current] = prefix; + hc->lengths[hc->current] = length; + } else { + hc->bits[hc->current] = 0; + hc->lengths[hc->current] = 0; + } + hc->values[hc->current] = bits.GetBits(8); + + hc->current++; + if (hc->maxlength < length) + hc->maxlength = length; + return 0; + } else { //Node + int r; + length++; + r = DecodeTree(bits, hc, prefix, length); + if (r) + return r; + return DecodeTree(bits, hc, prefix | (1 << (length - 1)), length); + } +} + +/** + * Decode header tree + */ +int SmackerDecoder::DecodeBigTree(SmackerCommon::BitReader &bits, HuffContext *hc, DBCtx *ctx) +{ + if (!bits.GetBit()) // Leaf + { + int val, i1, i2, b1, b2; + + i1 = 0; + i2 = 0; + + if (hc->current >= hc->length){ + Printf("SmackerDecoder::DecodeBigTree() - Tree size exceeded"); + return -1; + } + + b1 = bits.GetPosition(); + + if (VLC_GetSize(ctx->v1)) + { + i1 = VLC_GetCodeBits(bits, ctx->v1); + } + + b1 = bits.GetPosition() - b1; + b2 = bits.GetPosition(); + + if (VLC_GetSize(ctx->v2)) + { + i2 = VLC_GetCodeBits(bits, ctx->v2); + } + + b2 = bits.GetPosition() - b2; + if (i1 < 0 || i2 < 0) + return -1; + val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); + if (val == ctx->escapes[0]) { + ctx->last[0] = hc->current; + val = 0; + } else if (val == ctx->escapes[1]) { + ctx->last[1] = hc->current; + val = 0; + } else if (val == ctx->escapes[2]) { + ctx->last[2] = hc->current; + val = 0; + } + + hc->values[hc->current++] = val; + return 1; + } else { //Node + int r = 0, t; + + t = hc->current++; + r = DecodeBigTree(bits, hc, ctx); + if (r < 0) + return r; + hc->values[t] = kSMKnode | r; + r++; + r += DecodeBigTree(bits, hc, ctx); + return r; + } +} + +/** + * Store large tree as Libav's vlc codes + */ +int SmackerDecoder::DecodeHeaderTree(SmackerCommon::BitReader &bits, std::vector &recodes, int *last, int size) +{ + HuffContext huff; + HuffContext tmp1, tmp2; + int escapes[3]; + DBCtx ctx; + + if ((uint32_t)size >= UINT_MAX>>4) + { + Printf("SmackerDecoder::DecodeHeaderTree() - Size too large\n"); + return -1; + } + + tmp1.length = 256; + tmp1.maxlength = 0; + tmp1.current = 0; + + tmp1.bits.resize(256); + tmp1.lengths.resize(256); + tmp1.values.resize(256); + + tmp2.length = 256; + tmp2.maxlength = 0; + tmp2.current = 0; + + tmp2.bits.resize(256); + tmp2.lengths.resize(256); + tmp2.values.resize(256); + + // low byte tree + if (bits.GetBit()) // 1: Read Tag + { + DecodeTree(bits, &tmp1, 0, 0); + + bits.SkipBits(1); + + VLC_InitTable(ctx.v1, tmp1.maxlength, tmp1.current, &tmp1.lengths[0], &tmp1.bits[0]); + } + else + { + // Skipping low bytes tree + } + + // high byte tree + if (bits.GetBit()) + { + DecodeTree(bits, &tmp2, 0, 0); + + bits.SkipBits(1); + + VLC_InitTable(ctx.v2, tmp2.maxlength, tmp2.current, &tmp2.lengths[0], &tmp2.bits[0]); + } + else + { + // Skipping high bytes tree + } + + escapes[0] = bits.GetBits(8); + escapes[0] |= bits.GetBits(8) << 8; + escapes[1] = bits.GetBits(8); + escapes[1] |= bits.GetBits(8) << 8; + escapes[2] = bits.GetBits(8); + escapes[2] |= bits.GetBits(8) << 8; + + last[0] = last[1] = last[2] = -1; + + ctx.escapes[0] = escapes[0]; + ctx.escapes[1] = escapes[1]; + ctx.escapes[2] = escapes[2]; + + ctx.recode1 = tmp1.values; + ctx.recode2 = tmp2.values; + ctx.last = last; + + huff.length = ((size + 3) >> 2) + 3; + huff.maxlength = 0; + huff.current = 0; + huff.values.resize(huff.length); + + DecodeBigTree(bits, &huff, &ctx); + + bits.SkipBits(1); + + if (ctx.last[0] == -1) ctx.last[0] = huff.current++; + if (ctx.last[1] == -1) ctx.last[1] = huff.current++; + if (ctx.last[2] == -1) ctx.last[2] = huff.current++; + + recodes = huff.values; + + return 0; +} + +// static int decode_header_trees(SmackVContext *smk) { +bool SmackerDecoder::DecodeHeaderTrees() +{ + auto treeData = std::make_unique(treeSize); + file.ReadBytes(treeData.get(), treeSize); + + SmackerCommon::BitReader bits(treeData.get(), treeSize); + + if (!bits.GetBit()) + { + // Skipping MMAP tree + mmap_tbl.resize(2); + mmap_tbl[0] = 0; + mmap_last[0] = mmap_last[1] = mmap_last[2] = 1; + } + else + { + DecodeHeaderTree(bits, mmap_tbl, mmap_last, mMapSize); + } + + if (!bits.GetBit()) + { + // Skipping MCLR tree + mclr_tbl.resize(2); + mclr_tbl[0] = 0; + mclr_last[0] = mclr_last[1] = mclr_last[2] = 1; + } + else + { + DecodeHeaderTree(bits, mclr_tbl, mclr_last, MClrSize); + } + + if (!bits.GetBit()) + { + // Skipping FULL tree + full_tbl.resize(2); + full_tbl[0] = 0; + full_last[0] = full_last[1] = full_last[2] = 1; + } + else + { + DecodeHeaderTree(bits, full_tbl, full_last, fullSize); + } + + if (!bits.GetBit()) + { + // Skipping TYPE tree + type_tbl.resize(2); + type_tbl[0] = 0; + type_last[0] = type_last[1] = type_last[2] = 1; + } + else + { + DecodeHeaderTree(bits, type_tbl, type_last, typeSize); + } + + return true; +} + +void SmackerDecoder::GetNextFrame() +{ + if (currentFrame >= nFrames) + return; + + std::unique_lock flock(fileMutex); + while (framePacketData.empty()) + { + if (ReadPacket() > 0) + return; + } + SmackerPacket pkt = std::move(framePacketData.front()); + framePacketData.pop_front(); + flock.unlock(); + + uint32_t frameSize = (uint32_t)pkt.size; + uint8_t frameFlag = frameFlags[currentFrame]; + + const uint8_t *packetDataPtr = pkt.data.get(); + + // handle palette change + if (frameFlag & kSMKpal) + { + int size, sz, t, off, j; + uint8_t *pal = palette; + uint8_t oldpal[768]; + const uint8_t *dataEnd; + + memcpy(oldpal, pal, 768); + size = *(packetDataPtr++); + size = size * 4 - 1; + frameSize -= size; + frameSize--; + sz = 0; + dataEnd = packetDataPtr + size; + + while (sz < 256) + { + t = *(packetDataPtr++); + if (t & 0x80){ /* skip palette entries */ + sz += (t & 0x7F) + 1; + pal += ((t & 0x7F) + 1) * 3; + } else if (t & 0x40){ /* copy with offset */ + off = *(packetDataPtr++) * 3; + j = (t & 0x3F) + 1; + while (j-- && sz < 256) { + *pal++ = oldpal[off + 0]; + *pal++ = oldpal[off + 1]; + *pal++ = oldpal[off + 2]; + sz++; + off += 3; + } + } else { /* new entries */ + *pal++ = smk_pal[t]; + *pal++ = smk_pal[*(packetDataPtr++) & 0x3F]; + *pal++ = smk_pal[*(packetDataPtr++) & 0x3F]; + sz++; + } + } + + packetDataPtr = dataEnd; + } + + if (frameSize > 0) + DecodeFrame(packetDataPtr, frameSize); + + currentFrame++; +} + +int SmackerDecoder::ReadPacket() +{ + // test-remove + if (currentReadFrame >= nFrames) + return 1; + + // seek to next frame position + file.Seek(nextPos, SmackerCommon::FileStream::kSeekStart); + + uint32_t frameSize = frameSizes[currentReadFrame] & (~3); + uint8_t frameFlag = frameFlags[currentReadFrame]; + + packetData.resize(frameSize); + file.ReadBytes(packetData.data(), frameSize); + + const uint8_t *packetDataPtr = packetData.data(); + + // skip pal data for later, after getting audio data + if (frameFlag & kSMKpal) + { + int size = (*packetDataPtr * 4); + packetDataPtr += size; + frameSize -= size; + } + + frameFlag >>= 1; + for (int i = 0; i < kMaxAudioTracks; i++) + { + if (frameFlag & 1) + { + uint32_t size = *(packetDataPtr++); + size |= *(packetDataPtr++) << 8; + size |= *(packetDataPtr++) << 16; + size |= *(packetDataPtr++) << 24; + frameSize -= size; + size -= 4; + + if (audioTracks[i].flags & SMK_AUD_PRESENT) + { + SmackerPacket pkt; + pkt.size = size; + pkt.data = std::make_unique(size); + memcpy(pkt.data.get(), packetDataPtr, size); + audioTracks[i].packetData.emplace_back(std::move(pkt)); + } + packetDataPtr += size; + } + frameFlag >>= 1; + } + + SmackerPacket pkt; + frameFlag = frameFlags[currentReadFrame]; + if (frameSize != 0 || (frameFlag & kSMKpal)) + { + int palsize = (frameFlag & kSMKpal) ? packetData[0] * 4 : 0; + int totalSize = frameSize + palsize; + pkt.size = totalSize; + pkt.data = std::make_unique(totalSize); + memcpy(pkt.data.get(), packetData.data(), palsize); + memcpy(pkt.data.get()+palsize, packetDataPtr, frameSize); + } + framePacketData.emplace_back(std::move(pkt)); + + ++currentReadFrame; + + nextPos = file.GetPosition(); + + return 0; +} + +int SmackerDecoder::DecodeFrame(const uint8_t *dataPtr, uint32_t frameSize) +{ + last_reset(mmap_tbl, mmap_last); + last_reset(mclr_tbl, mclr_last); + last_reset(full_tbl, full_last); + last_reset(type_tbl, type_last); + + int blocks, blk, bw, bh; + int i; + int stride; + + uint8_t *out = picture; // set to output image + + blk = 0; + bw = frameWidth >> 2; + bh = frameHeight >> 2; + blocks = bw * bh; + + stride = frameWidth; + + SmackerCommon::BitReader bits(dataPtr, frameSize); + dataPtr += frameSize; + + while (blk < blocks) + { + int type, run, mode; + uint16_t pix; + + type = GetCode(bits, type_tbl, type_last); + run = block_runs[(type >> 2) & 0x3F]; + switch (type & 3) + { + case SMK_BLK_MONO: + while (run-- && blk < blocks) + { + int clr, map; + int hi, lo; + clr = GetCode(bits, mclr_tbl, mclr_last); + map = GetCode(bits, mmap_tbl, mmap_last); + + out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; + + hi = clr >> 8; + lo = clr & 0xFF; + for (i = 0; i < 4; i++) + { + if (map & 1) out[0] = hi; else out[0] = lo; + if (map & 2) out[1] = hi; else out[1] = lo; + if (map & 4) out[2] = hi; else out[2] = lo; + if (map & 8) out[3] = hi; else out[3] = lo; + map >>= 4; + out += stride; + } + blk++; + } + break; + case SMK_BLK_FULL: + mode = 0; + if (isVer4) // In case of Smacker v4 we have three modes + { + if (bits.GetBit()) mode = 1; + else if (bits.GetBit()) mode = 2; + } + + while (run-- && blk < blocks) + { + out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; + switch (mode) + { + case 0: + for (i = 0; i < 4; i++) + { + pix = GetCode(bits, full_tbl, full_last); +// FIX AV_WL16(out+2, pix); + out[2] = pix & 0xff; + out[3] = pix >> 8; + + pix = GetCode(bits, full_tbl, full_last); +// FIX AV_WL16(out, pix); + out[0] = pix & 0xff; + out[1] = pix >> 8; + out += stride; + } + break; + case 1: + pix = GetCode(bits, full_tbl, full_last); + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + pix = GetCode(bits, full_tbl, full_last); + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + break; + case 2: + for (i = 0; i < 2; i++) + { + uint16_t pix1, pix2; + pix2 = GetCode(bits, full_tbl, full_last); + pix1 = GetCode(bits, full_tbl, full_last); + +// FIX AV_WL16(out, pix1); +// FIX AV_WL16(out+2, pix2); + out[0] = pix1 & 0xff; + out[1] = pix1 >> 8; + out[2] = pix2 & 0xff; + out[3] = pix2 >> 8; + + out += stride; + +// FIX AV_WL16(out, pix1); +// FIX AV_WL16(out+2, pix2); + out[0] = pix1 & 0xff; + out[1] = pix1 >> 8; + out[2] = pix2 & 0xff; + out[3] = pix2 >> 8; + + out += stride; + } + break; + } + blk++; + } + break; + case SMK_BLK_SKIP: + while (run-- && blk < blocks) + blk++; + break; + case SMK_BLK_FILL: + mode = type >> 8; + while (run-- && blk < blocks) + { + uint32_t col; + out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; + col = mode * 0x01010101; + for (i = 0; i < 4; i++) { + *((uint32_t*)out) = col; + out += stride; + } + blk++; + } + break; + } + } + + return 0; +} + +/** + * Decode Smacker audio data + */ +int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAudioTrack &track) +{ + SmackerCommon::VLCtable vlc[4]; + int val; + int i, res; + int unpackedSize; + int sampleBits, stereo; + int pred[2] = {0, 0}; + + int16_t *samples = reinterpret_cast(track.buffer); + + SmackerCommon::BitReader bits(dataPtr, size); + + unpackedSize = bits.GetBits(32); + if (unpackedSize <= 4) { + Printf("SmackerDecoder::DecodeAudio() - Packet is too small\n"); + return -1; + } + + if (!bits.GetBit()) { + // no sound data + return 1; + } + + stereo = bits.GetBit(); + sampleBits = bits.GetBit(); + + if (stereo ^ (track.nChannels != 1)) { + Printf("SmackerDecoder::DecodeAudio() - Channels mismatch\n"); + return -1; + } + + HuffContext h[4]; + + // Initialize + for (i = 0; i < (1 << (sampleBits + stereo)); i++) { + h[i].length = 256; + h[i].maxlength = 0; + h[i].current = 0; + h[i].bits.resize(256); + h[i].lengths.resize(256); + h[i].values.resize(256); + + bits.SkipBits(1); + DecodeTree(bits, &h[i], 0, 0); + bits.SkipBits(1); + + if (h[i].current > 1) { + VLC_InitTable(vlc[i], h[i].maxlength, h[i].current, &h[i].lengths[0], &h[i].bits[0]); + } + } + if (sampleBits) { //decode 16-bit data + for (i = stereo; i >= 0; i--) + pred[i] = av_bswap16(bits.GetBits(16)); + for (i = 0; i <= stereo; i++) + *samples++ = pred[i]; + for (; i < unpackedSize / 2; i++) { + if (i & stereo) { + if (VLC_GetSize(vlc[2])) + res = VLC_GetCodeBits(bits, vlc[2]); + else + res = 0; + val = h[2].values[res]; + if (VLC_GetSize(vlc[3])) + res = VLC_GetCodeBits(bits, vlc[3]); + else + res = 0; + val |= h[3].values[res] << 8; + pred[1] += (int16_t)val; + *samples++ = pred[1]; + } else { + if (VLC_GetSize(vlc[0])) + res = VLC_GetCodeBits(bits, vlc[0]); + else + res = 0; + val = h[0].values[res]; + if (VLC_GetSize(vlc[1])) + res = VLC_GetCodeBits(bits, vlc[1]); + else + res = 0; + val |= h[1].values[res] << 8; + pred[0] += val; + *samples++ = pred[0]; + } + } + } + else { //8-bit data + for (i = stereo; i >= 0; i--) + pred[i] = bits.GetBits(8); + for (i = 0; i <= stereo; i++) + *samples++ = (pred[i]-128) << 8; + for (; i < unpackedSize; i++) { + if (i & stereo){ + if (VLC_GetSize(vlc[1])) + res = VLC_GetCodeBits(bits, vlc[1]); + else + res = 0; + pred[1] += (int8_t)h[1].values[res]; + *samples++ = (pred[1]-128) << 8; + } else { + if (VLC_GetSize(vlc[0])) + res = VLC_GetCodeBits(bits, vlc[0]); + else + res = 0; + pred[0] += (int8_t)h[0].values[res]; + *samples++ = (pred[0]-128) << 8; + } + } + unpackedSize *= 2; + } + + track.bytesReadThisFrame = unpackedSize; + + return 0; +} + +void SmackerDecoder::GetPalette(uint8_t *palette) +{ + memcpy(palette, this->palette, 768); +} + +void SmackerDecoder::GetFrame(uint8_t *frame) +{ + memcpy(frame, this->picture, frameWidth * frameHeight); +} + +void SmackerDecoder::GetFrameSize(uint32_t &width, uint32_t &height) +{ + width = this->frameWidth; + height = this->frameHeight; +} + +uint32_t SmackerDecoder::GetNumFrames() +{ + return nFrames; +} + +uint32_t SmackerDecoder::GetCurrentFrameNum() +{ + return currentFrame; +} + +float SmackerDecoder::GetFrameRate() +{ + return (float)fps; +} + +void SmackerDecoder::GotoFrame(uint32_t frameNum) +{ + if (frameNum > nFrames) { + Printf("SmackerDecoder::GotoFrame() - Invalid frame number\n"); + return; + } + +// file.Seek(firstFrameFilePos, SmackerCommon::FileStream::kSeekStart); + + currentReadFrame = 0; + currentFrame = 0; + nextPos = firstFrameFilePos; + + framePacketData.clear(); + for (unsigned j = 0; j < kMaxAudioTracks; j++) + audioTracks[j].packetData.clear(); + + for (unsigned i = 0; i < frameNum; i++) + { + GetNextFrame(); + for (unsigned j = 0; j < kMaxAudioTracks; j++) + audioTracks[j].packetData.clear(); + } + + GetNextFrame(); +} + +uint32_t SmackerDecoder::GetNumAudioTracks() +{ + for(uint32_t i = 0;i < kMaxAudioTracks;++i) + { + if (!(audioTracks[i].flags & SMK_AUD_PRESENT)) + return i; + } + return kMaxAudioTracks; +} + +SmackerAudioInfo SmackerDecoder::GetAudioTrackDetails(uint32_t trackIndex) +{ + SmackerAudioInfo info; + SmackerAudioTrack *track = &audioTracks[trackIndex]; + + info.sampleRate = track->sampleRate; + info.nChannels = track->nChannels; + + // audio buffer size in bytes + info.idealBufferSize = track->bufferSize; + + return info; +} + +uint32_t SmackerDecoder::GetAudioData(uint32_t trackIndex, int16_t *audioBuffer) +{ + if (!audioBuffer) { + return 0; + } + + SmackerAudioTrack *track = &audioTracks[trackIndex]; + + std::unique_lock flock(fileMutex); + if (!(track->flags & SMK_AUD_PRESENT)) + return 0; + + while (track->packetData.empty()) + { + if (ReadPacket() > 0) + return 0; + } + SmackerPacket pkt = std::move(track->packetData.front()); + track->packetData.pop_front(); + flock.unlock(); + + track->bytesReadThisFrame = 0; + + const uint8_t *packetDataPtr = pkt.data.get(); + uint32_t size = (uint32_t)pkt.size; + + DecodeAudio(packetDataPtr, size, *track); + + if (track->bytesReadThisFrame) { + memcpy(audioBuffer, track->buffer, std::min(track->bufferSize, track->bytesReadThisFrame)); + } + + return track->bytesReadThisFrame; +} + +void SmackerDecoder::DisableAudioTrack(uint32_t trackIndex) +{ + SmackerAudioTrack *track = &audioTracks[trackIndex]; + std::unique_lock flock(fileMutex); + track->flags &= ~SMK_AUD_PRESENT; + track->packetData.clear(); +} diff --git a/src/common/thirdparty/math/cmath.h b/src/common/thirdparty/math/cmath.h index 5c02c4e87..4da0afcb6 100644 --- a/src/common/thirdparty/math/cmath.h +++ b/src/common/thirdparty/math/cmath.h @@ -54,6 +54,16 @@ extern FFastTrig fasttrig; #define RAD2BAM(f) ((unsigned)xs_CRoundToInt((f) * (0x80000000/3.14159265358979323846))) +inline double fastcosbam(unsigned int v) +{ + return fasttrig.cos(v); +} + +inline double fastsinbam(unsigned int v) +{ + return fasttrig.sin(v); +} + inline double fastcosdeg(double v) { return fasttrig.cos(DEG2BAM(v)); @@ -129,6 +139,8 @@ inline double cosdeg(double v) #else #define g_sindeg fastsindeg #define g_cosdeg fastcosdeg +#define g_sinbam fastsinbam +#define g_cosbam fastcosbam #define g_sin fastsin #define g_cos fastcos #endif diff --git a/src/common/thirdparty/rapidjson/document.h b/src/common/thirdparty/rapidjson/document.h index 19f5a6a5f..9cab4e83d 100644 --- a/src/common/thirdparty/rapidjson/document.h +++ b/src/common/thirdparty/rapidjson/document.h @@ -29,6 +29,7 @@ RAPIDJSON_DIAG_PUSH #ifdef _MSC_VER RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +RAPIDJSON_DIAG_OFF(4996) // deprecation of std::iterator #endif #ifdef __clang__ @@ -1936,7 +1937,7 @@ private: if (count) { GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); SetElementsPointer(e); - std::memcpy(e, values, count * sizeof(GenericValue)); + std::memcpy((void*)e, (void*)values, count * sizeof(GenericValue)); } else SetElementsPointer(0); @@ -1949,7 +1950,7 @@ private: if (count) { Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); SetMembersPointer(m); - std::memcpy(m, members, count * sizeof(Member)); + std::memcpy((void*)m, (void*)members, count * sizeof(Member)); } else SetMembersPointer(0); diff --git a/src/common/thirdparty/rapidjson/rapidjson.h b/src/common/thirdparty/rapidjson/rapidjson.h index 053b2ce43..d5b7630b5 100644 --- a/src/common/thirdparty/rapidjson/rapidjson.h +++ b/src/common/thirdparty/rapidjson/rapidjson.h @@ -238,6 +238,8 @@ # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(_MSC_VER) && defined(_M_ARM) # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && defined(_M_ARM64) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else diff --git a/src/common/thirdparty/richpresence.cpp b/src/common/thirdparty/richpresence.cpp new file mode 100644 index 000000000..7a081adac --- /dev/null +++ b/src/common/thirdparty/richpresence.cpp @@ -0,0 +1,128 @@ +/* +** richpresence.cpp +** +** handles rich presence for Discord. does nothing but transmit the appid, +** game, and current level. +** +**--------------------------------------------------------------------------- +** Copyright 2022 Rachael Alexanderson +** Copyright 2017 Discord +** 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 "common/engine/printf.h" +#include "discord_rpc.h" +#include "version.h" + +static int64_t StartTime = 0; +static bool didInit = false; + +static void handleDiscordReady(const DiscordUser* connectedUser) +{ + Printf("\nDiscord: connected to user %s#%s - %s\n", + connectedUser->username, + connectedUser->discriminator, + connectedUser->userId); +} + +static void handleDiscordDisconnected(int errcode, const char* message) +{ + Printf("\nDiscord: disconnected (%d: %s)\n", errcode, message); +} + +static void handleDiscordError(int errcode, const char* message) +{ + Printf("\nDiscord: error (%d: %s)\n", errcode, message); +} + +static void handleDiscordSpectate(const char* secret) +{ + Printf("\nDiscord: spectate (%s)\n", secret); +} + +static void handleDiscordJoin(const char* secret) +{ + Printf("\nDiscord: join (%s)\n", secret); +} + +static void handleDiscordJoinRequest(const DiscordUser* request) +{ + // we can't join in-game + int response = DISCORD_REPLY_NO; + Discord_Respond(request->userId, response); + Printf("\nDiscord: join request from %s#%s - %s\n", + request->username, + request->discriminator, + request->userId); +} + +void I_UpdateDiscordPresence(bool SendPresence, const char* curstatus, const char* appid, const char* steamappid) +{ + const char* curappid = DEFAULT_DISCORD_APP_ID; + + if (appid && appid[0] != '\0') + curappid = appid; + + if (!didInit && !SendPresence) + return; // we haven't initted, there's nothing to do here, just exit + + if (!didInit) + { + didInit = true; + DiscordEventHandlers handlers; + memset(&handlers, 0, sizeof(handlers)); + handlers.ready = handleDiscordReady; + handlers.disconnected = handleDiscordDisconnected; + handlers.errored = handleDiscordError; + handlers.joinGame = handleDiscordJoin; + handlers.spectateGame = handleDiscordSpectate; + handlers.joinRequest = handleDiscordJoinRequest; + Discord_Initialize(curappid, &handlers, 1, steamappid); + } + + if (SendPresence) + { + DiscordRichPresence discordPresence; + memset(&discordPresence, 0, sizeof(discordPresence)); + discordPresence.state = "Playing"; + if (!StartTime) + StartTime = time(0); + discordPresence.startTimestamp = StartTime; + discordPresence.details = curstatus; + discordPresence.largeImageKey = "game-image"; + discordPresence.instance = 0; + Discord_UpdatePresence(&discordPresence); + } + else + { + Discord_ClearPresence(); + } +} + diff --git a/src/common/thirdparty/strnatcmp.c b/src/common/thirdparty/strnatcmp.c index 58fa5571a..8caadfbd7 100644 --- a/src/common/thirdparty/strnatcmp.c +++ b/src/common/thirdparty/strnatcmp.c @@ -85,8 +85,6 @@ compare_right(nat_char const *a, nat_char const *b) } else if (!*a && !*b) return bias; } - - return 0; } @@ -107,8 +105,6 @@ compare_left(nat_char const *a, nat_char const *b) else if (*a > *b) return +1; } - - return 0; } diff --git a/src/common/utility/TRS.h b/src/common/utility/TRS.h new file mode 100644 index 000000000..c39a870ad --- /dev/null +++ b/src/common/utility/TRS.h @@ -0,0 +1,56 @@ +/* +** TRS +** +**--------------------------------------------------------------------------- +** Copyright 2022 Andrew Clarke +** 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. +**--------------------------------------------------------------------------- +** +*/ + +#pragma once +#include "vectors.h" + +class TRS +{ +public: + FVector3 translation; + FVector4 rotation; + FVector3 scaling; + + TRS() + { + translation = FVector3(0,0,0); + rotation = FVector4(0,0,0,1); + scaling = FVector3(0,0,0); + } + + bool Equals(TRS& compare) + { + return compare.translation == this->translation && compare.rotation == this->rotation && compare.scaling == this->scaling; + } +}; + diff --git a/src/common/utility/basics.h b/src/common/utility/basics.h index 703a84c30..6655ede2c 100644 --- a/src/common/utility/basics.h +++ b/src/common/utility/basics.h @@ -3,6 +3,7 @@ #include #include #include +#include "xs_Float.h" #define MAXWIDTH 12000 #define MAXHEIGHT 5000 @@ -38,6 +39,13 @@ 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))) @@ -84,16 +92,27 @@ inline double DEG2RAD(double deg) return deg * (M_PI / 180.0); } -inline float RAD2DEG(float deg) +inline float RAD2DEG(float rad) { - return deg * float(180. / M_PI); + return rad * float(180. / M_PI); } -inline double RAD2DEG(double deg) +inline double RAD2DEG(double rad) { - return deg * (180. / M_PI); + 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 { @@ -105,3 +124,4 @@ enum EStateUseFlags using std::min; using std::max; +using std::clamp; diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index 9551cbf42..02ab18959 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -248,7 +248,7 @@ bool GetFileInfo(const char* pathname, size_t *size, time_t *time) bool res = _wstat64(wstr.c_str(), &info) == 0; #endif if (!res || (info.st_mode & S_IFDIR)) return false; - if (size) *size = info.st_size; + if (size) *size = (size_t)info.st_size; if (time) *time = info.st_mtime; return res; } @@ -359,7 +359,7 @@ FString StripExtension(const char* path) src = path + strlen(path) - 1; // - // back up until a . and abort on a \ + // back up until a . and abort on a '/' // while (src != path && !IsSeperator(*(src - 1))) { @@ -557,7 +557,7 @@ void CreatePath(const char *fn) void CreatePath(const char *fn) { char *copy, *p; - + if (fn[0] == '/' && fn[1] == '\0') { return; @@ -866,6 +866,10 @@ FString ExpandEnvVars(const char *searchpathstring) FString NicePath(const char *path) { #ifdef _WIN32 + if (*path == '\0') + { + return FString("."); + } return ExpandEnvVars(path); #else if (path == NULL || *path == '\0') @@ -982,7 +986,7 @@ bool IsAbsPath(const char *name) if (IsSeperator(name[0])) return true; #ifdef _WIN32 /* [A-Za-z]: (for Windows) */ - if (isalpha(name[0]) && name[1] == ':') return true; + if (isalpha((uint8_t)name[0]) && name[1] == ':') return true; #endif /* _WIN32 */ return 0; } @@ -1060,7 +1064,7 @@ void md5Update(FileReader& file, MD5Context& md5, unsigned len) while (len > 0) { - t = std::min(len, sizeof(readbuf)); + t = min(len, sizeof(readbuf)); len -= t; t = (long)file.Read(readbuf, t); md5.Update(readbuf, t); diff --git a/src/common/utility/cmdlib.h b/src/common/utility/cmdlib.h index b998cf99d..392d0f46d 100644 --- a/src/common/utility/cmdlib.h +++ b/src/common/utility/cmdlib.h @@ -80,11 +80,16 @@ bool ScanDirectory(TArray &list, const char *dirpath); bool IsAbsPath(const char*); FString M_ZLibError(int zerrnum); -inline int32_t Scale(int32_t a, int32_t b, int32_t c) +inline constexpr int32_t Scale(int32_t a, int32_t b, int32_t c) { return (int32_t)(((int64_t)a * b) / c); } +inline constexpr double Scale(double a, double b, double c) +{ + return (a * b) / c; +} + class FileReader; struct MD5Context; @@ -100,7 +105,7 @@ inline void fillshort(void* buff, size_t count, uint16_t clear) } } -template inline constexpr T Sgn(const T& val) { return (val > 0) - (val < 0); } +template inline constexpr int Sgn(const T& val) { return (val > 0) - (val < 0); } inline int sizeToBits(int w) diff --git a/src/common/utility/colormatcher.h b/src/common/utility/colormatcher.h index 6ec20879a..277505e81 100644 --- a/src/common/utility/colormatcher.h +++ b/src/common/utility/colormatcher.h @@ -58,7 +58,7 @@ public: return (uint8_t)BestColor ((uint32_t *)Pal, r, g, b, startindex, 255, indexmap); } - + uint8_t Pick (PalEntry pe) { return Pick(pe.r, pe.g, pe.b); diff --git a/src/common/utility/engineerrors.cpp b/src/common/utility/engineerrors.cpp index ccc459f72..4d0125819 100644 --- a/src/common/utility/engineerrors.cpp +++ b/src/common/utility/engineerrors.cpp @@ -36,6 +36,7 @@ bool gameisdead; #ifdef _WIN32 +#include #include #include "zstring.h" void I_DebugPrint(const char *cp) @@ -46,10 +47,31 @@ void I_DebugPrint(const char *cp) OutputDebugStringW(wstr.c_str()); } } + +void I_DebugPrintf(const char *fmt,...) +{ + if (IsDebuggerPresent()) + { + va_list args; + va_start(args, fmt); + + FString s; + s.VFormat(fmt, args); + + va_end(args); + + auto wstr = WideString(s); + OutputDebugStringW(wstr.c_str()); + } +} #else void I_DebugPrint(const char *cp) { -} +} + +void I_DebugPrintf(const char *fmt,...) +{ +} #endif #include "engineerrors.h" @@ -63,7 +85,7 @@ void I_DebugPrint(const char *cp) // //========================================================================== -void I_Error(const char *error, ...) +[[noreturn]] void I_Error(const char *error, ...) { va_list argptr; char errortext[MAX_ERRORTEXT]; @@ -85,7 +107,7 @@ void I_Error(const char *error, ...) //========================================================================== extern FILE *Logfile; -void I_FatalError(const char *error, ...) +[[noreturn]] void I_FatalError(const char *error, ...) { static bool alreadyThrown = false; gameisdead = true; diff --git a/src/common/utility/engineerrors.h b/src/common/utility/engineerrors.h index 36a755ade..18fe849bc 100644 --- a/src/common/utility/engineerrors.h +++ b/src/common/utility/engineerrors.h @@ -110,7 +110,7 @@ public: }; void I_ShowFatalError(const char *message); -void I_Error (const char *error, ...) GCCPRINTF(1,2); -void I_FatalError (const char *error, ...) GCCPRINTF(1,2); +[[noreturn]] void I_Error (const char *error, ...) GCCPRINTF(1,2); +[[noreturn]] void I_FatalError (const char *error, ...) GCCPRINTF(1,2); #endif //__ERRORS_H__ diff --git a/src/common/utility/filereadermusicinterface.h b/src/common/utility/filereadermusicinterface.h index 70fc3b107..f261f9dd0 100644 --- a/src/common/utility/filereadermusicinterface.h +++ b/src/common/utility/filereadermusicinterface.h @@ -19,4 +19,5 @@ inline ZMusicCustomReader *GetMusicReader(FileReader& fr) delete zr; }; return zcr; -} \ No newline at end of file +} + diff --git a/src/common/utility/files.cpp b/src/common/utility/files.cpp index e93262214..6f915a2ce 100644 --- a/src/common/utility/files.cpp +++ b/src/common/utility/files.cpp @@ -34,7 +34,7 @@ */ #include "files.h" -#include "templates.h" // just for 'clamp' + // just for 'clamp' #include "zstring.h" diff --git a/src/common/utility/files_decompress.cpp b/src/common/utility/files_decompress.cpp index c79d762e6..cd2e36ed7 100644 --- a/src/common/utility/files_decompress.cpp +++ b/src/common/utility/files_decompress.cpp @@ -42,7 +42,7 @@ #include #include "files.h" -#include "templates.h" + #include "zstring.h" #include "cmdlib.h" @@ -107,7 +107,7 @@ class DecompressorZ : public DecompressorBase bool SawEOF; z_stream Stream; uint8_t InBuff[BUFF_SIZE]; - + public: DecompressorZ (FileReader *file, bool zip, const std::function& cb) : SawEOF(false) @@ -198,7 +198,7 @@ class DecompressorBZ2 : public DecompressorBase bool SawEOF; bz_stream Stream; uint8_t InBuff[BUFF_SIZE]; - + public: DecompressorBZ2 (FileReader *file, const std::function& cb) : SawEOF(false) @@ -509,7 +509,7 @@ class DecompressorLZSS : public DecompressorBase // Partial overlap: Copy in 2 or 3 chunks. do { - unsigned int copy = std::min(len, pos+1); + unsigned int copy = min(len, pos+1); memcpy(Stream.InternalBuffer, copyStart, copy); Stream.InternalBuffer += copy; Stream.InternalOut += copy; @@ -575,7 +575,7 @@ public: break; } - unsigned int copy = std::min(Stream.InternalOut, AvailOut); + unsigned int copy = min(Stream.InternalOut, AvailOut); if(copy > 0) { memcpy(Out, Stream.WindowData, copy); @@ -627,7 +627,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b case METHOD_LZSS: dec = new DecompressorLZSS(p, cb); break; - + // todo: METHOD_IMPLODE, METHOD_SHRINK default: return false; diff --git a/src/common/utility/findfile.cpp b/src/common/utility/findfile.cpp index 6006a34a1..0da6a97ff 100644 --- a/src/common/utility/findfile.cpp +++ b/src/common/utility/findfile.cpp @@ -37,6 +37,7 @@ #include "cmdlib.h" #include "printf.h" #include "configfile.h" +#include "i_system.h" #ifndef _WIN32 @@ -128,7 +129,7 @@ int I_FindAttr(findstate_t *const fileinfo) } #else - + #include #include @@ -369,9 +370,8 @@ void D_AddConfigFiles(TArray& wadfiles, const char* section, const char void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config) { - char curdir[ZPATH_MAX]; - - if (getcwd(curdir, ZPATH_MAX)) + FString curdir = I_GetCWD(); + if (curdir.IsNotEmpty()) { char skindir[ZPATH_MAX]; findstate_t findstate; @@ -387,7 +387,7 @@ void D_AddDirectory(TArray& wadfiles, const char* dir, const char *file skindir[--stuffstart] = 0; } - if (!chdir(skindir)) + if (I_ChDir(skindir)) { skindir[stuffstart++] = '/'; if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) @@ -403,7 +403,7 @@ void D_AddDirectory(TArray& wadfiles, const char* dir, const char *file I_FindClose(handle); } } - chdir(curdir); + I_ChDir(curdir); } } @@ -417,27 +417,27 @@ void D_AddDirectory(TArray& wadfiles, const char* dir, const char *file // //========================================================================== +static FString BFSwad; // outside the function to evade C++'s insane rules for constructing static variables inside functions. + const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config) { - static char wad[ZPATH_MAX]; - if (file == nullptr || *file == '\0') { return nullptr; } if (lookfirstinprogdir) { - mysnprintf(wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); - if (DirEntryExists(wad)) + BFSwad.Format("%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); + if (DirEntryExists(BFSwad)) { - return wad; + return BFSwad.GetChars(); } } if (DirEntryExists(file)) { - mysnprintf(wad, countof(wad), "%s", file); - return wad; + BFSwad.Format("%s", file); + return BFSwad.GetChars(); } if (config != nullptr && config->SetSection("FileSearch.Directories")) @@ -454,10 +454,10 @@ const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinpr dir = NicePath(value); if (dir.IsNotEmpty()) { - mysnprintf(wad, countof(wad), "%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); - if (DirEntryExists(wad)) + BFSwad.Format("%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); + if (DirEntryExists(BFSwad)) { - return wad; + return BFSwad.GetChars(); } } } diff --git a/src/common/utility/findfile.h b/src/common/utility/findfile.h index 895bbde69..44bee1a35 100644 --- a/src/common/utility/findfile.h +++ b/src/common/utility/findfile.h @@ -43,7 +43,7 @@ inline const char *I_FindName(findstate_t *fileinfo) #else - + // Mirror WIN32_FIND_DATAW in struct findstate_t diff --git a/src/common/utility/geometry.h b/src/common/utility/geometry.h new file mode 100644 index 000000000..cbe0fc72d --- /dev/null +++ b/src/common/utility/geometry.h @@ -0,0 +1,234 @@ +#pragma once + +/* +** geometry.h +** basic geometry math routines +** +**--------------------------------------------------------------------------- +** Copyright 2005-2022 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 "vectors.h" + +inline DVector2 rotatepoint(const DVector2& pivot, const DVector2& point, DAngle angle) +{ + return (point - pivot).Rotated(angle) + pivot; +} + +//========================================================================== +// +// +// +//========================================================================== + +inline double PointOnLineSide(double x, double y, double linex, double liney, double deltax, double deltay) +{ + return (x - linex) * deltay - (y - liney) * deltax; +} + +//========================================================================== +// +// +// +//========================================================================== + +inline double SquareDist(double lx1, double ly1, double lx2, double ly2) +{ + double dx = lx2 - lx1; + double dy = ly2 - ly1; + return dx * dx + dy * dy; +} + +// This is for cases where only the factor is needed, and pre-validation was performed. +inline double NearestPointOnLineFast(double px, double py, double lx1, double ly1, double lx2, double ly2) +{ + double wall_length = SquareDist(lx1, ly1, lx2, ly2); + assert(wall_length > 0); + return ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; +} + + +inline DVector2 NearestPointOnLine(double px, double py, double lx1, double ly1, double lx2, double ly2, bool clamp = true) +{ + double wall_length = SquareDist(lx1, ly1, lx2, ly2); + + if (wall_length == 0) + { + return { lx1, ly1 }; + } + + double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; + if (clamp) + { + if (t <= 0) return { lx1, ly1 }; + if (t >= 1) return { lx2, ly2 }; + } + double xx = lx1 + t * (lx2 - lx1); + double yy = ly1 + t * (ly2 - ly1); + return { xx, yy }; +} + +//========================================================================== +// +// +// +//========================================================================== + +inline double SquareDistToLine(double px, double py, double lx1, double ly1, double lx2, double ly2) +{ + double wall_length = SquareDist(lx1, ly1, lx2, ly2); + + if (wall_length == 0) return SquareDist(px, py, lx1, ly1); + + double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; + t = clamp(t, 0., 1.); + double xx = lx1 + t * (lx2 - lx1); + double yy = ly1 + t * (ly2 - ly1); + return SquareDist(px, py, xx, yy); +} + +//========================================================================== +// +// taken from GZDoom with the divline_t parameters removed +// +//========================================================================== + +inline double InterceptVector(double v2x, double v2y, double v2dx, double v2dy, double v1x, double v1y, double v1dx, double v1dy) +{ + double den = v1dy * v2dx - v1dx * v2dy; + + if (den == 0) + return 0; // parallel + + double num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; + return num / den; +} + +//========================================================================== +// +// Essentially two InterceptVector calls. We can reduce the calculations +// because the denominators for both calculations only differ by their sign. +// +//========================================================================== + +inline double InterceptLineSegments(double v2x, double v2y, double v2dx, double v2dy, double v1x, double v1y, double v1dx, double v1dy, double* pfactor1 = nullptr, bool forcansee = false) +{ + double den = v1dy * v2dx - v1dx * v2dy; + + if (den == 0) + return -2 * (double)FLT_MAX; // parallel (return a magic value different from everything else, just in case it needs to be handled) + + if (forcansee && den < 0) // cansee does this added check here, aside from that its logic is virtually the same. + return -1; // hitting the backside + + // perform the division first for better parallelization. + den = 1 / den; + + double factor1 = ((v2x - v1x) * v2dy + (v1y - v2y) * v2dx) * -den; + 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. +} + +//========================================================================== +// +// calculates intersection between a plane and line in 3D +// +//========================================================================== + +inline double LinePlaneIntersect(const DVector3& start, const DVector3& trace, const DVector3& ppoint, const DVector3& pvec1, const DVector3& pvec2) +{ + auto normal = pvec1 ^ pvec2; // we do not need a unit vector here. + double dist = normal.dot(ppoint); + double dotStart = normal.dot(start); + double dotTrace = normal.dot(trace); + if (dotTrace == 0) return -FLT_MAX; + return (dist - dotStart) / dotTrace; // we are only interested in the factor +} + +//========================================================================== +// +// BoxOnLineSide +// +// Based on Doom's, but rewritten to be standalone +// +//========================================================================== + +inline int BoxOnLineSide(const DVector2& boxtl, const DVector2& boxbr, const DVector2& start, const DVector2& delta) +{ + int p1; + int p2; + + if (delta.X == 0) + { + p1 = boxbr.X < start.X; + p2 = boxtl.X < start.X; + if (delta.Y < 0) + { + p1 ^= 1; + p2 ^= 1; + } + } + else if (delta.Y == 0) + { + p1 = boxtl.Y > start.Y; + p2 = boxbr.Y > start.Y; + if (delta.X < 0) + { + p1 ^= 1; + p2 ^= 1; + } + } + else if (delta.X * delta.Y <= 0) + { + p1 = PointOnLineSide(boxtl.X, boxtl.Y, start.X, start.Y, delta.X, delta.Y) > 0; + p2 = PointOnLineSide(boxbr.X, boxbr.Y, start.X, start.Y, delta.X, delta.Y) > 0; + } + else + { + p1 = PointOnLineSide(boxbr.X, boxtl.Y, start.X, start.Y, delta.X, delta.Y) > 0; + p2 = PointOnLineSide(boxtl.X, boxbr.Y, start.X, start.Y, delta.X, delta.Y) > 0; + } + + return (p1 == p2) ? p1 : -1; +} + +//========================================================================== +// +// BoxInRange +// +//========================================================================== + +inline bool BoxInRange(const DVector2& boxtl, const DVector2& boxbr, const DVector2& start, const DVector2& end) +{ + return boxtl.X < max(start.X, end.X) && + boxbr.X > min(start.X, end.X) && + boxtl.Y < max(start.Y, end.Y) && + boxbr.Y > min(start.Y, end.Y); +} diff --git a/src/gitinfo.cpp b/src/common/utility/gitinfo.cpp similarity index 100% rename from src/gitinfo.cpp rename to src/common/utility/gitinfo.cpp diff --git a/src/common/utility/i_time.cpp b/src/common/utility/i_time.cpp index cc8f5f1de..d9117d8ea 100644 --- a/src/common/utility/i_time.cpp +++ b/src/common/utility/i_time.cpp @@ -35,6 +35,7 @@ #include #include +#include #include "i_time.h" //========================================================================== @@ -43,18 +44,31 @@ // //========================================================================== +static uint64_t StartupTimeNS; static uint64_t FirstFrameStartTime; static uint64_t CurrentFrameStartTime; static uint64_t FreezeTime; +static double lastinputtime; int GameTicRate = 35; // make sure it is not 0, even if the client doesn't set it. double TimeScale = 1.0; -static uint64_t GetClockTimeNS() +static uint64_t GetTimePoint() { using namespace std::chrono; - if (TimeScale == 1.0) return (uint64_t)(duration_cast(steady_clock::now().time_since_epoch()).count()); - else return (uint64_t)((duration_cast(steady_clock::now().time_since_epoch()).count()) * (uint64_t)(TimeScale * 1000)); + return (uint64_t)(duration_cast(steady_clock::now().time_since_epoch()).count()); +} + +void I_InitTime() +{ + StartupTimeNS = GetTimePoint(); +} + +static uint64_t GetClockTimeNS() +{ + auto tp = GetTimePoint() - StartupTimeNS; + if (TimeScale == 1.0) return tp; + else return uint64_t(tp / 1000 * TimeScale * 1000); } static uint64_t MSToNS(unsigned int ms) @@ -195,3 +209,22 @@ void I_ResetFrameTime() I_SetFrameTime(); FirstFrameStartTime += (CurrentFrameStartTime - ft); } + +double I_GetInputFrac(bool const synchronised) +{ + if (!synchronised) + { + const double now = I_msTimeF(); + const double result = (now - lastinputtime) * GameTicRate * (1. / 1000.); + lastinputtime = now; + return result; + } + + return 1; +} + +void I_ResetInputTime() +{ + // Reset lastinputtime to current time. + lastinputtime = I_msTimeF(); +} diff --git a/src/common/utility/i_time.h b/src/common/utility/i_time.h index 27ebdae2a..e5d3d5c8d 100644 --- a/src/common/utility/i_time.h +++ b/src/common/utility/i_time.h @@ -5,6 +5,8 @@ extern int GameTicRate; extern double TimeScale; +void I_InitTime(); + // Called by D_DoomLoop, sets the time for the current frame void I_SetFrameTime(); @@ -38,3 +40,14 @@ uint64_t I_nsTime(); // Reset the timer after a lengthy operation void I_ResetFrameTime(); + +// Return a decimal fraction to scale input operations at framerate +double I_GetInputFrac(bool const synchronised); + +// Reset the last input check to after a lengthy operation +void I_ResetInputTime(); + +// Pause a bit. +// [RH] Despite the name, it apparently never waited for the VBL, even in +// the original DOS version (if the Heretic/Hexen source is any indicator). +void I_WaitVBL(int count); diff --git a/src/common/utility/intrect.h b/src/common/utility/intrect.h index 3cda7613e..1de15df29 100644 --- a/src/common/utility/intrect.h +++ b/src/common/utility/intrect.h @@ -6,7 +6,6 @@ struct IntRect int left, top; int width, height; - void Offset(int xofs, int yofs) { left += xofs; @@ -26,6 +25,37 @@ struct IntRect height = y - top; } + int Left() const + { + return left; + } + + int Top() const + { + return top; + } + + + int Right() const + { + return left + width; + } + + int Bottom() const + { + return top + height; + } + + int Width() const + { + return width; + } + + int Height() const + { + return height; + } + }; diff --git a/src/common/utility/m_alloc.cpp b/src/common/utility/m_alloc.cpp index 5c2ea25b9..3b7e12f43 100644 --- a/src/common/utility/m_alloc.cpp +++ b/src/common/utility/m_alloc.cpp @@ -3,7 +3,7 @@ ** Wrappers for the malloc family of functions that count used bytes. ** **--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit +** Copyright 1998-2008 Marisa Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -45,7 +45,7 @@ #endif #include "engineerrors.h" -#include "dobject.h" +#include "dobjgc.h" #ifndef _MSC_VER #define _NORMAL_BLOCK 0 @@ -59,25 +59,22 @@ void *M_Malloc(size_t size) { void *block = malloc(size); - if (block == NULL) + if (block == nullptr) I_FatalError("Could not malloc %zu bytes", size); - GC::AllocBytes += _msize(block); + GC::ReportAlloc(_msize(block)); return block; } void *M_Realloc(void *memblock, size_t size) { - if (memblock != NULL) - { - GC::AllocBytes -= _msize(memblock); - } + size_t oldsize = memblock ? _msize(memblock) : 0; void *block = realloc(memblock, size); - if (block == NULL) + if (block == nullptr) { I_FatalError("Could not realloc %zu bytes", size); } - GC::AllocBytes += _msize(block); + GC::ReportRealloc(oldsize, _msize(block)); return block; } #else @@ -85,28 +82,25 @@ void *M_Malloc(size_t size) { void *block = malloc(size+sizeof(size_t)); - if (block == NULL) + if (block == nullptr) I_FatalError("Could not malloc %zu bytes", size); size_t *sizeStore = (size_t *) block; *sizeStore = size; block = sizeStore+1; - GC::AllocBytes += _msize(block); + GC::ReportAlloc(_msize(block)); return block; } void *M_Realloc(void *memblock, size_t size) { - if(memblock == NULL) + if (memblock == nullptr) return M_Malloc(size); - if (memblock != NULL) - { - GC::AllocBytes -= _msize(memblock); - } + size_t oldsize = _msize(memblock); void *block = realloc(((size_t*) memblock)-1, size+sizeof(size_t)); - if (block == NULL) + if (block == nullptr) { I_FatalError("Could not realloc %zu bytes", size); } @@ -115,7 +109,7 @@ void *M_Realloc(void *memblock, size_t size) *sizeStore = size; block = sizeStore+1; - GC::AllocBytes += _msize(block); + GC::ReportRealloc(oldsize, _msize(block)); return block; } #endif @@ -129,25 +123,22 @@ void *M_Malloc_Dbg(size_t size, const char *file, int lineno) { void *block = _malloc_dbg(size, _NORMAL_BLOCK, file, lineno); - if (block == NULL) + if (block == nullptr) I_FatalError("Could not malloc %zu bytes in %s, line %d", size, file, lineno); - GC::AllocBytes += _msize(block); + GC::ReportAlloc(_msize(block)); return block; } void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) { - if (memblock != NULL) - { - GC::AllocBytes -= _msize(memblock); - } + size_t oldsize = memblock ? _msize(memblock) : 0; void *block = _realloc_dbg(memblock, size, _NORMAL_BLOCK, file, lineno); - if (block == NULL) + if (block == nullptr) { I_FatalError("Could not realloc %zu bytes in %s, line %d", size, file, lineno); } - GC::AllocBytes += _msize(block); + GC::ReportRealloc(oldsize, _msize(block)); return block; } #else @@ -155,29 +146,26 @@ void *M_Malloc_Dbg(size_t size, const char *file, int lineno) { void *block = _malloc_dbg(size+sizeof(size_t), _NORMAL_BLOCK, file, lineno); - if (block == NULL) + if (block == nullptr) I_FatalError("Could not malloc %zu bytes in %s, line %d", size, file, lineno); size_t *sizeStore = (size_t *) block; *sizeStore = size; block = sizeStore+1; - GC::AllocBytes += _msize(block); + GC::ReportAlloc(_msize(block)); return block; } void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) { - if(memblock == NULL) + if (memblock == nullptr) return M_Malloc_Dbg(size, file, lineno); - if (memblock != NULL) - { - GC::AllocBytes -= _msize(memblock); - } + size_t oldsize = _msize(memblock); void *block = _realloc_dbg(((size_t*) memblock)-1, size+sizeof(size_t), _NORMAL_BLOCK, file, lineno); - if (block == NULL) + if (block == nullptr) { I_FatalError("Could not realloc %zu bytes in %s, line %d", size, file, lineno); } @@ -186,29 +174,22 @@ void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) *sizeStore = size; block = sizeStore+1; - GC::AllocBytes += _msize(block); + GC::ReportRealloc(oldsize, _msize(block)); return block; } #endif #endif +void M_Free (void *block) +{ + if (block != nullptr) + { + GC::ReportDealloc(_msize(block)); #if !defined(__solaris__) && !defined(__OpenBSD__) && !defined(__DragonFly__) -void M_Free (void *block) -{ - if (block != NULL) - { - GC::AllocBytes -= _msize(block); free(block); - } -} #else -void M_Free (void *block) -{ - if(block != NULL) - { - GC::AllocBytes -= _msize(block); free(((size_t*) block)-1); +#endif } } -#endif diff --git a/src/common/utility/m_fixed.h b/src/common/utility/m_fixed.h index 30209d635..09d297693 100644 --- a/src/common/utility/m_fixed.h +++ b/src/common/utility/m_fixed.h @@ -7,32 +7,44 @@ __forceinline constexpr int32_t MulScale(int32_t a, int32_t b, int32_t shift) { return (int32_t)(((int64_t)a * b) >> shift); } -__forceinline constexpr double MulScaleF(double a, double b, int32_t shift) { return (a * b) * (1. / (uint32_t(1) << shift)); } __forceinline constexpr int32_t DMulScale(int32_t a, int32_t b, int32_t c, int32_t d, int32_t shift) { return (int32_t)(((int64_t)a * b + (int64_t)c * d) >> shift); } -__forceinline constexpr int32_t TMulScale(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f, int32_t shift) { return (int32_t)(((int64_t)a * b + (int64_t)c * d + (int64_t)e * f) >> shift); } __forceinline constexpr int32_t DivScale(int32_t a, int32_t b, int shift) { return (int32_t)(((int64_t)a << shift) / b); } __forceinline constexpr int64_t DivScaleL(int64_t a, int64_t b, int shift) { return ((a << shift) / b); } #include "xs_Float.h" -inline fixed_t FloatToFixed(double f) +template +constexpr fixed_t FloatToFixed(double f) { - return xs_Fix<16>::ToFix(f); + return int(f * (1 << b)); } +constexpr fixed_t FloatToFixed(double f, int b) +{ + return int(f * (1 << b)); +} + +template inline constexpr fixed_t IntToFixed(int32_t f) { - return f << FRACBITS; + return f << b; } +template inline constexpr double FixedToFloat(fixed_t f) { - return f * (1/65536.); + return f * (1. / (1 << b)); } +inline constexpr double FixedToFloat(fixed_t f, int b) +{ + return f * (1. / (1 << b)); +} + +template inline constexpr int32_t FixedToInt(fixed_t f) { - return (f + FRACUNIT/2) >> FRACBITS; + return (f + (1 << (b-1))) >> b; } inline unsigned FloatToAngle(double f) @@ -40,20 +52,9 @@ inline unsigned FloatToAngle(double f) return xs_CRoundToInt((f)* (0x40000000 / 90.)); } -inline constexpr double AngleToFloat(unsigned f) -{ - return f * (90. / 0x40000000); -} - -inline constexpr double AngleToFloat(int f) -{ - return f * (90. / 0x40000000); -} - #define FLOAT2FIXED(f) FloatToFixed(f) #define FIXED2FLOAT(f) float(FixedToFloat(f)) #define FIXED2DBL(f) FixedToFloat(f) -#define ANGLE2DBL(f) AngleToFloat(f) #endif diff --git a/src/common/utility/matrix.cpp b/src/common/utility/matrix.cpp index 006a5fe5d..3d84d48e7 100644 --- a/src/common/utility/matrix.cpp +++ b/src/common/utility/matrix.cpp @@ -58,7 +58,7 @@ VSMatrix::loadIdentity() void VSMatrix::multMatrix(const FLOATTYPE *aMatrix) { - + FLOATTYPE res[16]; for (int i = 0; i < 4; ++i) @@ -98,6 +98,21 @@ VSMatrix::multMatrix(const float *aMatrix) } #endif +void VSMatrix::multQuaternion(const TVector4& q) +{ + FLOATTYPE m[16] = { FLOATTYPE(0.0) }; + m[0 * 4 + 0] = FLOATTYPE(1.0) - FLOATTYPE(2.0) * q.Y * q.Y - FLOATTYPE(2.0) * q.Z * q.Z; + m[1 * 4 + 0] = FLOATTYPE(2.0) * q.X * q.Y - FLOATTYPE(2.0) * q.W * q.Z; + m[2 * 4 + 0] = FLOATTYPE(2.0) * q.X * q.Z + FLOATTYPE(2.0) * q.W * q.Y; + m[0 * 4 + 1] = FLOATTYPE(2.0) * q.X * q.Y + FLOATTYPE(2.0) * q.W * q.Z; + m[1 * 4 + 1] = FLOATTYPE(1.0) - FLOATTYPE(2.0) * q.X * q.X - FLOATTYPE(2.0) * q.Z * q.Z; + m[2 * 4 + 1] = FLOATTYPE(2.0) * q.Y * q.Z - FLOATTYPE(2.0) * q.W * q.X; + m[0 * 4 + 2] = FLOATTYPE(2.0) * q.X * q.Z - FLOATTYPE(2.0) * q.W * q.Y; + m[1 * 4 + 2] = FLOATTYPE(2.0) * q.Y * q.Z + FLOATTYPE(2.0) * q.W * q.X; + m[2 * 4 + 2] = FLOATTYPE(1.0) - FLOATTYPE(2.0) * q.X * q.X - FLOATTYPE(2.0) * q.Y * q.Y; + m[3 * 4 + 3] = FLOATTYPE(1.0); + multMatrix(m); +} // gl LoadMatrix implementation @@ -129,6 +144,29 @@ VSMatrix::translate(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) mMatrix[14] = mMatrix[2] * x + mMatrix[6] * y + mMatrix[10] * z + mMatrix[14]; } +void VSMatrix::transpose() +{ + FLOATTYPE original[16]; + for (int cnt = 0; cnt < 16; cnt++) + original[cnt] = mMatrix[cnt]; + + mMatrix[0] = original[0]; + mMatrix[1] = original[4]; + mMatrix[2] = original[8]; + mMatrix[3] = original[12]; + mMatrix[4] = original[1]; + mMatrix[5] = original[5]; + mMatrix[6] = original[9]; + mMatrix[7] = original[13]; + mMatrix[8] = original[2]; + mMatrix[9] = original[6]; + mMatrix[10] = original[10]; + mMatrix[11] = original[14]; + mMatrix[12] = original[3]; + mMatrix[13] = original[7]; + mMatrix[14] = original[11]; + mMatrix[15] = original[15]; +} // gl Scale implementation void @@ -164,19 +202,19 @@ VSMatrix::rotate(FLOATTYPE angle, FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) mat[4] = v[0] * v[1] * (1 - co) - v[2] * si; mat[8] = v[0] * v[2] * (1 - co) + v[1] * si; mat[12]= 0.0f; - + mat[1] = v[0] * v[1] * (1 - co) + v[2] * si; // mat[5] = y2 + (x2 + z2) * co; mat[5] = co + y2 * (1 - co); mat[9] = v[1] * v[2] * (1 - co) - v[0] * si; mat[13]= 0.0f; - + mat[2] = v[0] * v[2] * (1 - co) - v[1] * si; mat[6] = v[1] * v[2] * (1 - co) + v[0] * si; // mat[10]= z2 + (x2 + y2) * co; mat[10]= co + z2 * (1 - co); mat[14]= 0.0f; - + mat[3] = 0.0f; mat[7] = 0.0f; mat[11]= 0.0f; @@ -323,9 +361,9 @@ VSMatrix::multMatrixPoint(const FLOATTYPE *point, FLOATTYPE *res) { res[i] = 0.0f; - + for (int j = 0; j < 4; j++) { - + res[i] += point[j] * mMatrix[j*4 + i]; } } @@ -444,7 +482,7 @@ VSMatrix::computeNormalMatrix(const FLOATTYPE *aMatrix) void VSMatrix::multMatrix(FLOATTYPE *resMat, const FLOATTYPE *aMatrix) { - + FLOATTYPE res[16]; for (int i = 0; i < 4; ++i) diff --git a/src/common/utility/matrix.h b/src/common/utility/matrix.h index 81d7be6f2..265981e1b 100644 --- a/src/common/utility/matrix.h +++ b/src/common/utility/matrix.h @@ -34,7 +34,7 @@ class VSMatrix { public: VSMatrix() = default; - + VSMatrix(int) { loadIdentity(); @@ -53,6 +53,7 @@ class VSMatrix { { multMatrix(aMatrix.mMatrix); } + void multQuaternion(const TVector4& q); void loadMatrix(const FLOATTYPE *aMatrix); #ifdef USE_DOUBLE void loadMatrix(const float *aMatrix); @@ -135,11 +136,11 @@ public: m[0][0] *=x; m[1][0] *=x; m[2][0] *=x; - + m[0][1] *=y; m[1][1] *=y; m[2][1] *=y; - + m[0][2] *=z; m[1][2] *=z; m[2][2] *=z; diff --git a/src/common/utility/memarena.cpp b/src/common/utility/memarena.cpp index 0e2be24ba..2a9467dc2 100644 --- a/src/common/utility/memarena.cpp +++ b/src/common/utility/memarena.cpp @@ -40,7 +40,14 @@ #include "basics.h" #include "memarena.h" #include "cmdlib.h" -#include "m_alloc.h" + +#if __has_include("m_alloc.h") + #include "m_alloc.h" +#else + #define M_Malloc malloc + #define M_Realloc realloc + #define M_Free free +#endif struct FMemArena::Block { @@ -117,6 +124,14 @@ void *FMemArena::Alloc(size_t size) return iAlloc((size + 15) & ~15); } +void* FMemArena::Calloc(size_t size) +{ + size = (size + 15) & ~15; + auto mem = iAlloc(size); + memset(mem, 0, size); + return mem; +} + //========================================================================== // // FMemArena :: FreeAll diff --git a/src/common/utility/memarena.h b/src/common/utility/memarena.h index 7f4903546..bb7f60b9a 100644 --- a/src/common/utility/memarena.h +++ b/src/common/utility/memarena.h @@ -44,6 +44,7 @@ public: ~FMemArena(); void *Alloc(size_t size); + void* Calloc(size_t size); void FreeAll(); void FreeAllBlocks(); FString DumpInfo(); diff --git a/src/common/utility/name.cpp b/src/common/utility/name.cpp index b1355a020..c9960ca93 100644 --- a/src/common/utility/name.cpp +++ b/src/common/utility/name.cpp @@ -75,6 +75,9 @@ static const char *PredefinedNames[] = #define xx(n) #n, #define xy(n, s) s, #include "namedef.h" +#if __has_include("namedef_custom.h") + #include "namedef_custom.h" +#endif #undef xx #undef xy }; diff --git a/src/common/utility/name.h b/src/common/utility/name.h index de8984073..fe2424f45 100644 --- a/src/common/utility/name.h +++ b/src/common/utility/name.h @@ -42,6 +42,9 @@ enum ENamedName #define xx(n) NAME_##n, #define xy(n, s) NAME_##n, #include "namedef.h" +#if __has_include("namedef_custom.h") + #include "namedef_custom.h" +#endif #undef xx #undef xy }; diff --git a/src/common/utility/palentry.h b/src/common/utility/palentry.h index 6d6d5a86a..4acbbfff8 100644 --- a/src/common/utility/palentry.h +++ b/src/common/utility/palentry.h @@ -12,6 +12,7 @@ struct PalEntry { PalEntry() = default; + PalEntry(const PalEntry&) = default; constexpr PalEntry (uint32_t argb) : d(argb) { } operator uint32_t () const { return d; } void SetRGB(PalEntry other) diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index 3b6e71e55..e7bc61f09 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -39,7 +39,7 @@ #include "files.h" #include "filesystem.h" #include "printf.h" -#include "templates.h" + #include "m_png.h" /****************************/ @@ -418,19 +418,34 @@ void MakeRemap(uint32_t* BaseColors, const uint32_t* colors, uint8_t* remap, con // color, so find a duplicate pair of palette entries, make one of them a // duplicate of color 0, and remap every graphic so that it uses that entry // instead of entry 0. -void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap) +void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap, const uint8_t* lastcolormap) { for (int i = 0; i < 256; i++) Remap[i] = i; PalEntry color0 = BaseColors[0]; int i; + // First try for an exact match of color 0. Only Hexen does not have one. - for (i = 1; i < 256; ++i) + if (!lastcolormap) { - if (BaseColors[i] == color0) + for (i = 1; i < 256; ++i) { - Remap[0] = i; - break; + if (BaseColors[i] == color0) + { + Remap[0] = i; + break; + } + } + } + else + { + for (i = 1; i < 256; ++i) + { + if ((BaseColors[i] == color0) && (lastcolormap[i] == lastcolormap[0])) + { + Remap[0] = i; + break; + } } } @@ -448,21 +463,44 @@ void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap) sortcopy[i] = (BaseColors[i] & 0xffffff) | (i << 24); } qsort(sortcopy, 256, 4, sortforremap); - for (i = 255; i > 0; --i) + if (!lastcolormap) { - if ((sortcopy[i] & 0xFFFFFF) == (sortcopy[i - 1] & 0xFFFFFF)) + for (i = 255; i > 0; --i) { - int new0 = sortcopy[i].a; - int dup = sortcopy[i - 1].a; - if (new0 > dup) + if ((sortcopy[i] & 0xFFFFFF) == (sortcopy[i - 1] & 0xFFFFFF)) { - // Make the lower-numbered entry a copy of color 0. (Just because.) - std::swap(new0, dup); + int new0 = sortcopy[i].a; + int dup = sortcopy[i - 1].a; + if (new0 > dup) + { + // Make the lower-numbered entry a copy of color 0. (Just because.) + std::swap(new0, dup); + } + Remap[0] = new0; + Remap[new0] = dup; + BaseColors[new0] = color0; + break; + } + } + } + else + { + for (i = 255; i > 0; --i) + { + if (((sortcopy[i] & 0xFFFFFF) == (sortcopy[i - 1] & 0xFFFFFF)) && (lastcolormap[sortcopy[i].a] == lastcolormap[sortcopy[i - 1].a])) + { + int new0 = sortcopy[i].a; + int dup = sortcopy[i - 1].a; + if (new0 > dup) + { + // Make the lower-numbered entry a copy of color 0. (Just because.) + std::swap(new0, dup); + } + Remap[0] = new0; + Remap[new0] = dup; + BaseColors[new0] = color0; + break; } - Remap[0] = new0; - Remap[new0] = dup; - BaseColors[new0] = color0; - break; } } } @@ -500,7 +538,7 @@ PalEntry averageColor(const uint32_t* data, int size, int maxout) g = g / size; b = b / size; - int maxv = MAX(MAX(r, g), b); + int maxv = max(max(r, g), b); if (maxv && maxout) { @@ -565,9 +603,9 @@ int V_GetColorFromString(const char* cstr, FScriptPosition* sc) { if (strlen(cstr) == 6) { - char* p; - int color = strtol(cstr, &p, 16); - if (*p == 0) + char* endp; + int color = strtol(cstr, &endp, 16); + if (*endp == 0) { // RRGGBB string c[0] = (color & 0xff0000) >> 16; @@ -802,9 +840,9 @@ void UpdateSpecialColormap(PalEntry* BaseColors, unsigned int index, float r1, f BaseColors[c].g * 143 + BaseColors[c].b * 37) / 256.0; - PalEntry pe = PalEntry(std::min(255, int(r1 + intensity * r2)), - std::min(255, int(g1 + intensity * g2)), - std::min(255, int(b1 + intensity * b2))); + PalEntry pe = PalEntry(min(255, int(r1 + intensity * r2)), + min(255, int(g1 + intensity * g2)), + min(255, int(b1 + intensity * b2))); cm->Colormap[c] = BestColor((uint32_t*)BaseColors, pe.r, pe.g, pe.b); } @@ -813,9 +851,9 @@ void UpdateSpecialColormap(PalEntry* BaseColors, unsigned int index, float r1, f // This table is used by the texture composition code for (int i = 0; i < 256; i++) { - cm->GrayscaleToColor[i] = PalEntry(std::min(255, int(r1 + i * r2)), - std::min(255, int(g1 + i * g2)), - std::min(255, int(b1 + i * b2))); + cm->GrayscaleToColor[i] = PalEntry(min(255, int(r1 + i * r2)), + min(255, int(g1 + i * g2)), + min(255, int(b1 + i * b2))); } } @@ -903,7 +941,6 @@ int ReadPalette(int lumpnum, uint8_t* buffer) fr.Seek(33, FileReader::SeekSet); fr.Read(&len, 4); fr.Read(&id, 4); - bool succeeded = false; while (id != MAKE_ID('I', 'D', 'A', 'T') && id != MAKE_ID('I', 'E', 'N', 'D')) { len = BigLong((unsigned int)len); @@ -911,7 +948,7 @@ int ReadPalette(int lumpnum, uint8_t* buffer) fr.Seek(len, FileReader::SeekCur); else { - int PaletteSize = MIN(len, 768); + int PaletteSize = min(len, 768); fr.Read(buffer, PaletteSize); return PaletteSize / 3; } @@ -930,7 +967,7 @@ int ReadPalette(int lumpnum, uint8_t* buffer) sc.MustGetString(); sc.MustGetNumber(); // version - ignore sc.MustGetNumber(); - int colors = MIN(256, sc.Number) * 3; + int colors = min(256, sc.Number) * 3; for (int i = 0; i < colors; i++) { sc.MustGetNumber(); @@ -944,7 +981,7 @@ int ReadPalette(int lumpnum, uint8_t* buffer) } else { - memcpy(buffer, lumpmem, MIN(768, lump.GetSize())); + memcpy(buffer, lumpmem, min(768, lump.GetSize())); return 256; } } diff --git a/src/common/utility/palutil.h b/src/common/utility/palutil.h index bbd8f9a2d..6faa7b5df 100644 --- a/src/common/utility/palutil.h +++ b/src/common/utility/palutil.h @@ -14,7 +14,7 @@ void DoBlending(const PalEntry* from, PalEntry* to, int count, int r, int g, int // Given an array of colors, fills in remap with values to remap the // passed array of colors to BaseColors. Used for loading palette downconversions of PNGs. void MakeRemap(uint32_t* BaseColors, const uint32_t* colors, uint8_t* remap, const uint8_t* useful, int numcolors); -void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap); +void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap, const uint8_t* cmapdata = nullptr); // Colorspace conversion RGB <-> HSV void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v); diff --git a/src/common/utility/parallel_for.h b/src/common/utility/parallel_for.h index d3e0e5de0..7f7ee5b6c 100644 --- a/src/common/utility/parallel_for.h +++ b/src/common/utility/parallel_for.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// 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, diff --git a/src/common/utility/quaternion.h b/src/common/utility/quaternion.h new file mode 100644 index 000000000..1437b56be --- /dev/null +++ b/src/common/utility/quaternion.h @@ -0,0 +1,352 @@ +#pragma once + +#include "vectors.h" + +template +class TQuaternion +{ +public: + typedef TVector2 Vector2; + typedef TVector3 Vector3; + + vec_t X, Y, Z, W; + + TQuaternion() = default; + + TQuaternion(vec_t x, vec_t y, vec_t z, vec_t w) + : X(x), Y(y), Z(z), W(w) + { + } + + TQuaternion(vec_t *o) + : X(o[0]), Y(o[1]), Z(o[2]), W(o[3]) + { + } + + TQuaternion(const TQuaternion &other) = default; + + TQuaternion(const Vector3 &v, vec_t s) + : X(v.X), Y(v.Y), Z(v.Z), W(s) + { + } + + TQuaternion(const vec_t v[4]) + : TQuaternion(v[0], v[1], v[2], v[3]) + { + } + + void Zero() + { + Z = Y = X = W = 0; + } + + bool isZero() const + { + return X == 0 && Y == 0 && Z == 0 && W == 0; + } + + TQuaternion &operator= (const TQuaternion &other) = default; + + // Access X and Y and Z as an array + vec_t &operator[] (int index) + { + return (&X)[index]; + } + + const vec_t &operator[] (int index) const + { + return (&X)[index]; + } + + // Test for equality + bool operator== (const TQuaternion &other) const + { + return X == other.X && Y == other.Y && Z == other.Z && W == other.W; + } + + // Test for inequality + bool operator!= (const TQuaternion &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 + { + return *reinterpret_cast(this); + } + + Vector2& XY() + { + return *reinterpret_cast(this); + } + + // returns the XY fields as a 2D-vector. + const Vector3& XYZ() const + { + return *reinterpret_cast(this); + } + + Vector3& XYZ() + { + return *reinterpret_cast(this); + } + + + // Test for approximate equality + bool ApproximatelyEquals(const TQuaternion &other) const + { + return fabs(X - other.X) < EQUAL_EPSILON && fabs(Y - other.Y) < EQUAL_EPSILON && fabs(Z - other.Z) < EQUAL_EPSILON && fabs(W - other.W) < EQUAL_EPSILON; + } + + // Test for approximate inequality + bool DoesNotApproximatelyEqual(const TQuaternion &other) const + { + return fabs(X - other.X) >= EQUAL_EPSILON || fabs(Y - other.Y) >= EQUAL_EPSILON || fabs(Z - other.Z) >= EQUAL_EPSILON || fabs(W - other.W) >= EQUAL_EPSILON; + } + + // Unary negation + TQuaternion operator- () const + { + return TQuaternion(-X, -Y, -Z, -W); + } + + // Scalar addition + TQuaternion &operator+= (vec_t scalar) + { + X += scalar, Y += scalar, Z += scalar; W += scalar; + return *this; + } + + friend TQuaternion operator+ (const TQuaternion &v, vec_t scalar) + { + return TQuaternion(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); + } + + friend TQuaternion operator+ (vec_t scalar, const TQuaternion &v) + { + return TQuaternion(v.X + scalar, v.Y + scalar, v.Z + scalar, v.W + scalar); + } + + // Scalar subtraction + TQuaternion &operator-= (vec_t scalar) + { + X -= scalar, Y -= scalar, Z -= scalar, W -= scalar; + return *this; + } + + TQuaternion operator- (vec_t scalar) const + { + return TQuaternion(X - scalar, Y - scalar, Z - scalar, W - scalar); + } + + // Scalar multiplication + TQuaternion &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 TQuaternion operator* (const TQuaternion &v, vec_t scalar) + { + return TQuaternion(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); + } + + friend TQuaternion operator* (vec_t scalar, const TQuaternion &v) + { + return TQuaternion(v.X * scalar, v.Y * scalar, v.Z * scalar, v.W * scalar); + } + + // Scalar division + TQuaternion &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; + } + + TQuaternion operator/ (vec_t scalar) const + { + scalar = 1 / scalar; + return TQuaternion(X * scalar, Y * scalar, Z * scalar, W * scalar); + } + + // Vector addition + TQuaternion &operator+= (const TQuaternion &other) + { + X += other.X, Y += other.Y, Z += other.Z, W += other.W; + return *this; + } + + TQuaternion operator+ (const TQuaternion &other) const + { + return TQuaternion(X + other.X, Y + other.Y, Z + other.Z, W + other.W); + } + + // Vector subtraction + TQuaternion &operator-= (const TQuaternion &other) + { + X -= other.X, Y -= other.Y, Z -= other.Z, W -= other.W; + return *this; + } + + TQuaternion operator- (const TQuaternion &other) const + { + return TQuaternion(X - other.X, Y - other.Y, Z - other.Z, W - other.W); + } + + // Quaternion length + double Length() const + { + return g_sqrt(X*X + Y*Y + Z*Z + W*W); + } + + double LengthSquared() const + { + return X*X + Y*Y + Z*Z + W*W; + } + + double Sum() const + { + return abs(X) + abs(Y) + abs(Z) + abs(W); + } + + + // Return a unit vector facing the same direction as this one + TQuaternion Unit() const + { + double len = Length(); + if (len != 0) len = 1 / len; + return *this * (vec_t)len; + } + + // Scales this vector into a unit vector + void MakeUnit() + { + double len = Length(); + if (len != 0) len = 1 / len; + *this *= (vec_t)len; + } + + // Resizes this vector to be the specified length (if it is not 0) + TQuaternion &MakeResize(double len) + { + double vlen = Length(); + if (vlen != 0.) + { + double scale = len / vlen; + X = vec_t(X * scale); + Y = vec_t(Y * scale); + Z = vec_t(Z * scale); + W = vec_t(W * scale); + } + return *this; + } + + TQuaternion Resized(double len) const + { + double vlen = Length(); + if (vlen != 0.) + { + double scale = len / vlen; + return{ vec_t(X * scale), vec_t(Y * scale), vec_t(Z * scale), vec_t(W * scale) }; + } + else + { + return *this; + } + } + + // Dot product + vec_t operator | (const TQuaternion &other) const + { + return X*other.X + Y*other.Y + Z*other.Z + W*other.W; + } + + vec_t dot(const TQuaternion &other) const + { + return X*other.X + Y*other.Y + Z*other.Z + W*other.W; + } + + TQuaternion& operator*= (const TQuaternion& q) + { + *this = *this * q; + return *this; + } + + friend TQuaternion operator* (const TQuaternion& q1, const TQuaternion& q2) + { + return TQuaternion( + q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y, + q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X, + q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W, + q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z + ); + } + + // Rotate Vector3 by Quaternion q + friend TVector3 operator* (const TQuaternion& q, const TVector3& v) + { + auto r = TQuaternion({ v.X, v.Y, v.Z, 0 }) * TQuaternion({ -q.X, -q.Y, -q.Z, q.W }); + r = q * r; + return TVector3(r.X, r.Y, r.Z); + } + + TQuaternion Conjugate() + { + return TQuaternion(-X, -Y, -Z, +W); + } + TQuaternion Inverse() + { + return Conjugate() / LengthSquared(); + } + + static TQuaternion AxisAngle(TVector3 axis, TAngle angle) + { + auto lengthSquared = axis.LengthSquared(); + auto halfAngle = angle * 0.5; + auto sinTheta = halfAngle.Sin(); + auto cosTheta = halfAngle.Cos(); + auto factor = sinTheta / g_sqrt(lengthSquared); + TQuaternion ret; + ret.W = cosTheta; + ret.XYZ() = factor * axis; + return ret; + } + static TQuaternion FromAngles(TAngle yaw, TAngle pitch, TAngle roll) + { + auto zRotation = TQuaternion::AxisAngle(Vector3(vec_t{0.0}, vec_t{0.0}, vec_t{1.0}), yaw); + auto yRotation = TQuaternion::AxisAngle(Vector3(vec_t{0.0}, vec_t{1.0}, vec_t{0.0}), pitch); + auto xRotation = TQuaternion::AxisAngle(Vector3(vec_t{1.0}, vec_t{0.0}, vec_t{0.0}), roll); + return zRotation * yRotation * xRotation; + } + + static TQuaternion NLerp(TQuaternion from, TQuaternion to, vec_t t) + { + return (from * (vec_t{1.0} - t) + to * t).Unit(); + } + static TQuaternion SLerp(TQuaternion from, TQuaternion to, vec_t t) + { + auto dot = from.dot(to); + const auto dotThreshold = vec_t{0.9995}; + if (dot < vec_t{0.0}) + { + to = -to; + dot = -dot; + } + if (dot > dotThreshold) + { + return NLerp(from, to, t); + } + else + { + auto robustDot = clamp(dot, vec_t{-1.0}, vec_t{1.0}); + auto theta = TAngle::fromRad(g_acos(robustDot)); + auto scale0 = (theta * (vec_t{1.0} - t)).Sin(); + auto scale1 = (theta * t).Sin(); + return (from * scale0 + to * scale1).Unit(); + } + } +}; + +typedef TQuaternion FQuaternion; +typedef TQuaternion DQuaternion; diff --git a/src/common/utility/r_memory.cpp b/src/common/utility/r_memory.cpp index 99a75d0f7..8ff821c38 100644 --- a/src/common/utility/r_memory.cpp +++ b/src/common/utility/r_memory.cpp @@ -21,14 +21,14 @@ */ #include -#include "templates.h" + #include "r_memory.h" #include void *RenderMemory::AllocBytes(int size) { size = (size + 15) / 16 * 16; // 16-byte align - + if (UsedBlocks.empty() || UsedBlocks.back()->Position + size > BlockSize) { if (!FreeBlocks.empty()) @@ -43,14 +43,14 @@ void *RenderMemory::AllocBytes(int size) UsedBlocks.push_back(std::unique_ptr(new MemoryBlock())); } } - + auto &block = UsedBlocks.back(); void *data = block->Data + block->Position; block->Position += size; return data; } - + void RenderMemory::Clear() { while (!UsedBlocks.empty()) diff --git a/src/common/utility/r_memory.h b/src/common/utility/r_memory.h index 8007b6cc1..d9db538ca 100644 --- a/src/common/utility/r_memory.h +++ b/src/common/utility/r_memory.h @@ -8,33 +8,33 @@ class RenderMemory { public: void Clear(); - + template T *AllocMemory(int size = 1) { return (T*)AllocBytes(sizeof(T) * size); } - + template T *NewObject(Types &&... args) { void *ptr = AllocBytes(sizeof(T)); return new (ptr)T(std::forward(args)...); } - + private: void *AllocBytes(int size); - + enum { BlockSize = 1024 * 1024 }; - + struct MemoryBlock { MemoryBlock(); ~MemoryBlock(); - + MemoryBlock(const MemoryBlock &) = delete; MemoryBlock &operator=(const MemoryBlock &) = delete; - + uint8_t *Data; uint32_t Position; }; diff --git a/src/common/utility/refcounted.h b/src/common/utility/refcounted.h index 81ea3fc6d..f8643f080 100644 --- a/src/common/utility/refcounted.h +++ b/src/common/utility/refcounted.h @@ -26,7 +26,7 @@ public: RefCountedPtr() : ptr(nullptr) {} - + explicit RefCountedPtr(T* p) : ptr(p) { if (ptr) ptr->IncRef(); @@ -52,7 +52,7 @@ public: } return *this; } - + RefCountedPtr& operator=(T* r) { if (ptr != r) @@ -99,18 +99,18 @@ public: { return *ptr; } - + T* operator-> () const { return ptr; } - + T* get() const { return ptr; } - + private: - + T * ptr; }; \ No newline at end of file diff --git a/src/common/utility/s_playlist.cpp b/src/common/utility/s_playlist.cpp index d284a3e90..d457d0137 100644 --- a/src/common/utility/s_playlist.cpp +++ b/src/common/utility/s_playlist.cpp @@ -37,7 +37,7 @@ #include "cmdlib.h" #include "s_playlist.h" -#include "templates.h" + #include "v_text.h" #include "files.h" diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 4a9e7388b..61dc5e12c 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -61,16 +61,22 @@ #include // for mingw #endif -#include "m_alloc.h" +#if __has_include("m_alloc.h") + #include "m_alloc.h" +#else + #define M_Malloc malloc + #define M_Realloc realloc + #define M_Free free +#endif -template class TIterator : public std::iterator +template class TIterator { public: - typedef typename TIterator::value_type value_type; - typedef typename TIterator::difference_type difference_type; - typedef typename TIterator::pointer pointer; - typedef typename TIterator::reference reference; - typedef typename TIterator::iterator_category iterator_category; + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; TIterator(T* ptr = nullptr) { m_ptr = ptr; } @@ -105,6 +111,17 @@ protected: T* m_ptr; }; +// magic little helper. :) +template +class backwards +{ + T& _obj; +public: + backwards(T &obj) : _obj(obj) {} + auto begin() {return _obj.rbegin();} + auto end() {return _obj.rend();} +}; + // TArray ------------------------------------------------------------------- @@ -125,6 +142,8 @@ public: typedef TIterator iterator; typedef TIterator const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; typedef T value_type; iterator begin() @@ -152,8 +171,33 @@ public: { return &Array[Count]; } - - + + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + //////// // This is a dummy constructor that does nothing. The purpose of this @@ -169,7 +213,7 @@ public: { } //////// - TArray () + constexpr TArray () { Most = 0; Count = 0; @@ -272,15 +316,32 @@ public: // Returns a reference to the last element T &Last() const { + assert(Count > 0); return Array[Count-1]; } + T SafeGet (size_t index, const T& defaultval) const + { + if (index <= Count) return Array[index]; + else return defaultval; + } + // returns address of first element T *Data() const { return &Array[0]; } + unsigned IndexOf(const T& elem) const + { + return &elem - Array; + } + + unsigned IndexOf(const T* elem) const + { + return unsigned(elem - Array); + } + unsigned int Find(const T& item) const { unsigned int i; @@ -354,6 +415,7 @@ public: { new(&Array[start + i]) T(std::move(item[i])); } + item.Clear(); return start; } @@ -636,6 +698,8 @@ public: typedef TIterator iterator; typedef TIterator const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; typedef T value_type; iterator begin() @@ -664,6 +728,32 @@ public: return &Array[Count]; } + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + void Init(T *ptr, unsigned cnt) { Array = ptr; @@ -826,6 +916,9 @@ public: typedef struct { const KT Key; VT Value; } Pair; typedef const Pair ConstPair; + typedef KT KeyType; + typedef VT ValueType; + TMap() { NumUsed = 0; SetNodeVector(1); } TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); } ~TMap() { ClearNodeVector(); } @@ -843,7 +936,7 @@ public: LastFree = o.LastFree; /* any free position is before this position */ Size = o.Size; /* must be a power of 2 */ NumUsed = o.NumUsed; - + o.Size = 0; o.NumUsed = 0; o.SetNodeVector(1); @@ -1579,7 +1672,7 @@ public: } BitArray(unsigned elem) - : bytes((elem + 7) / 8, true) + : bytes((elem + 7) / 8, true), size(elem) { } @@ -1617,6 +1710,12 @@ public: return !!(bytes[index >> 3] & (1 << (index & 7))); } + // for when array syntax cannot be used. + bool Check(size_t index) const + { + return !!(bytes[index >> 3] & (1 << (index & 7))); + } + void Set(size_t index, bool set = true) { if (!set) Clear(index); @@ -1637,6 +1736,11 @@ public: { memset(&bytes[0], 0, bytes.Size()); } + + TArray &Storage() + { + return bytes; + } }; @@ -1704,6 +1808,8 @@ public: typedef TIterator iterator; typedef TIterator const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; typedef T value_type; iterator begin() @@ -1732,6 +1838,32 @@ public: return &Array[Count]; } + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + //////// TArrayView() = default; // intended to keep this type trivial. @@ -1762,18 +1894,20 @@ public: // Return a reference to an element T &operator[] (size_t index) const { + assert(index < Count); return Array[index]; } // Returns a reference to the last element T &Last() const { + assert(Count > 0); return Array[Count - 1]; } // returns address of first element T *Data() const { - return &Array[0]; + return Array; } unsigned Size() const @@ -1807,3 +1941,9 @@ private: T *Array; unsigned int Count; }; + +#if !__has_include("m_alloc.h") + #undef M_Malloc + #undef M_Realloc + #undef M_Free +#endif diff --git a/src/common/utility/templates.h b/src/common/utility/templates.h index 3f3e596f0..22b9f3d3f 100644 --- a/src/common/utility/templates.h +++ b/src/common/utility/templates.h @@ -93,54 +93,5 @@ const ClassType *BinarySearch (const ClassType *first, int max, return NULL; } -//========================================================================== -// -// MIN -// -// Returns the minimum of a and b. -//========================================================================== - -#ifdef MIN -#undef MIN -#endif - -template -inline -const T MIN (const T a, const T b) -{ - return a < b ? a : b; -} - -//========================================================================== -// -// MAX -// -// Returns the maximum of a and b. -//========================================================================== - -#ifdef MAX -#undef MAX -#endif - -template -inline -const T MAX (const T a, const T b) -{ - return a > b ? a : b; -} - -//========================================================================== -// -// clamp -// -// Clamps in to the range [min,max]. -//========================================================================== - -template -inline constexpr -T clamp (const T in, const X min, const Y max) -{ - return in <= (T) min ? (T) min : in >= (T) max ? (T) max : in; -} #endif //__TEMPLATES_H__ diff --git a/src/common/utility/tflags.h b/src/common/utility/tflags.h index 98516fce8..f872d4574 100644 --- a/src/common/utility/tflags.h +++ b/src/common/utility/tflags.h @@ -53,42 +53,42 @@ public: TFlags() = default; TFlags(const Self& other) = default; - TFlags (T value) : Value (static_cast (value)) {} + constexpr TFlags (T value) : Value (static_cast (value)) {} // This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer. - TFlags (ZeroDummy*) : Value (0) {} + constexpr TFlags (ZeroDummy*) : Value (0) {} // Relation operators - Self operator| (Self other) const { return Self::FromInt (Value | other.GetValue()); } - Self operator& (Self other) const { return Self::FromInt (Value & other.GetValue()); } - Self operator^ (Self other) const { return Self::FromInt (Value ^ other.GetValue()); } - Self operator| (T value) const { return Self::FromInt (Value | value); } - Self operator& (T value) const { return Self::FromInt (Value & value); } - Self operator^ (T value) const { return Self::FromInt (Value ^ value); } - Self operator~() const { return Self::FromInt (~Value); } + constexpr Self operator| (const Self& other) const { return Self::FromInt (Value | other.GetValue()); } + constexpr Self operator& (const Self& other) const { return Self::FromInt (Value & other.GetValue()); } + constexpr Self operator^ (const Self& other) const { return Self::FromInt (Value ^ other.GetValue()); } + constexpr Self operator| (T value) const { return Self::FromInt (Value | value); } + constexpr Self operator& (T value) const { return Self::FromInt (Value & value); } + constexpr Self operator^ (T value) const { return Self::FromInt (Value ^ value); } + constexpr Self operator~() const { return Self::FromInt (~Value); } // Assignment operators - Self& operator= (Self other) { Value = other.GetValue(); return *this; } - Self& operator|= (Self other) { Value |= other.GetValue(); return *this; } - Self& operator&= (Self other) { Value &= other.GetValue(); return *this; } - Self& operator^= (Self other) { Value ^= other.GetValue(); return *this; } - Self& operator= (T value) { Value = value; return *this; } - Self& operator|= (T value) { Value |= value; return *this; } - Self& operator&= (T value) { Value &= value; return *this; } - Self& operator^= (T value) { Value ^= value; return *this; } + constexpr Self& operator= (const Self& other) = default; + constexpr Self& operator|= (const Self& other) { Value |= other.GetValue(); return *this; } + constexpr Self& operator&= (const Self& other) { Value &= other.GetValue(); return *this; } + constexpr Self& operator^= (const Self& other) { Value ^= other.GetValue(); return *this; } + constexpr Self& operator= (T value) { Value = value; return *this; } + constexpr Self& operator|= (T value) { Value |= value; return *this; } + constexpr Self& operator&= (T value) { Value &= value; return *this; } + constexpr Self& operator^= (T value) { Value ^= value; return *this; } // Access the value of the flagset - TT GetValue() const { return Value; } - operator TT() const { return Value; } + constexpr TT GetValue() const { return Value; } + constexpr operator TT() const { return Value; } // Set the value of the flagset manually with an integer. // Please think twice before using this. - static Self FromInt (TT value) { return Self (static_cast (value)); } + static constexpr Self FromInt (TT value) { return Self (static_cast (value)); } private: - template Self operator| (X value) const { return Self::FromInt (Value | value); } - template Self operator& (X value) const { return Self::FromInt (Value & value); } - template Self operator^ (X value) const { return Self::FromInt (Value ^ value); } + template constexpr Self operator| (X value) const { return Self::FromInt (Value | value); } + template constexpr Self operator& (X value) const { return Self::FromInt (Value & value); } + template constexpr Self operator^ (X value) const { return Self::FromInt (Value ^ value); } public: // to be removed. TT Value; @@ -98,11 +98,11 @@ public: // to be removed. * Additional operators for TFlags types. */ #define DEFINE_TFLAGS_OPERATORS(T) \ -inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ -inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ -inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ -inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ -inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ -inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ -inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); } +constexpr inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +constexpr inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +constexpr inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +constexpr inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +constexpr inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +constexpr inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +constexpr inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); } diff --git a/src/common/utility/utf8.cpp b/src/common/utility/utf8.cpp index b0b225ae5..5ca3506ef 100644 --- a/src/common/utility/utf8.cpp +++ b/src/common/utility/utf8.cpp @@ -124,7 +124,7 @@ int utf8_decode(const uint8_t *src, int *size) } return -1; } - + int c3 = src[3]; if (c3 < 0x80 || c1 >= 0xc0) return -1; c3 &= 0x3f; @@ -200,7 +200,7 @@ int GetCharFromString(const uint8_t *&string) if (z < 192) { string++; - + // Handle Windows 1252 characters if (z >= 128 && z < 160) { @@ -353,7 +353,7 @@ int getAlternative(int code) { default: return code; - + case '{': return '('; case '}': return ')'; case 0x17f: return 's'; // The 'long s' can be safely remapped to the regular variant, not that this gets used in any real text... @@ -428,7 +428,6 @@ int getAlternative(int code) case 0x457: return 0xef; case 0x458: return 'j'; } - return code; } //========================================================================== diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index 2118a22fa..89c5a642d 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -46,6 +46,8 @@ #include #include "xs_Float.h" #include "math/cmath.h" +#include "basics.h" +#include "cmdlib.h" #define EQUAL_EPSILON (1/65536.) @@ -141,11 +143,13 @@ struct TVector2 } // Scalar addition +#if 0 TVector2 &operator+= (double scalar) { X += scalar, Y += scalar; return *this; } +#endif friend TVector2 operator+ (const TVector2 &v, vec_t scalar) { @@ -233,6 +237,12 @@ struct TVector2 { return X*X + Y*Y; } + + double Sum() const + { + return abs(X) + abs(Y); + } + // Return a unit vector facing the same direction as this one TVector2 Unit() const @@ -261,6 +271,19 @@ struct TVector2 return *this; } + TVector2 Resized(double len) const + { + double vlen = Length(); + if (vlen != 0.) + { + double scale = len / vlen; + return{ vec_t(X * scale), vec_t(Y * scale) }; + } + else + { + return *this; + } + } // Dot product vec_t operator | (const TVector2 &other) const @@ -268,11 +291,16 @@ struct TVector2 return X*other.X + Y*other.Y; } + vec_t dot(const TVector2 &other) const + { + return X*other.X + Y*other.Y; + } + // Returns the angle that the ray (0,0)-(X,Y) faces TAngle Angle() const; // Returns a rotated vector. angle is in degrees. - TVector2 Rotated (double angle) + TVector2 Rotated (double angle) const { double cosval = g_cosdeg (angle); double sinval = g_sindeg (angle); @@ -281,21 +309,27 @@ struct TVector2 // Returns a rotated vector. angle is in degrees. template - TVector2 Rotated(TAngle angle) + TVector2 Rotated(TAngle angle) const { double cosval = angle.Cos(); double sinval = angle.Sin(); return TVector2(X*cosval - Y*sinval, Y*cosval + X*sinval); } + // Returns a rotated vector. angle is in degrees. + 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() + TVector2 Rotated90CW() const { return TVector2(Y, -X); } // Returns a vector rotated 90 degrees counterclockwise. - TVector2 Rotated90CCW() + TVector2 Rotated90CCW() const { return TVector2(-Y, X); } @@ -305,6 +339,8 @@ template struct TVector3 { typedef TVector2 Vector2; + // this does not compile - should be true on all relevant hardware. + //static_assert(myoffsetof(TVector3, X) == myoffsetof(Vector2, X) && myoffsetof(TVector3, Y) == myoffsetof(Vector2, Y), "TVector2 and TVector3 are not aligned"); vec_t X, Y, Z; @@ -341,6 +377,11 @@ struct TVector3 return X == 0 && Y == 0 && Z == 0; } + TVector3 plusZ(double z) const + { + return { X, Y, Z + z }; + } + TVector3 &operator= (const TVector3 &other) = default; // Access X and Y and Z as an array @@ -385,11 +426,13 @@ struct TVector3 } // Scalar addition +#if 0 TVector3 &operator+= (vec_t scalar) { X += scalar, Y += scalar, Z += scalar; return *this; } +#endif friend TVector3 operator+ (const TVector3 &v, vec_t scalar) { @@ -482,9 +525,14 @@ struct TVector3 } // returns the XY fields as a 2D-vector. - Vector2 XY() const + const Vector2& XY() const { - return{ X, Y }; + return *reinterpret_cast(this); + } + + Vector2& XY() + { + return *reinterpret_cast(this); } // Add a 3D vector and a 2D vector. @@ -553,7 +601,7 @@ struct TVector3 } up = n ^right; - right.MakeUnit();; + right.MakeUnit(); up.MakeUnit(); } @@ -572,6 +620,12 @@ struct TVector3 { return X*X + Y*Y + Z*Z; } + + double Sum() const + { + return abs(X) + abs(Y) + abs(Z); + } + // Return a unit vector facing the same direction as this one TVector3 Unit() const @@ -603,7 +657,7 @@ struct TVector3 return *this; } - TVector3 Resized(double len) + TVector3 Resized(double len) const { double vlen = Length(); if (vlen != 0.) @@ -623,6 +677,11 @@ struct TVector3 return X*other.X + Y*other.Y + Z*other.Z; } + 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 { @@ -641,6 +700,7 @@ struct TVector3 template struct TVector4 { + typedef TVector2 Vector2; typedef TVector3 Vector3; vec_t X, Y, Z, W; @@ -664,6 +724,11 @@ struct TVector4 { } + TVector4(const vec_t v[4]) + : TVector4(v[0], v[1], v[2], v[3]) + { + } + void Zero() { Z = Y = X = W = 0; @@ -699,6 +764,29 @@ struct TVector4 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 + { + return *reinterpret_cast(this); + } + + Vector2& XY() + { + return *reinterpret_cast(this); + } + + // returns the XY fields as a 2D-vector. + const Vector3& XYZ() const + { + return *reinterpret_cast(this); + } + + Vector3& XYZ() + { + return *reinterpret_cast(this); + } + + // Test for approximate equality bool ApproximatelyEquals(const TVector4 &other) const { @@ -814,12 +902,6 @@ struct TVector4 return *this; } - // returns the XYZ fields as a 3D-vector. - Vector3 XYZ() const - { - return{ X, Y, Z }; - } - // Add a 4D vector and a 3D vector. friend TVector4 operator+ (const TVector4 &v4, const Vector3 &v3) { @@ -853,6 +935,12 @@ struct TVector4 { return X*X + Y*Y + Z*Z + W*W; } + + double Sum() const + { + return abs(X) + abs(Y) + abs(Z) + abs(W); + } + // Return a unit vector facing the same direction as this one TVector4 Unit() const @@ -885,7 +973,7 @@ struct TVector4 return *this; } - TVector4 Resized(double len) + TVector4 Resized(double len) const { double vlen = Length(); if (vlen != 0.) @@ -904,6 +992,11 @@ struct TVector4 { return X*other.X + Y*other.Y + Z*other.Z + W*other.W; } + + vec_t dot(const TVector4 &other) const + { + return X*other.X + Y*other.Y + Z*other.Z + W*other.W; + } }; template @@ -915,6 +1008,7 @@ struct TMatrix3x3 TMatrix3x3() = default; TMatrix3x3(const TMatrix3x3 &other) = default; + TMatrix3x3& operator=(const TMatrix3x3& other) = default; TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3) { @@ -1134,7 +1228,7 @@ Outside comments: A faster version with only 10 (not 24) multiplies. template struct TAngle { - vec_t Degrees; + vec_t Degrees_; // This is to catch any accidental attempt to assign an angle_t to this type. Any explicit exception will require a type cast. TAngle(int) = delete; @@ -1148,180 +1242,156 @@ struct TAngle TAngle() = default; - TAngle (vec_t amt) - : Degrees(amt) +private: + // Both constructors are needed to avoid unnecessary conversions when assigning to FAngle. + constexpr TAngle (float amt) + : Degrees_((vec_t)amt) { } + constexpr TAngle (double amt) + : Degrees_((vec_t)amt) + { + } +public: + + vec_t& Degrees__() { return Degrees_; } + + static constexpr TAngle fromDeg(float deg) + { + return TAngle(deg); + } + static constexpr TAngle fromDeg(double deg) + { + return TAngle(deg); + } + static constexpr TAngle fromDeg(int deg) + { + return TAngle((vec_t)deg); + } + static constexpr TAngle fromDeg(unsigned deg) + { + return TAngle((vec_t)deg); + } + + static constexpr TAngle fromRad(float rad) + { + return TAngle(float(rad * (180.0f / pi::pif()))); + } + static constexpr TAngle fromRad(double rad) + { + return TAngle(double(rad * (180.0 / pi::pi()))); + } + + static constexpr TAngle fromBam(int f) + { + return TAngle(f * (90. / 0x40000000)); + } + static constexpr TAngle fromBam(unsigned f) + { + return TAngle(f * (90. / 0x40000000)); + } + + static constexpr TAngle fromBuild(double bang) + { + return TAngle(bang * (90. / 512)); + } + + static constexpr TAngle fromQ16(int bang) + { + return TAngle(bang * (90. / 16384)); + } TAngle(const TAngle &other) = default; TAngle &operator= (const TAngle &other) = default; - TAngle &operator= (double other) + constexpr TAngle operator- () const { - Degrees = (decltype(Degrees))other; + return TAngle(-Degrees_); + } + + constexpr TAngle &operator+= (TAngle other) + { + Degrees_ += other.Degrees_; return *this; } - // intentionally disabled so that common math functions cannot be accidentally called with a TAngle. - //operator vec_t() const { return Degrees; } - - TAngle operator- () const + constexpr TAngle &operator-= (TAngle other) { - return TAngle(-Degrees); - } - - TAngle &operator+= (TAngle other) - { - Degrees += other.Degrees; + Degrees_ -= other.Degrees_; return *this; } - TAngle &operator-= (TAngle other) + constexpr TAngle operator+ (TAngle other) const { - Degrees -= other.Degrees; + return Degrees_ + other.Degrees_; + } + + constexpr TAngle operator- (TAngle other) const + { + return Degrees_ - other.Degrees_; + } + + constexpr TAngle &operator*= (vec_t other) + { + Degrees_ = Degrees_ * other; return *this; } - TAngle &operator*= (TAngle other) + constexpr TAngle &operator/= (vec_t other) { - Degrees *= other.Degrees; + Degrees_ = Degrees_ / other; return *this; } - TAngle &operator/= (TAngle other) + constexpr TAngle operator* (vec_t other) const { - Degrees /= other.Degrees; - return *this; + return Degrees_ * other; } - TAngle operator+ (TAngle other) const + constexpr TAngle operator* (TAngle other) const { - return Degrees + other.Degrees; + return Degrees_ * other.Degrees_; } - TAngle operator- (TAngle other) const + constexpr TAngle operator/ (vec_t other) const { - return Degrees - other.Degrees; + return Degrees_ / other; } - TAngle operator* (TAngle other) const + constexpr double operator/ (TAngle other) const { - return Degrees * other.Degrees; - } - - TAngle operator/ (TAngle other) const - { - return Degrees / other.Degrees; - } - - TAngle &operator+= (vec_t other) - { - Degrees = Degrees + other; - return *this; - } - - TAngle &operator-= (vec_t other) - { - Degrees = Degrees - other; - return *this; - } - - TAngle &operator*= (vec_t other) - { - Degrees = Degrees * other; - return *this; - } - - TAngle &operator/= (vec_t other) - { - Degrees = Degrees / other; - return *this; - } - - TAngle operator+ (vec_t other) const - { - return Degrees + other; - } - - TAngle operator- (vec_t other) const - { - return Degrees - other; - } - - friend TAngle operator- (vec_t o1, TAngle o2) - { - return TAngle(o1 - o2.Degrees); - } - - TAngle operator* (vec_t other) const - { - return Degrees * other; - } - - TAngle operator/ (vec_t other) const - { - return Degrees / other; + return Degrees_ / other.Degrees_; } // Should the comparisons consider an epsilon value? - bool operator< (TAngle other) const + constexpr bool operator< (TAngle other) const { - return Degrees < other.Degrees; + return Degrees_ < other.Degrees_; } - bool operator> (TAngle other) const + constexpr bool operator> (TAngle other) const { - return Degrees > other.Degrees; + return Degrees_ > other.Degrees_; } - bool operator<= (TAngle other) const + constexpr bool operator<= (TAngle other) const { - return Degrees <= other.Degrees; + return Degrees_ <= other.Degrees_; } - bool operator>= (TAngle other) const + constexpr bool operator>= (TAngle other) const { - return Degrees >= other.Degrees; + return Degrees_ >= other.Degrees_; } - bool operator== (TAngle other) const + constexpr bool operator== (TAngle other) const { - return Degrees == other.Degrees; + return Degrees_ == other.Degrees_; } - bool operator!= (TAngle other) const + constexpr bool operator!= (TAngle other) const { - return Degrees != other.Degrees; - } - - bool operator< (vec_t other) const - { - return Degrees < other; - } - - bool operator> (vec_t other) const - { - return Degrees > other; - } - - bool operator<= (vec_t other) const - { - return Degrees <= other; - } - - bool operator>= (vec_t other) const - { - return Degrees >= other; - } - - bool operator== (vec_t other) const - { - return Degrees == other; - } - - bool operator!= (vec_t other) const - { - return Degrees != other; + return Degrees_ != other.Degrees_; } // Ensure the angle is between [0.0,360.0) degrees @@ -1338,14 +1408,29 @@ struct TAngle return (vec_t)(BAM_FACTOR * (signed int)BAMs()); } - vec_t Radians() const + constexpr vec_t Radians() const { - return vec_t(Degrees * (pi::pi() / 180.0)); + return vec_t(Degrees_ * (pi::pi() / 180.0)); } unsigned BAMs() const { - return xs_CRoundToInt(Degrees * (0x40000000 / 90.)); + return xs_CRoundToInt(Degrees_ * (0x40000000 / 90.)); + } + + constexpr vec_t Degrees() const + { + return Degrees_; + } + + constexpr int Buildang() const + { + return int(Degrees_ * (512 / 90.0)); + } + + constexpr int Q16() const + { + return int(Degrees_ * (16384 / 90.0)); } TVector2 ToVector(vec_t length = 1) const @@ -1355,17 +1440,18 @@ struct TAngle vec_t Cos() const { - return vec_t(g_cosdeg(Degrees)); + return vec_t(g_cosdeg(Degrees_)); } vec_t Sin() const { - return vec_t(g_sindeg(Degrees)); + return vec_t(g_sindeg(Degrees_)); } double Tan() const { - return vec_t(g_tan(Radians())); + auto bam = BAMs(); + return g_sinbam(bam) / g_cosbam(bam); } // This is for calculating vertical velocity. For high pitches the tangent will become too large to be useful. @@ -1374,23 +1460,22 @@ struct TAngle return clamp(Tan(), -max, max); } - static inline TAngle ToDegrees(double rad) + int Sgn() const { - return TAngle(double(rad * (180.0 / pi::pi()))); + return ::Sgn(int(BAMs())); } - }; -// Emulates the old floatbob offset table with direct calls to trig functions. -inline double BobSin(double fb) -{ - return TAngle(double(fb * (180.0 / 32))).Sin() * 8; -} - template inline TAngle fabs (const TAngle °) { - return TAngle(fabs(deg.Degrees)); + return TAngle::fromDeg(fabs(deg.Degrees())); +} + +template +inline TAngle abs (const TAngle °) +{ + return TAngle::fromDeg(fabs(deg.Degrees())); } template @@ -1399,18 +1484,6 @@ inline TAngle deltaangle(const TAngle &a1, const TAngle &a2) return (a2 - a1).Normalized180(); } -template -inline TAngle deltaangle(const TAngle &a1, double a2) -{ - return (a2 - a1).Normalized180(); -} - -template -inline TAngle deltaangle(double a1, const TAngle &a2) -{ - return (a2 - a1).Normalized180(); -} - template inline TAngle absangle(const TAngle &a1, const TAngle &a2) { @@ -1418,26 +1491,26 @@ inline TAngle absangle(const TAngle &a1, const TAngle &a2) } template -inline TAngle absangle(const TAngle &a1, double a2) +inline TAngle clamp(const TAngle &angle, const TAngle &min, const TAngle &max) { - return fabs((a1 - a2).Normalized180()); + return TAngle::fromDeg(clamp(angle.Degrees(), min.Degrees(), max.Degrees())); } inline TAngle VecToAngle(double x, double y) { - return g_atan2(y, x) * (180.0 / pi::pi()); + return TAngle::fromRad(g_atan2(y, x)); } template inline TAngle VecToAngle (const TVector2 &vec) { - return (T)g_atan2(vec.Y, vec.X) * (180.0 / pi::pi()); + return TAngle::fromRad(g_atan2(vec.Y, vec.X)); } template inline TAngle VecToAngle (const TVector3 &vec) { - return (T)g_atan2(vec.Y, vec.X) * (180.0 / pi::pi()); + return TAngle::fromRad(g_atan2(vec.Y, vec.X)); } template @@ -1458,6 +1531,34 @@ TAngle TVector3::Pitch() const return -VecToAngle(TVector2(X, Y).Length(), Z); } +template +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 +inline TAngle interpolatedvalue(const TAngle &oang, const TAngle &ang, const double interpfrac) +{ + return oang + (deltaangle(oang, ang) * interpfrac); +} + +template +inline TRotator interpolatedvalue(const TRotator &oang, const TRotator &ang, const double interpfrac) +{ + return TRotator( + interpolatedvalue(oang.Pitch, ang.Pitch, interpfrac), + interpolatedvalue(oang.Yaw, ang.Yaw, interpfrac), + interpolatedvalue(oang.Roll, ang.Roll, interpfrac) + ); +} + +template +inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac) +{ + return T(oval + (val - oval) * interpfrac); +} + // Much of this is copied from TVector3. Is all that functionality really appropriate? template struct TRotator @@ -1467,7 +1568,6 @@ struct TRotator Angle Pitch; // up/down Angle Yaw; // left/right Angle Roll; // rotation about the forward axis. - Angle CamRoll; // Roll specific to actor cameras. Used by quakes. TRotator() = default; @@ -1557,14 +1657,14 @@ struct TRotator // Scalar division TRotator &operator/= (const Angle &scalar) { - Angle mul(1 / scalar.Degrees); - Pitch *= scalar, Yaw *= scalar, Roll *= scalar; + Angle mul(1 / scalar.Degrees_); + Pitch *= mul, Yaw *= mul, Roll *= mul; return *this; } TRotator operator/ (const Angle &scalar) const { - Angle mul(1 / scalar.Degrees); + Angle mul(1 / scalar.Degrees_); return TRotator(Pitch * mul, Yaw * mul, Roll * mul); } @@ -1626,7 +1726,6 @@ inline TMatrix3x3::TMatrix3x3(const TVector3 &axis, TAngle degrees) Cells[2][2] = T( (t-txx-tyy) + c ); } - typedef TVector2 FVector2; typedef TVector3 FVector3; typedef TVector4 FVector4; @@ -1641,6 +1740,19 @@ 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 { @@ -1651,6 +1763,12 @@ public: m_d = d; } + void Init(const FVector3& p1, const FVector3& p2, const FVector3& p3) + { + m_normal = ((p2 - p1) ^ (p3 - p1)).Unit(); + m_d = -(p3 |m_normal); + } + // same for a play-vector. Note that y and z are inversed. void Set(DVector3 normal, double d) { @@ -1671,7 +1789,7 @@ public: return DistToPoint(x, y, z) < 0.f; } - bool PointOnSide(FVector3 &v) { return PointOnSide(v.X, v.Y, v.Z); } + bool PointOnSide(const FVector3 &v) { return PointOnSide(v.X, v.Y, v.Z); } float A() { return m_normal.X; } float B() { return m_normal.Y; } diff --git a/src/common/utility/x86.cpp b/src/common/utility/x86.cpp index 3312ff043..76e880834 100644 --- a/src/common/utility/x86.cpp +++ b/src/common/utility/x86.cpp @@ -164,7 +164,7 @@ void CheckCPUID(CPUInfo *cpu) FString DumpCPUInfo(const CPUInfo *cpu) { char cpustring[4*4*3+1]; - + // Why does Intel right-justify this string (on P4s) // or add extra spaces (on Cores)? const char *f = cpu->CPUString; diff --git a/src/common/utility/zstrformat.cpp b/src/common/utility/zstrformat.cpp index bf61ce282..0d8bcfbc2 100644 --- a/src/common/utility/zstrformat.cpp +++ b/src/common/utility/zstrformat.cpp @@ -318,9 +318,9 @@ namespace StringFormat */ const char *decimal_point = ".";/* locale specific decimal point */ int signflag; /* true if float is negative */ - int expt; /* integer value of exponent */ + int expt = 0; /* integer value of exponent */ char expchar = 'e'; /* exponent character: [eEpP\0] */ - char *dtoaend; /* pointer to end of converted digits */ + 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 */ diff --git a/src/common/utility/zstring.cpp b/src/common/utility/zstring.cpp index 8d4d4d119..2b3c4f1fe 100644 --- a/src/common/utility/zstring.cpp +++ b/src/common/utility/zstring.cpp @@ -843,7 +843,7 @@ void FString::StripLeftRight () } for (j = max - 1; j >= i; --j) { - if (Chars[i] < 0 || !isspace((unsigned char)Chars[j])) + if (Chars[j] < 0 || !isspace((unsigned char)Chars[j])) break; } if (i == 0 && j == max - 1) @@ -863,7 +863,7 @@ void FString::StripLeftRight () { FStringData *old = Data(); AllocBuffer(j - i + 1); - StrCopy(Chars, old->Chars(), j - i + 1); + StrCopy(Chars, old->Chars() + i, j - i + 1); old->Release(); } } @@ -899,8 +899,8 @@ void FString::StripLeftRight (const char *charset) else { FStringData *old = Data(); - AllocBuffer (j - i); - StrCopy (Chars, old->Chars(), j - i); + AllocBuffer (j - i + 1); + StrCopy (Chars, old->Chars() + i, j - i + 1); old->Release(); } } diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index 513434478..c5752c9b9 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -69,11 +69,13 @@ #include "s_music.h" #include "texturemanager.h" #include "v_draw.h" +#include "d_main.h" +#include "savegamemanager.h" extern FILE *Logfile; extern bool insave; -CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH) +CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO) CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO) CVAR (Int, cl_blockcheats, 0, 0) @@ -469,7 +471,7 @@ CCMD (puke) return; } int arg[4] = { 0, 0, 0, 0 }; - int argn = MIN(argc - 2, countof(arg)), i; + int argn = min(argc - 2, countof(arg)), i; for (i = 0; i < argn; ++i) { @@ -516,7 +518,7 @@ CCMD (pukename) always = true; argstart = 3; } - argn = MIN(argc - argstart, countof(arg)); + argn = min(argc - argstart, countof(arg)); for (i = 0; i < argn; ++i) { arg[i] = atoi(argv[argstart + i]); @@ -632,8 +634,27 @@ UNSAFE_CCMD (load) return; } FString fname = argv[1]; - DefaultExtension (fname, "." SAVEGAME_EXT); - G_LoadGame (fname); + FixPathSeperator(fname); + if (fname[0] == '/') + { + Printf("saving to an absolute path is not allowed\n"); + return; + } + if (fname.IndexOf("..") > 0) + { + Printf("'..' not allowed in file names\n"); + return; + } +#ifdef _WIN32 + // block all invalid characters for Windows file names + if (fname.IndexOfAny(":?*<>|") >= 0) + { + Printf("file name contains invalid characters\n"); + return; + } +#endif + fname = G_BuildSaveName(fname); + G_LoadGame (fname); } //========================================================================== @@ -644,15 +665,34 @@ UNSAFE_CCMD (load) // //========================================================================== -UNSAFE_CCMD (save) +UNSAFE_CCMD(save) { - if (argv.argc() < 2 || argv.argc() > 3) + if (argv.argc() < 2 || argv.argc() > 3 || argv[1][0] == 0) { Printf ("usage: save [description]\n"); return; } - FString fname = argv[1]; - DefaultExtension (fname, "." SAVEGAME_EXT); + FString fname = argv[1]; + FixPathSeperator(fname); + if (fname[0] == '/') + { + Printf("saving to an absolute path is not allowed\n"); + return; + } + if (fname.IndexOf("..") > 0) + { + Printf("'..' not allowed in file names\n"); + return; + } +#ifdef _WIN32 + // block all invalid characters for Windows file names + if (fname.IndexOfAny(":?*<>|") >= 0) + { + Printf("file name contains invalid characters\n"); + return; + } +#endif + fname = G_BuildSaveName(fname); G_SaveGame (fname, argv.argc() > 2 ? argv[2] : argv[1]); } @@ -941,8 +981,8 @@ CCMD(currentpos) AActor *mo = players[consoleplayer].mo; if(mo) { - Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, lightlevel: %d\n", - mo->X(), mo->Y(), mo->Z(), mo->Angles.Yaw.Normalized360().Degrees, mo->floorz, mo->Sector->sectornum, mo->Sector->lightlevel); + Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, sector lightlevel: %d, actor lightlevel: %d\n", + mo->X(), mo->Y(), mo->Z(), mo->Angles.Yaw.Normalized360().Degrees(), mo->floorz, mo->Sector->sectornum, mo->Sector->lightlevel, mo->LightLevel); } else { @@ -1023,10 +1063,10 @@ CCMD(secret) maphdr.Format("[%s]", mapname); FString linebuild; - char readbuffer[1024]; + char readbuffer[10240]; bool inlevel = false; - while (lump.Gets(readbuffer, 1024)) + while (lump.Gets(readbuffer, 10240)) { if (!inlevel) { @@ -1073,7 +1113,7 @@ CCMD(angleconvtest) Printf("Testing degrees to angle conversion:\n"); for (double ang = -5 * 180.; ang < 5 * 180.; ang += 45.) { - unsigned ang1 = DAngle(ang).BAMs(); + unsigned ang1 = DAngle::fromDeg(ang).BAMs(); unsigned ang2 = (unsigned)(ang * (0x40000000 / 90.)); unsigned ang3 = (unsigned)(int)(ang * (0x40000000 / 90.)); Printf("Angle = %.5f: xs_RoundToInt = %08x, unsigned cast = %08x, signed cast = %08x\n", diff --git a/src/console/c_functions.cpp b/src/console/c_functions.cpp index 7bbf314cc..b99c9a5d0 100644 --- a/src/console/c_functions.cpp +++ b/src/console/c_functions.cpp @@ -52,8 +52,8 @@ void C_PrintInfo(AActor *target, bool verbose) void C_AimLine(FTranslatedLineTarget *t, bool nonshootable) { - P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE, t, 0., - (nonshootable) ? ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART : 0); + P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE, t, nullAngle, + (nonshootable) ? ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART|ALF_IGNORENOAUTOAIM : ALF_IGNORENOAUTOAIM); } void C_PrintInv(AActor *target) diff --git a/src/console/c_notifybuffer.cpp b/src/console/c_notifybuffer.cpp index feb58343d..d25b320e4 100644 --- a/src/console/c_notifybuffer.cpp +++ b/src/console/c_notifybuffer.cpp @@ -64,7 +64,7 @@ CUSTOM_CVAR(Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high r if (self < 0) self = 0; } -enum { NOTIFYFADETIME = 6 }; +constexpr int NOTIFYFADETIME = 6; CUSTOM_CVAR(Int, con_notifylines, 4, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) { diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index d0d957145..5f16a872a 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -36,7 +36,7 @@ #include "d_gui.h" #include "g_input.h" #include "d_net.h" -#include "d_event.h" +#include "d_eventbase.h" #include "sbar.h" #include "v_video.h" #include "utf8.h" @@ -65,8 +65,6 @@ void CT_Drawer (); bool CT_Responder (event_t *ev); void CT_PasteChat(const char *clip); -int chatmodeon; - // Private data static void CT_ClearChatMessage (); @@ -88,7 +86,7 @@ CVAR (String, chatmacro8, "I'll take care of it.", CVAR_ARCHIVE) CVAR (String, chatmacro9, "Yes", CVAR_ARCHIVE) CVAR (String, chatmacro0, "No", CVAR_ARCHIVE) -FStringCVar *chat_macros[10] = +FStringCVarRef *chat_macros[10] = { &chatmacro0, &chatmacro1, @@ -240,11 +238,14 @@ void CT_Drawer (void) if (players[consoleplayer].camera != NULL && (buttonMap.ButtonDown(Button_ShowScores) || players[consoleplayer].camera->health <= 0 || - SB_ForceActive) && - // Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp. - gamestate != GS_INTERMISSION) + SB_ForceActive)) { - HU_DrawScores (&players[consoleplayer]); + bool skipit = false; + if (gamestate == GS_CUTSCENE) + { + // todo: check for summary screen + } + if (!skipit) HU_DrawScores (&players[consoleplayer]); } if (chatmodeon) { @@ -266,7 +267,7 @@ void CT_Drawer (void) y = (viewactive || gamestate != GS_LEVEL) ? -displayfont->GetHeight()-2 : -displayfont->GetHeight() - 22; scalex = 1; - int scale = active_con_scaletext(drawer); + int scale = active_con_scale(drawer); int screen_width = twod->GetWidth() / scale; int screen_height= twod->GetHeight() / scale; int st_y = StatusBar->GetTopOfStatusbar() / scale; diff --git a/src/d_anonstats.cpp b/src/d_anonstats.cpp index 42c4d34ef..48762bd6d 100644 --- a/src/d_anonstats.cpp +++ b/src/d_anonstats.cpp @@ -12,6 +12,7 @@ void D_ConfirmSendStats() #else // !NO_SEND_STATS #if defined(_WIN32) +#include "i_mainwindow.h" #define WIN32_LEAN_AND_MEAN #include #include @@ -37,13 +38,12 @@ extern int sys_ostype; #include "gl_interface.h" #include "printf.h" -CVAR(Int, sys_statsenabled47, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) +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) -// Each machine will only send two reports, one when started with hardware rendering and one when started with software rendering. -#define CHECKVERSION 470 -#define CHECKVERSIONSTR "470" +#define CHECKVERSION 490 +#define CHECKVERSIONSTR "490" CVAR(Int, sentstats_hwr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) std::pair gl_getInfo(); @@ -73,7 +73,7 @@ FString URLencode(const char *s) bool I_HTTPRequest(const char* request) { - if (sys_statshost.GetHumanString() == NULL) + if ((*sys_statshost)[0] == 0) return false; // no host, disable WSADATA wsaData; @@ -84,7 +84,7 @@ bool I_HTTPRequest(const char* request) } SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct hostent *host; - host = gethostbyname(sys_statshost.GetHumanString()); + host = gethostbyname(sys_statshost); if (host == nullptr) { DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); @@ -94,10 +94,10 @@ bool I_HTTPRequest(const char* request) SockAddr.sin_port = htons(sys_statsport); 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.GetHumanString()); + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *sys_statshost); if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *sys_statshost); return false; } send(Socket, request, (int)strlen(request), 0); @@ -119,7 +119,7 @@ bool I_HTTPRequest(const char* request) #else bool I_HTTPRequest(const char* request) { - if (sys_statshost.GetHumanString() == NULL || sys_statshost.GetHumanString()[0] == 0) + if ((*sys_statshost)[0] == 0) return false; // no host, disable int sockfd, portno, n; @@ -135,7 +135,7 @@ bool I_HTTPRequest(const char* request) return false; } - server = gethostbyname(sys_statshost.GetHumanString()); + server = gethostbyname(sys_statshost); if (server == NULL) { DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); @@ -148,10 +148,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.GetHumanString()); + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", *sys_statshost); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", *sys_statshost); return false; } @@ -174,20 +174,24 @@ bool I_HTTPRequest(const char* request) static int GetOSVersion() { #ifdef _WIN32 +#ifndef _M_ARM64 if (sizeof(void*) == 4) // 32 bit { BOOL res; if (IsWow64Process(GetCurrentProcess(), &res) && res) { - return 2; + return 1; } - return 1; + return 0; } else { - if (sys_ostype == 2) return 3; - else return 4; + if (sys_ostype == 2) return 2; + else return 3; } +#else + return 4; +#endif #elif defined __APPLE__ @@ -196,9 +200,8 @@ static int GetOSVersion() #else return 5; #endif -#else -// fall-through linux stuff here +#else // fall-through linux stuff here #ifdef __arm__ return 9; #else @@ -262,12 +265,12 @@ static int GetCoreInfo() static int GetRenderInfo() { + if (screen->Backend() == 0) return 1; if (screen->Backend() == 1) return 4; auto info = gl_getInfo(); if (!info.second) { - if ((screen->hwcaps & (RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE)) == (RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE)) return 2; - return 1; + return 2; } return 3; } @@ -291,7 +294,7 @@ void D_DoAnonStats() { #ifndef _DEBUG // Do not repeat if already sent. - if (sys_statsenabled47 != 1 || sentstats_hwr_done >= CHECKVERSION) + if (sys_statsenabled49 != 1 || sentstats_hwr_done >= CHECKVERSION) { return; } @@ -304,7 +307,7 @@ 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.GetHumanString(), GAMENAME, VERSIONSTR); + GetRenderInfo(), GetCoreInfo(), GetOSVersion(), GetGLVersion(), URLencode(screen->vendorstring).GetChars(), URLencode(screen->DeviceName()).GetChars(), *sys_statshost, GAMENAME, VERSIONSTR); DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); #if 1//ndef _DEBUG // Don't send info in debug builds @@ -317,7 +320,7 @@ void D_DoAnonStats() void D_ConfirmSendStats() { - if (sys_statsenabled47 >= 0) + if (sys_statsenabled49 >= 0) { return; } @@ -340,8 +343,7 @@ void D_ConfirmSendStats() UCVarValue enabled = { 0 }; #ifdef _WIN32 - extern HWND Window; - enabled.Int = MessageBoxA(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES; + enabled.Int = MessageBoxA(mainwindow.GetHandle(), MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES; #elif defined __APPLE__ const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); @@ -374,7 +376,7 @@ void D_ConfirmSendStats() enabled.Int = SDL_ShowMessageBox(&messageboxdata, &buttonid) == 0 && buttonid == 0; #endif // _WIN32 - sys_statsenabled47.ForceSet(enabled, CVAR_Int); + sys_statsenabled49->ForceSet(enabled, CVAR_Int); } #endif // NO_SEND_STATS diff --git a/src/d_defcvars.cpp b/src/d_defcvars.cpp index 4d38e57fa..2da8f0bd2 100644 --- a/src/d_defcvars.cpp +++ b/src/d_defcvars.cpp @@ -119,6 +119,15 @@ void D_GrabCVarDefaults() SHOULD_BLACKLIST(queryiwad_key) SHOULD_BLACKLIST(vid_gpuswitch) SHOULD_BLACKLIST(vr_enable_quadbuffered) + SHOULD_BLACKLIST(m_filter) + SHOULD_BLACKLIST(gl_debug) + SHOULD_BLACKLIST(vid_adapter) + SHOULD_BLACKLIST(sys_statsenabled47) + SHOULD_BLACKLIST(sys_statsenabled49) + SHOULD_BLACKLIST(save_dir) + SHOULD_BLACKLIST(sys_statsport) + SHOULD_BLACKLIST(sys_statshost) + SHOULD_BLACKLIST(sentstats_hwr_done) var = FindCVar(CurrentFindCVar, NULL); diff --git a/src/d_event.h b/src/d_event.h index 822286d0e..409dcb62b 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -27,31 +27,9 @@ #include "basics.h" #include #include "d_eventbase.h" - +#include "gamestate.h" -enum gameaction_t : int -{ - ga_nothing, - ga_loadlevel, // not used. - ga_newgame, - ga_newgame2, - ga_recordgame, - ga_loadgame, - ga_loadgamehidecon, - ga_loadgameplaydemo, - ga_autoloadgame, - ga_savegame, - ga_autosave, - ga_playdemo, - ga_completed, - ga_slideshow, - ga_worlddone, - ga_screenshot, - ga_togglemap, - ga_fullconsole, - ga_resumeconversation, -}; @@ -97,6 +75,31 @@ typedef enum // Called by IO functions when input is detected. void D_Render(std::function action, bool interpolate); +enum gameaction_t : int +{ + ga_nothing, + ga_loadlevel, // not used. + ga_newgame, + ga_newgame2, + ga_recordgame, + ga_loadgame, + ga_loadgamehidecon, + ga_loadgameplaydemo, + ga_autoloadgame, + ga_savegame, + ga_autosave, + ga_playdemo, + ga_completed, + ga_slideshow, + ga_worlddone, + ga_screenshot, + ga_togglemap, + ga_fullconsole, + ga_resumeconversation, + ga_intro, + ga_intermission, + ga_titleloop, +}; extern gameaction_t gameaction; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 567c7df45..431c37813 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -49,8 +49,12 @@ #include "findfile.h" #include "i_interface.h" -CVAR (Bool, queryiwad, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); -CVAR (String, defaultiwad, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); +EXTERN_CVAR(Bool, queryiwad); +EXTERN_CVAR(String, defaultiwad); +EXTERN_CVAR(Bool, disableautoload) +EXTERN_CVAR(Bool, autoloadlights) +EXTERN_CVAR(Bool, autoloadbrightmaps) +EXTERN_CVAR(Bool, autoloadwidescreen) //========================================================================== // @@ -221,6 +225,36 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, sc.MustGetString(); iwad->Song = sc.String; } + else if (sc.Compare("LoadLights")) + { + sc.MustGetStringName("="); + sc.MustGetNumber(); + iwad->LoadLights = sc.Number; + } + else if (sc.Compare("LoadBrightmaps")) + { + sc.MustGetStringName("="); + sc.MustGetNumber(); + iwad->LoadBrightmaps = sc.Number; + } + else if (sc.Compare("LoadWidescreen")) + { + sc.MustGetStringName("="); + sc.MustGetNumber(); + iwad->LoadWidescreen = sc.Number; + } + else if (sc.Compare("DiscordAppId")) + { + sc.MustGetStringName("="); + sc.MustGetString(); + iwad->DiscordAppId = sc.String; + } + else if (sc.Compare("SteamAppId")) + { + sc.MustGetStringName("="); + sc.MustGetString(); + iwad->SteamAppId = sc.String; + } else { sc.ScriptError("Unknown keyword '%s'", sc.String); @@ -264,8 +298,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, // Look for IWAD definition lump // //========================================================================== -extern const char* iwad_folders[14]; -extern const char* iwad_reserved[12]; +void GetReserved(LumpFilterInfo& lfi); FIWadManager::FIWadManager(const char *firstfn, const char *optfn) { @@ -352,8 +385,7 @@ int FIWadManager::CheckIWADInfo(const char* fn) FileSystem check; LumpFilterInfo lfi; - for (auto p : iwad_folders) lfi.reservedFolders.Push(p); - for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); + GetReserved(lfi); TArray filenames; filenames.Push(fn); @@ -721,9 +753,21 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, stuff.Path = ExtractFileBase(found.mFullPath); wads.Push(stuff); } - pick = I_PickIWad(&wads[0], (int)wads.Size(), queryiwad, pick); + int flags = 0;; + + if (disableautoload) flags |= 1; + if (autoloadlights) flags |= 2; + if (autoloadbrightmaps) flags |= 4; + if (autoloadwidescreen) flags |= 8; + + pick = I_PickIWad(&wads[0], (int)wads.Size(), queryiwad, pick, flags); if (pick >= 0) { + disableautoload = !!(flags & 1); + autoloadlights = !!(flags & 2); + autoloadbrightmaps = !!(flags & 4); + autoloadwidescreen = !!(flags & 8); + // The newly selected IWAD becomes the new default defaultiwad = mIWadInfos[picks[pick].mInfoIndex].Name; } @@ -805,8 +849,16 @@ const FIWADInfo *FIWadManager::FindIWAD(TArray &wadfiles, const char *i GameStartupInfo.BkColor = iwad_info->BkColor; GameStartupInfo.FgColor = iwad_info->FgColor; } + if (GameStartupInfo.LoadWidescreen == -1) + GameStartupInfo.LoadWidescreen = iwad_info->LoadWidescreen; + if (GameStartupInfo.LoadLights == -1) + GameStartupInfo.LoadLights = iwad_info->LoadLights; + if (GameStartupInfo.LoadBrightmaps == -1) + GameStartupInfo.LoadBrightmaps = iwad_info->LoadBrightmaps; if (GameStartupInfo.Type == 0) GameStartupInfo.Type = iwad_info->StartupType; if (GameStartupInfo.Song.IsEmpty()) GameStartupInfo.Song = iwad_info->Song; + if (GameStartupInfo.DiscordAppId.IsEmpty()) GameStartupInfo.DiscordAppId = iwad_info->DiscordAppId; + if (GameStartupInfo.SteamAppId.IsEmpty()) GameStartupInfo.SteamAppId = iwad_info->SteamAppId; I_SetIWADInfo(); return iwad_info; } diff --git a/src/d_main.cpp b/src/d_main.cpp index efa8ca878..89919af0f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -31,10 +31,6 @@ #include #endif -#ifdef HAVE_FPU_CONTROL -#include -#endif - #if defined(__unix__) || defined(__APPLE__) #include #endif @@ -54,7 +50,7 @@ #include "s_sound.h" #include "v_video.h" #include "intermission/intermission.h" -#include "f_wipe.h" +#include "wipe.h" #include "m_argv.h" #include "m_misc.h" #include "menu.h" @@ -118,6 +114,9 @@ #include "hw_clock.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "doomfont.h" +#include "screenjob.h" +#include "startscreen.h" +#include "shiftstate.h" #ifdef __unix__ #include "i_system.h" // for SHARE_DIR @@ -128,12 +127,13 @@ EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Bool, cl_customizeinvulmap) EXTERN_CVAR(Bool, log_vgafont) EXTERN_CVAR(Bool, dlg_vgafont) +CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window... void DrawHUD(); void D_DoAnonStats(); void I_DetectOS(); void UpdateGenericUI(bool cvar); - +void Local_Job_Init(); // MACROS ------------------------------------------------------------------ @@ -153,6 +153,8 @@ void M_SaveDefaultsFinal(); void R_Shutdown(); void I_ShutdownInput(); void SetConsoleNotifyBuffer(); +void I_UpdateDiscordPresence(bool SendPresence, const char* curstatus, const char* appid, const char* steamappid); +bool M_SetSpecialMenu(FName& menu, int param); // game specific checks const FIWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); @@ -164,12 +166,15 @@ void G_BuildTiccmd (ticcmd_t* cmd); void D_DoAdvanceDemo (); void D_LoadWadSettings (); void ParseGLDefs(); -void DrawFullscreenSubtitle(const char *text); +void DrawFullscreenSubtitle(FFont* font, const char *text); void D_Cleanup(); void FreeSBarInfoScript(); void I_UpdateWindowTitle(); void S_ParseMusInfo(); void D_GrabCVarDefaults(); +void LoadHexFont(const char* filename); +void InitBuildTiles(); +bool OkForLocalization(FTextureID texnum, const char* substitute); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -190,6 +195,7 @@ EXTERN_CVAR (Bool, sv_unlimited_pickup) EXTERN_CVAR (Bool, r_drawplayersprites) EXTERN_CVAR (Bool, show_messages) EXTERN_CVAR(Bool, ticker) +EXTERN_CVAR(Bool, vid_fps) extern bool setmodeneeded; extern bool demorecording; @@ -198,8 +204,9 @@ extern bool insave; extern TDeletingArray LightDefaults; extern FName MessageBoxClass; -const char* iwad_folders[14] = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/", "materials/"}; -const char* iwad_reserved[12] = { "mapinfo", "zmapinfo", "gameinfo", "sndinfo", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "maps/" }; +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) @@ -224,6 +231,7 @@ CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL | CVAR_VIRTUAL) // PUBLIC DATA DEFINITIONS ------------------------------------------------- +#ifndef NO_SWRENDERER CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (self < 0 || self > 4) @@ -244,6 +252,7 @@ CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN // No further checks needed. All this changes now is which scene drawer the render backend calls. } +#endif CUSTOM_CVAR (Int, fraglimit, 0, CVAR_SERVERINFO) { @@ -286,18 +295,27 @@ CUSTOM_CVAR (String, vid_cursor, "None", CVAR_ARCHIVE | CVAR_NOINITCALL) } // Controlled by startup dialog -CVAR (Bool, disableautoload, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -CVAR (Bool, autoloadbrightmaps, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -CVAR (Bool, autoloadlights, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -CVAR (Bool, autoloadwidescreen, true, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -CVAR (Bool, r_debug_disable_vis_filter, false, 0) -CVAR(Bool, vid_fps, false, 0) +CVAR(Bool, disableautoload, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) +CVAR(Bool, autoloadbrightmaps, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) +CVAR(Bool, autoloadlights, false, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) +CVAR(Bool, autoloadwidescreen, true, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) +CVAR(Bool, r_debug_disable_vis_filter, false, 0) CVAR(Int, vid_showpalette, 0, 0) +CUSTOM_CVAR (Bool, i_discordrpc, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + I_UpdateWindowTitle(); +} +CUSTOM_CVAR(Int, I_FriendlyWindowTitle, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL) +{ + I_UpdateWindowTitle(); +} +CVAR(Bool, cl_nointros, false, CVAR_ARCHIVE) + + bool hud_toggled = false; bool wantToRestart; bool DrawFSHUD; // [RH] Draw fullscreen HUD? -TArray allwads; bool devparm; // started game with -devparm const char *D_DrawIcon; // [RH] Patch name of icon to draw on next refresh int NoWipe; // [RH] Allow wipe? (Needs to be set each time) @@ -306,19 +324,19 @@ FString startmap; bool autostart; bool advancedemo; FILE *debugfile; -FILE *hashfile; gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe bool PageBlank; -FGameTexture *Advisory; +FTextureID Advisory; FTextureID Page; const char *Subtitle; bool nospriterename; -FStartupInfo GameStartupInfo; FString lastIWAD; int restart = 0; -bool AppActive = true; +extern bool AppActive; bool playedtitlemusic; +FStartScreen* StartScreen; + cycle_t FrameCycles; // [SP] Store the capabilities of the renderer in a global variable, to prevent excessive per-frame processing @@ -383,9 +401,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)) + if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4) || Level->LightProbes.Size() > 0) { - Level->HasDynamicLights = !!Level->lights; + Level->HasDynamicLights = Level->lights || Level->LightProbes.Size() > 0; } else Level->HasDynamicLights = false; // lights are off so effectively we have none. if (interpolate) Level->interpolator.DoInterpolations(I_GetTimeFrac()); @@ -546,6 +564,20 @@ CVAR (Flag, sv_nocountendmonst, dmflags2, DF2_NOCOUNTENDMONST); CVAR (Flag, sv_respawnsuper, dmflags2, DF2_RESPAWN_SUPER); CVAR (Flag, sv_nothingspawn, dmflags2, DF2_NO_COOP_THING_SPAWN); CVAR (Flag, sv_alwaysspawnmulti, dmflags2, DF2_ALWAYS_SPAWN_MULTI); +CVAR (Flag, sv_novertspread, dmflags2, DF2_NOVERTSPREAD); +CVAR (Flag, sv_noextraammo, dmflags2, DF2_NO_EXTRA_AMMO); + +//========================================================================== +// +// CVAR dmflags3 +// +//========================================================================== + +CUSTOM_CVAR(Int, dmflags3, 0, CVAR_SERVERINFO | CVAR_NOINITCALL) +{ +} + +CVAR(Flag, sv_noplayerclip, dmflags3, DF3_NO_PLAYER_CLIP); //========================================================================== // @@ -587,44 +619,44 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) v = COMPATF_SHORTTEX | COMPATF_STAIRINDEX | COMPATF_USEBLOCKING | COMPATF_NODOORLIGHT | COMPATF_SPRITESORT | COMPATF_TRACE | COMPATF_MISSILECLIP | COMPATF_SOUNDTARGET | COMPATF_DEHHEALTH | COMPATF_CROSSDROPOFF | COMPATF_LIGHT | COMPATF_MASKEDMIDTEX; - w = COMPATF2_FLOORMOVE | COMPATF2_EXPLODE1; + w = COMPATF2_FLOORMOVE | COMPATF2_EXPLODE1 | COMPATF2_NOMBF21; break; case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set) v = COMPATF_SHORTTEX | COMPATF_STAIRINDEX | COMPATF_USEBLOCKING | COMPATF_NODOORLIGHT | COMPATF_SPRITESORT | COMPATF_TRACE | COMPATF_MISSILECLIP | COMPATF_SOUNDTARGET | COMPATF_NO_PASSMOBJ | COMPATF_LIMITPAIN | - COMPATF_DEHHEALTH | COMPATF_INVISIBILITY | COMPATF_CROSSDROPOFF | COMPATF_CORPSEGIBS | COMPATF_HITSCAN | + COMPATF_DEHHEALTH | COMPATF_INVISIBILITY | COMPATF_CROSSDROPOFF | COMPATF_VILEGHOSTS | COMPATF_HITSCAN | COMPATF_WALLRUN | COMPATF_NOTOSSDROPS | COMPATF_LIGHT | COMPATF_MASKEDMIDTEX; - w = COMPATF2_BADANGLES | COMPATF2_FLOORMOVE | COMPATF2_POINTONLINE | COMPATF2_EXPLODE2; + w = COMPATF2_BADANGLES | COMPATF2_FLOORMOVE | COMPATF2_POINTONLINE | COMPATF2_EXPLODE2 | COMPATF2_NOMBF21; break; case 3: // Boom compat mode v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_MASKEDMIDTEX; - w = COMPATF2_EXPLODE1; + w = COMPATF2_EXPLODE1 | COMPATF2_NOMBF21; break; case 4: // Old ZDoom compat mode v = COMPATF_SOUNDTARGET | COMPATF_LIGHT; - w = COMPATF2_MULTIEXIT | COMPATF2_TELEPORT | COMPATF2_PUSHWINDOW | COMPATF2_CHECKSWITCHRANGE; + w = COMPATF2_MULTIEXIT | COMPATF2_TELEPORT | COMPATF2_PUSHWINDOW | COMPATF2_CHECKSWITCHRANGE | COMPATF2_NOMBF21; break; case 5: // MBF compat mode v = COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_MUSHROOM | COMPATF_MBFMONSTERMOVE | COMPATF_NOBLOCKFRIENDS | COMPATF_MASKEDMIDTEX; - w = COMPATF2_EXPLODE1 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT; + w = COMPATF2_EXPLODE1 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT | COMPATF2_NOMBF21; break; case 6: // Boom with some added settings to reenable some 'broken' behavior v = COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_NO_PASSMOBJ | - COMPATF_INVISIBILITY | COMPATF_CORPSEGIBS | COMPATF_HITSCAN | COMPATF_WALLRUN | COMPATF_NOTOSSDROPS | COMPATF_MASKEDMIDTEX; - w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE2; + COMPATF_INVISIBILITY | COMPATF_HITSCAN | COMPATF_WALLRUN | COMPATF_NOTOSSDROPS | COMPATF_MASKEDMIDTEX; + w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE2 | COMPATF2_NOMBF21; break; case 7: // Stricter MBF compatibility - v = COMPATF_CORPSEGIBS | COMPATF_NOBLOCKFRIENDS | COMPATF_MBFMONSTERMOVE | COMPATF_INVISIBILITY | + v = COMPATF_NOBLOCKFRIENDS | COMPATF_MBFMONSTERMOVE | COMPATF_INVISIBILITY | COMPATF_NOTOSSDROPS | COMPATF_MUSHROOM | COMPATF_NO_PASSMOBJ | COMPATF_BOOMSCROLL | COMPATF_WALLRUN | COMPATF_TRACE | COMPATF_HITSCAN | COMPATF_MISSILECLIP | COMPATF_MASKEDMIDTEX | COMPATF_SOUNDTARGET; - w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE1 | COMPATF2_EXPLODE2 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT; + w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE1 | COMPATF2_EXPLODE2 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT | COMPATF2_NOMBF21; break; } compatflags = v; @@ -656,7 +688,7 @@ CVAR (Flag, compat_anybossdeath, compatflags, COMPATF_ANYBOSSDEATH); CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR); CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM); CVAR (Flag, compat_mbfmonstermove, compatflags, COMPATF_MBFMONSTERMOVE); -CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS); +CVAR (Flag, compat_vileghosts, compatflags, COMPATF_VILEGHOSTS); CVAR (Flag, compat_noblockfriends, compatflags, COMPATF_NOBLOCKFRIENDS); CVAR (Flag, compat_spritesort, compatflags, COMPATF_SPRITESORT); CVAR (Flag, compat_hitscan, compatflags, COMPATF_HITSCAN); @@ -676,6 +708,7 @@ CVAR (Flag, compat_explode2, compatflags2, COMPATF2_EXPLODE2); CVAR (Flag, compat_railing, compatflags2, COMPATF2_RAILING); CVAR (Flag, compat_avoidhazard, compatflags2, COMPATF2_AVOID_HAZARDS); CVAR (Flag, compat_stayonlift, compatflags2, COMPATF2_STAYONLIFT); +CVAR (Flag, compat_nombf21, compatflags2, COMPATF2_NOMBF21); CVAR(Bool, vid_activeinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -745,7 +778,34 @@ static void DrawPaletteTester(int paletteno) // Draws the fps counter, dot ticker, and palette debug. // //========================================================================== -uint64_t LastCount; +uint64_t LastFPS, LastMSCount; + +void CalcFps() +{ + static uint64_t LastMS = 0, LastSec = 0, FrameCount = 0, LastTic = 0; + + uint64_t ms = screen->FrameTime; + uint64_t howlong = ms - LastMS; + if ((signed)howlong > 0) // do this only once per frame. + { + uint32_t thisSec = (uint32_t)(ms / 1000); + if (LastSec < thisSec) + { + LastFPS = FrameCount / (thisSec - LastSec); + LastSec = thisSec; + FrameCount = 0; + } + FrameCount++; + LastMS = ms; + LastMSCount = howlong; + } +} + +ADD_STAT(fps) +{ + CalcFps(); + return FStringf("%2llu ms (%3llu fps)", (unsigned long long)LastMSCount , (unsigned long long)LastFPS); +} static void DrawRateStuff() { @@ -754,34 +814,19 @@ static void DrawRateStuff() // Draws frame time and cumulative fps if (vid_fps) { - uint64_t ms = screen->FrameTime; - uint64_t howlong = ms - LastMS; - if ((signed)howlong >= 0) - { - char fpsbuff[40]; - int chars; - int rate_x; + CalcFps(); + char fpsbuff[40]; + int chars; + int rate_x; + int textScale = active_con_scale(twod); - int textScale = active_con_scale(twod); - - chars = mysnprintf(fpsbuff, countof(fpsbuff), "%2llu ms (%3llu fps)", (unsigned long long)howlong, (unsigned long long)LastCount); - rate_x = screen->GetWidth() / textScale - NewConsoleFont->StringWidth(&fpsbuff[0]); - ClearRect(twod, rate_x * textScale, 0, screen->GetWidth(), NewConsoleFont->GetHeight() * textScale, GPalette.BlackIndex, 0); - DrawText(twod, NewConsoleFont, CR_WHITE, rate_x, 0, (char*)&fpsbuff[0], - DTA_VirtualWidth, screen->GetWidth() / textScale, - DTA_VirtualHeight, screen->GetHeight() / textScale, - DTA_KeepRatio, true, TAG_DONE); - - uint32_t thisSec = (uint32_t)(ms / 1000); - if (LastSec < thisSec) - { - LastCount = FrameCount / (thisSec - LastSec); - LastSec = thisSec; - FrameCount = 0; - } - FrameCount++; - } - LastMS = ms; + chars = mysnprintf(fpsbuff, countof(fpsbuff), "%2llu ms (%3llu fps)", (unsigned long long)LastMSCount, (unsigned long long)LastFPS); + rate_x = screen->GetWidth() / textScale - NewConsoleFont->StringWidth(&fpsbuff[0]); + ClearRect(twod, rate_x * textScale, 0, screen->GetWidth(), NewConsoleFont->GetHeight() * textScale, GPalette.BlackIndex, 0); + DrawText(twod, NewConsoleFont, CR_WHITE, rate_x, 0, (char*)&fpsbuff[0], + DTA_VirtualWidth, screen->GetWidth() / textScale, + DTA_VirtualHeight, screen->GetHeight() / textScale, + DTA_KeepRatio, true, TAG_DONE); } int Height = screen->GetHeight(); @@ -807,9 +852,18 @@ static void DrawRateStuff() } } +static void DrawOverlays() +{ + NetUpdate (); + C_DrawConsole (); + M_Drawer (); + DrawRateStuff(); + if (!hud_toggled) + FStat::PrintStat (twod); +} + static void End2DAndUpdate() { - DrawRateStuff(); twod->End(); CheckBench(); screen->Update(); @@ -826,7 +880,7 @@ static void End2DAndUpdate() void D_Display () { - FGameTexture *wipe = nullptr; + FTexture *wipestart = nullptr; int wipe_type; sector_t *viewsec; @@ -854,14 +908,11 @@ void D_Display () auto &vp = r_viewpoint; if (viewactive) { - DAngle fov = 90.f; + DAngle fov = DAngle::fromDeg(90.); AActor *cam = players[consoleplayer].camera; if (cam) - { - if (cam->player) - fov = cam->player->FOV; - else fov = cam->CameraFOV; - } + fov = DAngle::fromDeg(cam->GetFOV(I_GetTimeFrac())); + R_SetFOV(vp, fov); } @@ -889,10 +940,10 @@ void D_Display () } // [RH] Allow temporarily disabling wipes - if (NoWipe) + if (NoWipe || !CanWipe()) { - NoWipe--; - wipe = nullptr; + if (NoWipe > 0) NoWipe--; + wipestart = nullptr; wipegamestate = gamestate; } // No wipes when in a stereo3D VR mode @@ -901,7 +952,7 @@ void D_Display () if (vr_mode == 0 || vid_rendermode != 4) { // save the current screen if about to wipe - wipe = MakeGameTexture(screen->WipeStartScreen(), nullptr, ETextureType::SWCanvas); + wipestart = screen->WipeStartScreen(); switch (wipegamestate) { @@ -927,7 +978,7 @@ void D_Display () } else { - wipe = nullptr; + wipestart = nullptr; } screen->FrameTime = I_msTimeFS(); @@ -1003,18 +1054,16 @@ void D_Display () End2DAndUpdate (); return; - case GS_INTERMISSION: - WI_Drawer (); - break; - - case GS_FINALE: - F_Drawer (); - break; - case GS_DEMOSCREEN: D_PageDrawer (); break; + case GS_CUTSCENE: + case GS_INTRO: + ScreenJobDraw(); + break; + + default: break; } @@ -1024,7 +1073,7 @@ void D_Display () CT_Drawer (); // draw pause pic - if ((paused || pauseext) && menuactive == MENU_Off) + if ((paused || pauseext) && menuactive == MENU_Off && StatusBar != nullptr) { // [MK] optionally let the status bar handle this bool skip = false; @@ -1075,54 +1124,17 @@ void D_Display () } } - if (!wipe || NoWipe < 0 || wipe_type == wipe_None || hud_toggled) + if (!wipestart || NoWipe < 0 || wipe_type == wipe_None || hud_toggled) { - if (wipe != nullptr) delete wipe; - wipe = nullptr; - NetUpdate (); // send out any new accumulation - // normal update - // draw ZScript UI stuff - C_DrawConsole (); // draw console - M_Drawer (); // menu is drawn even on top of everything - if (!hud_toggled) - FStat::PrintStat (twod); + if (wipestart != nullptr) wipestart->DecRef(); + wipestart = nullptr; + DrawOverlays(); End2DAndUpdate (); } else { - // wipe update - uint64_t wipestart, nowtime, diff; - bool done; - - GSnd->SetSfxPaused(true, 1); - I_FreezeTime(true); - twod->End(); - auto wipend = MakeGameTexture(screen->WipeEndScreen(), nullptr, ETextureType::SWCanvas); - auto wiper = Wiper::Create(wipe_type); - wiper->SetTextures(wipe, wipend); - - wipestart = I_msTime(); NetUpdate(); // send out any new accumulation - - do - { - do - { - I_WaitVBL(2); - nowtime = I_msTime(); - diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. - } while (diff < 1); - wipestart = nowtime; - twod->Begin(screen->GetWidth(), screen->GetHeight()); - done = wiper->Run(1); - C_DrawConsole (); // console and - M_Drawer (); // menu are drawn even on top of wipes - End2DAndUpdate (); - NetUpdate (); // [RH] not sure this is needed anymore - } while (!done); - delete wiper; - I_FreezeTime(false); - GSnd->SetSfxPaused(false, 1); + PerformWipe(wipestart, screen->WipeEndScreen(), wipe_type, false, DrawOverlays); } cycles.Unclock(); FrameCycles = cycles; @@ -1153,7 +1165,6 @@ void D_ErrorCleanup () { menuactive = MENU_Off; } - if (gamestate == GS_INTERMISSION) gamestate = GS_DEMOSCREEN; insave = false; ClearGlobalVMStack(); } @@ -1175,9 +1186,9 @@ void D_DoomLoop () r_NoInterpolate = true; Page.SetInvalid(); Subtitle = nullptr; - Advisory = nullptr; + Advisory.SetInvalid(); - vid_cursor.Callback(); + vid_cursor->Callback(); for (;;) { @@ -1215,6 +1226,7 @@ void D_DoomLoop () } // Update display, next frame, with current state. I_StartTic (); + D_ProcessEvents(); D_Display (); S_UpdateMusic(); if (wantToRestart) @@ -1227,14 +1239,14 @@ void D_DoomLoop () { if (error.GetMessage ()) { - Printf (PRINT_BOLD, "\n%s\n", error.GetMessage()); + Printf (PRINT_NONOTIFY | PRINT_BOLD, "\n%s\n", error.GetMessage()); } D_ErrorCleanup (); } catch (CVMAbortException &error) { error.MaybePrintMessage(); - Printf("%s", error.stacktrace.GetChars()); + Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", error.stacktrace.GetChars()); D_ErrorCleanup(); } } @@ -1263,7 +1275,7 @@ void D_PageDrawer (void) ClearRect(twod, 0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0); if (Page.Exists()) { - DrawTexture(twod, TexMan.GetGameTexture(Page, true), 0, 0, + DrawTexture(twod, Page, true, 0, 0, DTA_Fullscreen, true, DTA_Masked, false, DTA_BilinearFilter, true, @@ -1271,11 +1283,12 @@ void D_PageDrawer (void) } if (Subtitle != nullptr) { - DrawFullscreenSubtitle(GStrings[Subtitle]); + FFont* font = generic_ui ? NewSmallFont : SmallFont; + DrawFullscreenSubtitle(font, GStrings[Subtitle]); } - if (Advisory != nullptr) + if (Advisory.isValid()) { - DrawTexture(twod, Advisory, 4, 160, DTA_320x200, true, TAG_DONE); + DrawTexture(twod, Advisory, true, 4, 160, DTA_320x200, true, TAG_DONE); } } @@ -1349,7 +1362,7 @@ void D_DoStrifeAdvanceDemo () case 3: pagetic = 7 * TICRATE; pagename = "PANEL1"; - subtitle = "TXT_SUB_INTRO1"; + subtitle = "$TXT_SUB_INTRO1"; S_Sound (CHAN_VOICE, CHANF_UI, voices[0], 1, ATTN_NORM); // The new Strife teaser has D_FMINTR. // The full retail Strife has D_INTRO. @@ -1360,35 +1373,35 @@ void D_DoStrifeAdvanceDemo () case 4: pagetic = 9 * TICRATE; pagename = "PANEL2"; - subtitle = "TXT_SUB_INTRO2"; + subtitle = "$TXT_SUB_INTRO2"; S_Sound (CHAN_VOICE, CHANF_UI, voices[1], 1, ATTN_NORM); break; case 5: pagetic = 12 * TICRATE; pagename = "PANEL3"; - subtitle = "TXT_SUB_INTRO3"; + subtitle = "$TXT_SUB_INTRO3"; S_Sound (CHAN_VOICE, CHANF_UI, voices[2], 1, ATTN_NORM); break; case 6: pagetic = 11 * TICRATE; pagename = "PANEL4"; - subtitle = "TXT_SUB_INTRO4"; + subtitle = "$TXT_SUB_INTRO4"; S_Sound (CHAN_VOICE, CHANF_UI, voices[3], 1, ATTN_NORM); break; case 7: pagetic = 10 * TICRATE; pagename = "PANEL5"; - subtitle = "TXT_SUB_INTRO5"; + subtitle = "$TXT_SUB_INTRO5"; S_Sound (CHAN_VOICE, CHANF_UI, voices[4], 1, ATTN_NORM); break; case 8: pagetic = 16 * TICRATE; pagename = "PANEL6"; - subtitle = "TXT_SUB_INTRO6"; + subtitle = "$TXT_SUB_INTRO6"; S_Sound (CHAN_VOICE, CHANF_UI, voices[5], 1, ATTN_NORM); break; @@ -1464,7 +1477,7 @@ void D_DoAdvanceDemo (void) case 3: if (gameinfo.advisoryTime) { - Advisory = TexMan.GetGameTextureByName("ADVISOR"); + Advisory = TexMan.GetTextureID("ADVISOR", ETextureType::MiscPatch); demosequence = 1; pagetic = (int)(gameinfo.advisoryTime * TICRATE); break; @@ -1473,7 +1486,7 @@ void D_DoAdvanceDemo (void) [[fallthrough]]; case 1: - Advisory = NULL; + Advisory.SetInvalid(); if (!M_DemoNoPlay) { democount++; @@ -1763,14 +1776,6 @@ static void GetCmdLineFiles(TArray &wadfiles) } } -static void CopyFiles(TArray &to, TArray &from) -{ - unsigned int ndx = to.Reserve(from.Size()); - for(unsigned i=0;i &pwads, const char *fn, const char *data, int size) { @@ -1873,6 +1878,16 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char sc.MustGetNumber(); GameStartupInfo.LoadWidescreen = !!sc.Number; } + else if (!nextKey.CompareNoCase("DISCORDAPPID")) + { + sc.MustGetString(); + GameStartupInfo.DiscordAppId = sc.String; + } + else if (!nextKey.CompareNoCase("STEAMAPPID")) + { + sc.MustGetString(); + GameStartupInfo.SteamAppId = sc.String; + } else { // Silently ignore unknown properties @@ -1886,13 +1901,18 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char return iwad; } +void GetReserved(LumpFilterInfo& lfi) +{ + for (auto p : iwad_folders) lfi.reservedFolders.Push(p); + for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); +} + static FString CheckGameInfo(TArray & pwads) { FileSystem check; LumpFilterInfo lfi; - for (auto p : iwad_folders) lfi.reservedFolders.Push(p); - for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); + 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); @@ -1933,23 +1953,6 @@ static void SetMapxxFlag() static void D_DoomInit() { - // Set the FPU precision to 53 significant bits. This is the default - // for Visual C++, but not for GCC, so some slight math variances - // might crop up if we leave it alone. -#if defined(_FPU_GETCW) && defined(_FPU_EXTENDED) && defined(_FPU_DOUBLE) - { - int cw; - _FPU_GETCW(cw); - cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; - _FPU_SETCW(cw); - } -#elif defined(_PC_53) -// On the x64 architecture, changing the floating point precision is not supported. -#ifndef _WIN64 - int cfp = _control87(_PC_53, _MCW_PC); -#endif -#endif - // Check response files before coalescing file parameters. M_FindResponseFile (); @@ -1962,22 +1965,6 @@ static void D_DoomInit() gamestate = GS_STARTUP; - const char *v = Args->CheckValue("-rngseed"); - if (v) - { - rngseed = staticrngseed = atoi(v); - use_staticrng = true; - if (!batchrun) Printf("D_DoomInit: Static RNGseed %d set.\n", rngseed); - } - else - { - rngseed = I_MakeRNGSeed(); - use_staticrng = false; - } - srand(rngseed); - - FRandom::StaticClearRandom (); - if (!batchrun) Printf ("M_LoadDefaults: Load system defaults.\n"); M_LoadDefaults (); // load before initing other systems } @@ -1988,26 +1975,26 @@ static void D_DoomInit() // //========================================================================== -static void AddAutoloadFiles(const char *autoname) +static void AddAutoloadFiles(const char *autoname, TArray& allwads) { LumpFilterIWAD.Format("%s.", autoname); // The '.' is appened to simplify parsing the string // [SP] Dialog reaction - load lights.pk3 and brightmaps.pk3 based on user choices - if (!(gameinfo.flags & GI_SHAREWARE)) + if (!(gameinfo.flags & GI_SHAREWARE) && !(Args->CheckParm("-noextras"))) { - if (GameStartupInfo.LoadLights == 1 || (GameStartupInfo.LoadLights != 0 && autoloadlights)) + if ((GameStartupInfo.LoadLights == 1 || (GameStartupInfo.LoadLights != 0 && autoloadlights)) && !(Args->CheckParm("-nolights"))) { const char *lightswad = BaseFileSearch ("lights.pk3", NULL, true, GameConfig); if (lightswad) D_AddFile (allwads, lightswad, true, -1, GameConfig); } - if (GameStartupInfo.LoadBrightmaps == 1 || (GameStartupInfo.LoadBrightmaps != 0 && autoloadbrightmaps)) + if ((GameStartupInfo.LoadBrightmaps == 1 || (GameStartupInfo.LoadBrightmaps != 0 && autoloadbrightmaps)) && !(Args->CheckParm("-nobrightmaps"))) { const char *bmwad = BaseFileSearch ("brightmaps.pk3", NULL, true, GameConfig); if (bmwad) D_AddFile (allwads, bmwad, true, -1, GameConfig); } - if (GameStartupInfo.LoadWidescreen == 1 || (GameStartupInfo.LoadWidescreen != 0 && autoloadwidescreen)) + if ((GameStartupInfo.LoadWidescreen == 1 || (GameStartupInfo.LoadWidescreen != 0 && autoloadwidescreen)) && !(Args->CheckParm("-nowidescreen"))) { const char *wswad = BaseFileSearch ("game_widescreen_gfx.pk3", NULL, true, GameConfig); if (wswad) @@ -2178,6 +2165,7 @@ static void CheckCmdLine() timelimit = 20.f; } + if (!StartScreen) return; // // Build status bar line! // @@ -2666,6 +2654,8 @@ bool System_WantLeftButton() static bool System_DispatchEvent(event_t* ev) { + shiftState.AddEvent(ev); + if (ev->type == EV_Mouse && menuactive == MENU_Off && ConsoleState != c_down && ConsoleState != c_falling && !primaryLevel->localEventManager->Responder(ev) && !paused) { if (buttonMap.ButtonDown(Button_Mlook) || freelook) @@ -2710,7 +2700,7 @@ static bool System_CaptureModeInGame() case 0: return gamestate == GS_LEVEL; case 1: - return gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE; + return gamestate == GS_LEVEL || gamestate == GS_CUTSCENE; case 2: return true; } @@ -2773,7 +2763,7 @@ FString System_GetLocationDescription() auto& vp = r_viewpoint; auto Level = vp.ViewLevel; return Level == nullptr ? FString() : FStringf("Map %s: \"%s\",\nx = %1.4f, y = %1.4f, z = %1.4f, angle = %1.4f, pitch = %1.4f\n%llu fps\n\n", - Level->MapName.GetChars(), Level->LevelName.GetChars(), vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw.Degrees, vp.Angles.Pitch.Degrees, (unsigned long long)LastCount); + Level->MapName.GetChars(), Level->LevelName.GetChars(), vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw.Degrees(), vp.Angles.Pitch.Degrees(), (unsigned long long)LastFPS); } @@ -2788,6 +2778,16 @@ void System_ConsoleToggled(int state) D_ToggleHud(); } +void System_LanguageChanged(const char* lang) +{ + for (auto Level : AllLevels()) + { + // does this even make sense on secondary levels...? + if (Level->info != nullptr) Level->LevelName = Level->info->LookupLevelName(); + } + I_UpdateWindowTitle(); +} + //========================================================================== // // DoomSpecificInfo @@ -2833,7 +2833,7 @@ void System_CrashInfo(char* buffer, size_t bufflen, const char *lfstr) buffer += mysnprintf(buffer, buffend - buffer, "%s%sviewx = %f", lfstr, lfstr, vp.Pos.X); buffer += mysnprintf(buffer, buffend - buffer, "%sviewy = %f", lfstr, vp.Pos.Y); buffer += mysnprintf(buffer, buffend - buffer, "%sviewz = %f", lfstr, vp.Pos.Z); - buffer += mysnprintf(buffer, buffend - buffer, "%sviewangle = %f", lfstr, vp.Angles.Yaw.Degrees); + buffer += mysnprintf(buffer, buffend - buffer, "%sviewangle = %f", lfstr, vp.Angles.Yaw.Degrees()); } } buffer += mysnprintf(buffer, buffend - buffer, "%s", lfstr); @@ -2950,7 +2950,6 @@ extern DThinker* NextToThink; static void GC_MarkGameRoots() { - GC::Mark(DIntermissionController::CurrentIntermission); GC::Mark(staticEventManager.FirstEventHandler); GC::Mark(staticEventManager.LastEventHandler); for (auto Level : AllLevels()) @@ -2972,8 +2971,549 @@ static void System_ToggleFullConsole() gameaction = ga_fullconsole; } +static void System_StartCutscene(bool blockui) +{ + gameaction = blockui ? ga_intro : ga_intermission; +} + +static void System_SetTransition(int type) +{ + if (type != wipe_None) wipegamestate = type == wipe_Burn? GS_FORCEWIPEBURN : type == wipe_Fade? GS_FORCEWIPEFADE : GS_FORCEWIPEMELT; +} + +static void System_HudScaleChanged() +{ + if (StatusBar) + { + StatusBar->SetScale(); + setsizeneeded = true; + } +} + bool CheckSkipGameOptionBlock(const char* str); +//========================================================================== +// +// +// +//========================================================================== + +static FILE* D_GetHashFile() +{ + FILE *hashfile = nullptr; + + if (Args->CheckParm("-hashfiles")) + { + const char *filename = "fileinfo.txt"; + Printf("Hashing loaded content to: %s\n", filename); + hashfile = fopen(filename, "w"); + if (hashfile) + { + Printf("Notice: File hashing is incredibly verbose. Expect loading files to take much longer than usual.\n"); + fprintf(hashfile, "%s version %s (%s)\n", GAMENAME, GetVersionString(), GetGitHash()); +#ifdef __VERSION__ + fprintf(hashfile, "Compiler version: %s\n", __VERSION__); +#endif + fprintf(hashfile, "Command line:"); + for (int i = 0; i < Args->NumArgs(); ++i) + { + fprintf(hashfile, " %s", Args->GetArg(i)); + } + fprintf(hashfile, "\n"); + } + } + return hashfile; +} + +//========================================================================== +// +// D_InitGame +// +//========================================================================== + +static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArray& pwads) +{ + SavegameFolder = iwad_info->Autoname; + gameinfo.gametype = iwad_info->gametype; + gameinfo.flags = iwad_info->flags; + gameinfo.nokeyboardcheats = iwad_info->nokeyboardcheats; + gameinfo.ConfigName = iwad_info->Configname; + + const char *v = Args->CheckValue("-rngseed"); + if (v) + { + rngseed = staticrngseed = atoi(v); + use_staticrng = true; + if (!batchrun) Printf("D_DoomInit: Static RNGseed %d set.\n", rngseed); + } + else + { + rngseed = I_MakeRNGSeed(); + use_staticrng = false; + } + srand(rngseed); + + FRandom::StaticClearRandom (); + + FBaseCVar::DisableCallbacks(); + GameConfig->DoGameSetup (gameinfo.ConfigName); + + AddAutoloadFiles(iwad_info->Autoname, allwads); + + // Process automatically executed files + FExecList *exec; + FArgs *execFiles = new FArgs; + if (!(Args->CheckParm("-noautoexec"))) + GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName); + exec = D_MultiExec(execFiles, NULL); + delete execFiles; + + // Process .cfg files at the start of the command line. + execFiles = Args->GatherFiles ("-exec"); + exec = D_MultiExec(execFiles, exec); + delete execFiles; + + // [RH] process all + commands on the command line + exec = C_ParseCmdLineParams(exec); + + if (exec != NULL) + { + exec->AddPullins(allwads, GameConfig); + } + + if (!batchrun) Printf ("W_Init: Init WADfiles.\n"); + + LumpFilterInfo lfi; + lfi.dotFilter = LumpFilterIWAD; + + static const struct { int match; const char* name; } blanket[] = + { + { GAME_Raven, "game-Raven" }, + { GAME_DoomStrifeChex, "game-DoomStrifeChex" }, + { GAME_DoomChex, "game-DoomChex" }, + { GAME_Any, NULL } + }; + + for (auto& inf : blanket) + { + if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.Push(inf.name); + } + lfi.gameTypeFilter.Push(FStringf("game-%s", GameTypeName())); + + GetReserved(lfi); + + lfi.postprocessFunc = [&]() + { + RenameNerve(fileSystem); + RenameSprites(fileSystem, iwad_info->DeleteLumps); + FixMacHexen(fileSystem); + FindStrifeTeaserVoices(fileSystem); + }; + allwads.Append(std::move(pwads)); + + bool allowduplicates = Args->CheckParm("-allowduplicates"); + auto hashfile = D_GetHashFile(); + fileSystem.InitMultipleFiles (allwads, false, &lfi, allowduplicates, hashfile); + allwads.Clear(); + allwads.ShrinkToFit(); + SetMapxxFlag(); + + D_GrabCVarDefaults(); //parse DEFCVARS + InitPalette(); + + if (!batchrun) Printf("S_Init: Setting up sound.\n"); + S_Init(); + + int max_progress = TexMan.GuesstimateNumTextures(); + int per_shader_progress = 0;//screen->GetShaderCount()? (max_progress / 10 / screen->GetShaderCount()) : 0; + bool nostartscreen = batchrun || restart || Args->CheckParm("-join") || Args->CheckParm("-host") || Args->CheckParm("-norun"); + + if (GameStartupInfo.Type == FStartupInfo::DefaultStartup) + { + if (gameinfo.gametype == GAME_Hexen) + GameStartupInfo.Type = FStartupInfo::HexenStartup; + else if (gameinfo.gametype == GAME_Heretic) + GameStartupInfo.Type = FStartupInfo::HereticStartup; + else if (gameinfo.gametype == GAME_Strife) + GameStartupInfo.Type = FStartupInfo::StrifeStartup; + } + + StartScreen = nostartscreen? nullptr : GetGameStartScreen(per_shader_progress > 0 ? max_progress * 10 / 9 : max_progress + 3); + + GameConfig->DoKeySetup(gameinfo.ConfigName); + + // Now that wads are loaded, define mod-specific cvars. + ParseCVarInfo(); + + // Actually exec command line commands and exec files. + if (exec != NULL) + { + exec->ExecCommands(); + delete exec; + exec = NULL; + } + + // [RH] Initialize localizable strings. + GStrings.LoadStrings (language); + + V_InitFontColors (); + + // [RH] Moved these up here so that we can do most of our + // startup output in a fullscreen console. + + CT_Init (); + + if (!restart) + { + if (!batchrun) Printf ("I_Init: Setting up machine state.\n"); + CheckCPUID(&CPU); + CalculateCPUSpeed(); + auto ci = DumpCPUInfo(&CPU); + Printf("%s", ci.GetChars()); + } + + TexMan.Init(); + + 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(); + } + + } + else + { + // Update screen palette when restarting + screen->UpdatePalette(); + } + + // Base systems have been inited; enable cvar callbacks + FBaseCVar::EnableCallbacks (); + + // +compatmode cannot be used on the command line, so use this as a substitute + auto compatmodeval = Args->CheckValue("-compatmode"); + if (compatmodeval) + { + compatmode = (int)strtoll(compatmodeval, nullptr, 10); + } + + if (!batchrun) Printf ("ST_Init: Init startup screen.\n"); + if (!restart) + { + StartWindow = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5, StartScreen == nullptr); + } + else + { + StartWindow = new FStartupScreen(0); + } + + CheckCmdLine(); + + // [RH] Load sound environments + S_ParseReverbDef (); + + // [RH] Parse any SNDINFO lumps + if (!batchrun) Printf ("S_InitData: Load sound definitions.\n"); + S_InitData (); + + // [RH] Parse through all loaded mapinfo lumps + if (!batchrun) Printf ("G_ParseMapInfo: Load map definitions.\n"); + G_ParseMapInfo (iwad_info->MapInfo); + MessageBoxClass = gameinfo.MessageBoxClass; + endoomName = gameinfo.Endoom; + menuBlurAmount = gameinfo.bluramount; + ReadStatistics(); + + // MUSINFO must be parsed after MAPINFO + S_ParseMusInfo(); + + if (!batchrun) Printf ("Texman.Init: Init texture manager.\n"); + UpdateUpscaleMask(); + SpriteFrames.Clear(); + TexMan.AddTextures([]() + { + StartWindow->Progress(); + if (StartScreen) StartScreen->Progress(1); + }, CheckForHacks, InitBuildTiles); + PatchTextures(); + TexAnim.Init(); + C_InitConback(TexMan.CheckForTexture(gameinfo.BorderFlat, ETextureType::Flat), true, 0.25); + + FixWideStatusBar(); + + StartWindow->Progress(); + if (StartScreen) StartScreen->Progress(1); + V_InitFonts(); + InitDoomFonts(); + V_LoadTranslations(); + UpdateGenericUI(false); + + // [CW] Parse any TEAMINFO lumps. + if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); + TeamLibrary.ParseTeamInfo (); + + R_ParseTrnslate(); + PClassActor::StaticInit (); + Job_Init(); + + // [GRB] Initialize player class list + SetupPlayerClasses (); + + // [RH] Load custom key and weapon settings from WADs + D_LoadWadSettings (); + + // [GRB] Check if someone used clearplayerclasses but not addplayerclass + if (PlayerClasses.Size () == 0) + { + I_FatalError ("No player classes defined"); + } + + StartWindow->Progress(); + if (StartScreen) StartScreen->Progress (1); + + ParseGLDefs(); + + if (!batchrun) Printf ("R_Init: Init %s refresh subsystem.\n", gameinfo.ConfigName.GetChars()); + if (StartScreen) StartScreen->LoadingStatus ("Loading graphics", 0x3f); + if (StartScreen) StartScreen->Progress(1); + StartWindow->Progress(); + R_Init (); + + if (!batchrun) Printf ("DecalLibrary: Load decals.\n"); + DecalLibrary.ReadAllDecals (); + + // Load embedded Dehacked patches + D_LoadDehLumps(FromIWAD); + + // [RH] Add any .deh and .bex files on the command line. + // If there are none, try adding any in the config file. + // Note that the command line overrides defaults from the config. + + if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 && + gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked")) + { + const char *key; + const char *value; + + while (GameConfig->NextInSection (key, value)) + { + if (stricmp (key, "Path") == 0 && FileExists (value)) + { + if (!batchrun) Printf ("Applying patch %s\n", value); + D_LoadDehFile(value); + } + } + } + + // Load embedded Dehacked patches + D_LoadDehLumps(FromPWADs); + + // Create replacements for dehacked pickups + FinishDehPatch(); + + if (!batchrun) Printf("M_Init: Init menus.\n"); + SetDefaultMenuColors(); + M_Init(); + M_CreateGameMenus(); + + + // clean up the compiler symbols which are not needed any longer. + RemoveUnusedSymbols(); + + InitActorNumsFromMapinfo(); + InitSpawnablesFromMapinfo(); + PClassActor::StaticSetActorNums(); + + //Added by MC: + primaryLevel->BotInfo.getspawned.Clear(); + + FString *args; + int argcount = Args->CheckParmList("-bots", &args); + for (int p = 0; p < argcount; ++p) + { + primaryLevel->BotInfo.getspawned.Push(args[p]); + } + primaryLevel->BotInfo.spawn_tries = 0; + primaryLevel->BotInfo.wanted_botnum = primaryLevel->BotInfo.getspawned.Size(); + + if (!batchrun) Printf ("P_Init: Init Playloop state.\n"); + if (StartScreen) StartScreen->LoadingStatus ("Init game engine", 0x3f); + AM_StaticInit(); + P_Init (); + + P_SetupWeapons_ntohton(); + + //SBarInfo support. Note that the first SBARINFO lump contains the mugshot definition so it even needs to be read when a regular status bar is being used. + SBarInfo::Load(); + + if (!batchrun) + { + // [RH] User-configurable startup strings. Because BOOM does. + static const char *startupString[5] = { + "STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5" + }; + 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); + if (str != NULL && str[0] != '\0') + { + Printf("%s\n", str); + } + } + } + + if (!restart) + { + if (!batchrun) Printf ("D_CheckNetGame: Checking network game status.\n"); + if (StartScreen) StartScreen->LoadingStatus ("Checking network game status.", 0x3f); + if (!D_CheckNetGame ()) + { + return 0; + } + } + + // [SP] Force vanilla transparency auto-detection to re-detect our game lumps now + UpdateVanillaTransparency(); + + // [RH] Lock any cvars that should be locked now that we're + // about to begin the game. + FBaseCVar::EnableNoSet (); + + // [RH] Run any saved commands from the command line or autoexec.cfg now. + gamestate = GS_FULLCONSOLE; + Net_NewMakeTic (); + C_RunDelayedCommands(); + gamestate = GS_STARTUP; + + // enable custom invulnerability map here + if (cl_customizeinvulmap) + R_UpdateInvulnerabilityColormap(); + + if (!restart) + { + // start the apropriate game based on parms + auto v = Args->CheckValue ("-record"); + + if (v) + { + G_RecordDemo (v); + autostart = true; + } + + S_Sound (CHAN_BODY, 0, "misc/startupdone", 1, ATTN_NONE); + + if (Args->CheckParm("-norun") || batchrun) + { + return 1337; // special exit + } + + if (StartScreen == nullptr) V_Init2(); + if (StartScreen) + { + StartScreen->Progress(max_progress); // advance progress bar to the end. + StartScreen->Render(true); + StartScreen->Progress(max_progress); // do this again because Progress advances the counter after redrawing. + StartScreen->Render(true); + delete StartScreen; + StartScreen = NULL; + } + + while(!screen->CompileNextShader()) + { + // here we can do some visual updates later + } + twod->fullscreenautoaspect = gameinfo.fullscreenautoaspect; + // Initialize the size of the 2D drawer so that an attempt to access it outside the draw code won't crash. + twod->Begin(screen->GetWidth(), screen->GetHeight()); + twod->End(); + UpdateJoystickMenu(NULL); + UpdateVRModes(); + Local_Job_Init(); + + v = Args->CheckValue ("-loadgame"); + if (v) + { + FString file = G_BuildSaveName(v); + if (!FileExists(file)) + { + I_FatalError("Cannot find savegame %s", file.GetChars()); + } + G_LoadGame(file); + } + + v = Args->CheckValue("-playdemo"); + if (v != NULL) + { + singledemo = true; // quit after one demo + G_DeferedPlayDemo (v); + } + else + { + v = Args->CheckValue("-timedemo"); + if (v) + { + G_TimeDemo(v); + } + else + { + if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon) + { + if (autostart || netgame) + { + // Do not do any screenwipes when autostarting a game. + if (!Args->CheckParm("-warpwipe")) + { + NoWipe = TICRATE; + } + CheckWarpTransMap(startmap, true); + if (demorecording) + G_BeginRecording(startmap); + G_InitNew(startmap, false); + if (StoredWarp.IsNotEmpty()) + { + AddCommandString(StoredWarp); + StoredWarp = ""; + } + } + else + { + if (multiplayer || cl_nointros || Args->CheckParm("-nointro")) + { + D_StartTitle(); + } + else + { + I_SetFrameTime(); + if (!StartCutscene(gameinfo.IntroScene, SJ_BLOCKUI, [=](bool) { + gameaction = ga_titleloop; + })) D_StartTitle(); + } + } + } + else if (demorecording) + { + G_BeginRecording(NULL); + } + } + } + } + else + { + // These calls from inside V_Init2 are still necessary + C_NewModeAdjust(); + D_StartTitle (); // start up intro loop + setmodeneeded = false; // This may be set to true here, but isn't needed for a restart + } + return 0; +} //========================================================================== // // D_DoomMain @@ -2982,12 +3522,7 @@ bool CheckSkipGameOptionBlock(const char* str); static int D_DoomMain_Internal (void) { - int p; - const char *v; const char *wad; - TArray pwads; - FString *args; - int argcount; FIWadManager *iwad_man; GC::AddMarkerFunc(GC_MarkGameRoots); @@ -3000,6 +3535,7 @@ static int D_DoomMain_Internal (void) buttonMap.GetButton(Button_Klook)->bReleaseLock = true; sysCallbacks = { + G_Responder, System_WantGuiCapture, System_WantLeftButton, System_NetGame, @@ -3023,13 +3559,33 @@ static int D_DoomMain_Internal (void) nullptr, nullptr, System_ToggleFullConsole, - nullptr, + System_StartCutscene, + System_SetTransition, + CheckCheatmode, + System_HudScaleChanged, + M_SetSpecialMenu, + OnMenuOpen, + System_LanguageChanged, + OkForLocalization, + []() ->FConfigFile* { return GameConfig; } + }; std::set_new_handler(NewFailure); const char *batchout = Args->CheckValue("-errorlog"); + + D_DoomInit(); + // [RH] Make sure zdoom.pk3 is always loaded, + // as it contains magic stuff we need. + wad = BaseFileSearch(BASEWAD, NULL, true, GameConfig); + if (wad == NULL) + { + I_FatalError("Cannot find " BASEWAD); + } + LoadHexFont(wad); // load hex font early so we have it during startup. + C_InitConsole(80*8, 25*8, false); I_DetectOS(); @@ -3052,40 +3608,11 @@ static int D_DoomMain_Internal (void) Printf("\n"); } - if (Args->CheckParm("-hashfiles")) - { - const char *filename = "fileinfo.txt"; - Printf("Hashing loaded content to: %s\n", filename); - hashfile = fopen(filename, "w"); - if (hashfile) - { - fprintf(hashfile, "%s version %s (%s)\n", GAMENAME, GetVersionString(), GetGitHash()); -#ifdef __VERSION__ - fprintf(hashfile, "Compiler version: %s\n", __VERSION__); -#endif - fprintf(hashfile, "Command line:"); - for (int i = 0; i < Args->NumArgs(); ++i) - { - fprintf(hashfile, " %s", Args->GetArg(i)); - } - fprintf(hashfile, "\n"); - } - } - - if (!batchrun) Printf(PRINT_LOG, "%s version %s\n", GAMENAME, GetVersionString()); - - D_DoomInit(); + Printf("%s version %s\n", GAMENAME, GetVersionString()); extern void D_ConfirmSendStats(); D_ConfirmSendStats(); - // [RH] Make sure zdoom.pk3 is always loaded, - // as it contains magic stuff we need. - wad = BaseFileSearch (BASEWAD, NULL, true, GameConfig); - if (wad == NULL) - { - I_FatalError ("Cannot find " BASEWAD); - } FString basewad = wad; FString optionalwad = BaseFileSearch(OPTIONALWAD, NULL, true, GameConfig); @@ -3095,19 +3622,6 @@ static int D_DoomMain_Internal (void) // Now that we have the IWADINFO, initialize the autoload ini sections. GameConfig->DoAutoloadSetup(iwad_man); - // Prevent the game from starting if the savegame passed to -loadgame is invalid - v = Args->CheckValue("-loadgame"); - if (v) - { - FString file(v); - FixPathSeperator(file); - DefaultExtension(file, "." SAVEGAME_EXT); - if (!FileExists(file)) - { - I_FatalError("Cannot find savegame %s", file.GetChars()); - } - } - // reinit from here do @@ -3121,9 +3635,15 @@ static int D_DoomMain_Internal (void) } nospriterename = false; + if (iwad_man == NULL) + { + iwad_man = new FIWadManager(basewad, optionalwad); + } + // Load zdoom.pk3 alone so that we can get access to the internal gameinfos before // the IWAD is known. + TArray pwads; GetCmdLineFiles(pwads); FString iwad = CheckGameInfo(pwads); @@ -3131,458 +3651,24 @@ 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; - if (iwad_man == NULL) - { - iwad_man = new FIWadManager(basewad, optionalwad); - } + TArray allwads; + const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad, optionalwad); if (!iwad_info) return 0; // user exited the selection popup via cancel button. - gameinfo.gametype = iwad_info->gametype; - gameinfo.flags = iwad_info->flags; - gameinfo.nokeyboardcheats = iwad_info->nokeyboardcheats; - gameinfo.ConfigName = iwad_info->Configname; - lastIWAD = iwad; - - - if ((gameinfo.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; - FBaseCVar::DisableCallbacks(); - GameConfig->DoGameSetup (gameinfo.ConfigName); - - AddAutoloadFiles(iwad_info->Autoname); - - // Process automatically executed files - FExecList *exec; - FArgs *execFiles = new FArgs; - if (!(Args->CheckParm("-noautoexec"))) - GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName); - exec = D_MultiExec(execFiles, NULL); - delete execFiles; - - // Process .cfg files at the start of the command line. - execFiles = Args->GatherFiles ("-exec"); - exec = D_MultiExec(execFiles, exec); - delete execFiles; - - // [RH] process all + commands on the command line - exec = C_ParseCmdLineParams(exec); - - CopyFiles(allwads, pwads); - if (exec != NULL) - { - exec->AddPullins(allwads, GameConfig); - } - - // Since this function will never leave we must delete this array here manually. - pwads.Clear(); - pwads.ShrinkToFit(); - - if (hashfile) - { - Printf("Notice: File hashing is incredibly verbose. Expect loading files to take much longer than usual.\n"); - } - - if (!batchrun) Printf ("W_Init: Init WADfiles.\n"); - - LumpFilterInfo lfi; - lfi.dotFilter = LumpFilterIWAD; - - static const struct { int match; const char* name; } blanket[] = - { - { GAME_Raven, "game-Raven" }, - { GAME_DoomStrifeChex, "game-DoomStrifeChex" }, - { GAME_DoomChex, "game-DoomChex" }, - { GAME_Any, NULL } - }; - - for (auto& inf : blanket) - { - if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.Push(inf.name); - } - lfi.gameTypeFilter.Push(FStringf("game-%s", GameTypeName())); - - for (auto p : iwad_folders) lfi.reservedFolders.Push(p); - for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); - - lfi.postprocessFunc = [&]() - { - RenameNerve(fileSystem); - RenameSprites(fileSystem, iwad_info->DeleteLumps); - FixMacHexen(fileSystem); - FindStrifeTeaserVoices(fileSystem); - }; - - fileSystem.InitMultipleFiles (allwads, false, &lfi); - allwads.Clear(); - allwads.ShrinkToFit(); - SetMapxxFlag(); - - D_GrabCVarDefaults(); //parse DEFCVARS - - GameConfig->DoKeySetup(gameinfo.ConfigName); - - // Now that wads are loaded, define mod-specific cvars. - ParseCVarInfo(); - - // Actually exec command line commands and exec files. - if (exec != NULL) - { - exec->ExecCommands(); - delete exec; - exec = NULL; - } - - // [RH] Initialize localizable strings. - GStrings.LoadStrings (language); - - V_InitFontColors (); - - // [RH] Moved these up here so that we can do most of our - // startup output in a fullscreen console. - - CT_Init (); - - if (!restart) - { - if (!batchrun) Printf ("I_Init: Setting up machine state.\n"); - CheckCPUID(&CPU); - CalculateCPUSpeed(); - auto ci = DumpCPUInfo(&CPU); - Printf("%s", ci.GetChars()); - } - - // [RH] Initialize palette management - InitPalette (); - - if (!batchrun) Printf ("V_Init: allocate screen.\n"); - if (!restart) - { - V_InitScreenSize(); - } - - if (!restart) - { - // This allocates a dummy framebuffer as a stand-in until V_Init2 is called. - V_InitScreen (); - } - - if (restart) - { - // Update screen palette when restarting - screen->UpdatePalette(); - } - - // Base systems have been inited; enable cvar callbacks - FBaseCVar::EnableCallbacks (); - - if (!batchrun) Printf ("S_Init: Setting up sound.\n"); - S_Init (); - - if (!batchrun) Printf ("ST_Init: Init startup screen.\n"); - if (!restart) - { - if (GameStartupInfo.Type == FStartupInfo::DefaultStartup) - { - switch (gameinfo.gametype) - { - case GAME_Hexen: - GameStartupInfo.Type = FStartupInfo::HexenStartup; - break; - - case GAME_Heretic: - GameStartupInfo.Type = FStartupInfo::HereticStartup; - break; - - case GAME_Strife: - GameStartupInfo.Type = FStartupInfo::StrifeStartup; - break; - - default: - break; - } - } - StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5); - } - else - { - StartScreen = new FStartupScreen(0); - } - - CheckCmdLine(); - - // [RH] Load sound environments - S_ParseReverbDef (); - - // [RH] Parse any SNDINFO lumps - if (!batchrun) Printf ("S_InitData: Load sound definitions.\n"); - S_InitData (); - - // [RH] Parse through all loaded mapinfo lumps - if (!batchrun) Printf ("G_ParseMapInfo: Load map definitions.\n"); - G_ParseMapInfo (iwad_info->MapInfo); - MessageBoxClass = gameinfo.MessageBoxClass; - endoomName = gameinfo.Endoom; - menuBlurAmount = gameinfo.bluramount; - ReadStatistics(); - - // MUSINFO must be parsed after MAPINFO - S_ParseMusInfo(); - - if (!batchrun) Printf ("Texman.Init: Init texture manager.\n"); - UpdateUpscaleMask(); - SpriteFrames.Clear(); - TexMan.Init([]() { StartScreen->Progress(); }, CheckForHacks); - PatchTextures(); - TexAnim.Init(); - C_InitConback(TexMan.CheckForTexture(gameinfo.BorderFlat, ETextureType::Flat), true, 0.25); - - FixWideStatusBar(); - - StartScreen->Progress(); - V_InitFonts(); - InitDoomFonts(); - V_LoadTranslations(); - UpdateGenericUI(false); - - // [CW] Parse any TEAMINFO lumps. - if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); - TeamLibrary.ParseTeamInfo (); - - R_ParseTrnslate(); - PClassActor::StaticInit (); - - // [GRB] Initialize player class list - SetupPlayerClasses (); - - // [RH] Load custom key and weapon settings from WADs - D_LoadWadSettings (); - - // [GRB] Check if someone used clearplayerclasses but not addplayerclass - if (PlayerClasses.Size () == 0) - { - I_FatalError ("No player classes defined"); - } - - StartScreen->Progress (); - - ParseGLDefs(); - - if (!batchrun) Printf ("R_Init: Init %s refresh subsystem.\n", gameinfo.ConfigName.GetChars()); - StartScreen->LoadingStatus ("Loading graphics", 0x3f); - R_Init (); - - if (!batchrun) Printf ("DecalLibrary: Load decals.\n"); - DecalLibrary.ReadAllDecals (); - - // Load embedded Dehacked patches - D_LoadDehLumps(FromIWAD); - - // [RH] Add any .deh and .bex files on the command line. - // If there are none, try adding any in the config file. - // Note that the command line overrides defaults from the config. - - if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 && - gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked")) - { - const char *key; - const char *value; - - while (GameConfig->NextInSection (key, value)) - { - if (stricmp (key, "Path") == 0 && FileExists (value)) - { - if (!batchrun) Printf ("Applying patch %s\n", value); - D_LoadDehFile(value); - } - } - } - - // Load embedded Dehacked patches - D_LoadDehLumps(FromPWADs); - - // Create replacements for dehacked pickups - FinishDehPatch(); - - if (!batchrun) Printf("M_Init: Init menus.\n"); - SetDefaultMenuColors(); - M_Init(); - M_CreateGameMenus(); - - - // clean up the compiler symbols which are not needed any longer. - RemoveUnusedSymbols(); - - InitActorNumsFromMapinfo(); - InitSpawnablesFromMapinfo(); - PClassActor::StaticSetActorNums(); - - //Added by MC: - primaryLevel->BotInfo.getspawned.Clear(); - argcount = Args->CheckParmList("-bots", &args); - for (p = 0; p < argcount; ++p) - { - primaryLevel->BotInfo.getspawned.Push(args[p]); - } - primaryLevel->BotInfo.spawn_tries = 0; - primaryLevel->BotInfo.wanted_botnum = primaryLevel->BotInfo.getspawned.Size(); - - if (!batchrun) Printf ("P_Init: Init Playloop state.\n"); - StartScreen->LoadingStatus ("Init game engine", 0x3f); - AM_StaticInit(); - P_Init (); - - P_SetupWeapons_ntohton(); - - //SBarInfo support. Note that the first SBARINFO lump contains the mugshot definition so it even needs to be read when a regular status bar is being used. - SBarInfo::Load(); - - if (!batchrun) - { - // [RH] User-configurable startup strings. Because BOOM does. - static const char *startupString[5] = { - "STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5" - }; - for (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); - if (str != NULL && str[0] != '\0') - { - Printf("%s\n", str); - } - } - } - - if (!restart) - { - if (!batchrun) Printf ("D_CheckNetGame: Checking network game status.\n"); - StartScreen->LoadingStatus ("Checking network game status.", 0x3f); - if (!D_CheckNetGame ()) - { - return 0; - } - } - - // [SP] Force vanilla transparency auto-detection to re-detect our game lumps now - UpdateVanillaTransparency(); - - // [RH] Lock any cvars that should be locked now that we're - // about to begin the game. - FBaseCVar::EnableNoSet (); - + int ret = D_InitGame(iwad_info, allwads, pwads); + allwads.Reset(); delete iwad_man; // now we won't need this anymore iwad_man = NULL; - - // [RH] Run any saved commands from the command line or autoexec.cfg now. - gamestate = GS_FULLCONSOLE; - Net_NewMakeTic (); - C_RunDelayedCommands(); - gamestate = GS_STARTUP; - - // enable custom invulnerability map here - if (cl_customizeinvulmap) - R_UpdateInvulnerabilityColormap(); - - if (!restart) - { - // start the apropriate game based on parms - v = Args->CheckValue ("-record"); - - if (v) - { - G_RecordDemo (v); - autostart = true; - } - - delete StartScreen; - StartScreen = NULL; - S_Sound (CHAN_BODY, 0, "misc/startupdone", 1, ATTN_NONE); - - if (Args->CheckParm("-norun") || batchrun) - { - return 1337; // special exit - } - - V_Init2(); - twod->fullscreenautoaspect = gameinfo.fullscreenautoaspect; - // Initialize the size of the 2D drawer so that an attempt to access it outside the draw code won't crash. - twod->Begin(screen->GetWidth(), screen->GetHeight()); - twod->End(); - UpdateJoystickMenu(NULL); - UpdateVRModes(); - - v = Args->CheckValue ("-loadgame"); - if (v) - { - FString file(v); - FixPathSeperator (file); - DefaultExtension (file, "." SAVEGAME_EXT); - G_LoadGame (file); - } - - v = Args->CheckValue("-playdemo"); - if (v != NULL) - { - singledemo = true; // quit after one demo - G_DeferedPlayDemo (v); - D_DoomLoop (); // never returns - } - else - { - v = Args->CheckValue("-timedemo"); - if (v) - { - G_TimeDemo(v); - D_DoomLoop(); // never returns - } - else - { - if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon) - { - if (autostart || netgame) - { - // Do not do any screenwipes when autostarting a game. - if (!Args->CheckParm("-warpwipe")) - { - NoWipe = TICRATE; - } - CheckWarpTransMap(startmap, true); - if (demorecording) - G_BeginRecording(startmap); - G_InitNew(startmap, false); - if (StoredWarp.IsNotEmpty()) - { - AddCommandString(StoredWarp); - StoredWarp = ""; - } - } - else - { - D_StartTitle(); // start up intro loop - } - } - else if (demorecording) - { - G_BeginRecording(NULL); - } - } - } - } - else - { - // These calls from inside V_Init2 are still necessary - C_NewModeAdjust(); - D_StartTitle (); // start up intro loop - setmodeneeded = false; // This may be set to true here, but isn't needed for a restart - } + if (ret != 0) return ret; D_DoAnonStats(); - I_UpdateWindowTitle(); - D_DoomLoop (); // this only returns if a 'restart' CCMD is given. // // Clean up after a restart @@ -3599,6 +3685,7 @@ int GameMain() { int ret = 0; GameTicRate = TICRATE; + I_InitTime(); ConsoleCallbacks cb = { D_UserInfoChanged, @@ -3607,7 +3694,7 @@ int GameMain() G_GetUserCVar, []() { return gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP; } }; - + C_InitCVars(0); C_InstallHandlers(&cb); SetConsoleNotifyBuffer(); @@ -3638,6 +3725,7 @@ int GameMain() I_ShutdownInput(); M_SaveDefaultsFinal(); DeleteStartupScreen(); + C_UninitCVars(); // must come last so that nothing will access the CVARs anymore after deletion. delete Args; Args = nullptr; return ret; @@ -3663,11 +3751,11 @@ void D_Cleanup() G_ClearMapinfo(); M_ClearMenus(); // close menu if open - F_EndFinale(); // If an intermission is active, end it now AM_ClearColorsets(); DeinitSWColorMaps(); FreeSBarInfoScript(); - + DeleteScreenJob(); + // clean up game state D_ErrorCleanup (); P_Shutdown(); @@ -3694,7 +3782,9 @@ void D_Cleanup() GameStartupInfo.Name = ""; GameStartupInfo.BkColor = GameStartupInfo.FgColor = GameStartupInfo.Type = 0; GameStartupInfo.LoadWidescreen = GameStartupInfo.LoadLights = GameStartupInfo.LoadBrightmaps = -1; - + GameStartupInfo.DiscordAppId = ""; + GameStartupInfo.SteamAppId = ""; + GC::FullGC(); // clean up before taking down the object list. // Delete the reference to the VM functions here which were deleted and will be recreated after the restart. @@ -3762,11 +3852,6 @@ DEFINE_FIELD_X(InputEventData, event_t, data3) DEFINE_FIELD_X(InputEventData, event_t, x) DEFINE_FIELD_X(InputEventData, event_t, y) -CUSTOM_CVAR(Int, I_FriendlyWindowTitle, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL) -{ - I_UpdateWindowTitle(); -} - void I_UpdateWindowTitle() { FString titlestr; @@ -3783,6 +3868,7 @@ void I_UpdateWindowTitle() titlestr = GameStartupInfo.Name; break; default: + I_UpdateDiscordPresence(false, NULL, GameStartupInfo.DiscordAppId.GetChars(), GameStartupInfo.SteamAppId.GetChars()); I_SetWindowTitle(NULL); return; } @@ -3812,5 +3898,9 @@ void I_UpdateWindowTitle() } } *dstp = 0; + if (i_discordrpc) + I_UpdateDiscordPresence(true, copy.Data(), GameStartupInfo.DiscordAppId.GetChars(), GameStartupInfo.SteamAppId.GetChars()); + else + I_UpdateDiscordPresence(false, nullptr, nullptr, nullptr); I_SetWindowTitle(copy.Data()); } diff --git a/src/d_main.h b/src/d_main.h index e2159af64..a6f76a8d8 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -90,6 +90,11 @@ struct FIWADInfo TArray Lumps; // Lump names for identification TArray DeleteLumps; // Lumps which must be deleted from the directory. int flags = 0; + int LoadWidescreen = -1; + int LoadBrightmaps = -1; + int LoadLights = -1; + FString DiscordAppId = nullptr; + FString SteamAppId = nullptr; }; struct FFoundWadInfo @@ -144,7 +149,11 @@ public: }; +#ifndef NO_SWRENDERER EXTERN_CVAR(Int, vid_rendermode) +#else +constexpr int vid_rendermode = 4; +#endif inline bool V_IsHardwareRenderer() { @@ -156,4 +165,6 @@ inline bool V_IsTrueColor() return vid_rendermode == 1 || vid_rendermode == 4; } +bool CheckCheatmode(bool printmsg = true, bool sponly = false); + #endif diff --git a/src/d_net.cpp b/src/d_net.cpp index 28e28637a..e83b06939 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -51,7 +51,7 @@ #include "st_start.h" #include "teaminfo.h" #include "p_conversation.h" -#include "d_event.h" +#include "d_eventbase.h" #include "p_enemy.h" #include "m_argv.h" #include "p_lnspec.h" @@ -68,6 +68,10 @@ #include "vm.h" #include "gstrings.h" #include "s_music.h" +#include "screenjob.h" +#include "d_main.h" +#include "i_interface.h" +#include "savegamemanager.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) @@ -124,7 +128,7 @@ int playerfornode[MAXNETNODES]; int maketic; int skiptics; -int ticdup; +int ticdup = 1; void D_ProcessEvents (void); void G_BuildTiccmd (ticcmd_t *cmd); @@ -222,7 +226,7 @@ static struct TicSpecial { int i; - specialsize = MAX(specialsize * 2, needed + 30); + specialsize = max(specialsize * 2, needed + 30); DPrintf (DMSG_NOTIFY, "Expanding special size to %zu\n", specialsize); @@ -1151,7 +1155,7 @@ void NetUpdate (void) netbuffer[k++] = lowtic; } - numtics = MAX(0, lowtic - realstart); + numtics = max(0, lowtic - realstart); if (numtics > BACKUPTICS) I_Error ("NetUpdate: Node %d missed too many tics", i); @@ -1160,7 +1164,7 @@ void NetUpdate (void) case 0: default: resendto[i] = lowtic; break; - case 1: resendto[i] = MAX(0, lowtic - 1); break; + case 1: resendto[i] = max(0, lowtic - 1); break; case 2: resendto[i] = nettics[i]; break; } @@ -1451,7 +1455,7 @@ bool DoArbitrate (void *userdata) data->playersdetected[0] |= 1 << netbuffer[1]; - StartScreen->NetMessage ("Found %s (node %d, player %d)", + I_NetMessage ("Found %s (node %d, player %d)", players[netbuffer[1]].userinfo.GetName(), node, netbuffer[1]+1); } @@ -1460,7 +1464,7 @@ bool DoArbitrate (void *userdata) { data->gotsetup[0] = 0x80; - ticdup = doomcom.ticdup = netbuffer[1]; + ticdup = doomcom.ticdup = clamp(netbuffer[1], 1, MAXTICDUP); NetMode = netbuffer[2]; stream = &netbuffer[3]; @@ -1599,8 +1603,8 @@ bool D_ArbitrateNetStart (void) data.gotsetup[0] = 0x80; } - StartScreen->NetInit ("Exchanging game information", 1); - if (!StartScreen->NetLoop (DoArbitrate, &data)) + I_NetInit ("Exchanging game information", 1); + if (!I_NetLoop (DoArbitrate, &data)) { return false; } @@ -1618,7 +1622,7 @@ bool D_ArbitrateNetStart (void) fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]); } } - StartScreen->NetDone(); + I_NetDone(); return true; } @@ -1836,7 +1840,7 @@ static void TicStabilityEnd() { using namespace std::chrono; uint64_t stabilityendtime = duration_cast(steady_clock::now().time_since_epoch()).count(); - stabilityticduration = std::min(stabilityendtime - stabilitystarttime, (uint64_t)1'000'000); + stabilityticduration = min(stabilityendtime - stabilitystarttime, (uint64_t)1'000'000); } // @@ -1851,7 +1855,7 @@ void TryRunTics (void) int counts; int numplaying; - bool doWait = (cl_capfps || pauseext || (r_NoInterpolate && !M_IsAnimated() /*&& gamestate != GS_INTERMISSION && gamestate != GS_INTRO*/)); + bool doWait = (cl_capfps || pauseext || (r_NoInterpolate && !M_IsAnimated())); // get real tics if (doWait) @@ -1883,7 +1887,7 @@ void TryRunTics (void) } } - if (ticdup == 1) + if (ticdup <= 1) { availabletics = lowtic - gametic; } @@ -2402,7 +2406,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player) if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2) { - spawned->Angles.Yaw = source->Angles.Yaw - angle; + spawned->Angles.Yaw = source->Angles.Yaw - DAngle::fromDeg(angle); spawned->special = special; for(i = 0; i < 5; i++) { spawned->args[i] = args[i]; @@ -2454,21 +2458,8 @@ void Net_DoCommand (int type, uint8_t **stream, int player) { // 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. - const char *fileonly = savegamefile.GetChars(); - const char *slash = strrchr (fileonly, '\\'); - if (slash != NULL) - { - fileonly = slash + 1; - } - slash = strrchr (fileonly, '/'); - if (slash != NULL) - { - fileonly = slash + 1; - } - if (fileonly != savegamefile.GetChars()) - { - savegamefile = G_BuildSaveName (fileonly, -1); - } + FString basename = ExtractFileBase(savegamefile, true); + savegamefile = G_BuildSaveName (basename); } } gameaction = ga_savegame; @@ -2692,12 +2683,8 @@ void Net_DoCommand (int type, uint8_t **stream, int player) break; case DEM_SETPITCHLIMIT: - players[player].MinPitch = -(double)ReadByte(stream); // up - players[player].MaxPitch = (double)ReadByte(stream); // down - break; - - case DEM_ADVANCEINTER: - F_AdvanceIntermission(); + players[player].MinPitch = DAngle::fromDeg(-ReadByte(stream)); // up + players[player].MaxPitch = DAngle::fromDeg(ReadByte(stream)); // down break; case DEM_REVERTCAMERA: @@ -2717,10 +2704,14 @@ void Net_DoCommand (int type, uint8_t **stream, int player) for (int i = 0; i < 3; i++) arg[i] = ReadLong(stream); bool manual = !!ReadByte(stream); - primaryLevel->localEventManager->Console(player, s, arg[0], arg[1], arg[2], manual); + primaryLevel->localEventManager->Console(player, s, arg[0], arg[1], arg[2], manual, false); } break; + case DEM_ENDSCREENJOB: + EndScreenJob(); + break; + default: I_Error ("Unknown net command: %d", type); break; @@ -2750,7 +2741,7 @@ static void RunScript(uint8_t **stream, AActor *pawn, int snum, int argn, int al 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, arg, min(countof(arg), argn), ACS_NET | always); } void Net_SkipCommand (int type, uint8_t **stream) @@ -2913,15 +2904,15 @@ int Net_GetLatency(int *ld, int *ad) localdelay = ((localdelay / BACKUPTICS) * ticdup) * (1000 / TICRATE); int severity = 0; - if (MAX(localdelay, arbitratordelay) > 200) + if (max(localdelay, arbitratordelay) > 200) { severity = 1; } - if (MAX(localdelay, arbitratordelay) > 400) + if (max(localdelay, arbitratordelay) > 400) { severity = 2; } - if (MAX(localdelay, arbitratordelay) >= ((BACKUPTICS / 2 - 1) * ticdup) * (1000 / TICRATE)) + if (max(localdelay, arbitratordelay) >= ((BACKUPTICS / 2 - 1) * ticdup) * (1000 / TICRATE)) { severity = 3; } diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 27c91d851..e2876da9a 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -63,11 +63,13 @@ CVAR (Int, team, TEAM_NONE, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, gender, "male", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Bool, neverswitchonpickup, false, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, movebob, 0.25f, CVAR_USERINFO | CVAR_ARCHIVE); +CVAR (Bool, fviewbob, true, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, stillbob, 0.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, wbobspeed, 1.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, wbobfire, 0.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, playerclass, "Fighter", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Bool, classicflight, false, CVAR_USERINFO | CVAR_ARCHIVE); +CVAR (Bool, vertspread, false, CVAR_USERINFO | CVAR_ARCHIVE); enum { @@ -79,12 +81,14 @@ enum INFO_Gender, INFO_NeverSwitchOnPickup, INFO_MoveBob, + INFO_FViewBob, INFO_StillBob, INFO_WBobSpeed, INFO_WBobFire, INFO_PlayerClass, INFO_ColorSet, INFO_ClassicFlight, + INFO_VertSpread, }; const char *GenderNames[GENDER_MAX] = { "male", "female", "neutral", "other" }; @@ -394,8 +398,11 @@ void D_SetupUserInfo () // Initialize the console player's user info coninfo = &players[consoleplayer].userinfo; - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->GetNext()) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO) { FBaseCVar **newcvar; @@ -432,8 +439,11 @@ void userinfo_t::Reset() Clear(); // Create userinfo vars for this player, initialized to their defaults. - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->GetNext()) + decltype(cvarMap)::Iterator it2(cvarMap); + decltype(cvarMap)::Pair *pair2; + while (it2.NextPair(pair2)) { + auto cvar = pair2->Value; if ((cvar->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO) { ECVarType type; @@ -526,7 +536,8 @@ void D_UserInfoChanged (FBaseCVar *cvar) FString escaped_val; char foo[256]; - if (cvar == &autoaim) +#if 0 + if (cvar == autoaim->get()) { if (autoaim < 0.0f) { @@ -539,6 +550,7 @@ void D_UserInfoChanged (FBaseCVar *cvar) return; } } +#endif val = cvar->GetGenericRep (CVAR_String); escaped_val = D_EscapeUserInfo(val.String); @@ -602,7 +614,8 @@ static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, b delete[] value.String; } - if (var == &teamplay) +#if 0 + if (var == teamplay->get()) { // Put players on teams if teamplay turned on for (int i = 0; i < MAXPLAYERS; ++i) @@ -613,6 +626,7 @@ static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, b } } } +#endif if (var) { diff --git a/src/d_protocol.h b/src/d_protocol.h index ddae331a6..2c36a1874 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -162,6 +162,7 @@ enum EDemoCommand DEM_NETEVENT, // 70 String: Event name, Byte: Arg count; each arg is a 4-byte int DEM_MDK, // 71 String: Damage type DEM_SETINV, // 72 SetInventory + DEM_ENDSCREENJOB, }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/doomdata.h b/src/doomdata.h index 00487ec2f..12a286921 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -62,6 +62,7 @@ enum ML_BEHAVIOR, // [RH] Hexen-style scripts. If present, THINGS // and LINEDEFS are also Hexen-style. ML_CONVERSATION, // Strife dialog (only for TEXTMAP format) + ML_LIGHTMAP, // ZDRay generated lightmap ML_MAX, // [RH] These are compressed (and extended) nodes. They combine the data from @@ -372,7 +373,7 @@ struct FMapThing double Gravity; double Alpha; uint32_t fillcolor; - DVector2 Scale; + FVector2 Scale; double Health; int score; int16_t pitch; diff --git a/src/doomdef.h b/src/doomdef.h index 05e7ebb95..641e4597a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -57,15 +57,15 @@ typedef enum #endif #endif +// State updates, number of tics / second. +constexpr int TICRATE = 35; + // Global constants that were defines. enum { // The maximum number of players, multiplayer/networking. MAXPLAYERS = 8, - // State updates, number of tics / second. - TICRATE = 35, - // Amount of damage done by a telefrag. TELEFRAG_DAMAGE = 1000000 }; @@ -102,7 +102,7 @@ enum ESkillLevels #include "keydef.h" // [RH] dmflags bits (based on Q2's) -enum +enum : unsigned { DF_NO_HEALTH = 1 << 0, // Do not spawn health items (DM) DF_NO_ITEMS = 1 << 1, // Do not spawn powerups (DM) @@ -136,11 +136,11 @@ enum DF_COOP_LOSE_POWERUPS = 1 << 28, // Lose powerups when respawning in coop DF_COOP_LOSE_AMMO = 1 << 29, // Lose ammo when respawning in coop DF_COOP_HALVE_AMMO = 1 << 30, // Lose half your ammo when respawning in coop (but not less than the normal starting amount) - DF_INSTANT_REACTION = 1 << 31, // Monsters react instantly + DF_INSTANT_REACTION = 1u << 31, // Monsters react instantly }; // [BC] More dmflags. w00p! -enum +enum : unsigned { // DF2_YES_IMPALING = 1 << 0, // Player gets impaled on MF2_IMPALE items DF2_YES_WEAPONDROP = 1 << 1, // Drop current weapon upon death @@ -172,6 +172,14 @@ enum DF2_RESPAWN_SUPER = 1 << 27, // Respawn invulnerability and invisibility DF2_NO_COOP_THING_SPAWN = 1 << 28, // Don't spawn multiplayer things in coop games DF2_ALWAYS_SPAWN_MULTI = 1 << 29, // Always spawn multiplayer items + DF2_NOVERTSPREAD = 1 << 30, // Don't allow vertical spread for hitscan weapons (excluding ssg) + DF2_NO_EXTRA_AMMO = 1u << 31, // Don't add extra ammo when picking up weapons (like in original Doom) +}; + +// [Nash] dmflags3 in 2023 let's gooooo +enum : unsigned +{ + DF3_NO_PLAYER_CLIP = 1 << 0, // Players can walk through and shoot through each other }; // [RH] Compatibility flags. @@ -202,7 +210,7 @@ enum : unsigned int COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked mods. COMPATF_MBFMONSTERMOVE = 1 << 24, // Monsters are affected by friction and pushers/pullers. - COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs. + 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. @@ -224,6 +232,7 @@ enum : unsigned int COMPATF2_SCRIPTWAIT = 1 << 11, // Use old scriptwait implementation where it doesn't wait on a non-running script. COMPATF2_AVOID_HAZARDS = 1 << 12, // another MBF thing. COMPATF2_STAYONLIFT = 1 << 13, // yet another MBF thing. + COMPATF2_NOMBF21 = 1 << 14, // disable MBF21 features that may clash with certain maps }; @@ -233,7 +242,6 @@ enum { BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps - BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected. BCOMPATF_BADTELEPORTERS = 1 << 3, // Ignore tags on Teleport specials BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior BCOMPATF_REBUILDNODES = 1 << 5, // Force node rebuild diff --git a/src/doomstat.cpp b/src/doomstat.cpp index a2e4a38ce..ef681fb85 100644 --- a/src/doomstat.cpp +++ b/src/doomstat.cpp @@ -46,6 +46,4 @@ int NextSkill = -1; int SinglePlayerClass[MAXPLAYERS]; -bool ToggleFullscreen; - FString LumpFilterIWAD; diff --git a/src/doomstat.h b/src/doomstat.h index 729d3fffe..cc991a4fe 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -108,8 +108,6 @@ EXTERN_CVAR (Float, snd_musicvolume) // maximum volume for music #include "menustate.h" extern bool automapactive; // In AutoMap mode? -extern int paused; // Game Pause? -extern bool pauseext; extern bool viewactive; @@ -235,6 +233,7 @@ EXTERN_CVAR (Int, infighting) EXTERN_CVAR (Int, dmflags); EXTERN_CVAR (Int, dmflags2); // [BC] +EXTERN_CVAR (Int, dmflags3); // [Nash] EXTERN_CVAR (Int, compatflags); EXTERN_CVAR (Int, compatflags2); diff --git a/src/events.cpp b/src/events.cpp index a9362e03b..28caa1c38 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -162,7 +162,7 @@ bool EventManager::UnregisterHandler(DStaticEventHandler* handler) bool EventManager::SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual) { - if (gamestate != GS_LEVEL) + if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) return false; Net_WriteByte(DEM_NETEVENT); @@ -511,17 +511,17 @@ bool EventManager::Responder(const event_t* ev) return true; // event was processed } } - if (ShouldCallStatic(false)) uiProcessorsFound = staticEventManager.Responder(ev); + if (ShouldCallStatic(false) && staticEventManager.Responder(ev)) return true; return false; } -void EventManager::Console(int player, FString name, int arg1, int arg2, int arg3, bool manual) +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); + if (ShouldCallStatic(false)) staticEventManager.Console(player, name, arg1, arg2, arg3, manual, ui); for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) - handler->ConsoleProcess(player, name, arg1, arg2, arg3, manual); + handler->ConsoleProcess(player, name, arg1, arg2, arg3, manual, ui); } void EventManager::RenderOverlay(EHudState state) @@ -686,6 +686,21 @@ DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkEvent) ACTION_RETURN_BOOL(currentVMLevel->localEventManager->SendNetworkEvent(name, arg1, arg2, arg3, false)); } +DEFINE_ACTION_FUNCTION(DEventHandler, SendInterfaceEvent) +{ + PARAM_PROLOGUE; + PARAM_INT(playerNum); + PARAM_STRING(name); + PARAM_INT(arg1); + PARAM_INT(arg2); + PARAM_INT(arg3); + + if (playerNum == consoleplayer) + primaryLevel->localEventManager->Console(-1, name, arg1, arg2, arg3, false, true); + + return 0; +} + DEFINE_ACTION_FUNCTION(DEventHandler, Find) { PARAM_PROLOGUE; @@ -754,7 +769,7 @@ FWorldEvent EventManager::SetupWorldEvent() FWorldEvent e; e.IsSaveGame = savegamerestore; e.IsReopen = Level->FromSnapshot && !savegamerestore; // each one by itself isnt helpful, but with hub load we have savegamerestore==0 and level.FromSnapshot==1. - e.DamageAngle = 0.0; + e.DamageAngle = nullAngle; return e; } @@ -1143,26 +1158,49 @@ void DStaticEventHandler::PostUiTick() } } -void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual) +void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui) { if (player < 0) { - IFVIRTUAL(DStaticEventHandler, ConsoleProcess) + if (ui) { - // don't create excessive DObjects if not going to be processed anyway - if (isEmpty(func)) return; - FConsoleEvent e; + IFVIRTUAL(DStaticEventHandler, InterfaceProcess) + { + // don't create excessive DObjects if not going to be processed anyway + if (isEmpty(func)) return; + FConsoleEvent e; - // - e.Player = player; - e.Name = name; - e.Args[0] = arg1; - e.Args[1] = arg2; - e.Args[2] = arg3; - e.IsManual = manual; + // + e.Player = player; + e.Name = name; + e.Args[0] = arg1; + e.Args[1] = arg2; + e.Args[2] = arg3; + e.IsManual = manual; - VMValue params[2] = { (DStaticEventHandler*)this, &e }; - VMCall(func, params, 2, nullptr, 0); + VMValue params[2] = { (DStaticEventHandler*)this, &e }; + VMCall(func, params, 2, nullptr, 0); + } + } + else + { + IFVIRTUAL(DStaticEventHandler, ConsoleProcess) + { + // don't create excessive DObjects if not going to be processed anyway + if (isEmpty(func)) return; + FConsoleEvent e; + + // + e.Player = player; + e.Name = name; + e.Args[0] = arg1; + e.Args[1] = arg2; + e.Args[2] = arg3; + e.IsManual = manual; + + VMValue params[2] = { (DStaticEventHandler*)this, &e }; + VMCall(func, params, 2, nullptr, 0); + } } } else @@ -1238,6 +1276,25 @@ void DStaticEventHandler::OnDestroy() // console stuff // this is kinda like puke, except it distinguishes between local events and playsim events. +CCMD(interfaceevent) +{ + int argc = argv.argc(); + + if (argc < 2 || argc > 5) + { + Printf("Usage: interfaceevent [arg1] [arg2] [arg3]\n"); + } + else + { + int arg[3] = { 0, 0, 0 }; + int argn = min(argc - 2, countof(arg)); + for (int i = 0; i < argn; i++) + arg[i] = atoi(argv[2 + i]); + // call locally + primaryLevel->localEventManager->Console(-1, argv[1], arg[0], arg[1], arg[2], true, true); + } +} + CCMD(event) { int argc = argv.argc(); @@ -1249,11 +1306,11 @@ CCMD(event) else { int arg[3] = { 0, 0, 0 }; - int argn = MIN(argc - 2, countof(arg)); + int argn = min(argc - 2, countof(arg)); for (int i = 0; i < argn; i++) arg[i] = atoi(argv[2 + i]); // call locally - primaryLevel->localEventManager->Console(-1, argv[1], arg[0], arg[1], arg[2], true); + primaryLevel->localEventManager->Console(-1, argv[1], arg[0], arg[1], arg[2], true, false); } } @@ -1274,7 +1331,7 @@ CCMD(netevent) else { int arg[3] = { 0, 0, 0 }; - int argn = MIN(argc - 2, countof(arg)); + int argn = min(argc - 2, countof(arg)); for (int i = 0; i < argn; i++) arg[i] = atoi(argv[2 + i]); // call networked diff --git a/src/events.h b/src/events.h index f5ad75d88..b6ca6f6a4 100755 --- a/src/events.h +++ b/src/events.h @@ -111,7 +111,7 @@ public: void PostUiTick(); // - void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual); + void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui); // void CheckReplacement(PClassActor* replacee, PClassActor** replacement, bool* final); @@ -281,7 +281,7 @@ struct EventManager // this executes on events. 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); + void Console(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui); // called when looking up the replacement for an actor class bool CheckReplacement(PClassActor* replacee, PClassActor** replacement); diff --git a/src/g_cvars.cpp b/src/g_cvars.cpp index 06a5b4206..14c832568 100644 --- a/src/g_cvars.cpp +++ b/src/g_cvars.cpp @@ -148,16 +148,4 @@ CUSTOM_CVAR(Float, teamdamage, 0.f, CVAR_SERVERINFO | CVAR_NOINITCALL) } } -EXTERN_CVAR(Bool, ui_generic) - -CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -{ - GStrings.UpdateLanguage(self); - for (auto Level : AllLevels()) - { - // does this even make sense on secondary levels...? - if (Level->info != nullptr) Level->LevelName = Level->info->LookupLevelName(); - } - UpdateGenericUI(ui_generic); - I_UpdateWindowTitle(); -} +CVAR(Float, cl_scaleweaponfov, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 6cdcc593b..96951df6f 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -44,6 +44,7 @@ #include "c_functions.h" #include "gstrings.h" #include "texturemanager.h" +#include "d_main.h" //========================================================================== // @@ -74,7 +75,7 @@ CCMD(listlights) if (dl->target) { - FTextureID spr = sprites[dl->target->sprite].GetSpriteFrame(dl->target->frame, 0, 0., nullptr); + FTextureID spr = sprites[dl->target->sprite].GetSpriteFrame(dl->target->frame, 0, nullAngle, nullptr); Printf(", frame = %s ", TexMan.GetGameTexture(spr)->GetName().GetChars()); } @@ -360,6 +361,8 @@ CCMD(targetinv) CCMD(listmaps) { + int iwadNum = fileSystem.GetIwadNum(); + for (unsigned i = 0; i < wadlevelinfos.Size(); i++) { level_info_t *info = &wadlevelinfos[i]; @@ -367,13 +370,20 @@ CCMD(listmaps) if (map != NULL) { + int mapWadNum = fileSystem.GetFileContainer(map->lumpnum); + if (argv.argc() == 1 || CheckWildcards(argv[1], info->MapName.GetChars()) || CheckWildcards(argv[1], info->LookupLevelName().GetChars()) - || CheckWildcards(argv[1], fileSystem.GetResourceFileName(fileSystem.GetFileContainer(map->lumpnum)))) + || CheckWildcards(argv[1], fileSystem.GetResourceFileName(mapWadNum))) { - Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), - fileSystem.GetResourceFileName(fileSystem.GetFileContainer(map->lumpnum))); + bool isFromPwad = mapWadNum != iwadNum; + + const char* lineColor = isFromPwad ? TEXTCOLOR_LIGHTBLUE : ""; + + Printf("%s%s: '%s' (%s)\n", lineColor, info->MapName.GetChars(), + info->LookupLevelName().GetChars(), + fileSystem.GetResourceFileName(mapWadNum)); } delete map; } @@ -390,7 +400,7 @@ CCMD(skyfog) if (argv.argc() > 1) { // Do this only on the primary level. - primaryLevel->skyfog = MAX(0, (int)strtoull(argv[1], NULL, 0)); + primaryLevel->skyfog = max(0, (int)strtoull(argv[1], NULL, 0)); } } diff --git a/src/g_game.cpp b/src/g_game.cpp index f394d1a85..4a3398fde 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -29,7 +29,7 @@ #include #include "i_time.h" -#include "templates.h" + #include "version.h" #include "doomdef.h" #include "doomstat.h" @@ -77,6 +77,8 @@ #include "v_palette.h" #include "s_music.h" #include "p_setup.h" +#include "d_event.h" +#include "model.h" #include "v_video.h" #include "g_hub.h" @@ -86,6 +88,8 @@ #include "d_buttons.h" #include "hwrenderer/scene/hw_drawinfo.h" #include "doommenu.h" +#include "screenjob.h" +#include "i_interface.h" static FRandom pr_dmspawn ("DMSpawn"); @@ -109,13 +113,12 @@ void G_DoQuickSave (); void STAT_Serialize(FSerializer &file); bool WriteZip(const char *filename, TArray &filenames, TArray &content); -FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH); +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. CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH); CVAR (Bool, chasedemo, false, 0); CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Bool, longsavemessages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (String, save_dir, "", 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); EXTERN_CVAR (Float, con_midtime); @@ -141,11 +144,7 @@ CVAR(Int, nametagcolor, CR_GOLD, CVAR_ARCHIVE) extern bool playedtitlemusic; gameaction_t gameaction; -gamestate_t gamestate = GS_STARTUP; -FName SelectedSlideshow; // what to start when ga_slideshow -int paused; -bool pauseext; bool sendpause; // send a pause event next tic bool sendsave; // send a save event next tic bool sendturn180; // [RH] send a 180 degree turn next tic @@ -196,7 +195,7 @@ EXTERN_CVAR (Int, turnspeedwalkslow) EXTERN_CVAR (Int, turnspeedsprintslow) int forwardmove[2], sidemove[2]; -FIntCVar *angleturn[4] = {&turnspeedwalkfast, &turnspeedsprintfast, &turnspeedwalkslow, &turnspeedsprintslow}; +FIntCVarRef *angleturn[4] = {&turnspeedwalkfast, &turnspeedsprintfast, &turnspeedwalkslow, &turnspeedsprintslow}; int flyspeed[2] = {1*256, 3*256}; int lookspeed[2] = {450, 512}; @@ -837,7 +836,7 @@ void G_AddViewPitch (int look, bool mouse) } else { - LocalViewPitch = MIN(LocalViewPitch + look, 0x78000000); + LocalViewPitch = min(LocalViewPitch + look, 0x78000000); } } else if (look < 0) @@ -849,7 +848,7 @@ void G_AddViewPitch (int look, bool mouse) } else { - LocalViewPitch = MAX(LocalViewPitch + look, -0x78000000); + LocalViewPitch = max(LocalViewPitch + look, -0x78000000); } } if (look != 0) @@ -969,6 +968,11 @@ bool G_Responder (event_t *ev) if (ev->type != EV_Mouse && primaryLevel->localEventManager->Responder(ev)) // [ZZ] ZScript ate the event // update 07.03.17: mouse events are handled directly return true; + if (gamestate == GS_INTRO || gamestate == GS_CUTSCENE) + { + return ScreenJobResponder(ev); + } + // any other key pops up menu if in demos // [RH] But only if the key isn't bound to a "special" command if (gameaction == ga_nothing && @@ -1017,11 +1021,6 @@ bool G_Responder (event_t *ev) if (!viewactive && primaryLevel->automap && primaryLevel->automap->Responder (ev, false)) return true; // automap ate it } - else if (gamestate == GS_FINALE) - { - if (F_Responder (ev)) - return true; // finale ate the event - } switch (ev->type) { @@ -1069,7 +1068,7 @@ static void G_FullConsole() primaryLevel->Music = ""; S_Start(); S_StopMusic(true); - P_FreeLevelData(); + P_FreeLevelData(false); } } @@ -1173,9 +1172,6 @@ void G_Ticker () case ga_completed: G_DoCompleted (); break; - case ga_slideshow: - if (gamestate == GS_LEVEL) F_StartIntermission(SelectedSlideshow, FSTATE_InLevel); - break; case ga_worlddone: G_DoWorldDone (); break; @@ -1196,6 +1192,20 @@ void G_Ticker () P_ResumeConversation (); gameaction = ga_nothing; break; + case ga_intermission: + gamestate = GS_CUTSCENE; + gameaction = ga_nothing; + break; + case ga_titleloop: + D_StartTitle(); + break; + case ga_intro: + gamestate = GS_INTRO; + gameaction = ga_nothing; + break; + + + default: case ga_nothing: break; @@ -1203,14 +1213,6 @@ void G_Ticker () C_AdjustBottom (); } - if (oldgamestate != gamestate) - { - if (oldgamestate == GS_FINALE) - { - F_EndFinale (); - } - } - // get commands, check consistancy, and build new consistancy check int buf = (gametic/ticdup)%BACKUPTICS; @@ -1293,14 +1295,6 @@ void G_Ticker () P_Ticker (); break; - case GS_INTERMISSION: - WI_Ticker (); - break; - - case GS_FINALE: - F_Ticker (); - break; - case GS_DEMOSCREEN: D_PageTicker (); break; @@ -1313,18 +1307,18 @@ void G_Ticker () } break; + case GS_CUTSCENE: + case GS_INTRO: + if (ScreenJobTick()) + { + // synchronize termination with the playsim. + Net_WriteByte(DEM_ENDSCREENJOB); + } + break; + default: break; } - // Do some more aggressive GC maintenance when the game ticker is inactive. - if ((gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) || paused || P_CheckTickerPaused()) - { - size_t ac = std::max(10, GC::AllocCount); - for (size_t i = 0; i < ac; i++) - { - if (!GC::CheckGC()) break; - } - } // [MK] Additional ticker for UI events right after all others primaryLevel->localEventManager->PostUiTick(); @@ -1923,15 +1917,18 @@ static void LoadGameError(const char *label, const char *append = "") void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter) { - FBaseCVar* cvar; FString dump; if (arc.BeginObject(label)) { if (arc.isWriting()) { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; + if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) { UCVarValue val = cvar->GetGenericRep(CVAR_String); @@ -1942,8 +1939,11 @@ void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter) } else { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) { UCVarValue val; @@ -2123,6 +2123,14 @@ 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. @@ -2161,35 +2169,11 @@ void G_SaveGame (const char *filename, const char *description) } } -FString G_BuildSaveName (const char *prefix, int slot) +CCMD(opensaves) { - FString name; - FString leader; - const char *slash = ""; - - leader = Args->CheckValue ("-savedir"); - if (leader.IsEmpty()) - { - leader = save_dir; - if (leader.IsEmpty()) - { - leader = M_GetSavegamesPath(); - } - } - size_t len = leader.Len(); - if (leader[0] != '\0' && leader[len-1] != '\\' && leader[len-1] != '/') - { - slash = "/"; - } - name << leader << slash; - name = NicePath(name); + FString name = G_GetSavegamesFolder(); CreatePath(name); - name << prefix; - if (slot >= 0) - { - name.AppendFormat("%d." SAVEGAME_EXT, slot); - } - return name; + I_OpenShellFolder(name); } CVAR (Int, autosavenum, 0, CVAR_NOSET|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -2225,9 +2209,9 @@ void G_DoAutoSave () } num.Int = nextautosave; - autosavenum.ForceSet (num, CVAR_Int); + autosavenum->ForceSet (num, CVAR_Int); - file = G_BuildSaveName ("auto", nextautosave); + file = G_BuildSaveName(FStringf("auto%02d", nextautosave)); // The hint flag is only relevant on the primary level. if (!(primaryLevel->flags2 & LEVEL2_NOAUTOSAVEHINT)) @@ -2264,9 +2248,9 @@ void G_DoQuickSave () } num.Int = lastquicksave; - quicksavenum.ForceSet (num, CVAR_Int); + quicksavenum->ForceSet (num, CVAR_Int); - file = G_BuildSaveName ("quick", lastquicksave); + file = G_BuildSaveName(FStringf("quick%02d", lastquicksave)); readableTime = myasctime (); description.Format("Quicksave %s", readableTime); @@ -2341,7 +2325,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c if (demoplayback) { - filename = G_BuildSaveName ("demosave." SAVEGAME_EXT, -1); + filename = G_BuildSaveName ("demosave"); } if (cl_waitforsave) @@ -3087,8 +3071,16 @@ bool G_CheckDemoStatus (void) void G_StartSlideshow(FLevelLocals *Level, FName whichone) { - gameaction = ga_slideshow; - SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone; + auto SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone; + auto slide = F_StartIntermission(SelectedSlideshow); + RunIntermission(nullptr, nullptr, slide, nullptr, [](bool) + { + primaryLevel->SetMusic(); + gamestate = GS_LEVEL; + wipegamestate = GS_LEVEL; + gameaction = ga_resumeconversation; + + }); } DEFINE_ACTION_FUNCTION(FLevelLocals, StartSlideshow) @@ -3140,3 +3132,5 @@ DEFINE_GLOBAL(demoplayback) DEFINE_GLOBAL(automapactive); DEFINE_GLOBAL(Net_Arbitrator); DEFINE_GLOBAL(netgame); +DEFINE_GLOBAL(paused); +DEFINE_GLOBAL(Terrains); diff --git a/src/g_game.h b/src/g_game.h index 0a86c2916..cbb18d5d6 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -81,8 +81,6 @@ bool G_Responder (event_t* ev); void G_ScreenShot (const char* filename); void G_StartSlideshow(FLevelLocals *Level, FName whichone); -FString G_BuildSaveName (const char *prefix, int slot); - class FSerializer; bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn); @@ -106,6 +104,10 @@ void G_AddViewAngle (int yaw, bool mouse = false); class FBaseCVar; FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname); +class DIntermissionController; +struct level_info_t; +void RunIntermission(level_info_t* oldlevel, level_info_t* newlevel, DIntermissionController* intermissionScreen, DObject* statusScreen, std::function completionf); + extern const AActor *SendItemUse, *SendItemDrop; extern int SendItemDropAmount; diff --git a/src/g_level.cpp b/src/g_level.cpp index 5247c4968..0a19c44fa 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -33,7 +33,7 @@ */ #include -#include "templates.h" + #include "d_main.h" #include "g_level.h" #include "g_game.h" @@ -46,6 +46,7 @@ #include "filesystem.h" #include "am_map.h" #include "c_dispatch.h" +#include "i_interface.h" #include "p_setup.h" #include "p_local.h" @@ -82,9 +83,13 @@ #include "p_effect.h" #include "stringtable.h" #include "c_buttons.h" +#include "screenjob.h" +#include "types.h" +#include "gstrings.h" #include "gi.h" + #include "g_hub.h" #include "g_levellocals.h" #include "actorinlines.h" @@ -97,6 +102,7 @@ void STAT_StartNewGame(const char *lev); void STAT_ChangeLevel(const char *newl, FLevelLocals *Level); +FString STAT_EpisodeName(); EXTERN_CVAR(Bool, save_formatted) EXTERN_CVAR (Float, sv_gravity) @@ -177,8 +183,60 @@ void *statcopy; // for statistics driver FLevelLocals level; // info about current level FLevelLocals *primaryLevel = &level; // level for which to display the user interface. FLevelLocals *currentVMLevel = &level; // level which currently ticks. Used as global input to the VM and some functions called by it. +static PType* maprecordtype; +//============================================================================= +// +// +// +//============================================================================= + +void Local_Job_Init() +{ + maprecordtype = NewPointer(NewStruct("MapRecord", nullptr, true)); +} + +//============================================================================= +// +// +// +//============================================================================= + +static void CallCreateMapFunction(const char* qname, DObject* runner, level_info_t* map) +{ + auto func = LookupFunction(qname); + if (func->Proto->ArgumentTypes.Size() == 1) return CallCreateFunction(qname, runner); // accept functions without map parameter as well here. + if (func->Proto->ArgumentTypes.Size() != 2) I_Error("Bad map-cutscene function %s. Must receive precisely two arguments.", qname); + if (func->Proto->ArgumentTypes[0] != cutscene.runnerclasstype && func->Proto->ArgumentTypes[1] != maprecordtype) + I_Error("Bad cutscene function %s. Must receive ScreenJobRunner and LevelInfo reference.", qname); + VMValue val[2] = { runner, map }; + VMCall(func, val, 2, nullptr, 0); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool CreateCutscene(CutsceneDef* cs, DObject* runner, level_info_t* map) +{ + if (cs->function.CompareNoCase("none") == 0) + return true; // play nothing but return as being validated + if (cs->function.IsNotEmpty()) + { + CallCreateMapFunction(cs->function, runner, map); + return true; + } + else if (cs->video.IsNotEmpty()) + { + AddGenericVideo(runner, cs->video, cs->GetSound(), cs->framespersec); + return true; + } + return false; +} + //========================================================================== // // G_InitNew @@ -206,6 +264,26 @@ void G_DeferedInitNew (FNewGameStartup *gs) CheckWarpTransMap (d_mapname, true); gameaction = ga_newgame2; finishstate = FINISH_NoHub; + + if (AllEpisodes[gs->Episode].mIntro.isdefined()) + { + cutscene.runner = CreateRunner(false); + GC::WriteBarrier(cutscene.runner); + + if (!CreateCutscene(&AllEpisodes[gs->Episode].mIntro, cutscene.runner, nullptr)) + { + return; + } + + cutscene.completion = [](bool) { gameaction = ga_newgame2; }; + if (!ScreenJobValidate()) + { + DeleteScreenJob(); + cutscene.completion = nullptr; + return; + } + gameaction = ga_intermission; + } } //========================================================================== @@ -828,6 +906,167 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SecretExitLevel, LevelLocals_SecretE //========================================================================== static wbstartstruct_t staticWmInfo; +DIntermissionController* FLevelLocals::CreateIntermission() +{ + DIntermissionController* controller = nullptr; + cluster_info_t *nextcluster; + cluster_info_t *thiscluster; + + if (flags & LEVEL_CHANGEMAPCHEAT) + return nullptr; + + thiscluster = FindClusterInfo (cluster); + + bool endgame = strncmp (nextlevel, "enDSeQ", 6) == 0; + if (endgame) + { + FName endsequence = ENamedName(strtoll(nextlevel.GetChars()+6, NULL, 16)); + // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere. + if (endsequence == NAME_Inter_Strife) + { + if (Players[0]->mo->FindInventory (NAME_QuestItem25) || + Players[0]->mo->FindInventory (NAME_QuestItem28)) + { + endsequence = NAME_Inter_Strife_Good; + } + else + { + endsequence = NAME_Inter_Strife_Sad; + } + } + + 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, + ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, + -1, 0, + ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, + ext->mText, + false, + ext->mDefined & FExitText::DEF_PIC, + ext->mDefined & FExitText::DEF_LOOKUP, + true, endsequence); + } + else if (!(info->flags2 & LEVEL2_NOCLUSTERTEXT)) + { + controller = F_StartFinale(thiscluster->MessageMusic, thiscluster->musicorder, + thiscluster->cdtrack, thiscluster->cdid, + thiscluster->FinaleFlat, thiscluster->ExitText, + thiscluster->flags & CLUSTER_EXITTEXTINLUMP, + thiscluster->flags & CLUSTER_FINALEPIC, + thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, + true, endsequence); + } + } + else if (!deathmatch) + { + FExitText *ext = nullptr; + + if (flags3 & LEVEL3_EXITSECRETUSED) ext = info->ExitMapTexts.CheckKey(NAME_Secret); + else if (flags3 & LEVEL3_EXITNORMALUSED) ext = info->ExitMapTexts.CheckKey(NAME_Normal); + if (ext == nullptr) ext = info->ExitMapTexts.CheckKey(nextlevel); + + if (ext != nullptr) + { + if ((ext->mDefined & FExitText::DEF_TEXT)) + { + controller = F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic : gameinfo.finaleMusic, + ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, + -1, 0, + ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, + ext->mText, + false, + ext->mDefined & FExitText::DEF_PIC, + ext->mDefined & FExitText::DEF_LOOKUP, + false); + } + return controller; + } + + nextcluster = FindClusterInfo (FindLevelInfo (nextlevel)->cluster); + + if (nextcluster->cluster != cluster && !(info->flags2 & LEVEL2_NOCLUSTERTEXT)) + { + // Only start the finale if the next level's cluster is different + // than the current one and we're not in deathmatch. + if (nextcluster->EnterText.IsNotEmpty()) + { + controller = F_StartFinale (nextcluster->MessageMusic, nextcluster->musicorder, + nextcluster->cdtrack, nextcluster->cdid, + nextcluster->FinaleFlat, nextcluster->EnterText, + nextcluster->flags & CLUSTER_ENTERTEXTINLUMP, + nextcluster->flags & CLUSTER_FINALEPIC, + nextcluster->flags & CLUSTER_LOOKUPENTERTEXT, + false); + } + else if (thiscluster->ExitText.IsNotEmpty()) + { + controller = F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder, + thiscluster->cdtrack, nextcluster->cdid, + thiscluster->FinaleFlat, thiscluster->ExitText, + thiscluster->flags & CLUSTER_EXITTEXTINLUMP, + thiscluster->flags & CLUSTER_FINALEPIC, + thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, + false); + } + } + } + return controller; +} + +//============================================================================= +// +// +// +//============================================================================= + +void RunIntermission(level_info_t* fromMap, level_info_t* toMap, DIntermissionController* intermissionScreen, DObject* statusScreen, std::function completionf) +{ + cutscene.runner = CreateRunner(false); + GC::WriteBarrier(cutscene.runner); + cutscene.completion = std::move(completionf); + + // retrieve cluster relations for cluster-based cutscenes. + cluster_info_t* fromcluster = nullptr, *tocluster = nullptr; + if (fromMap) fromcluster = FindClusterInfo(fromMap->cluster); + if (toMap) tocluster = FindClusterInfo(toMap->cluster); + if (fromcluster == tocluster) fromcluster = tocluster = nullptr; + + if (fromMap) + { + if (!CreateCutscene(&fromMap->outro, cutscene.runner, fromMap)) + { + if (fromcluster != nullptr) CreateCutscene(&fromcluster->outro, cutscene.runner, fromMap); + } + } + + auto func = LookupFunction("DoomCutscenes.BuildMapTransition"); + if (func == nullptr) + { + I_Error("Script function 'DoomCutscenes.BuildMapTransition' not found"); + } + VMValue val[3] = { cutscene.runner, intermissionScreen, statusScreen }; + VMCall(func, val, 3, nullptr, 0); + + if (toMap) + { + if (!CreateCutscene(&toMap->intro, cutscene.runner, toMap)) + { + if (tocluster != nullptr) CreateCutscene(&tocluster->intro, cutscene.runner, toMap); + } + } + + if (!ScreenJobValidate()) + { + DeleteScreenJob(); + if (cutscene.completion) cutscene.completion(false); + cutscene.completion = nullptr; + return; + } + gameaction = ga_intermission; +} + void G_DoCompleted (void) { gameaction = ga_nothing; @@ -860,18 +1099,25 @@ void G_DoCompleted (void) SN_StopAllSequences(Level); } + // todo: create end of level screenjob + DObject* statusScreen = nullptr; + DIntermissionController* intermissionScreen = nullptr; if (playinter) { - gamestate = GS_INTERMISSION; - viewactive = false; - automapactive = false; - // [RH] If you ever get a statistics driver operational, adapt this. // if (statcopy) // memcpy (statcopy, &wminfo, sizeof(wminfo)); - WI_Start (&staticWmInfo); + statusScreen = WI_Start (&staticWmInfo); } + bool endgame = strncmp(nextlevel, "enDSeQ", 6) == 0; + intermissionScreen = primaryLevel->CreateIntermission(); + auto nextinfo = !playinter || endgame? nullptr : FindLevelInfo(nextlevel, false); + RunIntermission(primaryLevel->info, nextinfo, intermissionScreen, statusScreen, [=](bool) + { + if (!endgame) primaryLevel->WorldDone(); + else D_StartTitle(); + }); } //========================================================================== @@ -1036,12 +1282,7 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) finishstate = mode; - if (!ShouldDoIntermission(nextcluster, thiscluster)) - { - WorldDone (); - return false; - } - return true; + return ShouldDoIntermission(nextcluster, thiscluster); } //========================================================================== @@ -1120,7 +1361,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au { UCVarValue val; val.Int = NextSkill; - gameskill.ForceSet (val, CVAR_Int); + gameskill->ForceSet (val, CVAR_Int); NextSkill = -1; } @@ -1144,7 +1385,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au { FString mapname = nextmapname; mapname.ToUpper(); - Printf("\n%s\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", console_bar, mapname.GetChars(), LevelName.GetChars()); + Printf(PRINT_HIGH | PRINT_NONOTIFY, "\n" TEXTCOLOR_NORMAL "%s\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", console_bar, mapname.GetChars(), LevelName.GetChars()); } // Set the sky map. @@ -1281,10 +1522,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au //========================================================================== void FLevelLocals::WorldDone (void) -{ - cluster_info_t *nextcluster; - cluster_info_t *thiscluster; - +{ gameaction = ga_worlddone; @@ -1294,110 +1532,11 @@ void FLevelLocals::WorldDone (void) BotInfo.RemoveAllBots(this, consoleplayer != Net_Arbitrator); } - if (flags & LEVEL_CHANGEMAPCHEAT) - return; - - thiscluster = FindClusterInfo (cluster); - - if (strncmp (nextlevel, "enDSeQ", 6) == 0) - { - FName endsequence = ENamedName(strtoll(nextlevel.GetChars()+6, NULL, 16)); - // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere. - if (endsequence == NAME_Inter_Strife) - { - if (Players[0]->mo->FindInventory (NAME_QuestItem25) || - Players[0]->mo->FindInventory (NAME_QuestItem28)) - { - endsequence = NAME_Inter_Strife_Good; - } - else - { - endsequence = NAME_Inter_Strife_Sad; - } - } - - auto ext = info->ExitMapTexts.CheckKey(flags3 & LEVEL3_EXITSECRETUSED ? NAME_Secret : NAME_Normal); - if (ext != nullptr && (ext->mDefined & FExitText::DEF_TEXT)) - { - F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic : gameinfo.finaleMusic, - ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, - -1, 0, - ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, - ext->mText, - false, - ext->mDefined & FExitText::DEF_PIC, - ext->mDefined & FExitText::DEF_LOOKUP, - true, endsequence); - } - else if (!(info->flags2 & LEVEL2_NOCLUSTERTEXT)) - { - F_StartFinale(thiscluster->MessageMusic, thiscluster->musicorder, - thiscluster->cdtrack, thiscluster->cdid, - thiscluster->FinaleFlat, thiscluster->ExitText, - thiscluster->flags & CLUSTER_EXITTEXTINLUMP, - thiscluster->flags & CLUSTER_FINALEPIC, - thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, - true, endsequence); - } - } - else if (!deathmatch) - { - FExitText *ext = nullptr; - - if (flags3 & LEVEL3_EXITSECRETUSED) ext = info->ExitMapTexts.CheckKey(NAME_Secret); - else if (flags3 & LEVEL3_EXITNORMALUSED) ext = info->ExitMapTexts.CheckKey(NAME_Normal); - if (ext == nullptr) ext = info->ExitMapTexts.CheckKey(nextlevel); - - if (ext != nullptr) - { - if ((ext->mDefined & FExitText::DEF_TEXT)) - { - F_StartFinale(ext->mDefined & FExitText::DEF_MUSIC ? ext->mMusic : gameinfo.finaleMusic, - ext->mDefined & FExitText::DEF_MUSIC ? ext->mOrder : gameinfo.finaleOrder, - -1, 0, - ext->mDefined & FExitText::DEF_BACKDROP ? ext->mBackdrop : gameinfo.FinaleFlat, - ext->mText, - false, - ext->mDefined & FExitText::DEF_PIC, - ext->mDefined & FExitText::DEF_LOOKUP, - false); - } - return; - } - - nextcluster = FindClusterInfo (FindLevelInfo (nextlevel)->cluster); - - if (nextcluster->cluster != cluster && !(info->flags2 & LEVEL2_NOCLUSTERTEXT)) - { - // Only start the finale if the next level's cluster is different - // than the current one and we're not in deathmatch. - if (nextcluster->EnterText.IsNotEmpty()) - { - F_StartFinale (nextcluster->MessageMusic, nextcluster->musicorder, - nextcluster->cdtrack, nextcluster->cdid, - nextcluster->FinaleFlat, nextcluster->EnterText, - nextcluster->flags & CLUSTER_ENTERTEXTINLUMP, - nextcluster->flags & CLUSTER_FINALEPIC, - nextcluster->flags & CLUSTER_LOOKUPENTERTEXT, - false); - } - else if (thiscluster->ExitText.IsNotEmpty()) - { - F_StartFinale (thiscluster->MessageMusic, thiscluster->musicorder, - thiscluster->cdtrack, nextcluster->cdid, - thiscluster->FinaleFlat, thiscluster->ExitText, - thiscluster->flags & CLUSTER_EXITTEXTINLUMP, - thiscluster->flags & CLUSTER_FINALEPIC, - thiscluster->flags & CLUSTER_LOOKUPEXITTEXT, - false); - } - } - } -} +} DEFINE_ACTION_FUNCTION(FLevelLocals, WorldDone) { - primaryLevel->WorldDone(); + // This is just a dummy to make old status screens happy. return 0; } @@ -1540,6 +1679,7 @@ int FLevelLocals::FinishTravel () pawn->ceilingpic = pawndup->ceilingpic; pawn->Floorclip = pawndup->Floorclip; pawn->waterlevel = pawndup->waterlevel; + pawn->waterdepth = pawndup->waterdepth; } else if (failnum == 0) // In the failure case this may run into some undefined data. { @@ -1562,6 +1702,7 @@ int FLevelLocals::FinishTravel () } pawn->LinkToWorld (nullptr); pawn->ClearInterpolation(); + pawn->ClearFOVInterpolation(); const int tid = pawn->tid; // Save TID (actor isn't linked into the hash chain yet) pawn->tid = 0; // Reset TID pawn->SetTID(tid); // Set TID (and link actor into the hash chain) @@ -1634,8 +1775,7 @@ void FLevelLocals::Init() { P_InitParticles(this); P_ClearParticles(this); - BaseBlendA = 0.0f; // Remove underwater blend effect, if any - + gravity = sv_gravity * 35/TICRATE; aircontrol = sv_aircontrol; AirControlChanged(); @@ -1713,8 +1853,8 @@ void FLevelLocals::Init() pixelstretch = info->pixelstretch; - compatflags.Callback(); - compatflags2.Callback(); + compatflags->Callback(); + compatflags2->Callback(); DefaultEnvironment = info->DefaultEnvironment; @@ -2283,3 +2423,30 @@ void FLevelLocals::SetMusic() S_ChangeMusic(Music, musicorder); } + +DEFINE_ACTION_FUNCTION(FLevelLocals, GetClusterName) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals) + cluster_info_t* cluster = FindClusterInfo(self->cluster); + FString retval; + + if (cluster) + { + if (cluster->flags & CLUSTER_LOOKUPNAME) + retval = GStrings(cluster->ClusterName); + else + retval = cluster->ClusterName; + } + ACTION_RETURN_STRING(retval); +} + +DEFINE_ACTION_FUNCTION(FLevelLocals, GetEpisodeName) +{ + // this is a bit of a crapshoot because ZDoom never assigned a level to an episode + // and retroactively fixing this is not possible. + // 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())); +} + diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 887616e07..04ec8c6d9 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -55,6 +55,7 @@ #include "r_data/r_canvastexture.h" #include "r_data/r_interpolate.h" #include "doom_aabbtree.h" +#include "doom_levelmesh.h" //============================================================================ // @@ -102,6 +103,7 @@ struct EventManager; typedef TMap FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS) typedef TMap FDialogueMap; // maps actor class names to dialogue array index typedef TMap FUDMFKeyMap; +class DIntermissionController; struct FLevelLocals { @@ -122,12 +124,13 @@ struct FLevelLocals friend class MapLoader; + DIntermissionController* CreateIntermission(); void Tick(); void Mark(); void AddScroller(int secnum); void SetInterMusic(const char *nextmap); void SetMusicVolume(float v); - void ClearLevelData(); + void ClearLevelData(bool fullgc = true); void ClearPortals(); bool CheckIfExitIsGood(AActor *self, level_info_t *newmap); void FormatMapName(FString &mapname, const char *mapnamecolor); @@ -429,7 +432,6 @@ public: void SetMusic(); - TArray vertexes; TArray sectors; TArray extsectors; // container for non-trivial sector information. sector_t must be trivially copyable for *_fakeflat to work as intended. @@ -451,6 +453,20 @@ public: TArray sectorPortals; TArray linePortals; + // Lightmaps + TArray LMSurfaces; + TArray LMTexCoords; + int LMTextureCount = 0; + int LMTextureSize = 0; + TArray LMTextureData; + TArray LightProbes; + int LPMinX = 0; + int LPMinY = 0; + int LPWidth = 0; + int LPHeight = 0; + static const int LPCellSize = 32; + TArray LPCells; + // Portal information. FDisplacementTable Displacements; FPortalBlockmap PortalBlockmap; @@ -461,6 +477,7 @@ public: FCanvasTextureInfo canvasTextureInfo; EventManager *localEventManager = nullptr; DoomLevelAABBTree* aabbTree = nullptr; + DoomLevelMesh* levelMesh = nullptr; // [ZZ] Destructible geometry information TMap healthGroups; @@ -525,7 +542,7 @@ public: static const int BODYQUESIZE = 32; TObjPtr bodyque[BODYQUESIZE]; - TObjPtr automap = nullptr; + TObjPtr automap = MakeObjPtr(nullptr); int bodyqueslot; // For now this merely points to the global player array, but with this in place, access to this array can be moved over to the level. @@ -584,6 +601,12 @@ public: return p->camera == mo; } + bool MBF21Enabled() const + { + // The affected features only are a problem with Doom format maps - the flag should have no effect in Hexen and UDMF format. + return !(i_compatflags2 & COMPATF2_NOMBF21) || maptype != MAPTYPE_DOOM; + } + int NumMapSections; uint32_t flags; @@ -631,6 +654,7 @@ public: DSeqNode *SequenceListHead; // [RH] particle globals + uint32_t OldestParticle; // [MC] Oldest particle for replacing with PS_REPLACE uint32_t ActiveParticles; uint32_t InactiveParticles; TArray Particles; @@ -669,10 +693,10 @@ public: // links to global game objects TArray> CorpseQueue; - TObjPtr FraggleScriptThinker = nullptr; - TObjPtr ACSThinker = nullptr; + TObjPtr FraggleScriptThinker = MakeObjPtr(nullptr); + TObjPtr ACSThinker = MakeObjPtr(nullptr); - TObjPtr SpotState = nullptr; + TObjPtr SpotState = MakeObjPtr(nullptr); //========================================================================== // @@ -821,11 +845,31 @@ inline line_t *line_t::getPortalDestination() const return portalindex >= GetLevel()->linePortals.Size() ? (line_t*)nullptr : GetLevel()->linePortals[portalindex].mDestination; } +inline int line_t::getPortalFlags() const +{ + return portalindex >= GetLevel()->linePortals.Size() ? 0 : GetLevel()->linePortals[portalindex].mFlags; +} + inline int line_t::getPortalAlignment() const { return portalindex >= GetLevel()->linePortals.Size() ? 0 : GetLevel()->linePortals[portalindex].mAlign; } +inline int line_t::getPortalType() const +{ + return portalindex >= GetLevel()->linePortals.Size() ? 0 : GetLevel()->linePortals[portalindex].mType; +} + +inline DVector2 line_t::getPortalDisplacement() const +{ + return portalindex >= GetLevel()->linePortals.Size() ? DVector2(0., 0.) : GetLevel()->linePortals[portalindex].mDisplacement; +} + +inline DAngle line_t::getPortalAngleDiff() const +{ + return portalindex >= GetLevel()->linePortals.Size() ? DAngle::fromDeg(0.) : GetLevel()->linePortals[portalindex].mAngleDiff; +} + inline bool line_t::hitSkyWall(AActor* mo) const { return backsector && diff --git a/src/g_statusbar/hudmessages.cpp b/src/g_statusbar/hudmessages.cpp index ba9b7a190..ccf6174c3 100644 --- a/src/g_statusbar/hudmessages.cpp +++ b/src/g_statusbar/hudmessages.cpp @@ -32,7 +32,7 @@ ** */ -#include "templates.h" + #include "doomdef.h" #include "sbar.h" #include "c_cvars.h" @@ -340,7 +340,7 @@ void DHUDMessage::ResetText (const char *text) for (auto &line : Lines) { Height += Font->GetHeight (); - Width = MAX (Width, line.Width); + Width = max (Width, line.Width); } } @@ -751,7 +751,7 @@ void DHUDMessageTypeOnFadeOut::Serialize(FSerializer &arc) LineLen = CurrLine = 0; } - clamp(LineVisible, 0, LineLen); + LineVisible = clamp(LineVisible, 0, LineLen); } } diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 85fd62305..278f6d923 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -84,7 +84,8 @@ public: void CallDraw(int bottom, int visibility); private: - TObjPtr Next = nullptr; + TObjPtr Next = MakeObjPtr(nullptr); +; uint32_t SBarID = 0; friend class DBaseStatusBar; diff --git a/src/g_statusbar/sbar_mugshot.cpp b/src/g_statusbar/sbar_mugshot.cpp index 2fe24fae2..3f79b9643 100644 --- a/src/g_statusbar/sbar_mugshot.cpp +++ b/src/g_statusbar/sbar_mugshot.cpp @@ -355,11 +355,11 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags) // The next 12 lines are from the Doom statusbar code. DAngle badguyangle = player->mo->AngleTo(player->attacker); DAngle diffang = deltaangle(player->mo->Angles.Yaw, badguyangle); - if (diffang > 45.) + if (diffang > DAngle::fromDeg(45.)) { // turn face right damage_angle = 2; } - else if (diffang < -45.) + else if (diffang < DAngle::fromDeg(-45.)) { // turn face left damage_angle = 0; } diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 7efaff641..6d6b8b7b3 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -34,6 +34,7 @@ */ #include "doomtype.h" +#include "basics.h" #include "doomstat.h" #include "v_font.h" #include "v_video.h" @@ -65,7 +66,6 @@ enum EXTERN_CVAR(Int, fraglimit) EXTERN_CVAR(Int, screenblocks) -EXTERN_CVAR(Bool, vid_fps) class DSBarInfo; static double nulclip[] = { 0,0,0,0 }; @@ -1235,7 +1235,7 @@ public: wrapper->StatusbarToRealCoords(dx, dy, w, h); if(clearDontDraw) - ClearRect(twod, static_cast(MAX(dx, dcx)), static_cast(MAX(dy, dcy)), static_cast(MIN(dcr,w+MAX(dx, dcx))), static_cast(MIN(dcb,MAX(dy, dcy)+h)), GPalette.BlackIndex, 0); + ClearRect(twod, static_cast(max(dx, dcx)), static_cast(max(dy, dcy)), static_cast(min(dcr,w+max(dx, dcx))), static_cast(min(dcb,max(dy, dcy)+h)), GPalette.BlackIndex, 0); else { if(alphaMap) @@ -1245,8 +1245,8 @@ public: DTA_DestHeightF, h, DTA_ClipLeft, static_cast(dcx), DTA_ClipTop, static_cast(dcy), - DTA_ClipRight, static_cast(MIN(INT_MAX, dcr)), - DTA_ClipBottom, static_cast(MIN(INT_MAX, dcb)), + DTA_ClipRight, static_cast(min(INT_MAX, dcr)), + DTA_ClipBottom, static_cast(min(INT_MAX, dcb)), DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, @@ -1262,8 +1262,8 @@ public: DTA_DestHeightF, h, DTA_ClipLeft, static_cast(dcx), DTA_ClipTop, static_cast(dcy), - DTA_ClipRight, static_cast(MIN(INT_MAX, dcr)), - DTA_ClipBottom, static_cast(MIN(INT_MAX, dcb)), + DTA_ClipRight, static_cast(min(INT_MAX, dcr)), + DTA_ClipBottom, static_cast(min(INT_MAX, dcb)), DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, @@ -1286,8 +1286,6 @@ public: w = (forceWidth < 0 ? texture->GetDisplayWidth() : forceWidth); h = (forceHeight < 0 ? texture->GetDisplayHeight() : forceHeight); - if(vid_fps && rx < 0 && ry >= 0) - ry += 10; rx *= Scale.X; ry *= Scale.Y; @@ -1309,7 +1307,7 @@ public: } if(clearDontDraw) - ClearRect(twod, static_cast(rcx), static_cast(rcy), static_cast(MIN(rcr, rcx+w)), static_cast(MIN(rcb, rcy+h)), GPalette.BlackIndex, 0); + ClearRect(twod, static_cast(rcx), static_cast(rcy), static_cast(min(rcr, rcx+w)), static_cast(min(rcb, rcy+h)), GPalette.BlackIndex, 0); else { if(alphaMap) @@ -1431,8 +1429,6 @@ public: } else { - if(vid_fps && ax < 0 && ay >= 0) - ry += 10; bool xright = rx < 0; bool ybot = ry < 0; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 55cbefdbe..a6e084ea3 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -284,7 +284,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl if (Slots[armorType] > 0 && SlotsIncrement[armorType] > 0) { //combine the alpha values - alpha *= MIN(1., Slots[armorType] / SlotsIncrement[armorType]); + alpha *= min(1., Slots[armorType] / SlotsIncrement[armorType]); texture = statusBar->Images[image]; } else @@ -2796,7 +2796,7 @@ class CommandDrawBar : public SBarInfoCommand if(max != 0 && value > 0) { - value = MIN(value / max, 1.); + value = min(value / max, 1.); } else value = 0; @@ -2805,7 +2805,7 @@ class CommandDrawBar : public SBarInfoCommand // [BL] Since we used a percentage (in order to get the most fluid animation) // we need to establish a cut off point so the last pixel won't hang as the animation slows if(pixel == -1 && statusBar->Images[foreground]) - pixel = MAX(1 / 65536., 1./statusBar->Images[foreground]->GetDisplayWidth()); + pixel = std::max(1 / 65536., 1./statusBar->Images[foreground]->GetDisplayWidth()); if(fabs(drawValue - value) < pixel) drawValue = value; diff --git a/src/g_statusbar/shared_hud.cpp b/src/g_statusbar/shared_hud.cpp index c209e21cd..a6a6ea410 100644 --- a/src/g_statusbar/shared_hud.cpp +++ b/src/g_statusbar/shared_hud.cpp @@ -63,8 +63,11 @@ CVAR (Bool, hud_showitems, false,CVAR_ARCHIVE); // Show item stats on HUD CVAR (Bool, hud_showstats, false, CVAR_ARCHIVE); // for stamina and accuracy. CVAR (Bool, hud_showscore, false, CVAR_ARCHIVE); // for user maintained score CVAR (Bool, hud_showweapons, true, CVAR_ARCHIVE); // Show weapons collected +CVAR (Bool, am_showepisode, false, CVAR_ARCHIVE); // Show current episode name +CVAR (Bool, am_showcluster, false, CVAR_ARCHIVE); // Show current cluster name CVAR (Int , hud_showammo, 2, CVAR_ARCHIVE); // Show ammo collected CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD +CVAR (Int , hud_showtimestat, 0, CVAR_ARCHIVE); // Show time on HUD as statistics widget CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - gametic difference) @@ -159,17 +162,32 @@ void DBaseStatusBar::CreateAltHUD() // //--------------------------------------------------------------------------- EXTERN_CVAR(Bool, hud_aspectscale) +EXTERN_CVAR(Bool, hud_oldscale) +EXTERN_CVAR(Float, hud_scalefactor) void DBaseStatusBar::DrawAltHUD() { player_t * CPlayer = StatusBar->CPlayer; players[consoleplayer].inventorytics = 0; - int scale = GetUIScale(twod, hud_althudscale); - int hudwidth = twod->GetWidth() / scale; - int hudheight = hud_aspectscale ? int(twod->GetHeight() / (scale*1.2)) : twod->GetHeight() / scale; + int hudwidth; + int hudheight; - IFVM(AltHud, Draw) + if (hud_oldscale) + { + int scale = GetUIScale(twod, hud_althudscale); + hudwidth = twod->GetWidth() / scale; + hudheight = twod->GetHeight() / scale; + } + else + { + hudwidth = int(640 / hud_scalefactor); + hudheight = hudwidth * twod->GetHeight() / twod->GetWidth(); + } + if (hud_aspectscale) hudheight = hudheight * 5 / 6; + + + IFVIRTUALPTRNAME(AltHud, "AltHud", Draw) { VMValue params[] = { AltHud, CPlayer, hudwidth, hudheight }; VMCall(func, params, countof(params), nullptr, 0); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index e6f386b7c..55d18333b 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -35,7 +35,7 @@ #include -#include "templates.h" + #include "sbar.h" #include "c_cvars.h" #include "c_dispatch.h" @@ -85,8 +85,6 @@ EXTERN_CVAR (Bool, am_showsecrets) EXTERN_CVAR (Bool, am_showitems) EXTERN_CVAR (Bool, am_showtime) EXTERN_CVAR (Bool, am_showtotaltime) -EXTERN_CVAR (Bool, noisedebug) -EXTERN_CVAR(Bool, vid_fps) EXTERN_CVAR(Bool, inter_subtitles) EXTERN_CVAR(Bool, ui_screenborder_classic_scaling) @@ -104,17 +102,6 @@ CVAR (Flag, pf_poison, paletteflash, PF_POISON) CVAR (Flag, pf_ice, paletteflash, PF_ICE) CVAR (Flag, pf_hazard, paletteflash, PF_HAZARD) -CUSTOM_CVARD(Float, hud_scalefactor, 1, CVAR_ARCHIVE, "changes the hud scale") -{ - if (self < 0.36f) self = 0.36f; - else if (self > 1) self = 1; - else if (StatusBar) - { - StatusBar->SetScale(); - setsizeneeded = true; - } -} - // Stretch status bar to full screen width? CUSTOM_CVAR (Int, st_scale, 0, CVAR_ARCHIVE) @@ -130,14 +117,9 @@ CUSTOM_CVAR (Int, st_scale, 0, CVAR_ARCHIVE) setsizeneeded = true; } } -CUSTOM_CVAR(Bool, hud_aspectscale, false, CVAR_ARCHIVE) -{ - if (StatusBar) - { - StatusBar->SetScale(); - setsizeneeded = true; - } -} + +EXTERN_CVAR(Float, hud_scalefactor) +EXTERN_CVAR(Bool, hud_aspectscale) CVAR (Bool, crosshairon, true, CVAR_ARCHIVE); CVAR (Int, crosshair, 0, CVAR_ARCHIVE) @@ -531,7 +513,7 @@ DVector2 DBaseStatusBar::GetHUDScale() const // Since status bars and HUDs can be designed for non 320x200 screens this needs to be factored in here. // The global scaling factors are for resources at 320x200, so if the actual ones are higher resolution // the resulting scaling factor needs to be reduced accordingly. - int realscale = MAX(1, (320 * scale) / hres); + int realscale = max(1, (320 * scale) / hres); return{ double(realscale), double(realscale * (hud_aspectscale ? 1.2 : 1.)) }; } @@ -548,11 +530,12 @@ void FormatMapName(FLevelLocals *self, int cr, FString *result); void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) { - auto scale = GetUIScale(twod, hud_scale); + auto scalev = GetHUDScale(); + int vwidth = int(twod->GetWidth() / scalev.X); + int vheight = int(twod->GetHeight() / scalev.Y); + auto font = generic_ui ? NewSmallFont : SmallFont; auto font2 = font; - auto vwidth = twod->GetWidth() / scale; - auto vheight = twod->GetHeight() / scale; auto fheight = font->GetHeight(); FString textbuffer; int sec; @@ -568,7 +551,6 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) if (am_showtime) { - if (vid_fps) y += (NewConsoleFont->GetHeight() * active_con_scale(twod) + 5) / scale; 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, @@ -630,7 +612,7 @@ void DBaseStatusBar::DoDrawAutomapHUD(int crdefault, int highlight) IFVIRTUAL(DStatusBarCore, GetProtrusion) { int prot = 0; - VMValue params[] = { this, double(finalwidth * scale / w) }; + VMValue params[] = { this, double(finalwidth * scalev.X / w) }; VMReturn ret(&prot); VMCall(func, params, 2, &ret, 1); h = prot; @@ -1242,11 +1224,6 @@ void DBaseStatusBar::DrawTopStuff (EHudState state) DrawConsistancy (); DrawWaiting (); if ((ShowLog && MustDrawLog(state)) || (inter_subtitles && CPlayer->SubtitleCounter > 0)) DrawLog (); - - if (noisedebug) - { - S_NoiseDebug (); - } } diff --git a/src/g_statusbar/shiftstate.h b/src/g_statusbar/shiftstate.h new file mode 100644 index 000000000..4ac337ff9 --- /dev/null +++ b/src/g_statusbar/shiftstate.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include "d_event.h" + +class ShiftState +{ + bool ShiftStatus = false; + +public: + + bool ShiftPressed() + { + return ShiftStatus; + } + + void AddEvent(const event_t *ev) + { + if ((ev->type == EV_KeyDown || ev->type == EV_KeyUp) && (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT)) + { + ShiftStatus = ev->type == EV_KeyDown; + } + } + + void Clear() + { + ShiftStatus = false; + } + + +}; + +inline ShiftState shiftState; diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 17898f3ae..82b8071b6 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -73,6 +73,8 @@ EXTERN_CVAR(Float, m_sensitivity_y) EXTERN_CVAR(Int, adl_volume_model) EXTERN_CVAR (Int, gl_texture_hqresize_targets) EXTERN_CVAR(Int, wipetype) +EXTERN_CVAR(Bool, i_pauseinbackground) +EXTERN_CVAR(Bool, i_soundinbackground) #ifdef _WIN32 EXTERN_CVAR(Int, in_mouse) @@ -591,6 +593,11 @@ void FGameConfigFile::DoGlobalSetup () if (v.Float < 1.f) v.Float = 1.f; } } + if (last < 223) + { + // ooooh boy did i open a can of worms with this one. + i_pauseinbackground = !(i_soundinbackground); + } } } } @@ -915,40 +922,40 @@ void FGameConfigFile::SetRavenDefaults (bool isHexen) UCVarValue val; val.Bool = false; - wi_percents.SetGenericRepDefault (val, CVAR_Bool); + wi_percents->SetGenericRepDefault (val, CVAR_Bool); val.Bool = true; - con_centernotify.SetGenericRepDefault (val, CVAR_Bool); - snd_pitched.SetGenericRepDefault (val, CVAR_Bool); + con_centernotify->SetGenericRepDefault (val, CVAR_Bool); + snd_pitched->SetGenericRepDefault (val, CVAR_Bool); val.Int = 9; - msg0color.SetGenericRepDefault (val, CVAR_Int); + msg0color->SetGenericRepDefault (val, CVAR_Int); val.Int = CR_WHITE; - msgmidcolor.SetGenericRepDefault (val, CVAR_Int); + msgmidcolor->SetGenericRepDefault (val, CVAR_Int); val.Int = CR_YELLOW; - msgmidcolor2.SetGenericRepDefault (val, CVAR_Int); + msgmidcolor2->SetGenericRepDefault (val, CVAR_Int); val.Int = 0x543b17; - am_wallcolor.SetGenericRepDefault (val, CVAR_Int); + am_wallcolor->SetGenericRepDefault (val, CVAR_Int); val.Int = 0xd0b085; - am_fdwallcolor.SetGenericRepDefault (val, CVAR_Int); + am_fdwallcolor->SetGenericRepDefault (val, CVAR_Int); val.Int = 0x734323; - am_cdwallcolor.SetGenericRepDefault (val, CVAR_Int); + am_cdwallcolor->SetGenericRepDefault (val, CVAR_Int); val.Int = 0; - wipetype.SetGenericRepDefault(val, CVAR_Int); + wipetype->SetGenericRepDefault(val, CVAR_Int); // Fix the Heretic/Hexen automap colors so they are correct. // (They were wrong on older versions.) if (*am_wallcolor == 0x2c1808 && *am_fdwallcolor == 0x887058 && *am_cdwallcolor == 0x4c3820) { - am_wallcolor.ResetToDefault (); - am_fdwallcolor.ResetToDefault (); - am_cdwallcolor.ResetToDefault (); + am_wallcolor->ResetToDefault (); + am_fdwallcolor->ResetToDefault (); + am_cdwallcolor->ResetToDefault (); } if (!isHexen) { val.Int = 0x3f6040; - color.SetGenericRepDefault (val, CVAR_Int); + color->SetGenericRepDefault (val, CVAR_Int); } } @@ -956,7 +963,7 @@ void FGameConfigFile::SetStrifeDefaults () { UCVarValue val; val.Int = 3; - wipetype.SetGenericRepDefault(val, CVAR_Int); + wipetype->SetGenericRepDefault(val, CVAR_Int); } CCMD (whereisini) diff --git a/src/gamedata/a_keys.cpp b/src/gamedata/a_keys.cpp index d34e31caf..e3defc739 100644 --- a/src/gamedata/a_keys.cpp +++ b/src/gamedata/a_keys.cpp @@ -254,8 +254,8 @@ static void ParseLock(FScanner &sc, int ¤tnumber) auto lock = keynum == -1? &sink : &Locks.InsertNew(keynum); - lock->locksound.Push("*keytry"); - lock->locksound.Push("misc/keytry"); + lock->locksound.Push(S_FindSound("*keytry")); + lock->locksound.Push(S_FindSound("misc/keytry")); while (!sc.CheckString("}")) { @@ -298,7 +298,7 @@ static void ParseLock(FScanner &sc, int ¤tnumber) for (;;) { sc.MustGetString(); - lock->locksound.Push(sc.String); + lock->locksound.Push(S_FindSound(sc.String)); if (!sc.GetString()) { break; @@ -469,7 +469,7 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) // Just a safety precaution. The messages should have been initialized upon game start. if (!keysdone) P_InitKeyMessages(); - FSoundID failage[2] = { "*keytry", "misc/keytry" }; + FSoundID failage[2] = { S_FindSound("*keytry"), S_FindSound("misc/keytry") }; auto lock = Locks.CheckKey(keynum); if (!lock) @@ -501,10 +501,10 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) // Play the first defined key sound. for (int i = 0; i < numfailsounds; ++i) { - if (failsound[i] != 0) + if (failsound[i] != NO_SOUND) { - int snd = S_FindSkinnedSound(owner, failsound[i]); - if (snd != 0) + auto snd = S_FindSkinnedSound(owner, failsound[i]); + if (snd != NO_SOUND) { S_Sound (owner, CHAN_VOICE, 0, snd, 1, ATTN_NORM); break; @@ -516,6 +516,12 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) return false; } +// [MK] for ZScript, simply returns if a lock is defined or not +int P_IsLockDefined(int keynum) +{ + return !!Locks.CheckKey(keynum); +} + //========================================================================== // // These functions can be used to get color information for diff --git a/src/gamedata/a_keys.h b/src/gamedata/a_keys.h index 15c19c017..7eee7e3df 100644 --- a/src/gamedata/a_keys.h +++ b/src/gamedata/a_keys.h @@ -5,6 +5,7 @@ class AActor; class PClassActor; int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false); +int P_IsLockDefined (int lock); void P_InitKeyMessages (); int P_GetMapColorForLock (int lock); int P_GetMapColorForKey (AActor *key); diff --git a/src/gamedata/a_weapons.cpp b/src/gamedata/a_weapons.cpp index c8918a95c..fa527d770 100644 --- a/src/gamedata/a_weapons.cpp +++ b/src/gamedata/a_weapons.cpp @@ -208,20 +208,6 @@ void FWeaponSlot::Sort() } } -//=========================================================================== -// -// FWeaponSlots - Copy Constructor -// -//=========================================================================== - -FWeaponSlots::FWeaponSlots(const FWeaponSlots &other) -{ - for (int i = 0; i < NUM_WEAPON_SLOTS; ++i) - { - Slots[i] = other.Slots[i]; - } -} - //=========================================================================== // // FWeaponSlots :: Clear diff --git a/src/gamedata/a_weapons.h b/src/gamedata/a_weapons.h index 786990223..1ef6d6cc1 100644 --- a/src/gamedata/a_weapons.h +++ b/src/gamedata/a_weapons.h @@ -51,7 +51,7 @@ enum ESlotDef struct FWeaponSlots { FWeaponSlots() { Clear(); } - FWeaponSlots(const FWeaponSlots &other); + FWeaponSlots(const FWeaponSlots &other) = default; private: FWeaponSlot Slots[NUM_WEAPON_SLOTS]; diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index a82146ad5..442068a67 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -44,7 +44,7 @@ #include #include "doomtype.h" -#include "templates.h" + #include "doomstat.h" #include "info.h" #include "d_dehacked.h" @@ -184,7 +184,7 @@ struct MBFParamState int 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]; + if (num > 0 && num <= int(SoundMap.Size())) return SoundMap[num-1].index(); return 0; } @@ -405,7 +405,7 @@ static bool ReadChars (char **stuff, int size); static char *igets (void); static int GetLine (void); -inline double DEHToDouble(int acsval) +inline double DEHToDouble(int64_t acsval) { return acsval / 65536.; } @@ -724,7 +724,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] : 0); // hit sound + emitters.AddParameterIntConst(value2 ? (int)SoundMap[value2 - 1].index() : 0); // hit sound emitters.AddParameterIntConst(0); // miss sound emitters.AddParameterIntConst(NAME_None); // damage type emitters.AddParameterIntConst(true); // bleed @@ -733,7 +733,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] : 0); // soundid + emitters.AddParameterIntConst(value1 ? (int)SoundMap[value1 - 1].index() : 0); // soundid emitters.AddParameterIntConst(CHAN_BODY); // channel emitters.AddParameterFloatConst(1); // volume emitters.AddParameterIntConst(false); // looping @@ -802,7 +802,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->GetIntArg(2, 0)); + emitters.AddParameterIntConst(state->GetSoundArg(2, 0)); emitters.AddParameterFloatConst(state->GetFloatArg(3)); } @@ -886,12 +886,12 @@ static void CreateWeaponBulletAttackFunc(FunctionCallEmitter &emitters, int valu static void CreateWeaponMeleeAttackFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { - state->ValidateArgCount(5, "A_WeaponBulletAttack"); + state->ValidateArgCount(5, "A_WeaponMeleeAttack"); emitters.AddParameterIntConst(state->GetIntArg(0, 2)); emitters.AddParameterIntConst(state->GetIntArg(1, 10)); emitters.AddParameterFloatConst(state->GetFloatArg(2, 1)); - emitters.AddParameterIntConst(state->GetIntArg(3)); - emitters.AddParameterIntConst(state->GetIntArg(4)); + emitters.AddParameterIntConst(state->GetSoundArg(3)); + emitters.AddParameterFloatConst(state->GetFloatArg(4)); } static void CreateWeaponSoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) @@ -1138,16 +1138,21 @@ static int PatchThing (int thingy) while ((result = GetLine ()) == 1) { char *endptr; - uint32_t val = (uint32_t)strtoull (Line2, &endptr, 10); + int64_t val = (int64_t)strtoll (Line2, &endptr, 10); size_t linelen = strlen (Line1); - if (linelen == 10 && stricmp (Line1, "Hit points") == 0) + // Supported value range is all valid representations of signed int and unsigned int. + if (val < INT_MIN || val > UINT_MAX) { - info->health = val; + Printf("Bad numeric constant %s for %s\n", Line2, Line1); + } + else if (linelen == 10 && stricmp (Line1, "Hit points") == 0) + { + info->health = (int)val; } else if (linelen == 13 && stricmp (Line1, "Reaction time") == 0) { - info->reactiontime = val; + info->reactiontime = (int)val; } else if (linelen == 11 && stricmp (Line1, "Pain chance") == 0) { @@ -1169,13 +1174,13 @@ static int PatchThing (int thingy) } else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) { - info->SetDamage(val); + info->SetDamage((int)val); } else if (linelen == 5) { if (stricmp (Line1, "Speed") == 0) { - info->Speed = (signed long)val; // handle fixed point later. + info->Speed = (double)val; // handle fixed point later. } else if (stricmp (Line1, "Width") == 0) { @@ -1188,7 +1193,7 @@ static int PatchThing (int thingy) } else if (stricmp (Line1, "Scale") == 0) { - info->Scale.Y = info->Scale.X = clamp(atof (Line2), 1./65536, 256.); + info->Scale.Y = info->Scale.X = clamp((float)atof (Line2), 1.f/65536, 256.f); } else if (stricmp (Line1, "Decal") == 0) { @@ -1232,12 +1237,12 @@ static int PatchThing (int thingy) Printf("Infighting groups must be >= 0 (check your dehacked)\n"); val = 0; } - type->ActorInfo()->infighting_group = val; + type->ActorInfo()->infighting_group = (int)val; } else if (linelen == 16 && stricmp(Line1, "projectile group") == 0) { if (val < 0) val = -1; - type->ActorInfo()->projectile_group = val; + type->ActorInfo()->projectile_group = (int)val; } else if (linelen == 12 && stricmp(Line1, "splash group") == 0) { @@ -1246,11 +1251,11 @@ static int PatchThing (int thingy) Printf("Splash groups must be >= 0 (check your dehacked)\n"); val = 0; } - type->ActorInfo()->splash_group = val; + type->ActorInfo()->splash_group = (int)val; } else if (linelen == 10 && stricmp(Line1, "fast speed") == 0) { - double fval = val >= 256 ? DEHToDouble(val) : val; + double fval = val >= 256 ? DEHToDouble(val) : double(val); info->FloatVar(NAME_FastSpeed) = fval; } else if (linelen == 11 && stricmp(Line1, "melee range") == 0) @@ -1259,15 +1264,21 @@ 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()) { FDropItem* di = (FDropItem*)ClassDataAllocator.Alloc(sizeof(FDropItem)); + di->Next = nullptr; di->Name = InfoNames[val]->TypeName.GetChars(); di->Probability = 255; di->Amount = -1; info->GetInfo()->DropItems = di; } + else if ((int)val == -1) + { + info->GetInfo()->DropItems = nullptr; + } } else if (linelen == 11 && stricmp(Line1, "blood color") == 0) { @@ -1283,7 +1294,7 @@ static int PatchThing (int thingy) 0xffff8000, // 8 - Orange }; - if (val < 0 || val > 8) val = 0; + if (val > 8 || val < 0) val = 0; unsigned color = bloodcolor[val]; info->BloodColor = color; info->BloodTranslation = val == 0? 0 : TRANSLATION(TRANSLATION_Blood, CreateBloodTranslation(color)); @@ -1337,7 +1348,7 @@ static int PatchThing (int thingy) { if (stricmp (Line1 + linelen - 6, " frame") == 0) { - FState *state = FindState (val); + FState *state = FindState ((int)val); if (type != NULL && !patchedStates) { @@ -1375,7 +1386,7 @@ static int PatchThing (int thingy) } else if (stricmp (Line1 + linelen - 6, " sound") == 0) { - FSoundID snd = 0; + FSoundID snd = NO_SOUND; if (val == 0 || val >= SoundMap.Size()) { @@ -1383,7 +1394,7 @@ static int PatchThing (int thingy) { // Sound was not a (valid) number, // so treat it as an actual sound name. stripwhite (Line2); - snd = Line2; + snd = S_FindSound(Line2); } } else @@ -1410,7 +1421,7 @@ static int PatchThing (int thingy) { if (stricmp (Line1, "Mass") == 0) { - info->Mass = val; + info->Mass = (int)val; } else if (stricmp (Line1, "Bits") == 0) { @@ -2055,64 +2066,62 @@ static int PatchWeapon (int weapNum) Printf ("Weapon %d out of range.\n", weapNum); } + FState* readyState = nullptr; while ((result = GetLine ()) == 1) { int val = atoi (Line2); - if (strlen (Line1) >= 9) + size_t len = strlen(Line1); + if (len > 6 && stricmp (Line1 + len - 6, " frame") == 0) { - if (stricmp (Line1 + strlen (Line1) - 6, " frame") == 0) + FState *state = FindState (val); + + if (type != nullptr && !patchedStates) { - FState *state = FindState (val); - - if (type != NULL && !patchedStates) - { - statedef.MakeStateDefines(type); - patchedStates = true; - } - - if (strnicmp (Line1, "Deselect", 8) == 0) - statedef.SetStateLabel("Select", state); - else if (strnicmp (Line1, "Select", 6) == 0) - statedef.SetStateLabel("Deselect", state); - else if (strnicmp (Line1, "Bobbing", 7) == 0) - statedef.SetStateLabel("Ready", state); - else if (strnicmp (Line1, "Shooting", 8) == 0) - statedef.SetStateLabel("Fire", state); - else if (strnicmp (Line1, "Firing", 6) == 0) - statedef.SetStateLabel("Flash", state); + statedef.MakeStateDefines(type); + patchedStates = true; } - else if (stricmp (Line1, "Ammo type") == 0) + + if (strnicmp (Line1, "Deselect", 8) == 0) + statedef.SetStateLabel("Select", state); + else if (strnicmp (Line1, "Select", 6) == 0) + statedef.SetStateLabel("Deselect", state); + else if (strnicmp(Line1, "Bobbing", 7) == 0) { - if (val < 0 || val >= 12 || (unsigned)val >= AmmoNames.Size()) + readyState = state; + statedef.SetStateLabel("Ready", state); + } + else if (strnicmp (Line1, "Shooting", 8) == 0) + statedef.SetStateLabel("Fire", state); + else if (strnicmp (Line1, "Firing", 6) == 0) + statedef.SetStateLabel("Flash", state); + } + else if (stricmp (Line1, "Ammo type") == 0) + { + if (val < 0 || val >= 12 || (unsigned)val >= AmmoNames.Size()) + { + val = 5; + } + if (info) + { + auto &AmmoType = info->PointerVar(NAME_AmmoType1); + AmmoType = AmmoNames[val]; + if (AmmoType != nullptr) { - val = 5; - } - if (info) - { - auto &AmmoType = info->PointerVar(NAME_AmmoType1); - AmmoType = AmmoNames[val]; - if (AmmoType != nullptr) + info->IntVar(NAME_AmmoGive1) = GetDefaultByType(AmmoType)->IntVar(NAME_Amount) * 2; + auto &AmmoUse = info->IntVar(NAME_AmmoUse1); + if (AmmoUse == 0) { - info->IntVar(NAME_AmmoGive1) = GetDefaultByType(AmmoType)->IntVar(NAME_Amount) * 2; - auto &AmmoUse = info->IntVar(NAME_AmmoUse1); - if (AmmoUse == 0) - { - AmmoUse = 1; - } + AmmoUse = 1; } } } - else - { - Printf (unknown_str, Line1, "Weapon", weapNum); - } } else if (stricmp (Line1, "Decal") == 0) { stripwhite (Line2); const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2); - if (decal != NULL) + if (decal != nullptr) { if (info) info->DecalGenerator = const_cast (decal); } @@ -2192,6 +2201,20 @@ static int PatchWeapon (int weapNum) if (info) { + // Emulate the hard coded ready sound of the chainsaw as good as possible. + if (readyState) + { + FState* state = FindState(67); // S_SAW + if (readyState == state) + { + info->IntVar(NAME_ReadySound) = S_FindSound("weapons/sawidle").index(); + } + else + { + info->IntVar(NAME_ReadySound) = 0; + } + } + if (info->PointerVar(NAME_AmmoType1) == nullptr) { info->IntVar(NAME_AmmoUse1) = 0; @@ -2587,12 +2610,16 @@ static int PatchCodePtrs (int dummy) { FString symname; - if ((Line2[0] == 'A' || Line2[0] == 'a') && Line2[1] == '_') symname = Line2; else symname.Format("A_%s", Line2); + // Hack alert: If A_ConsumeAmmo is used we need to handle the ammo use differently. + // Since this is a parameterized code pointer the AmmoPerAttack check cannot find it easily without some help. + if (symname.CompareNoCase("A_ConsumeAmmo") == 0) + state->StateFlags |= STF_CONSUMEAMMO; + // Let's consider as aliases some redundant MBF pointer bool ismbfcp = false; for (unsigned int i = 0; i < MBFCodePointers.Size(); i++) @@ -2749,7 +2776,17 @@ static int PatchText (int oldSize) // Search through most other texts const char *str; - do + + // hackhack: If the given string is "Doom", only replace "MUSIC_DOOM". + // This is the only music or texture name clashing with common words in the string table. + if (!stricmp(oldStr, "Doom")) + { + str = "MUSIC_DOOM"; + TableElement te = { LumpFileNum, { newStrData, newStrData, newStrData, newStrData } }; + DehStrings.Insert(str, te); + good = true; + } + else do { oldStrData.MergeChars(' '); str = EnglishStrings.MatchString(oldStr); @@ -3502,11 +3539,11 @@ void FinishDehPatch () // Retry until we find a free name. This is unlikely to happen but not impossible. mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++); bool newlycreated; - subclass = static_cast(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated)); + subclass = static_cast(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated, 0)); if (newlycreated) subclass->InitializeDefaults(); } while (subclass == nullptr); - NewClassType(subclass); // This needs a VM type to work as intended. + NewClassType(subclass, 0); // This needs a VM type to work as intended. AActor *defaults2 = GetDefaultByType (subclass); memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); @@ -3570,8 +3607,8 @@ void FinishDehPatch () } else { + bool handled = false; weap->BoolVar(NAME_bDehAmmo) = true; - weap->IntVar(NAME_AmmoUse1) = 0; // to allow proper checks in CheckAmmo we have to find the first attack pointer in the Fire sequence // and set its default ammo use as the weapon's AmmoUse1. @@ -3586,25 +3623,39 @@ void FinishDehPatch () break; // State has already been checked so we reached a loop } StateVisited[state] = true; + if (state->StateFlags & STF_CONSUMEAMMO) + { + // If A_ConsumeAmmo is being used we have to rely on the existing AmmoUse1 value. + handled = true; + state->StateFlags &= ~STF_CONSUMEAMMO; + break; + } for(unsigned j = 0; AmmoPerAttacks[j].func != NAME_None; j++) { if (AmmoPerAttacks[j].ptr == nullptr) { auto p = dyn_cast(wcls->FindSymbol(AmmoPerAttacks[j].func, true)); if (p != nullptr) AmmoPerAttacks[j].ptr = p->Variants[0].Implementation; + assert(AmmoPerAttacks[j].ptr); } - if (state->ActionFunc == AmmoPerAttacks[j].ptr) + if (state->ActionFunc == AmmoPerAttacks[j].ptr && AmmoPerAttacks[j].ptr) { found = true; int use = AmmoPerAttacks[j].ammocount; if (use < 0) use = deh.BFGCells; weap->IntVar(NAME_AmmoUse1) = use; + handled = true; break; } } if (found) break; state = state->GetNextState(); } + if (!handled) + { + weap->IntVar(NAME_AmmoUse1) = 0; + + } } } WeaponNames.Clear(); @@ -3838,6 +3889,20 @@ void ClearMissile(AActor* info) if (info->BounceFlags & BOUNCE_DEH) info->BounceFlags = BOUNCE_Grenade | BOUNCE_DEH; } +void SetShadow(AActor* info) +{ + info->flags |= MF_SHADOW; + info->RenderStyle = LegacyRenderStyles[STYLE_OptFuzzy]; + info->renderflags &= ~RF_ZDOOMTRANS; +} + +void ClearShadow(AActor* info) +{ + info->flags &= ~MF_SHADOW; + info->RenderStyle = LegacyRenderStyles[info->Alpha >= 1 - FLT_EPSILON? STYLE_Normal : STYLE_Translucent]; + info->renderflags &= ~RF_ZDOOMTRANS; +} + static FlagHandler flag1handlers[32] = { F(MF_SPECIAL), F(MF_SOLID), @@ -3857,7 +3922,7 @@ static FlagHandler flag1handlers[32] = { F(MF_TELEPORT), { SetMissile, ClearMissile, [](AActor* a)->bool { return a->flags & MF_MISSILE; } }, F(MF_DROPPED), - F(MF_SHADOW), + { SetShadow, ClearShadow, [](AActor* a)->bool { return a->flags & MF_SHADOW; } }, F(MF_NOBLOOD), F(MF_CORPSE), F(MF_INFLOAT), @@ -3870,7 +3935,7 @@ static FlagHandler flag1handlers[32] = { F6(MF6_TOUCHY), { SetBounces, ClearBounces, [](AActor* a)->bool { return a->BounceFlags & BOUNCE_DEH; } }, F(MF_FRIENDLY), - { SetTranslucent, ClearTranslucent, CheckTranslucent } + { SetTranslucent, ClearTranslucent, CheckTranslucent }, }; static FlagHandler flag2handlers[32] = { diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index 807945545..e765959b8 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -40,7 +40,7 @@ #include "m_random.h" #include "weightedlist.h" #include "statnums.h" -#include "templates.h" + #include "a_sharedglobal.h" #include "gi.h" #include "b_bot.h" diff --git a/src/gamedata/doomfont.h b/src/gamedata/doomfont.h index c960a9b35..9b44a480f 100644 --- a/src/gamedata/doomfont.h +++ b/src/gamedata/doomfont.h @@ -56,7 +56,7 @@ void InitDoomFonts() } else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) { - OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true); + OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true, true); } diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 3b823c59e..e2848c015 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -34,7 +34,7 @@ */ #include -#include "templates.h" + #include "g_level.h" #include "filesystem.h" #include "cmdlib.h" @@ -50,6 +50,7 @@ #include "g_levellocals.h" #include "events.h" #include "i_system.h" +#include "screenjob.h" static TArray wadclusterinfos; TArray wadlevelinfos; @@ -301,7 +302,8 @@ void level_info_t::Reset() lightadditivesurfaces = -1; skyrotatevector = FVector3(0, 0, 1); skyrotatevector2 = FVector3(0, 0, 1); - + lightblendmode = ELightBlendMode::DEFAULT; + tonemap = ETonemapMode::None; } @@ -741,6 +743,30 @@ void FMapInfoParser::ParseMusic(FString &name, int &order) } } +//========================================================================== +// +// +// +//========================================================================== + +void FMapInfoParser::ParseCutscene(CutsceneDef& cdef) +{ + FString sound; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("video")) { ParseAssign(); sc.MustGetString(); cdef.video = sc.String; cdef.function = ""; } + else if (sc.Compare("function")) { ParseAssign(); sc.SetCMode(false); sc.MustGetString(); sc.SetCMode(true); cdef.function = sc.String; cdef.video = ""; } + else if (sc.Compare("sound")) { ParseAssign(); sc.MustGetString(); cdef.soundName = sc.String; } + else if (sc.Compare("soundid")) { ParseAssign(); sc.MustGetNumber(); cdef.soundID = sc.Number; } + else if (sc.Compare("fps")) { ParseAssign(); sc.MustGetNumber(); cdef.framespersec = sc.Number; } + //else if (sc.Compare("transitiononly")) cdef.transitiononly = true; + else if (sc.Compare("delete")) { cdef.function = "none"; cdef.video = ""; } // this means 'play nothing', not 'not defined'. + else if (sc.Compare("clear")) cdef = {}; + } +} + //========================================================================== // // ParseCluster @@ -845,6 +871,18 @@ void FMapInfoParser::ParseCluster() { clusterinfo->flags |= CLUSTER_EXITTEXTINLUMP; } + else if (sc.Compare("intro")) + { + ParseCutscene(clusterinfo->intro); + } + else if (sc.Compare("outro")) + { + ParseCutscene(clusterinfo->outro); + } + else if (sc.Compare("gameover")) + { + ParseCutscene(clusterinfo->gameover); + } else if (!ParseCloseBrace()) { // Unknown @@ -1205,8 +1243,8 @@ DEFINE_MAP_OPTION(PrecacheSounds, true) do { parse.sc.MustGetString(); - FSoundID snd = parse.sc.String; - if (snd == 0) + FSoundID snd = S_FindSound(parse.sc.String); + if (snd == NO_SOUND) { parse.sc.ScriptMessage("Unknown sound \"%s\"", parse.sc.String); } @@ -1459,6 +1497,57 @@ DEFINE_MAP_OPTION(lightmode, false) } } +DEFINE_MAP_OPTION(lightblendmode, false) +{ + parse.ParseAssign(); + parse.sc.MustGetString(); + + if (parse.sc.Compare("Default") || parse.sc.Compare("Clamp")) + { + info->lightblendmode = ELightBlendMode::DEFAULT; + } + else if (parse.sc.Compare("ColoredClamp")) + { + info->lightblendmode = ELightBlendMode::CLAMP_COLOR; + } + else if (parse.sc.Compare("Unclamped")) + { + info->lightblendmode = ELightBlendMode::NOCLAMP; + if(parse.sc.CheckString(",")) + { + parse.sc.MustGetString(); + if (parse.sc.Compare("None")) + { + info->tonemap = ETonemapMode::None; + } + else if (parse.sc.Compare("Linear")) + { + info->tonemap = ETonemapMode::Linear; + } + else if (parse.sc.Compare("Uncharted2")) + { + info->tonemap = ETonemapMode::Uncharted2; + } + else if (parse.sc.Compare("HejlDawson")) + { + info->tonemap = ETonemapMode::HejlDawson; + } + else if (parse.sc.Compare("Reinhard")) + { + info->tonemap = ETonemapMode::Reinhard; + } + else + { + parse.sc.ScriptMessage("Invalid tonemap %s", parse.sc.String); + } + } + } + else + { + parse.sc.ScriptMessage("Invalid light blend mode %s", parse.sc.String); + } +} + DEFINE_MAP_OPTION(notexturefill, false) { if (parse.CheckAssign()) @@ -1540,6 +1629,16 @@ DEFINE_MAP_OPTION(loadacs, false) info->acsName = parse.sc.String; } +DEFINE_MAP_OPTION(intro, true) +{ + parse.ParseCutscene(info->intro); +} + +DEFINE_MAP_OPTION(outro, true) +{ + parse.ParseCutscene(info->outro); +} + //========================================================================== // @@ -1663,6 +1762,7 @@ MapFlagHandlers[] = { "enableskyboxao", MITYPE_SETFLAG3, LEVEL3_SKYBOXAO, 0 }, { "disableskyboxao", MITYPE_CLRFLAG3, LEVEL3_SKYBOXAO, 0 }, { "avoidmelee", MITYPE_SETFLAG3, LEVEL3_AVOIDMELEE, 0 }, + { "attenuatelights", MITYPE_SETFLAG3, LEVEL3_ATTENUATE, 0 }, { "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes { "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX, 0 }, { "compat_stairs", MITYPE_COMPATFLAG, COMPATF_STAIRINDEX, 0 }, @@ -1686,7 +1786,8 @@ MapFlagHandlers[] = { "compat_minotaur", MITYPE_COMPATFLAG, COMPATF_MINOTAUR, 0 }, { "compat_mushroom", MITYPE_COMPATFLAG, COMPATF_MUSHROOM, 0 }, { "compat_mbfmonstermove", MITYPE_COMPATFLAG, COMPATF_MBFMONSTERMOVE, 0 }, - { "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS, 0 }, + { "compat_corpsegibs", MITYPE_COMPATFLAG, 0, 0 }, // this flag no longer exists, but we need it here for old mapinfos. + { "compat_vileghosts", MITYPE_COMPATFLAG, COMPATF_VILEGHOSTS, 0 }, { "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS, 0 }, { "compat_spritesort", MITYPE_COMPATFLAG, COMPATF_SPRITESORT, 0 }, { "compat_light", MITYPE_COMPATFLAG, COMPATF_LIGHT, 0 }, @@ -1706,6 +1807,7 @@ MapFlagHandlers[] = { "compat_scriptwait", MITYPE_COMPATFLAG, 0, COMPATF2_SCRIPTWAIT }, { "compat_avoidhazards", MITYPE_COMPATFLAG, 0, COMPATF2_AVOID_HAZARDS }, { "compat_stayonlift", MITYPE_COMPATFLAG, 0, COMPATF2_STAYONLIFT }, + { "compat_nombf21", MITYPE_COMPATFLAG, 0, COMPATF2_NOMBF21 }, { "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, @@ -2064,6 +2166,7 @@ void FMapInfoParser::ParseEpisodeInfo () bool noskill = false; bool optional = false; bool extended = false; + CutsceneDef introscene; // Get map name sc.MustGetString (); @@ -2120,6 +2223,11 @@ void FMapInfoParser::ParseEpisodeInfo () { noskill = true; } + else if (sc.Compare("intro")) + { + ParseCutscene(introscene); + } + else if (!ParseCloseBrace()) { // Unknown @@ -2178,6 +2286,7 @@ void FMapInfoParser::ParseEpisodeInfo () epi->mPicName = pic; epi->mShortcut = tolower(key); epi->mNoSkill = noskill; + epi->mIntro = introscene; } } @@ -2242,9 +2351,11 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(inclump)), sc.String); } } - FScanner saved_sc = sc; - ParseMapInfo(inclump, gamedefaults, defaultinfo); - sc = saved_sc; + // use a new parser object to parse the include. Otherwise we'd have to save the entire FScanner in a local variable which is a lot more messy. + FMapInfoParser includer(&sc); + includer.format_type = format_type; + includer.HexenHack = HexenHack; + includer.ParseMapInfo(inclump, gamedefaults, defaultinfo); } else if (sc.Compare("gamedefaults")) { diff --git a/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index 4ed13e5ba..166a53439 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -39,6 +39,9 @@ #include "vectors.h" #include "sc_man.h" #include "file_zip.h" +#include "screenjob.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include "hw_viewpointuniforms.h" struct level_info_t; struct cluster_info_t; @@ -73,9 +76,14 @@ FSerializer &Serialize(FSerializer &arc, const char *key, acsdefered_t &defer, a struct FIntermissionDescriptor; struct FIntermissionAction; +struct CutsceneDef; struct FMapInfoParser { + FMapInfoParser(FScanner* parent) + : sc(parent ? &parent->GetSymbols() : nullptr) + { + } enum EFormatType { FMT_Unknown, @@ -95,6 +103,8 @@ struct FMapInfoParser bool ParseLookupName(FString &dest); void ParseMusic(FString &name, int &order); + void ParseCutscene(CutsceneDef& cdef); + //void ParseLumpOrTextureName(char *name); void ParseLumpOrTextureName(FString &name); void ParseExitText(FName formap, level_info_t *info); @@ -385,7 +395,7 @@ struct level_info_t TArray specialactions; - TArray PrecacheSounds; + TArray PrecacheSounds; TArray PrecacheTextures; TArray PrecacheClasses; @@ -401,6 +411,10 @@ struct level_info_t FString EDName; FString acsName; bool fs_nocheckposition; + ELightBlendMode lightblendmode; + ETonemapMode tonemap; + + CutsceneDef intro, outro; level_info_t() @@ -430,6 +444,9 @@ struct cluster_info_t FString ExitText; FString EnterText; FString MessageMusic; + CutsceneDef intro; // plays when entering this cluster, aside from starting a new game + CutsceneDef outro; // plays when leaving this cluster + CutsceneDef gameover; // when defined, plays when the player dies in this cluster int musicorder; int flags; int cdtrack; @@ -571,6 +588,7 @@ struct FEpisode FString mPicName; char mShortcut; bool mNoSkill; + CutsceneDef mIntro; }; extern TArray AllEpisodes; diff --git a/src/gamedata/gi.cpp b/src/gamedata/gi.cpp index 1f5eec9ca..643f63fc3 100644 --- a/src/gamedata/gi.cpp +++ b/src/gamedata/gi.cpp @@ -156,7 +156,7 @@ const char* GameInfoBorders[] = { \ sc.ScriptError("Value for '%s' can not be longer than %d characters.", #key, length); \ } \ - gameinfo.key[gameinfo.key.Reserve(1)] = FSoundID(sc.String); \ + gameinfo.key[gameinfo.key.Reserve(1)] = S_FindSound(sc.String); \ } \ while (sc.CheckToken(',')); \ } @@ -274,6 +274,12 @@ void FMapInfoParser::ParseGameInfo() if (sc.TokenType == '}') break; sc.TokenMustBe(TK_Identifier); + if (sc.Compare("intro")) + { + ParseCutscene(gameinfo.IntroScene); + continue; + } + FString nextKey = sc.String; sc.MustGetToken('='); @@ -362,6 +368,7 @@ void FMapInfoParser::ParseGameInfo() gameinfo.Dialogue = sc.String; gameinfo.AddDialogues.Clear(); } + // Insert valid keys here. GAMEINFOKEY_STRING(mCheatKey, "cheatKey") GAMEINFOKEY_STRING(mEasyKey, "easyKey") @@ -384,7 +391,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRINGARRAY(PrecachedTextures, "precachetextures", 0, false) GAMEINFOKEY_SOUNDARRAY(PrecachedSounds, "precachesounds", 0, false) GAMEINFOKEY_STRINGARRAY(EventHandlers, "addeventhandlers", 0, false) - GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, true) + GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, false) GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") GAMEINFOKEY_STRING(BorderFlat, "borderFlat") @@ -463,7 +470,7 @@ void FMapInfoParser::ParseGameInfo() SkipToNext(); } } - turbo.Callback(); + turbo->Callback(); } const char *gameinfo_t::GetFinalePage(unsigned int num) const diff --git a/src/gamedata/gi.h b/src/gamedata/gi.h index ce811ea3e..5f11ecfa5 100644 --- a/src/gamedata/gi.h +++ b/src/gamedata/gi.h @@ -37,6 +37,7 @@ #include "basics.h" #include "zstring.h" #include "name.h" +#include "screenjob.h" // Flags are not user configurable and only depend on the standard IWADs enum @@ -130,7 +131,7 @@ struct gameinfo_t TArray PrecachedClasses; TArray PrecachedTextures; - TArray PrecachedSounds; + TArray PrecachedSounds; TArray EventHandlers; FString titleMusic; @@ -212,6 +213,7 @@ struct gameinfo_t int fullscreenautoaspect = 3; bool nomergepickupmsg; bool mHideParTimes; + CutsceneDef IntroScene; const char *GetFinalePage(unsigned int num) const; }; diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index 455a4cb22..22ad8d42b 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -53,6 +53,7 @@ #include "filesystem.h" #include "g_levellocals.h" #include "texturemanager.h" +#include "d_main.h" extern void LoadActors (); extern void InitBotStuff(); @@ -730,7 +731,7 @@ void PClassActor::SetPainChance(FName type, int chance) if (chance >= 0) { - ActorInfo()->PainChances.Push({ type, MIN(chance, 256) }); + ActorInfo()->PainChances.Push({ type, min(chance, 256) }); } } diff --git a/src/gamedata/info.h b/src/gamedata/info.h index 0d2eadac4..d9e89037b 100644 --- a/src/gamedata/info.h +++ b/src/gamedata/info.h @@ -72,6 +72,7 @@ enum EStateFlags STF_SAMEFRAME = 16, // Ignore Frame (except when spawning actor) STF_CANRAISE = 32, // Allows a monster to be resurrected without waiting for an infinate frame STF_DEHACKED = 64, // Modified by Dehacked + STF_CONSUMEAMMO = 128, // Needed by the Dehacked parser. }; enum EStateType : int // this must ensure proper alignment. diff --git a/src/gamedata/keysections.cpp b/src/gamedata/keysections.cpp index e48808646..5f06f192e 100644 --- a/src/gamedata/keysections.cpp +++ b/src/gamedata/keysections.cpp @@ -282,6 +282,16 @@ CCMD(addplayerclass) newclass.Type = ti; newclass.Flags = 0; + + // If this class was already added, don't add it again + for(unsigned i = 0; i < PlayerClasses.Size(); i++) + { + if(PlayerClasses[i].Type == ti) + { + return; + } + } + int arg = 2; while (arg < argv.argc()) diff --git a/src/gamedata/options.cpp b/src/gamedata/options.cpp new file mode 100644 index 000000000..85a9b930d --- /dev/null +++ b/src/gamedata/options.cpp @@ -0,0 +1,205 @@ +// +// Copyright(C) 2020 by Ryan Krafnick +// +// 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: +// DSDA Options Lump +// + +#include "filesystem.h" +#include "g_mapinfo.h" +#include "doomdef.h" +#include "templates.h" + + +struct dsda_options +{ + int monsters_remember = -1; + int monster_infighting = -1; + int monster_backing = -1; + int monster_avoid_hazards = -1; + int monster_friction = -1; + int help_friends = 0; + int player_helpers = 0; + int friend_distance = 128; + int dog_jumping = -1; + int comp_dropoff = -1; + int comp_vile = -1; + int comp_pain = -1; + int comp_doorlight = -1; + int comp_model = -1; + int comp_floors = -1; + int comp_pursuit = -1; // 1 for 'latest' + int comp_staylift = -1; + int comp_stairs = -1; + int comp_ledgeblock = -1; + int comp_friendlyspawn = -1; +}; + +struct dsda_option_t +{ + const char* key; + int dsda_options::* value; + int min; + int max; +}; + +static dsda_option_t option_list[] = { + { "monsters_remember", &dsda_options::monsters_remember, 0, 1 }, + { "monster_infighting", &dsda_options::monster_infighting, 0, 1 }, + { "monster_backing", &dsda_options::monster_backing, 0, 1 }, + { "monster_avoid_hazards", &dsda_options::monster_avoid_hazards, 0, 1 }, + { "monster_friction", &dsda_options::monster_friction, 0, 1 }, + { "help_friends", &dsda_options::help_friends, 0, 1 }, + { "player_helpers", &dsda_options::player_helpers, 0, 3 }, + { "friend_distance", &dsda_options::friend_distance, 0, 999 }, + { "dog_jumping", &dsda_options::dog_jumping, 0, 1 }, + { "comp_dropoff", &dsda_options::comp_dropoff, 0, 1 }, + { "comp_vile", &dsda_options::comp_vile, 0, 1 }, + { "comp_pain", &dsda_options::comp_pain, 0, 1 }, + { "comp_doorlight", &dsda_options::comp_doorlight, 0, 1 }, + { "comp_model", &dsda_options::comp_model, 0, 1 }, + { "comp_floors", &dsda_options::comp_floors, 0, 1 }, + { "comp_pursuit", &dsda_options::comp_pursuit, 0, 1 }, + { "comp_staylift", &dsda_options::comp_staylift, 0, 1 }, + { "comp_stairs", &dsda_options::comp_stairs, 0, 1 }, + { "comp_ledgeblock", &dsda_options::comp_ledgeblock, 0, 1 }, + { "comp_friendlyspawn", &dsda_options::comp_friendlyspawn, 0, 1 }, + { 0 } +}; + +enum { OPTIONS_LINE_LENGTH = 80 }; + +struct options_lump_t +{ + const char* data; + int length; +}; + +static const char* dsda_ReadOption(char* buf, size_t size, options_lump_t* lump) +{ + if (lump->length <= 0) + return nullptr; + + while (size > 1 && *lump->data && lump->length) + { + size--; + lump->length--; + if ((*buf++ = *lump->data++) == '\n') + break; + } + + *buf = '\0'; + + return lump->data; +} + +static struct dsda_options dsda_LumpOptions(int lumpnum) +{ + struct dsda_options mbf_options; + + options_lump_t lump; + char buf[OPTIONS_LINE_LENGTH]; + char key[OPTIONS_LINE_LENGTH]; + char* scan; + int value, count; + dsda_option_t* option; + + lump.length = fileSystem.FileLength(lumpnum); + auto data = fileSystem.ReadFile(lumpnum); + lump.data = (char*)data.GetMem(); + + while (dsda_ReadOption(buf, OPTIONS_LINE_LENGTH, &lump)) + { + if (buf[0] == '#') + continue; + + scan = buf; + count = sscanf(scan, "%79s %d", key, &value); + + if (count != 2) + continue; + + for (option = option_list; option->value; option++) + { + if (!strncmp(key, option->key, OPTIONS_LINE_LENGTH)) + { + mbf_options.*option->value = clamp(option->min, option->max, value); + + //lprintf(LO_INFO, "dsda_LumpOptions: %s = %d\n", key, value); + + break; + } + } + } + return mbf_options; +} + + +void parseOptions() +{ + int lumpnum = fileSystem.FindFile("OPTIONS"); + + if (lumpnum == -1) + return; + + auto opt = dsda_LumpOptions(lumpnum); + + auto setflag = [](auto& flag, auto mask, bool set) + { + if (set) flag |= mask; + else flag &= ~mask; + }; + + for (auto& lev : wadlevelinfos) + { + setflag(lev.flags2, LEVEL2_NOINFIGHTING, opt.monster_infighting); + setflag(lev.flags3, LEVEL3_AVOIDMELEE, opt.monster_backing); + setflag(lev.compatflags2, COMPATF2_AVOID_HAZARDS, opt.monster_avoid_hazards); + setflag(lev.compatmask2, COMPATF2_AVOID_HAZARDS, opt.monster_avoid_hazards); + setflag(lev.compatflags, COMPATF_MBFMONSTERMOVE, opt.monster_friction); + setflag(lev.compatmask, COMPATF_MBFMONSTERMOVE, opt.monster_friction); + setflag(lev.compatflags, COMPATF_DROPOFF, opt.comp_dropoff); + setflag(lev.compatmask, COMPATF_DROPOFF, opt.comp_dropoff); + setflag(lev.compatflags, COMPATF_DROPOFF, opt.comp_dropoff); + setflag(lev.compatmask, COMPATF_DROPOFF, opt.comp_dropoff); + setflag(lev.compatflags, COMPATF_CORPSEGIBS, opt.comp_vile); + setflag(lev.compatmask, COMPATF_CORPSEGIBS, opt.comp_vile); + setflag(lev.flags3, LEVEL3_VILEOPTION, opt.comp_vile); + setflag(lev.flags3, LEVEL3_NOJUMPDOWN, !opt.dog_jumping); // this one's rather pointless, but well... + setflag(lev.compatflags, COMPATF_LIMITPAIN, opt.comp_pain); + setflag(lev.compatmask, COMPATF_LIMITPAIN, opt.comp_pain); + setflag(lev.compatflags, COMPATF_NODOORLIGHT, opt.comp_doorlight); + setflag(lev.compatmask, COMPATF_NODOORLIGHT, opt.comp_doorlight); + setflag(lev.compatflags, COMPATF_LIGHT | COMPATF_SHORTTEX, opt.comp_model); // only the relevant parts of this catch-all option. + setflag(lev.compatmask, COMPATF_LIGHT | COMPATF_SHORTTEX, opt.comp_model); + setflag(lev.compatflags2, COMPATF2_FLOORMOVE, opt.comp_floors); + setflag(lev.compatmask2, COMPATF2_FLOORMOVE, opt.comp_floors); + setflag(lev.compatflags2, COMPATF2_STAYONLIFT, opt.comp_staylift); + setflag(lev.compatmask2, COMPATF2_STAYONLIFT, opt.comp_staylift); + setflag(lev.compatflags, COMPATF_STAIRINDEX, opt.comp_stairs); + setflag(lev.compatmask, COMPATF_STAIRINDEX, opt.comp_stairs); + setflag(lev.compatflags, COMPATF_CROSSDROPOFF, opt.comp_ledgeblock); + setflag(lev.compatmask, COMPATF_CROSSDROPOFF, opt.comp_ledgeblock); + + /* later. these should be supported but are not implemented yet. + if (opt.monsters_remember == 0) + if (opt.comp_pursuit) + if (opt.comp_friendlyspawn == 0) + int help_friends = 0; + int player_helpers = 0; + int friend_distance = 128; + */ + + } +} + diff --git a/src/gamedata/p_blockmap.h b/src/gamedata/p_blockmap.h index f528ae156..06c03deb3 100644 --- a/src/gamedata/p_blockmap.h +++ b/src/gamedata/p_blockmap.h @@ -43,10 +43,7 @@ struct FBlockmap // mapblocks are used to check movement // against lines and things - enum - { - MAPBLOCKUNITS = 128 - }; + static constexpr int MAPBLOCKUNITS = 128; inline int GetBlockX(double xpos) { diff --git a/src/gamedata/p_terrain.cpp b/src/gamedata/p_terrain.cpp index 6371502c5..4d0efcff9 100644 --- a/src/gamedata/p_terrain.cpp +++ b/src/gamedata/p_terrain.cpp @@ -355,7 +355,7 @@ static void ParseOuter (FScanner &sc) static void SetSplashDefaults (FSplashDef *splashdef) { splashdef->SmallSplashSound = - splashdef->NormalSplashSound = 0; + splashdef->NormalSplashSound = NO_SOUND; splashdef->SmallSplash = splashdef->SplashBase = splashdef->SplashChunk = NULL; @@ -537,7 +537,7 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw case GEN_Sound: sc.MustGetString (); - SET_FIELD (FSoundID, FSoundID(sc.String)); + SET_FIELD (FSoundID, S_FindSound(sc.String)); /* unknown sounds never produce errors anywhere else so they shouldn't here either. if (val == 0) { @@ -645,11 +645,15 @@ static void ParseFloor (FScanner &sc) return; } sc.MustGetString (); + if (sc.Compare("Null") || sc.Compare("None")) + { + TerrainTypes.Set(picnum.GetIndex(), 0xffff); + return; + } terrain = P_FindTerrain (sc.String); if (terrain == -1) { Printf ("Unknown terrain %s\n", sc.String); - terrain = 0; } TerrainTypes.Set(picnum.GetIndex(), terrain); } @@ -704,7 +708,7 @@ int P_FindTerrain (FName name) { unsigned int i; - if (name == NAME_Null) return -1; + if (name == NAME_Null || name == NAME_None) return -1; for (i = 0; i < Terrains.Size (); i++) { if (Terrains[i].Name == name) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index c2606635a..c6284b2f1 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -31,12 +31,14 @@ #define __R_DEFS_H__ #include "doomdef.h" -#include "templates.h" + #include "m_bbox.h" #include "dobjgc.h" #include "r_data/r_translate.h" #include "texmanip.h" #include "fcolormap.h" +#include "r_sky.h" +#include "p_terrain.h" #include "hwrenderer/data/buffers.h" @@ -58,6 +60,8 @@ struct sector_t; class AActor; struct FSection; struct FLevelLocals; +struct LightmapSurface; +struct LightProbe; const uint16_t NO_INDEX = 0xffffu; const uint32_t NO_SIDE = 0xffffffffu; @@ -707,6 +711,8 @@ struct sector_t int vbocount[2]; // Total count of vertices belonging to this sector's planes. This is used when a sector height changes and also contains all attached planes. int ibocount; // number of indices per plane (identical for all planes.) If this is -1 the index buffer is not in use. + bool HasLightmaps = false; // Sector has lightmaps, each subsector vertex needs its own unique lightmap UV data + // Below are all properties which are not used by the renderer. TObjPtr SoundTarget; @@ -781,7 +787,6 @@ public: bool IsLinked(sector_t *other, bool ceiling) const; - sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH] void RemoveForceField(); int Index() const { return sectornum; } @@ -793,6 +798,7 @@ public: int GetFloorLight() const; int GetCeilingLight() const; + int GetSpriteLight() const; sector_t *GetHeightSec() const { @@ -1148,15 +1154,20 @@ class DBaseDecal; enum { - WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative - WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall - WALLF_NOFAKECONTRAST = 4, // Don't do fake contrast for this wall in side_t::GetLightLevel - WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles. - WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side. - WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side. - WALLF_POLYOBJ = 64, // This wall belongs to a polyobject. - WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog. - WALLF_EXTCOLOR = 256, // enables the extended color options (flagged to allow the renderer to easily skip the relevant code) + WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative + WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall + WALLF_NOFAKECONTRAST = 4, // Don't do fake contrast for this wall in side_t::GetLightLevel + WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles. + WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side. + WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side. + WALLF_POLYOBJ = 64, // This wall belongs to a polyobject. + WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog. + WALLF_EXTCOLOR = 256, // enables the extended color options (flagged to allow the renderer to easily skip the relevant code) + + WALLF_ABSLIGHTING_TIER = 512, // Per-tier absolute lighting flags + WALLF_ABSLIGHTING_TOP = WALLF_ABSLIGHTING_TIER << 0, // Top tier light is absolute instead of relative + WALLF_ABSLIGHTING_MID = WALLF_ABSLIGHTING_TIER << 1, // Mid tier light is absolute instead of relative + WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative }; struct side_t @@ -1213,20 +1224,28 @@ struct side_t uint32_t LeftSide, RightSide; // [RH] Group walls into loops uint16_t TexelLength; int16_t Light; + int16_t TierLights[3]; // per-tier light levels 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; seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering int numsegs; int sidenum; - int GetLightLevel (bool foggy, int baselight, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const; + int GetLightLevel (bool foggy, int baselight, int which, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const; void SetLight(int16_t l) { Light = l; } + void SetLight(int16_t l, int which) + { + TierLights[which] = l; + } + + FLevelLocals *GetLevel() { return sector->Level; @@ -1437,10 +1456,24 @@ enum AutomapLineStyle : int AMLS_COUNT }; -struct line_t +struct linebase_t { - vertex_t *v1, *v2; // vertices, from v1 to v2 + vertex_t* v1, * v2; // vertices, from v1 to v2 DVector2 delta; // precalculated v2 - v1 for side checking + + DVector2 Delta() const + { + return delta; + } + + void setDelta(double x, double y) + { + delta = { x, y }; + } +}; + +struct line_t : public linebase_t +{ uint32_t flags, flags2; uint32_t activation; // activation type int special; @@ -1458,16 +1491,6 @@ struct line_t int healthgroup; // [ZZ] this is the "destructible object" id int linenum; - DVector2 Delta() const - { - return delta; - } - - void setDelta(double x, double y) - { - delta = { x, y }; - } - void setAlpha(double a) { alpha = a; @@ -1481,7 +1504,11 @@ struct line_t inline bool isLinePortal() const; inline bool isVisualPortal() const; inline line_t *getPortalDestination() const; + inline int getPortalFlags() const; inline int getPortalAlignment() const; + inline int getPortalType() const; + inline DVector2 getPortalDisplacement() const; + inline DAngle getPortalAngleDiff() const; inline bool hitSkyWall(AActor* mo) const; int Index() const { return linenum; } @@ -1615,6 +1642,8 @@ struct subsector_t int Index() const { return subsectornum; } // 2: has one-sided walls FPortalCoverage portalcoverage[2]; + + LightmapSurface *lightmap[2]; }; @@ -1659,6 +1688,40 @@ 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; +}; + +struct LightProbe +{ + float X, Y, Z; + float Red, Green, Blue; +}; + +struct LightProbeCell +{ + LightProbe* FirstProbe = nullptr; + int NumProbes = 0; +}; + // // OTHER TYPES // @@ -1717,6 +1780,7 @@ void TransferSpecial(sector_t *self, sector_t *model); void GetSpecial(sector_t *self, secspecial_t *spec); void SetSpecial(sector_t *self, const secspecial_t *spec); int GetTerrain(const sector_t *, int pos); +FTerrainDef *GetFloorTerrain_S(const sector_t* sec, int pos); void CheckPortalPlane(sector_t *sector, int plane); void AdjustFloorClip(const sector_t *sector); void SetColor(sector_t *sector, int color, int desat); @@ -1726,6 +1790,8 @@ int GetCeilingLight(const sector_t *); double GetFriction(const sector_t *self, int plane, double *movefac); double HighestCeilingAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); double LowestFloorAt(sector_t *sec, double x, double y, sector_t **resultsec = nullptr); +sector_t* P_NextSpecialSector(sector_t* sect, int type, sector_t* prev); +sector_t* P_NextSpecialSectorVC(sector_t* sect, int type); // uses validcount inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); } inline bool sector_t::PlaneMoving(int pos) { return !!::PlaneMoving(this, pos); } @@ -1739,6 +1805,10 @@ inline void sector_t::SetColor(PalEntry pe, int desat) { ::SetColor(this, pe, de inline void sector_t::SetFade(PalEntry pe) { ::SetFade(this, pe); } inline int sector_t::GetFloorLight() const { return ::GetFloorLight(this); } inline int sector_t::GetCeilingLight() const { return ::GetCeilingLight(this); } +inline int sector_t::GetSpriteLight() const +{ + return GetTexture(ceiling) == skyflatnum ? GetCeilingLight() : GetFloorLight(); +} inline double sector_t::GetFriction(int plane, double *movefac) const { return ::GetFriction(this, plane, movefac); } inline void sector_t::CheckExColorFlag() diff --git a/src/gamedata/statistics.cpp b/src/gamedata/statistics.cpp index 589c2b46f..39f67a998 100644 --- a/src/gamedata/statistics.cpp +++ b/src/gamedata/statistics.cpp @@ -561,6 +561,12 @@ void STAT_Serialize(FSerializer &arc) } +FString STAT_EpisodeName() +{ + if (StartEpisode == nullptr) return ""; + return StartEpisode->mEpisodeName; +} + //========================================================================== // // show statistics @@ -589,7 +595,7 @@ CCMD(printstats) CCMD(finishgame) { - bool gamestatecheck = gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE; + bool gamestatecheck = gamestate == GS_LEVEL || gamestate == GS_CUTSCENE; if (!gamestatecheck) { Printf("Cannot use 'finishgame' while not in a game!\n"); diff --git a/src/gamedata/textures/anim_switches.cpp b/src/gamedata/textures/anim_switches.cpp index 7767539ab..78e49508d 100644 --- a/src/gamedata/textures/anim_switches.cpp +++ b/src/gamedata/textures/anim_switches.cpp @@ -32,7 +32,7 @@ ** */ -#include "templates.h" + #include "textures.h" #include "s_sound.h" #include "r_state.h" @@ -87,10 +87,11 @@ void FTextureAnimator::InitSwitchList () def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def1->PreTexture = def2->frames[0].Texture = TexMan.CheckForTexture (list_p /* .name1 */, ETextureType::Wall, texflags); def2->PreTexture = def1->frames[0].Texture = TexMan.CheckForTexture (list_p + 9, ETextureType::Wall, texflags); - def1->Sound = def2->Sound = 0; + def1->Sound = def2->Sound = NO_SOUND; def1->NumFrames = def2->NumFrames = 1; def1->frames[0].TimeMin = def2->frames[0].TimeMin = 0; def1->frames[0].TimeRnd = def2->frames[0].TimeRnd = 0; + def1->QuestPanel = def2->QuestPanel = false; AddSwitchPair(def1, def2); } } @@ -228,7 +229,7 @@ FSwitchDef *FTextureAnimator::ParseSwitchDef (FScanner &sc, bool ignoreBad) FSwitchDef::frame thisframe; FTextureID picnum; bool bad; - FSoundID sound = 0; + FSoundID sound = NO_SOUND; bad = false; @@ -236,12 +237,12 @@ FSwitchDef *FTextureAnimator::ParseSwitchDef (FScanner &sc, bool ignoreBad) { if (sc.Compare ("sound")) { - if (sound != 0) + if (sound != NO_SOUND) { sc.ScriptError ("Switch state already has a sound"); } sc.MustGetString (); - sound = sc.String; + sound = S_FindSound(sc.String); } else if (sc.Compare ("pic")) { diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 55dcf060c..61bb6d29c 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -43,6 +43,7 @@ #include "serializer.h" #include "animations.h" #include "texturemanager.h" +#include "image.h" // MACROS ------------------------------------------------------------------ @@ -61,14 +62,6 @@ static FRandom pr_animatepictures ("AnimatePics"); void FTextureAnimator::DeleteAll() { - for (unsigned i = 0; i < mAnimations.Size(); i++) - { - if (mAnimations[i] != NULL) - { - M_Free(mAnimations[i]); - mAnimations[i] = NULL; - } - } mAnimations.Clear(); for (unsigned i = 0; i < mSwitchDefs.Size(); i++) @@ -80,15 +73,6 @@ void FTextureAnimator::DeleteAll() } } mSwitchDefs.Clear(); - - for (unsigned i = 0; i < mAnimatedDoors.Size(); i++) - { - if (mAnimatedDoors[i].TextureFrames != NULL) - { - delete[] mAnimatedDoors[i].TextureFrames; - mAnimatedDoors[i].TextureFrames = NULL; - } - } mAnimatedDoors.Clear(); } @@ -101,22 +85,21 @@ void FTextureAnimator::DeleteAll() // //========================================================================== -FAnimDef *FTextureAnimator::AddAnim (FAnimDef *anim) +FAnimDef *FTextureAnimator::AddAnim (FAnimDef& anim) { // Search for existing duplicate. for (unsigned int i = 0; i < mAnimations.Size(); ++i) { - if (mAnimations[i]->BasePic == anim->BasePic) + if (mAnimations[i].BasePic == anim.BasePic) { // Found one! - M_Free (mAnimations[i]); mAnimations[i] = anim; - return anim; + return &mAnimations[i]; } } // Didn't find one, so add it at the end. mAnimations.Push (anim); - return anim; + return &mAnimations.Last(); } //========================================================================== @@ -132,19 +115,20 @@ FAnimDef *FTextureAnimator::AddSimpleAnim (FTextureID picnum, int animcount, uin { if (TexMan.AreTexturesCompatible(picnum, picnum + (animcount - 1))) { - FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef)); - anim->CurFrame = 0; - anim->BasePic = picnum; - anim->NumFrames = animcount; - anim->AnimType = FAnimDef::ANIM_Forward; - anim->bDiscrete = false; - anim->SwitchTime = 0; - anim->Frames[0].SpeedMin = speedmin; - anim->Frames[0].SpeedRange = speedrange; - anim->Frames[0].FramePic = anim->BasePic; + FAnimDef anim; + anim.CurFrame = 0; + anim.BasePic = picnum; + anim.NumFrames = animcount; + anim.AnimType = FAnimDef::ANIM_Forward; + anim.bDiscrete = false; + anim.SwitchTime = 0; + anim.Frames = (FAnimDef::FAnimFrame*)ImageArena.Alloc(sizeof(FAnimDef::FAnimFrame)); + anim.Frames[0].SpeedMin = speedmin; + anim.Frames[0].SpeedRange = speedrange; + anim.Frames[0].FramePic = anim.BasePic; return AddAnim (anim); } - return NULL; + return nullptr; } //========================================================================== @@ -157,14 +141,15 @@ FAnimDef *FTextureAnimator::AddSimpleAnim (FTextureID picnum, int animcount, uin FAnimDef *FTextureAnimator::AddComplexAnim (FTextureID picnum, const TArray &frames) { - FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef) + (frames.Size()-1) * sizeof(frames[0])); - anim->BasePic = picnum; - anim->NumFrames = frames.Size(); - anim->CurFrame = 0; - anim->AnimType = FAnimDef::ANIM_Forward; - anim->bDiscrete = true; - anim->SwitchTime = 0; - memcpy (&anim->Frames[0], &frames[0], frames.Size() * sizeof(frames[0])); + FAnimDef anim; + anim.BasePic = picnum; + anim.NumFrames = frames.Size(); + anim.CurFrame = 0; + anim.AnimType = FAnimDef::ANIM_Forward; + anim.bDiscrete = true; + anim.SwitchTime = 0; + anim.Frames = (FAnimDef::FAnimFrame*)ImageArena.Alloc(frames.Size() * sizeof(frames[0])); + memcpy (&anim.Frames[0], &frames[0], frames.Size() * sizeof(frames[0])); return AddAnim (anim); } @@ -340,6 +325,10 @@ void FTextureAnimator::InitAnimDefs () { ParseWarp(sc); } + else if (sc.Compare("canvastexture")) + { + ParseCanvasTexture(sc); + } else if (sc.Compare ("cameratexture")) { ParseCameraTexture(sc); @@ -455,6 +444,17 @@ void FTextureAnimator::ParseAnim (FScanner &sc, ETextureType usetype) defined = 1; ani = ParseRangeAnim (sc, picnum, usetype, missing); } + else if (sc.Compare("notrim")) + { + if (picnum.isValid()) + { + auto tex = TexMan.GetGameTexture(picnum); + + if (tex) tex->SetNoTrimming(true); + else sc.ScriptError("NoTrim: %s not found", sc.String); + } + else sc.ScriptError("NoTrim: %s is not a sprite", sc.String); + } else if (sc.Compare ("pic")) { if (defined == 1) @@ -687,6 +687,21 @@ void FTextureAnimator::ParseWarp(FScanner &sc) } } + +//========================================================================== +// +// ParseCameraTexture +// +// Parses a canvas texture definition +// +//========================================================================== + +void FTextureAnimator::ParseCanvasTexture(FScanner& sc) +{ + // This is currently identical to camera textures. + ParseCameraTexture(sc); +} + //========================================================================== // // ParseCameraTexture @@ -772,7 +787,7 @@ void FTextureAnimator::FixAnimations () for (i = 0; i < mAnimations.Size(); ++i) { - FAnimDef *anim = mAnimations[i]; + const FAnimDef *anim = &mAnimations[i]; if (!anim->bDiscrete) { bool nodecals; @@ -859,7 +874,7 @@ void FTextureAnimator::ParseAnimatedDoor(FScanner &sc) } if (!error) { - anim.TextureFrames = new FTextureID[frames.Size()]; + anim.TextureFrames = (FTextureID*)ImageArena.Alloc(sizeof(FTextureID) * frames.Size()); memcpy (anim.TextureFrames, &frames[0], sizeof(FTextureID) * frames.Size()); anim.NumTextureFrames = frames.Size(); mAnimatedDoors.Push (anim); @@ -917,7 +932,7 @@ void FTextureAnimator::UpdateAnimations (uint64_t mstime) { for (unsigned int j = 0; j < mAnimations.Size(); ++j) { - FAnimDef *anim = mAnimations[j]; + FAnimDef *anim = &mAnimations[j]; // If this is the first time through R_UpdateAnimations, just // initialize the anim's switch time without actually animating. diff --git a/src/gamedata/textures/animations.h b/src/gamedata/textures/animations.h index 078ed5f67..639005bd2 100644 --- a/src/gamedata/textures/animations.h +++ b/src/gamedata/textures/animations.h @@ -4,21 +4,24 @@ #include "name.h" #include "textureid.h" #include "tarray.h" +#include "s_soundinternal.h" struct FAnimDef { + struct FAnimFrame + { + uint32_t SpeedMin; // Speeds are in ms, not tics + uint32_t SpeedRange; + FTextureID FramePic; + }; + FTextureID BasePic; uint16_t NumFrames; uint16_t CurFrame; uint8_t AnimType; bool bDiscrete; // taken out of AnimType to have better control uint64_t SwitchTime; // Time to advance to next frame - struct FAnimFrame - { - uint32_t SpeedMin; // Speeds are in ms, not tics - uint32_t SpeedRange; - FTextureID FramePic; - } Frames[1]; + FAnimFrame* Frames; enum { ANIM_Forward, @@ -37,7 +40,7 @@ struct FSwitchDef FSwitchDef* PairDef; // switch def to use to return to PreTexture uint16_t NumFrames; // # of animation frames bool QuestPanel; // Special texture for Strife mission - int Sound; // sound to play at start of animation. Changed to int to avoiud having to include s_sound here. + FSoundID Sound; // sound to play at start of animation. Changed to int to avoiud having to include s_sound here. struct frame // Array of times followed by array of textures { // actual length of each array is uint16_t TimeMin; @@ -59,7 +62,7 @@ struct FDoorAnimation class FTextureAnimator { - TArray mAnimations; + TArray mAnimations; TArray mSwitchDefs; TArray mAnimatedDoors; @@ -67,6 +70,7 @@ class FTextureAnimator FAnimDef* ParseRangeAnim(FScanner& sc, FTextureID picnum, ETextureType usetype, bool missing); void ParsePicAnim(FScanner& sc, FTextureID picnum, ETextureType usetype, bool missing, TArray& frames); void ParseWarp(FScanner& sc); + void ParseCanvasTexture(FScanner& sc); void ParseCameraTexture(FScanner& sc); FTextureID ParseFramenum(FScanner& sc, FTextureID basepicnum, ETextureType usetype, bool allowMissing); void ParseTime(FScanner& sc, uint32_t& min, uint32_t& max); @@ -88,7 +92,7 @@ public: } // Animation stuff - FAnimDef* AddAnim(FAnimDef* anim); + FAnimDef* AddAnim(FAnimDef& anim); void DeleteAll(); FAnimDef* AddSimpleAnim(FTextureID picnum, int animcount, uint32_t speedmin, uint32_t speedrange = 0); @@ -98,7 +102,7 @@ public: FDoorAnimation* FindAnimatedDoor(FTextureID picnum); void UpdateAnimations(uint64_t mstime); - const TArray& GetAnimations() const { return mAnimations; } + const TArray& GetAnimations() const { return mAnimations; } void Init() { diff --git a/src/gamedata/textures/buildloader.cpp b/src/gamedata/textures/buildloader.cpp index 047ad14be..bfcc63225 100644 --- a/src/gamedata/textures/buildloader.cpp +++ b/src/gamedata/textures/buildloader.cpp @@ -36,7 +36,7 @@ #include "files.h" #include "filesystem.h" -#include "templates.h" + #include "cmdlib.h" #include "colormatcher.h" #include "bitmap.h" @@ -178,7 +178,7 @@ void AddTiles(const FString& pathprefix, const void* tiles, FRemapTable *remap) } speed = (anm >> 24) & 15; - speed = MAX(1, (1 << speed) * 1000 / 120); // Convert from 120 Hz to 1000 Hz. + speed = max(1, (1 << speed) * 1000 / 120); // Convert from 120 Hz to 1000 Hz. TexAnim.AddSimpleAnim(texnum, picanm[pic] & 63, type, speed); } diff --git a/src/hu_scores.cpp b/src/hu_scores.cpp index 6e662ab6b..d9c36f8b4 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -37,7 +37,7 @@ #include "c_console.h" #include "teaminfo.h" -#include "templates.h" + #include "v_video.h" #include "doomstat.h" #include "g_level.h" @@ -149,7 +149,7 @@ static int FontScale; void HU_DrawScores (player_t *player) { displayFont = NewSmallFont; - FontScale = MAX(screen->GetHeight() / 400, 1); + FontScale = max(screen->GetHeight() / 400, 1); if (deathmatch) { @@ -273,11 +273,11 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER HU_GetPlayerWidths(maxnamewidth, maxscorewidth, maxiconheight); height = displayFont->GetHeight() * FontScale; - lineheight = MAX(height, maxiconheight * CleanYfac); + lineheight = max(height, maxiconheight * CleanYfac); ypadding = (lineheight - height + 1) / 2; bottom = StatusBar->GetTopOfStatusbar(); - y = MAX(48*CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2); + y = max(48*CleanYfac, (bottom - MAXPLAYERS * (height + CleanYfac + 1)) / 2); HU_DrawTimeRemaining (bottom - height); @@ -304,7 +304,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER } } - int scorexwidth = twod->GetWidth() / MAX(8, numTeams); + int scorexwidth = twod->GetWidth() / max(8, numTeams); int numscores = 0; int scorex; @@ -430,8 +430,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, auto icon = FSetTextureID(player->mo->IntVar(NAME_ScoreIcon)); if (icon.isValid()) { - auto pic = TexMan.GetGameTexture(icon); - DrawTexture(twod, pic, col3, y, + DrawTexture(twod, icon, false, col3, y, DTA_CleanNoMove, true, TAG_DONE); } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index cdaed2e9b..5c6fe4b02 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -40,8 +40,6 @@ void CT_Init (void); bool CT_Responder (event_t* ev); void CT_Drawer (void); -extern int chatmodeon; - // [RH] Draw deathmatch scores void HU_DrawScores (player_t *me); diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index bca2de20f..fdcdd0325 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -50,12 +50,14 @@ #include "d_net.h" #include "g_levellocals.h" #include "utf8.h" -#include "templates.h" + #include "s_music.h" #include "texturemanager.h" #include "v_draw.h" #include "doommenu.h" #include "sbar.h" +#include "screenjob.h" +#include "vm.h" FIntermissionDescriptorList IntermissionDescriptors; @@ -73,25 +75,32 @@ IMPLEMENT_POINTERS_END extern int NoWipe; CVAR(Bool, nointerscrollabort, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -CVAR(Bool, inter_subtitles, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Bool, inter_classic_scaling, true, CVAR_ARCHIVE); +DEFINE_ACTION_FUNCTION(_Screen, GetTextScreenSize) +{ + auto scale = active_con_scaletext(twod, generic_ui); + int hudwidth = twod->GetWidth() / scale; + int hudheight = twod->GetHeight() / scale; + ACTION_RETURN_VEC2(DVector2(hudwidth, hudheight)); +} + //========================================================================== // // This also gets used by the title loop. // //========================================================================== -void DrawFullscreenSubtitle(const char *text) +void DrawFullscreenSubtitle(FFont* font, const char *text) { if (!text || !*text || !inter_subtitles) return; + if (*text == '$') text = GStrings[text + 1]; // This uses the same scaling as regular HUD messages auto scale = active_con_scaletext(twod, generic_ui); int hudwidth = twod->GetWidth() / scale; int hudheight = twod->GetHeight() / scale; - FFont *font = generic_ui? NewSmallFont : SmallFont; int linelen = hudwidth < 640 ? Scale(hudwidth, 9, 10) - 40 : 560; auto lines = V_BreakLines(font, linelen, text); @@ -135,12 +144,7 @@ void DrawFullscreenSubtitle(const char *text) void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) { - if (desc->mMusic.IsEmpty()) - { - // only start the default music if this is the first action in an intermission - if (first) S_ChangeMusic (gameinfo.finaleMusic, gameinfo.finaleOrder, desc->mMusicLooping); - } - else + if (!first && desc->mMusic.IsNotEmpty()) { S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping); } @@ -184,12 +188,31 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) } mTicker = 0; mSubtitle = desc->mSubtitle; + mFirst = first; + // If this is the first element of an intermission we must delay starting the music until Start() is called. + mMusic = desc->mMusic; + mMusicLooping = desc->mMusicLooping; + mMusicOrder = desc->mMusicOrder; } - -int DIntermissionScreen::Responder (event_t *ev) +void DIntermissionScreen::Start() { - if (ev->type == EV_KeyDown) + if (mFirst) + { + if (mMusic.IsEmpty()) + { + S_ChangeMusic(gameinfo.finaleMusic, gameinfo.finaleOrder, mMusicLooping); + } + else + { + S_ChangeMusic(mMusic, mMusicOrder, mMusicLooping); + } + } +} + +int DIntermissionScreen::Responder (FInputEvent *ev) +{ + if (ev->Type == EV_KeyDown) { return -1; } @@ -221,7 +244,7 @@ void DIntermissionScreen::Drawer () { if (!mFlatfill) { - DrawTexture(twod, TexMan.GetGameTexture(mBackground), 0, 0, DTA_Fullscreen, true, TAG_DONE); + DrawTexture(twod, mBackground, false, 0, 0, DTA_Fullscreen, true, TAG_DONE); } else { @@ -235,11 +258,10 @@ void DIntermissionScreen::Drawer () for (unsigned i=0; i < mOverlays.Size(); i++) { if (CheckOverlay(i)) - DrawTexture(twod, TexMan.GetGameTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE); + DrawTexture(twod, mOverlays[i].mPic, false, mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE); } - const char *sub = mSubtitle.GetChars(); - if (sub && *sub == '$') sub = GStrings[sub + 1]; - if (sub) DrawFullscreenSubtitle(sub); + FFont* font = generic_ui ? NewSmallFont : SmallFont; + DrawFullscreenSubtitle(font, mSubtitle); } void DIntermissionScreen::OnDestroy() @@ -266,9 +288,9 @@ void DIntermissionScreenFader::Init(FIntermissionAction *desc, bool first) // //=========================================================================== -int DIntermissionScreenFader::Responder (event_t *ev) +int DIntermissionScreenFader::Responder (FInputEvent *ev) { - if (ev->type == EV_KeyDown) + if (ev->Type == EV_KeyDown) { return -1; } @@ -289,11 +311,11 @@ void DIntermissionScreenFader::Drawer () if (mType == FADE_In) factor = 1.0 - factor; int color = MAKEARGB(int(factor*255), 0,0,0); - DrawTexture(twod, TexMan.GetGameTexture(mBackground), 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE); + DrawTexture(twod, mBackground, false, 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE); for (unsigned i=0; i < mOverlays.Size(); i++) { if (CheckOverlay(i)) - DrawTexture(twod, TexMan.GetGameTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE); + DrawTexture(twod, mOverlays[i].mPic, false, mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE); } } } @@ -358,9 +380,9 @@ void DIntermissionScreenText::Init(FIntermissionAction *desc, bool first) if (mDuration > 0) mDuration += mTextDelay + mTextSpeed * mTextLen; } -int DIntermissionScreenText::Responder (event_t *ev) +int DIntermissionScreenText::Responder (FInputEvent *ev) { - if (ev->type == EV_KeyDown) + if (ev->Type == EV_KeyDown) { if (mTicker < mTextDelay + (mTextLen * mTextSpeed)) { @@ -376,7 +398,6 @@ void DIntermissionScreenText::Drawer () Super::Drawer(); if (mTicker >= mTextDelay) { - FGameTexture *pic; int w; size_t count; int c; @@ -386,7 +407,7 @@ void DIntermissionScreenText::Drawer () // line feed characters. int numrows; auto font = generic_ui ? NewSmallFont : SmallFont; - auto fontscale = MAX(generic_ui ? MIN(twod->GetWidth() / 640, twod->GetHeight() / 400) : MIN(twod->GetWidth() / 400, twod->GetHeight() / 250), 1); + auto fontscale = max(generic_ui ? min(twod->GetWidth() / 640, twod->GetHeight() / 400) : min(twod->GetWidth() / 400, twod->GetHeight() / 250), 1); int cleanwidth = twod->GetWidth() / fontscale; int cleanheight = twod->GetHeight() / fontscale; int refwidth = generic_ui ? 640 : 320; @@ -403,7 +424,7 @@ void DIntermissionScreenText::Drawer () int cx = (mTextX - refwidth/2) * fontscale + twod->GetWidth() / 2; int cy = (mTextY - refheight/2) * fontscale + twod->GetHeight() / 2; - cx = MAX(0, cx); + cx = max(0, cx); int startx = cx; if (usesDefault) @@ -446,7 +467,7 @@ void DIntermissionScreenText::Drawer () continue; } - pic = font->GetChar (c, mTextColor, &w); + w = font->GetCharWidth(c); w += kerning; w *= fontscale; if (cx + w > twod->GetWidth()) @@ -482,7 +503,7 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) { mCastSounds[i].mSequence = static_cast(desc)->mCastSounds[i].mSequence; mCastSounds[i].mIndex = static_cast(desc)->mCastSounds[i].mIndex; - mCastSounds[i].mSound = static_cast(desc)->mCastSounds[i].mSound; + mCastSounds[i].mSound = S_FindSound(static_cast(desc)->mCastSounds[i].mSound); } caststate = mDefaults->SeeState; if (mClass->IsDescendantOf(NAME_PlayerPawn)) @@ -503,15 +524,15 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) castframes = 0; castonmelee = 0; castattacking = false; - if (mDefaults->SeeSound) + if (mDefaults->SeeSound.isvalid()) { S_Sound (CHAN_VOICE, CHANF_UI, mDefaults->SeeSound, 1, ATTN_NONE); } } -int DIntermissionScreenCast::Responder (event_t *ev) +int DIntermissionScreenCast::Responder (FInputEvent *ev) { - if (ev->type != EV_KeyDown) return 0; + if (ev->Type != EV_KeyDown) return 0; if (castdeath) return 1; // already in dying frames @@ -530,10 +551,10 @@ int DIntermissionScreenCast::Responder (event_t *ev) if (mClass->IsDescendantOf(NAME_PlayerPawn)) { - int snd = S_FindSkinnedSound(players[consoleplayer].mo, "*death"); - if (snd != 0) S_Sound (CHAN_VOICE, CHANF_UI, snd, 1, ATTN_NONE); + auto snd = S_FindSkinnedSound(players[consoleplayer].mo, S_FindSound("*death")); + if (snd != NO_SOUND) S_Sound (CHAN_VOICE, CHANF_UI, snd, 1, ATTN_NONE); } - else if (mDefaults->DeathSound) + else if (mDefaults->DeathSound.isvalid()) { S_Sound (CHAN_VOICE, CHANF_UI, mDefaults->DeathSound, 1, ATTN_NONE); } @@ -707,7 +728,7 @@ void DIntermissionScreenScroller::Init(FIntermissionAction *desc, bool first) mScrollDir = static_cast(desc)->mScrollDir; } -int DIntermissionScreenScroller::Responder (event_t *ev) +int DIntermissionScreenScroller::Responder (FInputEvent *ev) { int res = Super::Responder(ev); if (res == -1 && !nointerscrollabort) @@ -827,9 +848,7 @@ void DIntermissionScreenScroller::Drawer () // //========================================================================== -DIntermissionController *DIntermissionController::CurrentIntermission; - -DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, bool DeleteDesc, uint8_t state) +DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, bool DeleteDesc, bool ending) { mDesc = Desc; mDeleteDesc = DeleteDesc; @@ -838,7 +857,7 @@ DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, mSentAdvance = false; mScreen = nullptr; mFirst = true; - mGameState = state; + mEndGame = ending; } bool DIntermissionController::NextPage () @@ -848,8 +867,8 @@ bool DIntermissionController::NextPage () if (mIndex == (int)mDesc->mActions.Size() && mDesc->mLink == NAME_None) { - // last page - return false; + // last page (must block when ending the game.) + return mEndGame; } bg.SetInvalid(); @@ -868,8 +887,6 @@ again: } else if (action->mClass == TITLE_ID) { - Destroy(); - D_StartTitle (); return false; } else @@ -897,13 +914,18 @@ again: return false; } -bool DIntermissionController::Responder (event_t *ev) +void DIntermissionController::Start() +{ + if (mScreen) mScreen->Start(); +} + +bool DIntermissionController::Responder (FInputEvent *ev) { if (mScreen != NULL) { - if (ev->type == EV_KeyDown) + if (ev->Type == EV_KeyDown) { - const char *cmd = Bindings.GetBind (ev->data1); + const char *cmd = Bindings.GetBind (ev->KeyScan); if (cmd != nullptr) { @@ -924,17 +946,16 @@ bool DIntermissionController::Responder (event_t *ev) if (mScreen->mTicker < 2) return false; // prevent some leftover events from auto-advancing int res = mScreen->Responder(ev); - if (res == -1 && !mSentAdvance) + if (res == -1) { - Net_WriteByte(DEM_ADVANCEINTER); - mSentAdvance = true; + mAdvance = true; } return !!res; } return false; } -void DIntermissionController::Ticker () +bool DIntermissionController::Ticker () { if (mAdvance) { @@ -949,27 +970,10 @@ void DIntermissionController::Ticker () mAdvance = false; if (!NextPage()) { - switch (mGameState) - { - case FSTATE_InLevel: - primaryLevel->SetMusic(); - gamestate = GS_LEVEL; - wipegamestate = GS_LEVEL; - gameaction = ga_resumeconversation; - viewactive = true; - Destroy(); - break; - - case FSTATE_ChangingLevel: - gameaction = ga_worlddone; - Destroy(); - break; - - default: - break; - } + return false; } } + return true; } void DIntermissionController::Drawer () @@ -987,7 +991,6 @@ void DIntermissionController::OnDestroy () if (mScreen != NULL) mScreen->Destroy(); if (mDeleteDesc) delete mDesc; mDesc = NULL; - if (CurrentIntermission == this) CurrentIntermission = NULL; } @@ -997,28 +1000,24 @@ void DIntermissionController::OnDestroy () // //========================================================================== -void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state) +DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, bool ending) { ScaleOverrider s(twod); - if (DIntermissionController::CurrentIntermission != NULL) - { - DIntermissionController::CurrentIntermission->Destroy(); - } S_StopAllChannels (); gameaction = ga_nothing; gamestate = GS_FINALE; - if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level. - viewactive = false; - automapactive = false; - DIntermissionController::CurrentIntermission = Create(desc, deleteme, state); + //if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level. + auto CurrentIntermission = Create(desc, deleteme, ending); // If the intermission finishes straight away then cancel the wipe. - if (!DIntermissionController::CurrentIntermission->NextPage()) + if (!CurrentIntermission->NextPage()) { - wipegamestate = GS_FINALE; + CurrentIntermission->Destroy(); + return nullptr; } - GC::WriteBarrier(DIntermissionController::CurrentIntermission); + GC::WriteBarrier(CurrentIntermission); + return CurrentIntermission; } @@ -1028,94 +1027,59 @@ void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t s // //========================================================================== -void F_StartIntermission(FName seq, uint8_t state) +DIntermissionController* F_StartIntermission(FName seq) { FIntermissionDescriptor **pdesc = IntermissionDescriptors.CheckKey(seq); - if (pdesc == nullptr) + if (pdesc == nullptr || (*pdesc)->mActions.Size() == 0) { - gameaction = ga_nothing; + return nullptr; } else { - F_StartIntermission(*pdesc, false, state); - } -} + auto desc = *pdesc; + auto action = desc->mActions[0]; + if (action->mClass == TITLE_ID) + { + // is handled elsewhere. + return nullptr; + } -//========================================================================== -// -// Called by main loop. -// -//========================================================================== - -bool F_Responder (event_t* ev) -{ - ScaleOverrider s(twod); - if (DIntermissionController::CurrentIntermission != NULL) - { - return DIntermissionController::CurrentIntermission->Responder(ev); - } - return false; -} - -//========================================================================== -// -// Called by main loop. -// -//========================================================================== - -void F_Ticker () -{ - ScaleOverrider s(twod); - if (DIntermissionController::CurrentIntermission != NULL) - { - DIntermissionController::CurrentIntermission->Ticker(); - } -} - -//========================================================================== -// -// Called by main loop. -// -//========================================================================== - -void F_Drawer () -{ - ScaleOverrider s(twod); - if (DIntermissionController::CurrentIntermission != NULL) - { - DIntermissionController::CurrentIntermission->Drawer(); + return F_StartIntermission(desc, false); } } -//========================================================================== -// -// Called by main loop. -// -//========================================================================== - -void F_EndFinale () +DEFINE_ACTION_FUNCTION(DIntermissionController, Responder) { - if (DIntermissionController::CurrentIntermission != NULL) - { - DIntermissionController::CurrentIntermission->Destroy(); - DIntermissionController::CurrentIntermission = NULL; - } + PARAM_SELF_PROLOGUE(DIntermissionController); + PARAM_POINTER(evt, FInputEvent); + ACTION_RETURN_BOOL(self->Responder(evt)); } -//========================================================================== -// -// Called by net loop. -// -//========================================================================== - -void F_AdvanceIntermission() +DEFINE_ACTION_FUNCTION(DIntermissionController, Ticker) { - ScaleOverrider s(twod); - if (DIntermissionController::CurrentIntermission != NULL) - { - DIntermissionController::CurrentIntermission->mAdvance = true; - } + PARAM_SELF_PROLOGUE(DIntermissionController); + ACTION_RETURN_BOOL(self->Ticker()); +} + +DEFINE_ACTION_FUNCTION(DIntermissionController, Start) +{ + PARAM_SELF_PROLOGUE(DIntermissionController); + self->Start(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DIntermissionController, Drawer) +{ + PARAM_SELF_PROLOGUE(DIntermissionController); + self->Drawer(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DIntermissionController, NextPage) +{ + PARAM_SELF_PROLOGUE(DIntermissionController); + ACTION_RETURN_BOOL(self->NextPage()); } #include "c_dispatch.h" diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index be2d9a563..e25354c87 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -10,7 +10,7 @@ #include "g_game.h" #include "v_text.h" -struct event_t; +struct FInputEvent; struct FState; #define DECLARE_SUPER_CLASS(cls,parent) \ @@ -166,7 +166,11 @@ protected: int mDuration; FTextureID mBackground; FString mSubtitle; + FString mMusic; + int mMusicOrder; + bool mMusicLooping; bool mFlatfill; + bool mFirst; TArray mOverlays; bool CheckOverlay(int i); @@ -176,7 +180,8 @@ public: DIntermissionScreen() {} virtual void Init(FIntermissionAction *desc, bool first); - virtual int Responder (event_t *ev); + virtual void Start(); + virtual int Responder (FInputEvent *ev); virtual int Ticker (); virtual void Drawer (); void OnDestroy() override; @@ -202,7 +207,7 @@ public: DIntermissionScreenFader() {} virtual void Init(FIntermissionAction *desc, bool first); - virtual int Responder (event_t *ev); + virtual int Responder (FInputEvent *ev); virtual int Ticker (); virtual void Drawer (); }; @@ -227,7 +232,7 @@ public: DIntermissionScreenText() {} virtual void Init(FIntermissionAction *desc, bool first); - virtual int Responder (event_t *ev); + virtual int Responder (FInputEvent *ev); virtual void Drawer (); }; @@ -256,7 +261,7 @@ public: DIntermissionScreenCast() {} virtual void Init(FIntermissionAction *desc, bool first); - virtual int Responder (event_t *ev); + virtual int Responder (FInputEvent *ev); virtual int Ticker (); virtual void Drawer (); }; @@ -275,7 +280,7 @@ public: DIntermissionScreenScroller() {} virtual void Init(FIntermissionAction *desc, bool first); - virtual int Responder (event_t *ev); + virtual int Responder (FInputEvent *ev); virtual void Drawer (); }; @@ -296,36 +301,29 @@ class DIntermissionController : public DObject bool mDeleteDesc; bool mFirst; bool mAdvance, mSentAdvance; - uint8_t mGameState; int mIndex; - bool NextPage(); - public: - static DIntermissionController *CurrentIntermission; + bool mEndGame; - DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false, uint8_t state = FSTATE_ChangingLevel); - bool Responder (event_t *ev); - void Ticker (); + DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false, bool ending = false); + bool Responder (FInputEvent *ev); + bool Ticker (); + void Start(); void Drawer (); void OnDestroy() override; + bool NextPage(); - friend void F_AdvanceIntermission(); - friend void F_StartIntermission(FIntermissionDescriptor *, bool, uint8_t); + friend DIntermissionController* F_StartIntermission(FIntermissionDescriptor *, bool, uint8_t); }; // Interface for main loop -bool F_Responder (event_t* ev); -void F_Ticker (); -void F_Drawer (); -void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state); -void F_StartIntermission(FName desc, uint8_t state); -void F_EndFinale (); -void F_AdvanceIntermission(); +DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, bool ending = false); +DIntermissionController* F_StartIntermission(FName desc); // Create an intermission from old cluster data -void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat, +DIntermissionController* F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat, const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText, bool ending, FName endsequence = NAME_None); diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index cabd269a9..5b2de2c4d 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -41,6 +41,8 @@ #include "c_dispatch.h" #include "gstrings.h" #include "gi.h" +#include "screenjob.h" +#include "d_event.h" static void ReplaceIntermission(FName intname,FIntermissionDescriptor *desc) @@ -849,7 +851,7 @@ FName FMapInfoParser::CheckEndSequence() // //========================================================================== -void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat, +DIntermissionController* F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat, const char *text, INTBOOL textInLump, INTBOOL finalePic, INTBOOL lookupText, bool ending, FName endsequence) { @@ -909,19 +911,19 @@ void F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int desc->mActions.Push(wiper); } - F_StartIntermission(desc, true, ending? FSTATE_EndingGame : FSTATE_ChangingLevel); + return F_StartIntermission(desc, true, ending && endsequence != NAME_None); } else if (ending) { FIntermissionDescriptor **pdesc = IntermissionDescriptors.CheckKey(endsequence); if (pdesc != NULL) { - F_StartIntermission(*pdesc, false, ending? FSTATE_EndingGame : FSTATE_ChangingLevel); + return F_StartIntermission(*pdesc, false, ending); } } + return nullptr; } - CCMD(testfinale) { if (argv.argc() < 2) @@ -952,5 +954,7 @@ CCMD(testfinale) return; } - F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true); + auto controller = F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true); + RunIntermission(nullptr, nullptr, controller, nullptr, [=](bool) { gameaction = ga_nothing; }); + } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 5964d1c28..a4ac6bc39 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -54,6 +54,7 @@ #include "a_morph.h" #include "g_levellocals.h" #include "vm.h" +#include "d_main.h" uint8_t globalfreeze, globalchangefreeze; // user's freeze state. @@ -165,7 +166,7 @@ void cht_DoCheat (player_t *player, int cheat) else { player->cheats &= ~CF_NOCLIP; - msg = GStrings("STSTR_NCOFF"); + msg = GStrings("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; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 6680911ac..6e40991da 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -292,7 +292,7 @@ bool M_SaveDefaults (const char *filename) void M_SaveDefaultsFinal () { if (GameConfig == nullptr) return; - while (!M_SaveDefaults (nullptr) && I_WriteIniFailed ()) + while (!M_SaveDefaults (nullptr) && I_WriteIniFailed (GameConfig->GetPathName())) { /* Loop until the config saves or I_WriteIniFailed() returns false */ } @@ -313,6 +313,12 @@ UNSAFE_CCMD (writeini) } } +CCMD(openconfig) +{ + M_SaveDefaults(nullptr); + I_OpenShellFolder(ExtractFilePath(GameConfig->GetPathName())); +} + // // M_LoadDefaults // @@ -657,3 +663,32 @@ UNSAFE_CCMD (screenshot) G_ScreenShot (argv[1]); } +CCMD(openscreenshots) +{ + size_t dirlen; + FString autoname; + autoname = Args->CheckValue("-shotdir"); + if (autoname.IsEmpty()) + { + autoname = screenshot_dir; + } + dirlen = autoname.Len(); + if (dirlen == 0) + { + autoname = M_GetScreenshotsPath(); + dirlen = autoname.Len(); + } + if (dirlen > 0) + { + if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') + { + autoname += '/'; + } + } + autoname = NicePath(autoname); + + CreatePath(autoname); + + I_OpenShellFolder(autoname.GetChars()); +} + diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 2ceaa85cd..9b74a879a 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -119,7 +119,7 @@ static FCompatOption Options[] = { { "setslopeoverflow", BCOMPATF_SETSLOPEOVERFLOW, SLOT_BCOMPAT }, { "resetplayerspeed", BCOMPATF_RESETPLAYERSPEED, SLOT_BCOMPAT }, - { "vileghosts", BCOMPATF_VILEGHOSTS, SLOT_BCOMPAT }, + { "vileghosts", COMPATF_VILEGHOSTS, SLOT_COMPAT }, { "ignoreteleporttags", BCOMPATF_BADTELEPORTERS, SLOT_BCOMPAT }, { "rebuildnodes", BCOMPATF_REBUILDNODES, SLOT_BCOMPAT }, { "linkfrozenprops", BCOMPATF_LINKFROZENPROPS, SLOT_BCOMPAT }, @@ -150,7 +150,6 @@ static FCompatOption Options[] = { "anybossdeath", COMPATF_ANYBOSSDEATH, SLOT_COMPAT },// [GZ] Added for UAC_DEAD { "mushroom", COMPATF_MUSHROOM, SLOT_COMPAT }, { "mbfmonstermove", COMPATF_MBFMONSTERMOVE, SLOT_COMPAT }, - { "corpsegibs", COMPATF_CORPSEGIBS, SLOT_COMPAT }, { "noblockfriends", COMPATF_NOBLOCKFRIENDS, SLOT_COMPAT }, { "spritesort", COMPATF_SPRITESORT, SLOT_COMPAT }, { "hitscan", COMPATF_HITSCAN, SLOT_COMPAT }, @@ -169,6 +168,7 @@ static FCompatOption Options[] = { "explode2", COMPATF2_EXPLODE2, SLOT_COMPAT2 }, { "railing", COMPATF2_RAILING, SLOT_COMPAT2 }, { "scriptwait", COMPATF2_SCRIPTWAIT, SLOT_COMPAT2 }, + { "nombf21", COMPATF2_NOMBF21, SLOT_COMPAT2 }, { NULL, 0, 0 } }; diff --git a/src/maploader/edata.cpp b/src/maploader/edata.cpp index 9d50b26b4..3bc4928f0 100644 --- a/src/maploader/edata.cpp +++ b/src/maploader/edata.cpp @@ -296,7 +296,7 @@ static void parseSector(FScanner &sc, TMap &EDSectors) { sc.CheckString("="); sc.MustGetFloat(); - sec.angle[sector_t::floor] = sc.Float; + sec.angle[sector_t::floor] = DAngle::fromDeg(sc.Float); } else if (sc.Compare("flooroffsetx")) { @@ -320,7 +320,7 @@ static void parseSector(FScanner &sc, TMap &EDSectors) { sc.CheckString("="); sc.MustGetFloat(); - sec.angle[sector_t::ceiling] = sc.Float; + sec.angle[sector_t::ceiling] = DAngle::fromDeg(sc.Float); } else if (sc.Compare("ceilingoffsetx")) { diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index 843afeaa5..21da9462a 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -43,7 +43,7 @@ #endif #include -#include "templates.h" + #include "m_argv.h" #include "c_dispatch.h" #include "m_swap.h" @@ -708,7 +708,7 @@ static bool MatchHeader(const char * label, const char * hdata) if (memcmp(hdata, "LEVEL=", 6) == 0) { size_t labellen = strlen(label); - labellen = MIN(size_t(8), labellen); + labellen = min(size_t(8), labellen); if (strnicmp(hdata+6, label, labellen)==0 && (hdata[6+labellen]==0xa || hdata[6+labellen]==0xd)) diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 7faaa01d1..f57a51b65 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -59,6 +59,7 @@ #include +#include // needed for std::floor on mac #include "maploader.h" #include "c_cvars.h" #include "actor.h" @@ -82,6 +83,7 @@ #include "vm.h" #include "texturemanager.h" #include "hw_vertexbuilder.h" +#include "version.h" enum { @@ -870,7 +872,7 @@ bool MapLoader::LoadSegs (MapData * map) if (vnum1 >= numvertexes || vnum2 >= numvertexes) { - throw badseg(0, i, MAX(vnum1, vnum2)); + throw badseg(0, i, max(vnum1, vnum2)); } li->v1 = &Level->vertexes[vnum1]; @@ -909,10 +911,10 @@ bool MapLoader::LoadSegs (MapData * map) // errors _can_ cause firelines. DAngle ptp_angle = (li->v2->fPos() - li->v1->fPos()).Angle(); - DAngle seg_angle = AngleToFloat(segangle << 16); + DAngle seg_angle = DAngle::fromBam(segangle << 16); DAngle delta_angle = absangle(ptp_angle, seg_angle); - if (delta_angle >= 1.) + if (delta_angle >= DAngle::fromDeg(1.)) { double dis = (li->v2->fPos() - li->v1->fPos()).Length(); DVector2 delta = seg_angle.ToVector(dis); @@ -1890,7 +1892,7 @@ void MapLoader::LoadLineDefs2 (MapData * map) Level->sides.Alloc(count); memset(&Level->sides[0], 0, count * sizeof(side_t)); - sidetemp.Resize(MAX(count, Level->vertexes.Size())); + sidetemp.Resize(max(count, Level->vertexes.Size())); for (i = 0; i < count; i++) { sidetemp[i].a.special = sidetemp[i].a.tag = 0; @@ -1918,7 +1920,7 @@ void MapLoader::LoopSidedefs (bool firstloop) int i; int numsides = Level->sides.Size(); - sidetemp.Resize(MAX(Level->vertexes.Size(), numsides)); + sidetemp.Resize(max(Level->vertexes.Size(), numsides)); for (i = 0; i < (int)Level->vertexes.Size(); ++i) { @@ -1994,7 +1996,7 @@ void MapLoader::LoopSidedefs (bool firstloop) if (sidetemp[right].b.next != NO_SIDE) { int bestright = right; // Shut up, GCC - DAngle bestang = 360.; + DAngle bestang = DAngle::fromDeg(360.); line_t *leftline, *rightline; DAngle ang1, ang2, ang; @@ -2002,7 +2004,7 @@ void MapLoader::LoopSidedefs (bool firstloop) ang1 = leftline->Delta().Angle(); if (!sidetemp[i].b.lineside) { - ang1 += 180; + ang1 += DAngle::fromDeg(180); } while (right != NO_SIDE) @@ -2015,12 +2017,12 @@ void MapLoader::LoopSidedefs (bool firstloop) ang2 = rightline->Delta().Angle(); if (sidetemp[right].b.lineside) { - ang2 += 180; + ang2 += DAngle::fromDeg(180); } ang = (ang2 - ang1).Normalized360(); - if (ang != 0 && ang <= bestang) + if (ang != nullAngle && ang <= bestang) { bestright = right; bestang = ang; @@ -2816,7 +2818,7 @@ void MapLoader::LoadReject (MapData * map, bool junk) else { // Check if the reject has some actual content. If not, free it. - rejectsize = MIN (rejectsize, neededsize); + rejectsize = min (rejectsize, neededsize); Level->rejectmatrix.Alloc(rejectsize); map->Read (ML_REJECT, &Level->rejectmatrix[0], rejectsize); @@ -3206,6 +3208,12 @@ 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) @@ -3241,6 +3249,8 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) Level->ClearDynamic3DFloorData(); // CreateVBO must be run on the plain 3D floor data. CreateVBO(screen->mVertexData, Level->sectors); + screen->InitLightmap(Level->LMTextureSize, Level->LMTextureCount, Level->LMTextureData); + for (auto &sec : Level->sectors) { P_Recalculate3DFloors(&sec); @@ -3256,5 +3266,256 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) 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); } +//========================================================================== +// +// +// +//========================================================================== + +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->LightProbes.Reset(); + Level->LPCells.Reset(); + Level->LMTexCoords.Reset(); + Level->LMSurfaces.Reset(); + Level->LMTextureData.Reset(); + Level->LMTextureCount = 0; + Level->LMTextureSize = 0; + Level->LPMinX = 0; + Level->LPMinY = 0; + Level->LPWidth = 0; + Level->LPHeight = 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: 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 numLightProbes = fr.ReadUInt32(); + uint32_t numSubsectors = fr.ReadUInt32(); + uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2; + + if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0) + return; + + Printf(PRINT_HIGH, "WARNING! Lightmaps are an experimental feature and are subject to change before being finalized. Do not expect this to work as-is in future releases of %s!\n", GAMENAME); + + /*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()); + }*/ + + if (numLightProbes > 0) + { + Level->LightProbes.Resize(numLightProbes); + fr.Read(&Level->LightProbes[0], sizeof(LightProbe) * numLightProbes); + + // Sort the light probes so that they are ordered by cell. + // This lets us point at the first probe knowing all other probes in the cell will follow. + // Also improves locality. + + double rcpCellSize = 1.0 / Level->LPCellSize; + auto cellCompareLess = [=](const LightProbe& a, const LightProbe& b) + { + double cellY_A = std::floor(a.Y * rcpCellSize); + double cellY_B = std::floor(b.Y * rcpCellSize); + if (cellY_A != cellY_B) + return cellY_A < cellY_B; + double cellX_A = std::floor(a.X * rcpCellSize); + double cellX_B = std::floor(b.X * rcpCellSize); + return cellX_A < cellX_B; + }; + std::sort(Level->LightProbes.begin(), Level->LightProbes.end(), cellCompareLess); + + // Find probe bounds and the grid that covers it + float probesMinX = Level->LightProbes[0].X; + float probesMaxX = Level->LightProbes[0].X; + float probesMinY = Level->LightProbes[0].Y; + float probesMaxY = Level->LightProbes[0].Y; + for (const LightProbe& p : Level->LightProbes) + { + probesMinX = std::min(probesMinX, p.X); + probesMaxX = std::max(probesMaxX, p.X); + probesMinY = std::min(probesMinY, p.Y); + probesMaxY = std::max(probesMaxY, p.Y); + } + Level->LPMinX = (int)std::floor(probesMinX * rcpCellSize); + Level->LPMinY = (int)std::floor(probesMinY * rcpCellSize); + Level->LPWidth = (int)std::floor(probesMaxX * rcpCellSize) + 1 - Level->LPMinX; + Level->LPHeight = (int)std::floor(probesMaxY * rcpCellSize) + 1 - Level->LPMinY; + + // Place probes in a grid for faster search + Level->LPCells.Resize(Level->LPWidth * Level->LPHeight); + int minX = Level->LPMinX; + int minY = Level->LPMinY; + int width = Level->LPWidth; + int height = Level->LPHeight; + for (LightProbe& p : Level->LightProbes) + { + int gridX = (int)std::floor(p.X * rcpCellSize) - minX; + int gridY = (int)std::floor(p.Y * rcpCellSize) - minY; + if (gridX >= 0 && gridY >= 0 && gridX < width && gridY < height) + { + LightProbeCell& cell = Level->LPCells[gridX + (size_t)gridY * width]; + if (!cell.FirstProbe) + cell.FirstProbe = &p; + cell.NumProbes++; + } + } + } + + 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++) + { + 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); + } + } + + // 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 +} diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 4330b9309..93c65f983 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -110,8 +110,6 @@ private: int firstglvertex; // helpers for loading GL nodes from GWA files. bool format5; - TArray vertexdatas; - TMap MapThingsUserDataIndex; // from mapthing idx -> user data idx TArray MapThingsUserData; int sidecount = 0; @@ -120,6 +118,8 @@ private: public: // for the scripted compatibility system these two members need to be public. TArray MapThingsConverted; bool ForceNodeBuild = false; + // This needs to be public to fetch this from DLevelPostProcessor native functions + TArray vertexdatas; private: // Extradata loader @@ -304,6 +304,10 @@ public: void SetSlopes(); void CopySlopes(); + void SetSubsectorLightmap(const LightmapSurface &surface); + void SetSideLightmap(const LightmapSurface &surface); + void LoadLightmap(MapData *map); + void LoadLevel(MapData *map, const char *lumpname, int position); MapLoader(FLevelLocals *lev) diff --git a/src/maploader/polyobjects.cpp b/src/maploader/polyobjects.cpp index d88947ac1..00b7ccca4 100644 --- a/src/maploader/polyobjects.cpp +++ b/src/maploader/polyobjects.cpp @@ -295,8 +295,8 @@ void MapLoader::TranslateToStartSpot (int tag, const DVector2 &origin) Printf(TEXTCOLOR_RED "TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); return; } - po->OriginalPts.Resize(po->Sidedefs.Size()); - po->PrevPts.Resize(po->Sidedefs.Size()); + po->OriginalPts.Resize(po->Vertices.Size()); + po->PrevPts.Resize(po->Vertices.Size()); delta = origin - po->StartSpot.pos; for (unsigned i = 0; i < po->Sidedefs.Size(); i++) diff --git a/src/maploader/postprocessor.cpp b/src/maploader/postprocessor.cpp index d47b2df8e..e94e7d4d7 100644 --- a/src/maploader/postprocessor.cpp +++ b/src/maploader/postprocessor.cpp @@ -110,6 +110,37 @@ DEFINE_ACTION_FUNCTION(DLevelPostProcessor, OffsetSectorPlane) return 0; } +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetSectorPlane) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + PARAM_INT(sector); + PARAM_INT(planeval); + PARAM_FLOAT(normal_x); + PARAM_FLOAT(normal_y); + PARAM_FLOAT(normal_z); + PARAM_FLOAT(d); + + if ((unsigned)sector < self->Level->sectors.Size()) + { + sector_t* sec = &self->Level->sectors[sector]; + secplane_t& plane = sector_t::floor == planeval ? sec->floorplane : sec->ceilingplane; + if (normal_z != 0) + { + plane.normal = DVector3(normal_x, normal_y, normal_z); + plane.D = d; + plane.negiC = -1 / normal_z; + } + else + { + plane.normal = DVector3(0, 0, sector_t::floor == planeval ? 1 : -1); + plane.D = d; + plane.negiC = -1 / plane.normal.Z; + } + } + + return 0; +} + DEFINE_ACTION_FUNCTION(DLevelPostProcessor, ClearSectorTags) { PARAM_SELF_PROLOGUE(DLevelPostProcessor); @@ -437,6 +468,75 @@ DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetVertex) return 0; } +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetVertexZ) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + PARAM_UINT(vertex); + PARAM_INT(planeval); + + double value = 0; + bool isset = false; + + if (vertex < self->Level->vertexes.Size() && vertex < self->loader->vertexdatas.Size()) + { + vertexdata_t& data = self->loader->vertexdatas[vertex]; + value = sector_t::floor == planeval ? data.zFloor : data.zCeiling; + isset = data.flags & (sector_t::floor == planeval ? VERTEXFLAG_ZFloorEnabled : VERTEXFLAG_ZCeilingEnabled); + } + + if (numret > 1) + { + numret = 2; + ret[1].SetInt(isset); + } + + if (numret > 0) + { + ret[0].SetFloat(value); + } + + return numret; +} + +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetVertexZ) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + PARAM_UINT(vertex); + PARAM_INT(planeval); + PARAM_FLOAT(z); + + if (vertex < self->Level->vertexes.Size() && vertex < self->loader->vertexdatas.Size()) + { + vertexdata_t& data = self->loader->vertexdatas[vertex]; + if (sector_t::floor == planeval) { + data.flags |= VERTEXFLAG_ZFloorEnabled; + data.zFloor = z; + } + else + { + data.flags |= VERTEXFLAG_ZCeilingEnabled; + data.zCeiling = z; + } + } + + return 0; +} + +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, RemoveVertexZ) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + PARAM_UINT(vertex); + PARAM_INT(planeval); + + if (vertex < self->Level->vertexes.Size() && vertex < self->loader->vertexdatas.Size()) + { + vertexdata_t& data = self->loader->vertexdatas[vertex]; + data.flags &= ~(sector_t::floor == planeval ? VERTEXFLAG_ZFloorEnabled : VERTEXFLAG_ZCeilingEnabled); + } + + return 0; +} + DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetLineVertexes) { PARAM_SELF_PROLOGUE(DLevelPostProcessor); diff --git a/src/maploader/slopes.cpp b/src/maploader/slopes.cpp index 2fb44e628..9567c6ef4 100644 --- a/src/maploader/slopes.cpp +++ b/src/maploader/slopes.cpp @@ -160,22 +160,22 @@ void MapLoader::SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi if (zangi >= 180) { - zang = 179.; + zang = DAngle::fromDeg(179.); } else if (zangi <= 0) { - zang = 1.; + zang = DAngle::fromDeg(1.); } else { - zang = (double)zangi; + zang = DAngle::fromDeg(zangi); } if (setCeil) { - zang += 180.; + zang += DAngle::fromDeg(180.); } - xyang = (double)xyangi; + xyang = DAngle::fromDeg(xyangi); DVector3 norm; @@ -417,6 +417,7 @@ void MapLoader::SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const i mt->EdNum = 0; } } + SetSlopesFromVertexHeights(firstmt, lastmt, oldvertextable); for (mt = firstmt; mt < lastmt; ++mt) { @@ -428,7 +429,6 @@ void MapLoader::SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const i } } - SetSlopesFromVertexHeights(firstmt, lastmt, oldvertextable); } diff --git a/src/maploader/specials.cpp b/src/maploader/specials.cpp index 280eba279..369f1377c 100644 --- a/src/maploader/specials.cpp +++ b/src/maploader/specials.cpp @@ -67,7 +67,7 @@ #include -#include "templates.h" + #include "doomdef.h" #include "doomstat.h" #include "d_event.h" @@ -452,7 +452,7 @@ static void SetupSectorDamage(sector_t *sector, int damage, int interval, int le if (sector->damageamount == 0 && !(sector->Flags & (SECF_EXIT1|SECF_EXIT2))) { sector->damageamount = damage; - sector->damageinterval = MAX(1, interval); + sector->damageinterval = max(1, interval); sector->leakydamage = leakchance; sector->damagetype = type; sector->Flags = (sector->Flags & ~SECF_DAMAGEFLAGS) | (flags & SECF_DAMAGEFLAGS); @@ -484,11 +484,12 @@ void MapLoader::InitSectorSpecial(sector_t *sector, int special) { sector->Flags |= SECF_PUSH; } - if (sector->special & KILL_MONSTERS_MASK) + // Nom MBF21 compatibility needs to be checked here, because after this point there is no longer any context in which it can be done. + if ((sector->special & KILL_MONSTERS_MASK) && Level->MBF21Enabled()) { sector->Flags |= SECF_KILLMONSTERS; } - if (!(sector->special & DEATH_MASK)) + if (!(sector->special & DEATH_MASK) || !Level->MBF21Enabled()) { if ((sector->special & DAMAGE_MASK) == 0x100) { @@ -1147,8 +1148,8 @@ AActor *MapLoader::GetPushThing(int s) thing = sec->thinglist; while (thing && - thing->GetClass()->TypeName != NAME_PointPusher && - thing->GetClass()->TypeName != NAME_PointPuller) + !thing->IsKindOf(NAME_PointPusher) && + !thing->IsKindOf(NAME_PointPuller)) { thing = thing->snext; } @@ -1207,8 +1208,8 @@ void MapLoader::SpawnPushers() while ((thing = iterator.Next())) { - if (thing->GetClass()->TypeName == NAME_PointPusher || - thing->GetClass()->TypeName == NAME_PointPuller) + if (thing->IsKindOf(NAME_PointPusher) || + thing->IsKindOf(NAME_PointPuller)) { Level->CreateThinker(DPusher::p_push, l->args[3] ? l : NULL, l->args[2], 0, thing, thing->Sector->Index()); } @@ -1414,9 +1415,9 @@ void MapLoader::SpawnScrollers() else { auto it = Level->GetLineIdIterator(l->args[1]); - while (int ln = it.Next()) + while ((s = it.Next()) >= 0) { - Level->CreateThinker(EScroll::sc_side, dx, dy, control, nullptr, Level->lines[ln].sidedef[0], accel, SCROLLTYPE(l->args[0])); + Level->CreateThinker(EScroll::sc_side, dx, dy, control, nullptr, Level->lines[s].sidedef[0], accel, SCROLLTYPE(l->args[0])); } } break; diff --git a/src/maploader/strifedialogue.cpp b/src/maploader/strifedialogue.cpp index 247aaa5a9..cb2b2665b 100644 --- a/src/maploader/strifedialogue.cpp +++ b/src/maploader/strifedialogue.cpp @@ -319,7 +319,7 @@ FStrifeDialogueNode *MapLoader::ReadRetailNode (const char *name, FileReader &lu // The speaker's voice for this node, if any. speech.Backdrop[0] = 0; //speech.Sound[8] = 0; mysnprintf (fullsound, countof(fullsound), "svox/%s", speech.Sound); - node->SpeakerVoice = fullsound; + node->SpeakerVoice = S_FindSound(fullsound); // The speaker's name, if any. speech.Sound[0] = 0; //speech.Name[16] = 0; @@ -345,7 +345,7 @@ FStrifeDialogueNode *MapLoader::ReadRetailNode (const char *name, FileReader &lu for (j = 0; j < 3; ++j) { auto inv = GetStrifeType(speech.ItemCheck[j]); - if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; + if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; node->ItemCheck[j].Item = inv; node->ItemCheck[j].Amount = -1; } @@ -415,11 +415,11 @@ FStrifeDialogueNode *MapLoader::ReadTeaserNode (const char *name, FileReader &lu if (speech.VoiceNumber != 0) { mysnprintf (fullsound, countof(fullsound), "svox/voc%u", speech.VoiceNumber); - node->SpeakerVoice = fullsound; + node->SpeakerVoice = S_FindSound(fullsound); } else { - node->SpeakerVoice = 0; + node->SpeakerVoice = NO_SOUND; } // The speaker's name, if any. @@ -516,7 +516,7 @@ void MapLoader::ParseReplies (const char *name, int pos, FStrifeDialogueReply ** for (k = 0; k < 3; ++k) { auto inv = GetStrifeType(rsp->Item[k]); - if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; + if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; reply->ItemCheck[k].Item = inv; reply->ItemCheck[k].Amount = rsp->Count[k]; } diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 642708d2a..fb8fd8379 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -262,7 +262,7 @@ double UDMFParserBase::CheckCoordinate(FName key) DAngle UDMFParserBase::CheckAngle(FName key) { - return DAngle(CheckFloat(key)).Normalized360(); + return DAngle::fromDeg(CheckFloat(key)).Normalized360(); } bool UDMFParserBase::CheckBool(FName key) @@ -737,15 +737,15 @@ public: break; case NAME_ScaleX: - th->Scale.X = CheckFloat(key); + th->Scale.X = (float)CheckFloat(key); break; case NAME_ScaleY: - th->Scale.Y = CheckFloat(key); + th->Scale.Y = (float)CheckFloat(key); break; case NAME_Scale: - th->Scale.X = th->Scale.Y = CheckFloat(key); + th->Scale.X = th->Scale.Y = (float)CheckFloat(key); break; case NAME_FriendlySeeBlocks: @@ -753,6 +753,12 @@ public: th->friendlyseeblocks = CheckInt(key); break; + case NAME_lm_suncolor: + case NAME_lm_sampledistance: + case NAME_lm_gridsize: + CHECK_N(Zd | Zdt) + break; + default: CHECK_N(Zd | Zdt) if (0 == strnicmp("user_", key.GetChars(), 5)) @@ -1123,6 +1129,16 @@ public: 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_top: + case NAME_lm_sampledist_mid: + case NAME_lm_sampledist_bot: + CHECK_N(Zd | Zdt) + break; + default: if (strnicmp("user_", key.GetChars(), 5)) DPrintf(DMSG_WARNING, "Unknown UDMF linedef key %s\n", key.GetChars()); @@ -1302,6 +1318,30 @@ public: Flag(sd->Flags, WALLF_ABSLIGHTING, key); continue; + case NAME_light_top: + sd->SetLight(CheckInt(key), side_t::top); + continue; + + case NAME_lightabsolute_top: + Flag(sd->Flags, WALLF_ABSLIGHTING_TOP, key); + continue; + + case NAME_light_mid: + sd->SetLight(CheckInt(key), side_t::mid); + continue; + + case NAME_lightabsolute_mid: + Flag(sd->Flags, WALLF_ABSLIGHTING_MID, key); + continue; + + case NAME_light_bottom: + sd->SetLight(CheckInt(key), side_t::bottom); + continue; + + case NAME_lightabsolute_bottom: + Flag(sd->Flags, WALLF_ABSLIGHTING_BOTTOM, key); + continue; + case NAME_lightfog: Flag(sd->Flags, WALLF_LIGHT_FOG, key); continue; @@ -1948,7 +1988,18 @@ public: case NAME_Health3DGroup: 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: + case NAME_lm_sampledist_ceiling: + CHECK_N(Zd | Zdt) + break; + default: if (strnicmp("user_", key.GetChars(), 5)) DPrintf(DMSG_WARNING, "Unknown UDMF sector key %s\n", key.GetChars()); diff --git a/src/maploader/usdf.cpp b/src/maploader/usdf.cpp index 05eb50f88..ed8bc4cfe 100644 --- a/src/maploader/usdf.cpp +++ b/src/maploader/usdf.cpp @@ -359,10 +359,10 @@ class USDFParser : public UDMFParserBase { FString soundname = "svox/"; soundname += name; - node->SpeakerVoice = FSoundID(S_FindSound(soundname)); - if (node->SpeakerVoice == 0 && (namespace_bits & ( Zd | Gz ))) + node->SpeakerVoice = S_FindSound(soundname); + if (node->SpeakerVoice == NO_SOUND && (namespace_bits & ( Zd | Gz ))) { - node->SpeakerVoice = FSoundID(S_FindSound(name)); + node->SpeakerVoice = S_FindSound(name); } } } diff --git a/src/menu/doommenu.cpp b/src/menu/doommenu.cpp index 0851323d4..5fd354202 100644 --- a/src/menu/doommenu.cpp +++ b/src/menu/doommenu.cpp @@ -56,7 +56,7 @@ #include "g_level.h" #include "d_event.h" #include "p_tick.h" -#include "st_start.h" +#include "startscreen.h" #include "d_main.h" #include "i_system.h" #include "doommenu.h" @@ -64,6 +64,9 @@ #include "gameconfigfile.h" #include "d_player.h" #include "teaminfo.h" +#include "i_time.h" +#include "shiftstate.h" +#include "s_music.h" #include "hwrenderer/scene/hw_drawinfo.h" EXTERN_CVAR(Int, cl_gfxlocalization) @@ -71,16 +74,17 @@ EXTERN_CVAR(Bool, m_quickexit) EXTERN_CVAR(Bool, saveloadconfirmation) // [mxd] EXTERN_CVAR(Bool, quicksaverotation) EXTERN_CVAR(Bool, show_messages) +EXTERN_CVAR(Float, hud_scalefactor) CVAR(Bool, m_simpleoptions, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) typedef void(*hfunc)(); DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr); bool OkForLocalization(FTextureID texnum, const char* substitute); -void I_WaitVBL(int count); FNewGameStartup NewGameStartupInfo; +int LastSkill = -1; bool M_SetSpecialMenu(FName& menu, int param) @@ -147,6 +151,7 @@ bool M_SetSpecialMenu(FName& menu, int param) { // sent from the skill menu for a skill that needs to be confirmed NewGameStartupInfo.Skill = param; + LastSkill = param; const char *msg = AllSkills[param].MustConfirmText; if (*msg==0) msg = GStrings("NIGHTMARE"); @@ -157,6 +162,7 @@ bool M_SetSpecialMenu(FName& menu, int param) case NAME_Startgame: // sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu // Now we can finally start the game. Ugh... + LastSkill = param; NewGameStartupInfo.Skill = param; [[fallthrough]]; case NAME_StartgameConfirmed: @@ -229,7 +235,7 @@ bool M_SetSpecialMenu(FName& menu, int param) // //============================================================================= -void M_StartControlPanel(bool makeSound, bool scaleoverride) +void OnMenuOpen(bool makeSound) { if (hud_toggled) D_ToggleHud(); @@ -244,7 +250,6 @@ void M_StartControlPanel(bool makeSound, bool scaleoverride) { S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE); } - M_DoStartControlPanel(scaleoverride); } @@ -290,6 +295,14 @@ void System_M_Dim() } +static void M_Quit() +{ + S_StopAllChannels(); + S_StopMusic(true); + CleanSWDrawer(); + ST_Endoom(); +} + //============================================================================= // // @@ -300,8 +313,7 @@ CCMD (menu_quit) { // F10 if (m_quickexit) { - CleanSWDrawer(); - ST_Endoom(); + M_Quit(); } M_StartControlPanel (true); @@ -332,8 +344,7 @@ CCMD (menu_quit) I_WaitVBL(105); } } - CleanSWDrawer(); - ST_Endoom(); + M_Quit(); }); @@ -501,14 +512,28 @@ EXTERN_CVAR (Int, screenblocks) CCMD (sizedown) { - screenblocks = screenblocks - 1; + if (shiftState.ShiftPressed()) + { + hud_scalefactor = hud_scalefactor - 0.04f; + } + else + { + screenblocks = screenblocks - 1; + } S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); } CCMD (sizeup) { - screenblocks = screenblocks + 1; - S_Sound (CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); + if (shiftState.ShiftPressed()) + { + hud_scalefactor = hud_scalefactor + 0.04f; + } + else + { + screenblocks = screenblocks + 1; + } + S_Sound(CHAN_VOICE, CHANF_UI, "menu/change", snd_menuvolume, ATTN_NONE); } CCMD(reset2defaults) @@ -591,9 +616,9 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) // center the menu on the screen if the top space is larger than the bottom space int totalheight = posy + AllEpisodes.Size() * spacing - topy; - if (totalheight < 190 || AllEpisodes.Size() == 1) + if (ld->mForceList || totalheight < 190 || AllEpisodes.Size() == 1) { - int newtop = (200 - totalheight) / 2; + int newtop = max(10, 200 - totalheight) / 2; int topdelta = newtop - topy; if (topdelta < 0) { @@ -620,7 +645,7 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) if (*c == '$') c = GStrings(c + 1); int textwidth = ld->mFont->StringWidth(c); int textright = posx + textwidth; - if (posx + textright > 320) posx = std::max(0, 320 - textright); + if (posx + textright > 320) posx = max(0, 320 - textright); } for(unsigned i = 0; i < AllEpisodes.Size(); i++) @@ -669,6 +694,9 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs) od->mScrollTop = 0; od->mIndent = 160; od->mDontDim = false; + od->mDontBlur = false; + od->mAnimatedTransition = false; + od->mAnimated = false; GC::WriteBarrier(od); for(unsigned i = 0; i < AllEpisodes.Size(); i++) { @@ -735,9 +763,9 @@ static void BuildPlayerclassMenu() ld->mAutoselect = ld->mItems.Push(it); success = true; } - else if (totalheight <= 190) + else if (ld->mForceList || totalheight <= 190) { - int newtop = (200 - totalheight + topy) / 2; + int newtop = (max(10, 200 - totalheight) + topy) / 2; int topdelta = newtop - topy; if (topdelta < 0) { @@ -804,6 +832,9 @@ static void BuildPlayerclassMenu() od->mScrollTop = 0; od->mIndent = 160; od->mDontDim = false; + od->mDontBlur = false; + od->mAnimatedTransition = false; + od->mAnimated = false; od->mNetgameMessage = "$NEWGAME"; GC::WriteBarrier(od); for (unsigned i = 0; i < PlayerClasses.Size (); i++) @@ -1048,7 +1079,7 @@ void M_StartupSkillMenu(FNewGameStartup *gs) } if (MenuSkills.Size() == 0) I_Error("No valid skills for menu found. At least one must be defined."); - int defskill = DefaultSkill; + int defskill = LastSkill > -1? LastSkill : DefaultSkill; // use the last selected skill, if available. if ((unsigned int)defskill >= MenuSkills.Size()) { defskill = SkillIndices[(MenuSkills.Size() - 1) / 2]; @@ -1121,9 +1152,9 @@ void M_StartupSkillMenu(FNewGameStartup *gs) // center the menu on the screen if the top space is larger than the bottom space int totalheight = posy + MenuSkills.Size() * spacing - topy; - if (totalheight < 190 || MenuSkills.Size() == 1) + if (ld->mForceList || totalheight < 190 || MenuSkills.Size() == 1) { - int newtop = (200 - totalheight) / 2; + int newtop = max(10, 200 - totalheight) / 2; int topdelta = newtop - topy; if (topdelta < 0) { @@ -1164,7 +1195,7 @@ void M_StartupSkillMenu(FNewGameStartup *gs) if (*c == '$') c = GStrings(c + 1); int textwidth = ld->mFont->StringWidth(c); int textright = posx + textwidth; - if (posx + textright > 320) posx = std::max(0, 320 - textright); + if (posx + textright > 320) posx = max(0, 320 - textright); } unsigned firstitem = ld->mItems.Size(); @@ -1227,6 +1258,9 @@ fail: od->mScrollTop = 0; od->mIndent = 160; od->mDontDim = false; + od->mDontBlur = false; + od->mAnimatedTransition = false; + od->mAnimated = false; GC::WriteBarrier(od); } else @@ -1444,31 +1478,3 @@ CCMD (menu_video) M_StartControlPanel (true); M_SetMenu(NAME_VideoModeMenu, -1); } - - -#ifdef _WIN32 -EXTERN_CVAR(Bool, vr_enable_quadbuffered) -#endif - -void UpdateVRModes(bool considerQuadBuffered) -{ - 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); - } - vals = filteredValues; -} diff --git a/src/menu/doommenu.h b/src/menu/doommenu.h index 2de0bdb7f..f80c7571f 100644 --- a/src/menu/doommenu.h +++ b/src/menu/doommenu.h @@ -2,9 +2,6 @@ #include "menu.h" #include "savegamemanager.h" -void M_StartControlPanel (bool makeSound, bool scaleoverride = false); - - struct FNewGameStartup { const char *PlayerClass; @@ -17,6 +14,7 @@ void M_StartupEpisodeMenu(FNewGameStartup *gs); void M_StartupSkillMenu(FNewGameStartup *gs); void M_CreateGameMenus(); void SetDefaultMenuColors(); +void OnMenuOpen(bool makeSound); class FSavegameManager : public FSavegameManagerBase { diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 23d05b58d..3eba26114 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -68,14 +68,14 @@ void FSavegameManager::ReadSaveStrings() LastSaved = LastAccessed = -1; quickSaveSlot = nullptr; - filter = G_BuildSaveName("*." SAVEGAME_EXT, -1); + filter = G_BuildSaveName("*"); filefirst = I_FindFirst(filter.GetChars(), &c_file); if (filefirst != ((void *)(-1))) { do { // I_FindName only returns the file's name and not its full path - FString filepath = G_BuildSaveName(I_FindName(&c_file), -1); + FString filepath = G_BuildSaveName(I_FindName(&c_file)); std::unique_ptr savegame(FResourceFile::OpenResourceFile(filepath, true, true)); if (savegame != nullptr) @@ -252,7 +252,7 @@ FString FSavegameManager::ExtractSaveComment(FSerializer &arc) FString FSavegameManager::BuildSaveName(const char* prefix, int slot) { - return G_BuildSaveName(prefix, slot); + return G_BuildSaveName(FStringf("%s%02d", prefix, slot)); } //============================================================================= diff --git a/src/namedef_custom.h b/src/namedef_custom.h new file mode 100644 index 000000000..d0964ce7f --- /dev/null +++ b/src/namedef_custom.h @@ -0,0 +1,872 @@ +// GZDoom specific names + +xx(Doom) +xx(Heretic) +xx(Hexen) +xx(Strife) +xx(Raven) + +// blood spawning +xx(Blood) +xx(BloodSplatter) +xx(AxeBlood) +xx(Spray) + +// Invulnerability types +xx(Ghost) +xx(Reflective) + +// Iron Feet types +//xx(Normal) // defined below +xx(Full) + +// Invisibility types +xx(Additive) +xx(Fuzzy) +xx(Stencil) +xx(AddStencil) + +// Healingradius types +xx(Mana) +xx(Armor) + +// Hexen sound sequence names +xx(Platform) +xx(PlatformMetal) +xx(Silence) +xx(Lava) +xx(Water) +xx(Ice) +xx(Earth) +xx(PlatformMetal2) +xx(DoorNormal) +xx(DoorHeavy) +xx(DoorMetal) +xx(DoorCreak) +xx(DoorMetal2) +xx(Wind) + +xx(PointPusher) +xx(PointPuller) + +xx(UpperStackLookOnly) +xx(LowerStackLookOnly) +xx(StackPoint) +xx(SkyCamCompat) + +xx(BasicArmorBonus) +xx(BasicArmorPickup) +xx(SaveAmount) +xx(SavePercent) +xx(MaxAbsorb) +xx(MaxFullAbsorb) +xx(MaxAmount) +xx(ActualSaveAmount) +xx(ArmorType) +xx(HexenArmor) +xx(Slots) +xx(SlotsIncrement) +xx(InterHubAmount) +xx(Icon) +xx(AltHUDIcon) +xx(PickupFlash) + +xx(BulletPuff) +xx(StrifePuff) +xx(MaulerPuff) + +// Special bosses A_BossDeath knows about +xx(Fatso) +xx(Arachnotron) +xx(BaronOfHell) +xx(Cyberdemon) +xx(SpiderMastermind) +xx(Ironlich) +xx(Minotaur) +xx(Sorcerer2) + +// Bots check this +xx(Megasphere) +xx(MegasphereHealth) + +// Standard player classes +xx(DoomPlayer) +xx(HereticPlayer) +xx(StrifePlayer) +xx(FighterPlayer) +xx(ClericPlayer) +xx(MagePlayer) +xx(ChexPlayer) +xx(ChickenPlayer) +xx(PigPlayer) + +// Flechette names for the different Hexen player classes +xx(ArtiPoisonBag1) +xx(ArtiPoisonBag2) +xx(ArtiPoisonBag3) + +// Strife quests +xx(QuestItem) +xx(Sigil) +xx(GiveSigilPiece) +xx(SetWeapon) +xx(SetSprite) + +// Armor +xx(BasicArmor) + +// Doom ammo types +xx(Clip) + +xx(PuzzleItem) +xx(PuzzleItemNumber) +xx(HealthPickup) +xx(autousemode) +xx(Ammo) +xx(WeaponGiver) +xx(DehackedPickup) +xx(PowerTargeter) +xx(PowerInvulnerable) +xx(PowerStrength) +xx(PowerInvisibility) +xx(PowerIronFeet) +xx(PowerLightAmp) +xx(PowerWeaponLevel2) +xx(PowerFlight) +xx(PowerSpeed) +xx(PowerTorch) +xx(PowerHighJump) +xx(PowerReflection) +xx(PowerDrain) +xx(Reflection) +xx(CustomInventory) +xx(Inventory) +xx(StateProvider) +xx(CallTryPickup) +xx(QuestItem25) +xx(QuestItem28) +xx(PowerDoubleFiringSpeed) +xx(PowerInfiniteAmmo) +xx(PowerBuddha) + +xx(TeleportDest) +xx(TeleportDest2) + + +xx(Fist) +//xx(Berserk) +xx(Chainsaw) +xx(Pistol) +xx(Shotgun) +xx(SSG) +xx(Chaingun) +xx(Rocket) +xx(Plasma) +xx(BFG) +//xx(Railgun) +xx(Dagger) + +// Damage types +//xx(Fire) already defined above +//xx(Ice) +//xx(Disintegrate) +xx(Drowning) +xx(Slime) +//xx(Crush) +xx(Telefrag) +xx(Falling) +xx(Suicide) +xx(Exit) +xx(Railgun) +xx(Poison) +xx(Electric) +xx(BFGSplash) +xx(DrainLife) // A weapon like the Sigil that drains your life away. +xx(Massacre) // For death by a cheater! +//(Melee) already defined above, so don't define it again +xx(InstantDeath) // Strife "instant death" +xx(PoisonCloud) // makes monsters howl. +xx(Hitscan) // for normal guns and the like +xx(Quake) + +// Special death name for getting killed excessively. Could be used as +// a damage type if you wanted to force an extreme death. +xx(Extreme) +xx(MDK) +xx(Cast) // 'damage type' for the cast call + +// Various actor names which are used internally +xx(MapSpot) +xx(PatrolPoint) +xx(PatrolSpecial) +xx(Communicator) +xx(PowerScanner) + +xx(DeathmatchStatusScreen) +xx(CoopStatusScreen) +xx(DoomStatusScreen) +xx(RavenStatusScreen) +xx(DoomStatusScreenSized) +xx(RavenStatusScreenSized) + +xx(Owner) +xx(FlameThrower) + +// Dehacked +xx(A_Punch) +xx(A_FirePistol) +xx(A_FireShotgun) +xx(A_FireShotgun2) +xx(A_FireCGun) +xx(A_FireMissile) +xx(A_Saw) +xx(A_FirePlasma) +xx(A_FireBFG) +xx(A_FireOldBFG) +xx(A_FireRailgun) +xx(MBF21_ConsumeAmmo) + +// Special translation names +xx(RainPillar1) +xx(RainPillar2) +xx(RainPillar3) +xx(RainPillar4) +xx(RainPillar5) +xx(RainPillar6) +xx(RainPillar7) +xx(RainPillar8) + +xx(Player1) +xx(Player2) +xx(Player3) +xx(Player4) +xx(Player5) +xx(Player6) +xx(Player7) +xx(Player8) +xx(PlayerChunk) +xx(RestrictedToPlayerClass) +xx(ForbiddenToPlayerClass) + +// Weapon member fields that need direct access +xx(Ammo1) +xx(Ammo2) +xx(AmmoType1) +xx(AmmoType2) +xx(AmmoGive1) +xx(AmmoGive2) +xx(AmmoUse1) +xx(SisterWeapon) +xx(BobStyle) +xx(Kickback) +xx(MinSelAmmo1) +xx(bDehAmmo) +xx(FOVScale) +xx(LookScale) +xx(YAdjust) +xx(Crosshair) +xx(WeaponFlags) +xx(DropTime) +xx(PickupSound) +xx(WeaponScaleX) +xx(WeaponScaleY) +xx(ReadySound) +xx(A_WeaponReady) + +// PlayerPawn member fields +xx(ColorRangeStart) +xx(ColorRangeEnd) +xx(InvFirst) +xx(ForwardMove1) +xx(ForwardMove2) +xx(SideMove1) +xx(SideMove2) +xx(Face) +xx(Slot) +xx(SoundClass) +xx(FlyBob) +xx(ViewBob) +xx(WaterClimbSpeed) +xx(DamageFade) +xx(MaxHealth) +xx(crouchsprite) +xx(UseRange) +xx(AttackZOffset) +xx(SpawnMask) +xx(ScoreIcon) +xx(ViewHeight) +xx(ViewAngle) +xx(ViewPitch) +xx(ViewRoll) +xx(FallingScreamMinSpeed) +xx(FallingScreamMaxSpeed) +xx(GruntSpeed) +xx(JumpZ) +xx(MugShotMaxHealth) +xx(BonusHealth) +xx(PlayerFlags) +xx(InvSel) +xx(FullHeight) + +xx(BlueCard) +xx(YellowCard) +xx(RedCard) +xx(BlueSkull) +xx(YellowSkull) +xx(RedSkull) +xx(DynamicLight) +xx(SpotInnerAngle) +xx(SpotOuterAngle) +xx(lightflags) +xx(lighttype) +xx(InternalDynamicLight) +xx(_a_chase_default) +xx(MapMarker) +xx(Spawn2) +xx(PlayerTeam) +xx(PlayerColors) +xx(PlayerSkin) +xx(NewPlayerMenu) +xx(AltHud) +xx(GameScreen) +xx(ListM) + +// Standard animator names. +xx(Spawn) +xx(See) +xx(Pain) +xx(Melee) +xx(Missile) +xx(Crash) +xx(Death) +xx(Raise) +xx(Wound) +xx(Heal) +xx(Crush) +xx(Yes) +xx(No) +xx(Greetings) +xx(Idle) +xx(GenericFreezeDeath) +xx(GenericCrush) +xx(DieFromSpawn) +xx(Slam) + +// Bounce state names +xx(Bounce) +xx(Wall) +xx(Ceiling) +xx(Creature) + +// Compatible death names for the decorate parser. +xx(XDeath) +xx(Burn) +//xx(Ice) // already defined above +xx(Disintegrate) +xx(Smash) + +// Weapon animator names. +xx(Select) +xx(Deselect) +xx(DeadLowered) +xx(Ready) +xx(Fire) +xx(Hold) +xx(AltFire) +xx(AltHold) +xx(Flash) +xx(AltFlash) +xx(Reload) +xx(Zoom) +xx(User1) +xx(User2) +xx(User3) +xx(User4) + +// State names used by ASwitchableDecoration +xx(Active) +xx(Inactive) + +// State names used by ACustomInventory +xx(Pickup) +xx(Use) +xx(Drop) + + +// ScriptUtil entry points +xx(ScriptUtil) +xx(SetMarineWeapon) +xx(SetMarineSprite) +xx(GiveInventory) +xx(TakeInventory) +xx(ClearInventory) + +// summary +xx(cwidth) +xx(cheight) +xx(wrapwidth) +xx(scalefactorx) +xx(scalefactory) +xx(scalemode) + +xx(Team) +xx(Skin) +xx(Gender) +xx(Autoaim) +xx(Multiplayer) + +xx(CustomizeControls) +xx(MessageOptions) +xx(AutomapOptions) +xx(ScoreboardOptions) +xx(MapColorMenu) +xx(GameplayOptions) +xx(CompatibilityOptions) +xx(MouseOptions) +xx(SoundOptions) +xx(AdvSoundOptions) +xx(ModReplayerOptions) +xx(VideoOptions) +xx(JoystickConfigMenu) +xx(VideoModeMenu) + +// end sequences +xx(Inter_Chess) +xx(Inter_Strife) +xx(Inter_Strife_Good) +xx(Inter_Strife_Sad) +xx(Inter_Strife_Bad) +xx(Inter_Strife_Lose) +xx(Inter_Strife_MAP03) +xx(Inter_Strife_MAP10) + +xx(BuiltinCallLineSpecial) + +xx(MainmenuTextOnly) +xx(Playerclassmenu) +xx(HexenDefaultPlayerclassmenu) +xx(Readthismenu) +xx(Playermenu) + +// more stuff +xx(ColorSet) +xx(NeverSwitchOnPickup) +xx(MoveBob) +xx(FViewBob) +xx(StillBob) +xx(ClassicFlight) +xx(WBobSpeed) +xx(WBobFire) +xx(PlayerClass) +xx(MonsterClass) +xx(MorphedMonster) +xx(Wi_NoAutostartMap) + +xx(Duration) +xx(MorphStyle) +xx(MorphFlash) +xx(UnMorphFlash) +xx(Powerup) +xx(EffectTics) +xx(PowerupGiver) +xx(BlendColor) +xx(Strength) +xx(Mode) +xx(PowerupType) +xx(PlayerPawn) +xx(RipSound) +xx(Archvile) + +xx(ResolveState) + + + +// UDMF keywords (todo: take these out of the global name table +xx(Alpha) +//xx(Angle) +xx(Args) +xx(CeilingZ) +xx(FloorZ) +xx(Health) +xx(Pitch) +xx(SpecialName) +xx(Special) +xx(TID) +xx(TIDtoHate) +xx(WaterLevel) +xx(WaterDepth) +xx(MomX) +xx(MomY) +xx(MomZ) +xx(Threshold) +xx(DefThreshold) +xx(TeleportSpecial) +xx(Teleport) +xx(CallACS) +xx(IsPointerEqual) +xx(Pick) +xx(Mass) +xx(VelX) +xx(VelY) +xx(VelZ) +xx(Accuracy) +xx(Stamina) +xx(Radius) +xx(ReactionTime) +xx(MeleeRange) +xx(Speed) +xx(FastSpeed) +xx(HowlSound) +xx(VisibleStartAngle) +xx(VisibleStartPitch) +xx(VisibleEndAngle) +xx(VisibleEndPitch) +xx(Format) +xx(PickupMsg) +xx(Respawnable) +xx(ExplosionDamage) +xx(ExplosionRadius) +xx(DontHurtShooter) +xx(Noattack) +xx(PushSound) + +//xx(X) +//xx(Y) +xx(ZFloor) +xx(ZCeiling) +xx(Height) +//xx(Tid) +//xx(Angle) +xx(Type) +//xx(Special) +xx(Arg0) +xx(Arg1) +xx(Arg2) +xx(Arg3) +xx(Arg4) +xx(Arg0Str) +xx(Arg1Str) +xx(Id) +xx(MoreIds) +xx(V1) +xx(V2) + +xx(Sidefront) +xx(Sideback) +xx(Offsetx) +xx(Offsety) +xx(Texturetop) +xx(Texturebottom) +xx(Texturemiddle) +xx(Sector) +xx(Heightfloor) +xx(Heightceiling) +xx(Lightlevel) +xx(Texturefloor) +xx(Textureceiling) +xx(Nodecals) + +xx(Skill1) +xx(Skill2) +xx(Skill3) +xx(Skill4) +xx(Skill5) +xx(Skill6) +xx(Skill7) +xx(Skill8) +xx(Skill9) +xx(Skill10) +xx(Skill11) +xx(Skill12) +xx(Skill13) +xx(Skill14) +xx(Skill15) +xx(Skill16) +xx(Medium) +xx(Hard) +xx(Ambush) +xx(Dormant) +xx(Class0) +xx(Class1) +xx(Class2) +xx(Class3) +xx(Class4) +xx(Class5) +xx(Class6) +xx(Class7) +xx(Class8) +xx(Class9) +xx(Class10) +xx(Class11) +xx(Class12) +xx(Class13) +xx(Class14) +xx(Class15) +xx(Class16) +xx(Single) +xx(Coop) +xx(Dm) +xx(Translucent) +xx(Invisible) +xx(Friend) +xx(Strifeally) +xx(Standing) +xx(Countsecret) +xx(NoCount) +xx(Score) +xx(Roll) +xx(Scale) +xx(ScaleX) +xx(ScaleY) +xx(FriendlySeeBlocks) +xx(Floatbobphase) +xx(Floatbobstrength) +xx(Target) +xx(Master) +xx(Tracer) + +xx(Blocking) +xx(Blockmonsters) +xx(Twosided) +xx(Dontpegtop) +xx(Dontpegbottom) +xx(Secret) +xx(Blocksound) +xx(Dontdraw) +xx(Mapped) +xx(Monsteractivate) +xx(Blockplayers) +xx(Blockeverything) +xx(Zoneboundary) +xx(Jumpover) +xx(Blockfloaters) +xx(Blocklandmonsters) +xx(Clipmidtex) +xx(Wrapmidtex) +xx(Midtex3d) +xx(Checkswitchrange) +xx(Firstsideonly) +xx(Transparent) +xx(Passuse) +xx(Repeatspecial) +xx(Conversation) +xx(Locknumber) +xx(Midtex3dimpassible) +xx(Revealed) +xx(AutomapStyle) +xx(DrawFullHeight) + +xx(Playercross) +xx(Playeruse) +xx(Playeruseback) +xx(Monstercross) +xx(Impact) +xx(Playerpush) +xx(Missilecross) +xx(Anycross) +xx(Monsteruse) +xx(Monsterpush) + +xx(ZDoom) +xx(ZDoomTranslated) +xx(Vavoom) +xx(GZDoom) +xx(Eternity) + +xx(Xpanningfloor) +xx(Ypanningfloor) +xx(Xpanningceiling) +xx(Ypanningceiling) +xx(Xscalefloor) +xx(Yscalefloor) +xx(Xscaleceiling) +xx(Yscaleceiling) +xx(Rotationfloor) +xx(Rotationceiling) +xx(Lightfloor) +xx(Lightceiling) +xx(Lightfloorabsolute) +xx(Lightceilingabsolute) +xx(Gravity) +xx(Lightcolor) +xx(Fadecolor) +xx(Color_Floor) +xx(Color_Ceiling) +xx(Color_Walltop) +xx(Color_Wallbottom) +xx(Color_Sprites) +xx(ColorAdd_Floor) +xx(ColorAdd_Ceiling) +xx(ColorAdd_Sprites) +xx(ColorAdd_Walls) +xx(NoSkyWalls) +xx(Desaturation) +xx(SoundSequence) +xx(Silent) +xx(Nofallingdamage) +xx(Dropactors) +xx(NoRespawn) +xx(Alphafloor) +xx(Alphaceiling) +xx(Renderstylefloor) +xx(Renderstyleceiling) +xx(Waterzone) +xx(portal_ceil_blocksound) +xx(portal_ceil_disabled) +xx(portal_ceil_nopass) +xx(portal_ceil_norender) +xx(portal_ceil_overlaytype) +xx(portal_ceil_useglobaltex) +xx(portal_floor_blocksound) +xx(portal_floor_disabled) +xx(portal_floor_nopass) +xx(portal_floor_norender) +xx(portal_floor_overlaytype) +xx(portal_floor_useglobaltex) +xx(scroll_ceil_x) +xx(scroll_ceil_y) +xx(scroll_ceil_type) +xx(scroll_floor_x) +xx(scroll_floor_y) +xx(scroll_floor_type) + +xx(offsetx_top) +xx(offsety_top) +xx(offsetx_mid) +xx(offsety_mid) +xx(offsetx_bottom) +xx(offsety_bottom) +xx(scalex_top) +xx(scaley_top) +xx(scalex_mid) +xx(scaley_mid) +xx(scalex_bottom) +xx(scaley_bottom) +xx(light) +xx(lightabsolute) +xx(lightfog) +xx(light_top) +xx(lightabsolute_top) +xx(light_mid) +xx(lightabsolute_mid) +xx(light_bottom) +xx(lightabsolute_bottom) +xx(nofakecontrast) +xx(smoothlighting) +xx(blockprojectiles) +xx(blockuse) +xx(hidden) +xx(blocksight) +xx(blockhitscan) + +xx(nogradient_top) +xx(flipgradient_top) +xx(clampgradient_top) +xx(useowncolors_top) +xx(uppercolor_top) +xx(lowercolor_top) +xx(nogradient_mid) +xx(flipgradient_mid) +xx(clampgradient_mid) +xx(useowncolors_mid) +xx(uppercolor_mid) +xx(lowercolor_mid) +xx(nogradient_bottom) +xx(flipgradient_bottom) +xx(clampgradient_bottom) +xx(useowncolors_bottom) +xx(uppercolor_bottom) +xx(lowercolor_bottom) +xx(useowncoloradd_top) +xx(coloradd_top) +xx(useowncoloradd_mid) +xx(coloradd_mid) +xx(useowncoloradd_bottom) +xx(coloradd_bottom) +xx(colorization_top) +xx(colorization_mid) +xx(colorization_bottom) +xx(colorization_floor) +xx(colorization_ceiling) + +xx(ceilingplane_a) +xx(ceilingplane_b) +xx(ceilingplane_c) +xx(ceilingplane_d) +xx(floorplane_a) +xx(floorplane_b) +xx(floorplane_c) +xx(floorplane_d) +xx(damageamount) +xx(damagetype) +xx(damageinterval) +xx(leakiness) +xx(damageterraineffect) +xx(damagehazard) +xx(floorterrain) +xx(ceilingterrain) +xx(floor_reflect) +xx(ceiling_reflect) +xx(floorglowcolor) +xx(floorglowheight) +xx(ceilingglowcolor) +xx(ceilingglowheight) +xx(fogdensity) + +xx(HealthFloor) +xx(HealthCeiling) +xx(Health3D) +xx(DamageSpecial) +xx(DeathSpecial) +xx(HealthFloorGroup) +xx(HealthCeilingGroup) +xx(Health3DGroup) +xx(HealthGroup) +xx(Renderstyle) + +// USDF keywords +xx(Amount) +xx(Text) +xx(Displaycost) +xx(Yesmessage) +xx(Nomessage) +xx(Giveitem) +xx(Nextpage) +xx(Closedialog) +xx(Cost) +xx(Page) +xx(Count) +xx(Panel) +xx(Dialog) +xx(Ifitem) +xx(Choice) +xx(Link) +xx(Goodbye) +xx(Require) +xx(Exclude) +xx(Userstring) +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_top) +xx(lm_sampledist_mid) +xx(lm_sampledist_bot) +xx(lm_sampledist_floor) +xx(lm_sampledist_ceiling) +xx(lm_suncolor) +xx(lm_sampledistance) +xx(lm_gridsize) + +xx(Corona) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index a3b031464..47d9a896f 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -33,6 +33,7 @@ */ #include +#include #include "actor.h" #include "p_conversation.h" @@ -59,6 +60,7 @@ #include "actorinlines.h" #include "v_draw.h" #include "doommenu.h" +#include "g_game.h" static FRandom pr_randomspeech("RandomSpeech"); @@ -164,7 +166,7 @@ static void ClearConversationStuff(player_t* player) player->ConversationFaceTalker = false; player->ConversationNPC = nullptr; player->ConversationPC = nullptr; - player->ConversationNPCAngle = 0.; + player->ConversationNPCAngle = nullAngle; } //============================================================================ @@ -393,12 +395,12 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang } // [Nash] Play voice clip from the actor so that positional audio can be heard by all players - if (CurNode->SpeakerVoice != 0) S_Sound(npc, CHAN_VOICE, CHANF_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM); + if (CurNode->SpeakerVoice != NO_SOUND) S_Sound(npc, CHAN_VOICE, CHANF_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM); // The rest is only done when the conversation is actually displayed. if (pc->player == Level->GetConsolePlayer()) { - if (CurNode->SpeakerVoice != 0) + if (CurNode->SpeakerVoice != NO_SOUND) { I_SetMusicVolume (dlg_musicvolume); } @@ -489,7 +491,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply if (!(npc->flags8 & MF8_DONTFACETALKER)) npc->Angles.Yaw = player->ConversationNPCAngle; npc->flags5 &= ~MF5_INCONVERSATION; - if (gameaction != ga_slideshow) ClearConversationStuff(player); + if (gameaction != ga_intermission) ClearConversationStuff(player); return; } @@ -507,7 +509,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply if (!(npc->flags8 & MF8_DONTFACETALKER)) npc->Angles.Yaw = player->ConversationNPCAngle; npc->flags5 &= ~MF5_INCONVERSATION; - if (gameaction != ga_slideshow) ClearConversationStuff(player); + if (gameaction != ga_intermission) ClearConversationStuff(player); return; } } @@ -548,7 +550,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply } if (reply->GiveType->IsDescendantOf("SlideshowStarter")) - gameaction = ga_slideshow; + G_StartSlideshow(primaryLevel, NAME_None); } else { @@ -617,7 +619,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply if (!(reply->CloseDialog)) { - if (gameaction != ga_slideshow) + if (gameaction != ga_intermission) { P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false); return; @@ -643,7 +645,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply // [CW] Set these to NULL because we're not using to them // anymore. However, this can interfere with slideshows // so we don't set them to NULL in that case. - if (gameaction != ga_slideshow) + if (gameaction != ga_intermission) { npc->flags5 &= ~MF5_INCONVERSATION; ClearConversationStuff(player); @@ -716,7 +718,7 @@ static void TerminalResponse (const char *str) if (StatusBar != NULL) { - Printf(PRINT_NONOTIFY, "%s\n", str); + Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s\n", str); // The message is positioned a bit above the menu choices, because // merchants can tell you something like this but continue to show // their dialogue screen. I think most other conversations use this diff --git a/src/p_conversation.h b/src/p_conversation.h index 84f0fb407..b055d5f4c 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -29,7 +29,7 @@ struct FStrifeDialogueNode PClassActor *SpeakerType = nullptr; FString SpeakerName; - FSoundID SpeakerVoice = 0; + FSoundID SpeakerVoice = NO_SOUND; FString Backdrop; FString Dialogue; FString Goodbye; // must init to null for binary scripts to work as intended diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp index 98f03906a..771ae1d87 100644 --- a/src/p_openmap.cpp +++ b/src/p_openmap.cpp @@ -81,6 +81,7 @@ static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, {"REJECT", false}, {"BLOCKMAP", false}, {"BEHAVIOR", false}, + {"LIGHTMAP", false }, //{"SCRIPTS", false}, }; @@ -235,6 +236,10 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) index = ML_BEHAVIOR; map->HasBehavior = true; } + else if (!stricmp(lumpname, "LIGHTMAP")) + { + index = ML_LIGHTMAP; + } else if (!stricmp(lumpname, "ENDMAP")) { break; @@ -312,6 +317,10 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) index = ML_BEHAVIOR; map->HasBehavior = true; } + else if (!strnicmp(lumpname, "LIGHTMAP", 8)) + { + index = ML_LIGHTMAP; + } else if (!strnicmp(lumpname, "ENDMAP",8)) { return map; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 9d0189f41..25b244ffd 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -61,6 +61,7 @@ #include "version.h" #include "fragglescript/t_script.h" #include "s_music.h" +#include "model.h" EXTERN_CVAR(Bool, save_formatted) @@ -525,9 +526,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj &poly, FPolyO if (arc.isReading()) { - poly.RotatePolyobj(angle, true); - delta -= poly.StartSpot.pos; - poly.MovePolyobj(delta, true); + if (poly.OriginalPts.Size() > 0) + { + poly.RotatePolyobj(angle, true); + delta -= poly.StartSpot.pos; + poly.MovePolyobj(delta, true); + } } } return arc; @@ -993,7 +997,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) ("scrolls", Scrolls) ("automap", automap) ("interpolator", interpolator) - ("frozenstate", frozenstate); + ("frozenstate", frozenstate) + ("savedModelFiles", savedModelFiles); // Hub transitions must keep the current total time diff --git a/src/p_setup.cpp b/src/p_setup.cpp index d05865820..4491b80c8 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -30,7 +30,7 @@ #include // for alloca() #endif -#include "templates.h" + #include "d_player.h" #include "m_argv.h" #include "g_game.h" @@ -102,11 +102,11 @@ static void AddToList(uint8_t *hitlist, FTextureID texid, int bitmask) const auto addAnimations = [hitlist, bitmask](const FTextureID texid) { - for (auto anim : TexAnim.GetAnimations()) + for (auto& anim : TexAnim.GetAnimations()) { - if (texid == anim->BasePic || (!anim->bDiscrete && anim->BasePic < texid && texid < anim->BasePic + anim->NumFrames)) + if (texid == anim.BasePic || (!anim.bDiscrete && anim.BasePic < texid && texid < anim.BasePic + anim.NumFrames)) { - for (int i = anim->BasePic.GetIndex(); i < anim->BasePic.GetIndex() + anim->NumFrames; i++) + for (int i = anim.BasePic.GetIndex(); i < anim.BasePic.GetIndex() + anim.NumFrames; i++) { hitlist[i] |= (uint8_t)bitmask; } @@ -279,7 +279,7 @@ void FLevelLocals::ClearPortals() // //========================================================================== -void FLevelLocals::ClearLevelData() +void FLevelLocals::ClearLevelData(bool fullgc) { { auto it = GetThinkerIterator(NAME_None, STAT_TRAVELLING); @@ -291,7 +291,7 @@ void FLevelLocals::ClearLevelData() } interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. - Thinkers.DestroyAllThinkers(); + Thinkers.DestroyAllThinkers(fullgc); ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. total_monsters = total_items = total_secrets = @@ -372,7 +372,9 @@ void FLevelLocals::ClearLevelData() Behaviors.UnloadModules(); localEventManager->Shutdown(); if (aabbTree) delete aabbTree; + if (levelMesh) delete levelMesh; aabbTree = nullptr; + levelMesh = nullptr; if (screen) screen->SetAABBTree(nullptr); } @@ -383,13 +385,13 @@ void FLevelLocals::ClearLevelData() // //========================================================================== -void P_FreeLevelData () +void P_FreeLevelData (bool fullgc) { R_FreePastViewers(); for (auto Level : AllLevels()) { - Level->ClearLevelData(); + Level->ClearLevelData(fullgc); } // primaryLevel->FreeSecondaryLevels(); } diff --git a/src/p_setup.h b/src/p_setup.h index e6bef780d..27c646b5b 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -141,8 +141,9 @@ MapData * P_OpenMapData(const char * mapname, bool justcheck); bool P_CheckMapData(const char * mapname); void P_SetupLevel (FLevelLocals *Level, int position, bool newGame); +void P_LoadLightmap(MapData *map); -void P_FreeLevelData(); +void P_FreeLevelData(bool fullgc = true); // Called by startup code. void P_Init (void); diff --git a/src/p_states.cpp b/src/p_states.cpp index 2e52243b1..6c3ff2f33 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,6 +39,7 @@ #include "v_text.h" #include "thingdef.h" #include "r_state.h" +#include "templates.h" // stores indices for symbolic state labels for some old-style DECORATE functions. @@ -79,7 +80,7 @@ DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture) if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex()); if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation))); if (numret > 2) ret[2].SetVector2(DVector2(scalex, scaley)); - return MIN(3, numret); + return min(3, numret); } diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 2889a06a5..59d66a285 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -38,6 +38,7 @@ #include "events.h" #include "actorinlines.h" #include "g_game.h" +#include "i_interface.h" extern gamestate_t wipegamestate; extern uint8_t globalfreeze, globalchangefreeze; @@ -157,6 +158,7 @@ void P_Ticker (void) while ((ac = it.Next())) { ac->ClearInterpolation(); + ac->ClearFOVInterpolation(); } P_ThinkParticles(Level); // [RH] make the particles think diff --git a/src/playsim/a_action.cpp b/src/playsim/a_action.cpp index 63fca0ece..d9f53903d 100644 --- a/src/playsim/a_action.cpp +++ b/src/playsim/a_action.cpp @@ -104,7 +104,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) if (corpse) corpse->Destroy(); corpsequeue.Delete(0); } - corpsequeue.Push(self); + corpsequeue.Push(MakeObjPtr(self)); GC::WriteBarrier(self); } return 0; diff --git a/src/common/rendering/polyrenderer/drawers/screen_shader.h b/src/playsim/a_corona.cpp similarity index 79% rename from src/common/rendering/polyrenderer/drawers/screen_shader.h rename to src/playsim/a_corona.cpp index 567b4d6c9..edeba7566 100644 --- a/src/common/rendering/polyrenderer/drawers/screen_shader.h +++ b/src/playsim/a_corona.cpp @@ -1,6 +1,6 @@ /* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl +** 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 @@ -17,11 +17,18 @@ ** 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 -class PolyTriangleThreadData; +#include "actor.h" +#include "a_corona.h" +#include "a_dynlight.h" -void SelectFragmentShader(PolyTriangleThreadData* thread); +#if 0 +IMPLEMENT_CLASS(ACorona, false, false) + +void ACorona::Tick() +{ + Super::Tick(); +} +#endif \ No newline at end of file diff --git a/src/common/rendering/polyrenderer/drawers/screen_scanline_setup.h b/src/playsim/a_corona.h similarity index 72% rename from src/common/rendering/polyrenderer/drawers/screen_scanline_setup.h rename to src/playsim/a_corona.h index 5ea66cf96..c1863f8a2 100644 --- a/src/common/rendering/polyrenderer/drawers/screen_scanline_setup.h +++ b/src/playsim/a_corona.h @@ -1,6 +1,6 @@ /* -** Polygon Doom software renderer -** Copyright (c) 2016 Magnus Norddahl +** 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 @@ -17,13 +17,24 @@ ** 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 -struct TriDrawTriangleArgs; -class PolyTriangleThreadData; +#include "actor.h" -void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); -void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread); +EXTERN_CVAR(Bool, gl_coronas) + +class AActor; + +#if 0 +class ACorona : public AActor +{ + DECLARE_CLASS(ACorona, AActor) + +public: + void Tick(); + + float CoronaFade = 0.0f; +}; +#endif \ No newline at end of file diff --git a/src/playsim/a_decals.cpp b/src/playsim/a_decals.cpp index 73dc86771..fdb63a0a6 100644 --- a/src/playsim/a_decals.cpp +++ b/src/playsim/a_decals.cpp @@ -891,7 +891,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], NULL, 0, 0, permanent); + return DImpactDecal::StaticCreate(Level, tpl, trace.HitPos, trace.Line->sidedef[trace.Side], trace.ffloor, 0, 0, permanent); } return NULL; } @@ -929,7 +929,7 @@ static void SpawnDecal(AActor *self) // Look for a wall within 64 units behind the actor. If none can be // found, then no decal is created, and this actor is destroyed // without effectively doing anything. - if (!ShootDecal(self->Level, tpl, self->Sector, self->X(), self->Y(), self->Z(), self->Angles.Yaw + 180, 64., true)) + if (!ShootDecal(self->Level, tpl, self->Sector, self->X(), self->Y(), self->Z(), self->Angles.Yaw + DAngle::fromDeg(180), 64., true)) { DPrintf (DMSG_WARNING, "Could not find a wall to stick decal to at (%f,%f)\n", self->X(), self->Y()); } diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 8a5838f1d..dddb9f54e 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -115,7 +115,7 @@ void AttachLight(AActor *self) light->pPitch = &self->Angles.Pitch; light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags); light->pArgs = self->args; - light->specialf1 = DAngle(double(self->SpawnAngle)).Normalized360().Degrees; + light->specialf1 = DAngle::fromDeg(double(self->SpawnAngle)).Normalized360().Degrees(); light->Sector = self->Sector; light->target = self; light->mShadowmapIndex = 1024; @@ -395,7 +395,7 @@ void FDynamicLight::UpdateLocation() if (lighttype == FlickerLight || lighttype == RandomFlickerLight || lighttype == PulseLight) { - intensity = float(MAX(GetIntensity(), GetSecondaryIntensity())); + intensity = float(max(GetIntensity(), GetSecondaryIntensity())); } else { diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index d5be0438a..0aee31790 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -40,7 +40,9 @@ enum LightFlag LF_ATTENUATE = 8, LF_NOSHADOWMAP = 16, LF_DONTLIGHTACTORS = 32, - LF_SPOT = 64 + LF_SPOT = 64, + LF_DONTLIGHTOTHERS = 128, + LF_DONTLIGHTMAP = 256 }; typedef TFlags LightFlags; @@ -72,20 +74,23 @@ public: void SetDontLightSelf(bool add) { if (add) m_lightFlags |= LF_DONTLIGHTSELF; else m_lightFlags &= ~LF_DONTLIGHTSELF; } void SetAttenuate(bool on) { m_attenuate = on; if (on) m_lightFlags |= LF_ATTENUATE; else m_lightFlags &= ~LF_ATTENUATE; } void SetDontLightActors(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTACTORS; else m_lightFlags &= ~LF_DONTLIGHTACTORS; } + void SetDontLightOthers(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTOTHERS; else m_lightFlags &= ~LF_DONTLIGHTOTHERS; } + void SetDontLightMap(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTMAP; else m_lightFlags &= ~LF_DONTLIGHTMAP; } void SetNoShadowmap(bool on) { if (on) m_lightFlags |= LF_NOSHADOWMAP; else m_lightFlags &= ~LF_NOSHADOWMAP; } void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; } - void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; } - void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; } + void SetSpotInnerAngle(double angle) { m_spotInnerAngle = DAngle::fromDeg(angle); } + void SetSpotOuterAngle(double angle) { m_spotOuterAngle = DAngle::fromDeg(angle); } void SetSpotPitch(double pitch) { - m_pitch = pitch; + m_pitch = DAngle::fromDeg(pitch); m_explicitPitch = true; } void UnsetSpotPitch() { - m_pitch = 0.; + m_pitch = nullAngle; m_explicitPitch = false; } + void SetType(ELightType type) { m_type = type; } void CopyFrom(const FLightDefaults &other) { @@ -120,9 +125,9 @@ protected: bool m_swapped = false; bool m_spot = false; bool m_explicitPitch = false; - DAngle m_spotInnerAngle = 10.0; - DAngle m_spotOuterAngle = 25.0; - DAngle m_pitch = 0.0; + DAngle m_spotInnerAngle = DAngle::fromDeg(10.0); + DAngle m_spotOuterAngle = DAngle::fromDeg(25.0); + DAngle m_pitch = nullAngle; friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def); }; @@ -201,7 +206,10 @@ struct FDynamicLight bool ShouldLightActor(AActor *check) { - return visibletoplayer && IsActive() && (!((*pLightFlags) & LF_DONTLIGHTSELF) || target != check) && !((*pLightFlags) & LF_DONTLIGHTACTORS); + return visibletoplayer && IsActive() && + (!((*pLightFlags) & LF_DONTLIGHTSELF) || target != check) && + (!((*pLightFlags) & LF_DONTLIGHTOTHERS) || target == check) && + (!((*pLightFlags) & LF_DONTLIGHTACTORS)); } void SetOffset(const DVector3 &pos) @@ -225,6 +233,8 @@ struct FDynamicLight bool DontShadowmap() const { return !!((*pLightFlags) & LF_NOSHADOWMAP); } bool DontLightSelf() const { return !!((*pLightFlags) & (LF_DONTLIGHTSELF|LF_DONTLIGHTACTORS)); } // dontlightactors implies dontlightself. bool DontLightActors() const { return !!((*pLightFlags) & LF_DONTLIGHTACTORS); } + bool DontLightOthers() const { return !!((*pLightFlags) & (LF_DONTLIGHTOTHERS)); } + bool DontLightMap() const { return !!((*pLightFlags) & (LF_DONTLIGHTMAP)); } void Deactivate() { m_active = false; } void Activate(); diff --git a/src/playsim/a_sharedglobal.h b/src/playsim/a_sharedglobal.h index 349c4c670..3c86aa109 100644 --- a/src/playsim/a_sharedglobal.h +++ b/src/playsim/a_sharedglobal.h @@ -112,6 +112,10 @@ enum QF_MAX = 1 << 3, QF_FULLINTENSITY = 1 << 4, QF_WAVE = 1 << 5, + QF_3D = 1 << 6, + QF_GROUNDONLY = 1 << 7, + QF_AFFECTACTORS = 1 << 8, + QF_SHAKEONLY = 1 << 9, }; struct FQuakeJiggers @@ -129,8 +133,8 @@ class DEarthquake : public DThinker HAS_OBJECT_POINTERS public: static const int DEFAULT_STAT = STAT_EARTHQUAKE; - void Construct(AActor *center, int intensityX, int intensityY, int intensityZ, int duration, - int damrad, int tremrad, FSoundID quakesfx, int flags, + 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); void Serialize(FSerializer &arc); @@ -150,6 +154,7 @@ public: 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; static int StaticGetQuakeIntensities(double ticFrac, AActor *viewer, FQuakeJiggers &jiggers); }; diff --git a/src/playsim/actor.h b/src/playsim/actor.h index e604cbfeb..b1c848e40 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -30,7 +30,7 @@ #define __P_MOBJ_H__ // Basics. -#include "templates.h" + // We need the thinker_t stuff. #include "dthinker.h" @@ -47,6 +47,7 @@ #include "g_level.h" #include "tflags.h" #include "portal.h" +#include "bonecomponents.h" struct subsector_t; struct FBlockNode; @@ -423,6 +424,12 @@ enum ActorFlag8 MF8_MAP07BOSS2 = 0x00800000, // MBF21 boss death. MF8_AVOIDHAZARDS = 0x01000000, // MBF AI enhancement. 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_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.renderflags --- @@ -472,6 +479,12 @@ enum ActorRenderFlag 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 +}; + // This translucency value produces the closest match to Heretic's TINTTAB. // ~40% of the value of the overlaid image shows through. const double HR_SHADOW = (0x6800 / 65536.); @@ -574,6 +587,7 @@ typedef TFlags ActorFlags6; typedef TFlags ActorFlags7; typedef TFlags ActorFlags8; typedef TFlags ActorRenderFlags; +typedef TFlags ActorRenderFlags2; typedef TFlags ActorBounceFlags; typedef TFlags ActorRenderFeatureFlags; DEFINE_TFLAGS_OPERATORS (ActorFlags) @@ -585,6 +599,7 @@ DEFINE_TFLAGS_OPERATORS (ActorFlags6) DEFINE_TFLAGS_OPERATORS (ActorFlags7) DEFINE_TFLAGS_OPERATORS (ActorFlags8) DEFINE_TFLAGS_OPERATORS (ActorRenderFlags) +DEFINE_TFLAGS_OPERATORS (ActorRenderFlags2) DEFINE_TFLAGS_OPERATORS (ActorBounceFlags) DEFINE_TFLAGS_OPERATORS (ActorRenderFeatureFlags) @@ -654,18 +669,70 @@ struct FDropItem int Amount; }; +enum EViewPosFlags // [MC] Flags for SetViewPos. +{ + VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles. + VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position. +}; + +class DActorModelData : public DObject +{ + DECLARE_CLASS(DActorModelData, DObject); +public: + FName modelDef; + bool hasModel; + TArray modelIDs; + TArray skinIDs; + TArray surfaceSkinIDs; + TArray animationIDs; + TArray modelFrameGenerators; + + DActorModelData() = default; + virtual void Serialize(FSerializer& arc) override; +}; + +class DViewPosition : public DObject +{ + DECLARE_CLASS(DViewPosition, DObject); +public: + // Variables + // Exposed to ZScript + DVector3 Offset; + int Flags; + + // Functions + DViewPosition() + { + Offset = { 0,0,0 }; + Flags = 0; + } + + void Set(DVector3 &off, int f = -1) + { + Offset = off; + + if (f > -1) + Flags = f; + } + + bool isZero() + { + return Offset.isZero(); + } +}; + 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 public: AActor() = default; AActor(const AActor &other) = delete; // Calling this would be disastrous. - AActor &operator= (const AActor &other); - ~AActor (); + AActor &operator= (const AActor &other) = delete; + ~AActor () = default; virtual void OnDestroy() override; virtual void Serialize(FSerializer &arc) override; @@ -730,9 +797,12 @@ public: bool CallSlam(AActor *victim); // Something just touched this actor. - virtual void Touch(AActor *toucher); void CallTouch(AActor *toucher); + // Apply gravity and/or make actor sink in water. + virtual void FallAndSink(double grav, double oldfloorz); + void CallFallAndSink(double grav, double oldfloorz); + // Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed // Made a metadata property so no longer virtual void Howl (); @@ -740,6 +810,9 @@ public: // plays bouncing sound void PlayBounceSound(bool onfloor); + // plays pushing sound + void PlayPushSound(); + // Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor bool FloorBounceMissile (secplane_t &plane); @@ -767,9 +840,6 @@ public: // Tosses an item out of the inventory. AActor *DropInventory (AActor *item, int amt = -1); - // Removes all items from the inventory. - void ClearInventory(); - // Returns true if this view is considered "local" for the player. bool CheckLocalView() const; @@ -784,9 +854,6 @@ public: // Adds one item of a particular type. Returns NULL if it could not be added. AActor *GiveInventoryType (PClassActor *type); - // Destroys all the inventory the actor is holding. - void DestroyAllInventory (); - // Set the alphacolor field properly void SetShade (uint32_t rgb); void SetShade (int r, int g, int b); @@ -804,7 +871,6 @@ public: bool Massacre (); // Transforms the actor into a finely-ground paste - bool Grind(bool items); bool CallGrind(bool items); // Get this actor's team @@ -857,10 +923,14 @@ public: void SetPitch(DAngle p, int fflags); void SetAngle(DAngle ang, int fflags); void SetRoll(DAngle roll, int fflags); + + // These also set CF_INTERPVIEWANGLES for players. void SetViewPitch(DAngle p, int fflags); void SetViewAngle(DAngle ang, int fflags); void SetViewRoll(DAngle roll, int fflags); + double GetFOV(double ticFrac); + PClassActor *GetBloodType(int type = 0) const; double Distance2DSquared(AActor *other, bool absolute = false) @@ -930,6 +1000,7 @@ public: DVector3 Vec3Angle(double length, DAngle angle, double dz, bool absolute = false); void ClearInterpolation(); + void ClearFOVInterpolation(); void Move(const DVector3 &vel) { @@ -974,7 +1045,8 @@ public: DAngle SpriteAngle; DAngle SpriteRotation; DRotator Angles; - DRotator ViewAngles; // Offsets for cameras + DRotator ViewAngles; // Angle offsets for cameras + TObjPtr ViewPos; // Position offsets for cameras DVector2 Scale; // Scaling values; 1 is normal size double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. @@ -991,6 +1063,7 @@ public: uint32_t RenderHidden; // current renderer must *not* have any of these features ActorRenderFlags renderflags; // Different rendering flags + ActorRenderFlags2 renderflags2; // More rendering flags... ActorFlags flags; ActorFlags2 flags2; // Heretic flags ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable @@ -1010,8 +1083,11 @@ public: DVector3 OldRenderPos; DVector3 Vel; DVector2 SpriteOffset; + DVector3 WorldOffset; double Speed; double FloatSpeed; + TObjPtr modelData; + TObjPtr boneComponentData; // interaction info FBlockNode *BlockNode; // links in blocks (if needed) @@ -1043,32 +1119,36 @@ public: FState *state; //VMFunction *Damage; // For missiles and monster railgun int DamageVal; - VMFunction *DamageFunc; int projectileKickback; + VMFunction *DamageFunc; // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it. - uint32_t VisibleToTeam; int special1; // Special info int special2; // Special info double specialf1; // With floats we cannot use the int versions for storing position or angle data without reverting to fixed point (which we do not want.) double specialf2; + uint32_t VisibleToTeam; int weaponspecial; // Special info for weapons. int health; - uint8_t movedir; // 0-7 - int8_t visdir; - int16_t movecount; // when 0, select a new dir - int16_t strafecount; // for MF3_AVOIDMELEE - uint16_t SpawnAngle; - TObjPtr target; // thing being chased/attacked (or NULL) - // also the originator for missiles - TObjPtr lastenemy; // Last known enemy -- killough 2/15/98 - TObjPtr LastHeard; // [RH] Last actor this one heard int32_t reactiontime; // if non 0, don't attack yet; used by // player to freeze a bit after teleporting int32_t threshold; // if > 0, the target will be chased int32_t DefThreshold; // [MC] Default threshold which the actor will reset its threshold to after switching targets + + uint8_t movedir; // 0-7 + int8_t visdir; + int16_t movecount; // when 0, select a new dir + + int16_t strafecount; // for MF3_AVOIDMELEE + int16_t LightLevel; // Allows for overriding sector light levels. + uint16_t SpawnAngle; + + TObjPtr target; // thing being chased/attacked (or NULL) + // also the originator for missiles + TObjPtr lastenemy; // Last known enemy -- killough 2/15/98 + TObjPtr LastHeard; // [RH] Last actor this one heard // no matter what (even if shot) player_t *player; // only valid if type of PlayerPawn TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) @@ -1092,6 +1172,7 @@ public: AActor *inext, **iprev;// Links to other mobjs in same bucket TObjPtr goal; // Monster's goal if not chasing anything int waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes + double waterdepth; // Stores how deep into water you are, in map units uint8_t boomwaterlevel; // splash information for non-swimmable water sectors uint8_t MinMissileChance;// [RH] If a random # is > than this, then missile attack. int8_t LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0) @@ -1123,6 +1204,8 @@ public: sector_t *BlockingCeiling; // Sector that blocked the last move (ceiling plane slope) sector_t *BlockingFloor; // Sector that blocked the last move (floor plane slope) + uint32_t freezetics; // actor has actions completely frozen (including movement) for this many tics, but they still get Tick() calls + int PoisonDamage; // Damage received per tic from poison. FName PoisonDamageType; // Damage type dealt by poison. int PoisonDuration; // Duration left for receiving poison damage. @@ -1153,15 +1236,15 @@ public: uint32_t BloodTranslation; // [RH] Stuff that used to be part of an Actor Info - FSoundIDNoInit SeeSound; - FSoundIDNoInit AttackSound; - FSoundIDNoInit PainSound; - FSoundIDNoInit DeathSound; - FSoundIDNoInit ActiveSound; - FSoundIDNoInit UseSound; // [RH] Sound to play when an actor is used. - FSoundIDNoInit BounceSound; - FSoundIDNoInit WallBounceSound; - FSoundIDNoInit CrushPainSound; + FSoundID SeeSound; + FSoundID AttackSound; + FSoundID PainSound; + FSoundID DeathSound; + FSoundID ActiveSound; + FSoundID UseSound; // [RH] Sound to play when an actor is used. + FSoundID BounceSound; + FSoundID WallBounceSound; + FSoundID CrushPainSound; double MaxDropOffHeight; double MaxStepHeight; @@ -1198,6 +1281,7 @@ public: // [RH] Used to interpolate the view to get >35 FPS DVector3 Prev; DRotator PrevAngles; + DAngle PrevFOV; int PrevPortalGroup; TArray AttachedLights; TDeletingArray UserLights; @@ -1228,10 +1312,9 @@ public: void UnlinkFromWorld(FLinkContext *ctx); void AdjustFloorClip (); bool IsMapActor(); - int GetTics(FState * newstate); bool SetState (FState *newstate, bool nofunction=false); - virtual void SplashCheck(); - virtual bool UpdateWaterLevel (bool splash=true); + void SplashCheck(); + bool UpdateWaterLevel (bool splash=true); bool isFast(); bool isSlow(); void SetIdle(bool nofunction=false); @@ -1301,7 +1384,7 @@ public: double RenderRadius() const { - return MAX(radius, renderradius); + return max(radius, renderradius); } DVector3 PosRelative(int grp) const; @@ -1453,15 +1536,17 @@ public: // Better have it in one place, if something needs to be changed about the formula. double DistanceBySpeed(AActor *dest, double speed) const { - return MAX(1., Distance2D(dest) / speed); + return max(1., Distance2D(dest) / speed); } + int GetLightLevel(sector_t* rendersector); int ApplyDamageFactor(FName damagetype, int damage) const; int GetModifiedDamage(FName damagetype, int damage, bool passive, AActor *inflictor, AActor *source, int flags = 0); void DeleteAttachedLights(); bool isFrozen() const; bool hasmodel; + }; class FActorIterator diff --git a/src/playsim/actorinlines.h b/src/playsim/actorinlines.h index c2485bdbd..939807c98 100644 --- a/src/playsim/actorinlines.h +++ b/src/playsim/actorinlines.h @@ -34,6 +34,14 @@ inline void AActor::ClearInterpolation() else PrevPortalGroup = 0; } +inline void AActor::ClearFOVInterpolation() +{ + if (player) + PrevFOV = DAngle::fromDeg(player->FOV); + else + PrevFOV = DAngle::fromDeg(CameraFOV); +} + inline double secplane_t::ZatPoint(const AActor *ac) const { return (D + normal.X*ac->X() + normal.Y*ac->Y()) * negiC; @@ -49,6 +57,12 @@ inline double sector_t::LowestFloorAt(AActor *a, sector_t **resultsec) return ::LowestFloorAt(this, a->X(), a->Y(), resultsec); } +// Emulates the old floatbob offset table with direct calls to trig functions. +inline double BobSin(double fb) +{ + return g_sindeg(double(fb * (180.0 / 32))) * 8; +} + inline double AActor::GetBobOffset(double ticfrac) const { if (!(flags2 & MF2_FLOATBOB)) @@ -159,6 +173,8 @@ inline DVector3 AActor::Vec3Angle(double length, DAngle angle, double dz, bool a inline bool AActor::isFrozen() const { + if (freezetics > 0) + return true; if (!(flags5 & MF5_NOTIMEFREEZE)) { auto state = Level->isFrozen(); @@ -178,6 +194,22 @@ inline bool AActor::isFrozen() const return false; } +inline int AActor::GetLightLevel(sector_t* rendersector) +{ + int lightlevel = rendersector->GetSpriteLight(); + + if (flags8 & MF8_ADDLIGHTLEVEL) + { + lightlevel += LightLevel; + } + else if (LightLevel > -1) + { + lightlevel = LightLevel; + } + return lightlevel; +} + + // Consolidated from all (incomplete) variants that check if a line should block. inline bool P_IsBlockedByLine(AActor* actor, line_t* line) { @@ -197,11 +229,11 @@ inline bool P_IsBlockedByLine(AActor* actor, line_t* line) // the regular 'blockmonsters' flag. if (line->flags & ML_BLOCKMONSTERS) return true; // MBF21's flag for walking monsters - if ((line->flags2 & ML2_BLOCKLANDMONSTERS) && !(actor->flags & MF_FLOAT)) return true; + if ((line->flags2 & ML2_BLOCKLANDMONSTERS) && actor->Level->MBF21Enabled() && !(actor->flags & MF_FLOAT)) return true; } // Blocking players - if (((actor->player != nullptr) || (actor->flags8 & MF8_BLOCKASPLAYER)) && (line->flags & ML_BLOCK_PLAYERS)) return true; + if ((((actor->player != nullptr) || (actor->flags8 & MF8_BLOCKASPLAYER)) && (line->flags & ML_BLOCK_PLAYERS)) && actor->Level->MBF21Enabled()) return true; // Blocking floaters. if ((actor->flags & MF_FLOAT) && (line->flags & ML_BLOCK_FLOATERS)) return true; diff --git a/src/playsim/bots/b_bot.cpp b/src/playsim/bots/b_bot.cpp index 97eb37829..415cc271d 100644 --- a/src/playsim/bots/b_bot.cpp +++ b/src/playsim/bots/b_bot.cpp @@ -51,6 +51,7 @@ #include "filesystem.h" #include "vm.h" #include "g_levellocals.h" +#include "d_main.h" IMPLEMENT_CLASS(DBot, false, true) @@ -73,7 +74,7 @@ void DBot::Construct() void DBot::Clear () { player = nullptr; - Angle = 0.; + Angle = nullAngle; dest = nullptr; prev = nullptr; enemy = nullptr; @@ -155,7 +156,7 @@ CVAR (Int, bot_next_color, 11, 0) CCMD (addbot) { - if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION) + if (gamestate != GS_LEVEL) { Printf ("Bots cannot be added when not in a game!\n"); return; diff --git a/src/playsim/bots/b_func.cpp b/src/playsim/bots/b_func.cpp index b38fd1723..07cdd08d0 100644 --- a/src/playsim/bots/b_func.cpp +++ b/src/playsim/bots/b_func.cpp @@ -151,9 +151,9 @@ bool DBot::Check_LOS (AActor *to, DAngle vangle) { if (!P_CheckSight (player->mo, to, SF_SEEPASTBLOCKEVERYTHING)) return false; // out of sight - if (vangle >= 360.) + if (vangle >= DAngle::fromDeg(360.)) return true; - if (vangle == 0) + if (vangle == nullAngle) return false; //Looker seems to be blind. return absangle(player->mo->AngleTo(to), player->mo->Angles.Yaw) <= (vangle/2); @@ -212,7 +212,7 @@ void DBot::Dofire (ticcmd_t *cmd) { //MAKEME: This should be smarter. if ((pr_botdofire()%200)<=skill.reaction) - if(Check_LOS(enemy, SHOOTFOV)) + if(Check_LOS(enemy, DAngle::fromDeg(SHOOTFOV))) no_fire = false; } else if (GetBotInfo(player->ReadyWeapon).projectileType != NULL) @@ -221,11 +221,11 @@ void DBot::Dofire (ticcmd_t *cmd) { //Special rules for RL an = FireRox (enemy, cmd); - if(an != 0) + if(an != nullAngle) { Angle = an; //have to be somewhat precise. to avoid suicide. - if (absangle(an, player->mo->Angles.Yaw) < 12.) + if (absangle(an, player->mo->Angles.Yaw) < DAngle::fromDeg(12.)) { t_rocket = 9; no_fire = false; @@ -237,7 +237,7 @@ void DBot::Dofire (ticcmd_t *cmd) fm = Dist / GetDefaultByType (GetBotInfo(player->ReadyWeapon).projectileType)->Speed; Level->BotInfo.SetBodyAt(Level, enemy->Pos() + enemy->Vel.XY() * fm * 2, 1); Angle = player->mo->AngleTo(Level->BotInfo.body1); - if (Check_LOS (enemy, SHOOTFOV)) + if (Check_LOS (enemy, DAngle::fromDeg(SHOOTFOV))) no_fire = false; } else @@ -254,11 +254,11 @@ void DBot::Dofire (ticcmd_t *cmd) aiming_value = skill.aiming - aiming_penalty; if (aiming_value <= 0) aiming_value = 1; - m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate - if (m <= 0) - m = 1.; //Prevents lock. + m = DAngle::fromDeg(((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200))); //Higher skill is more accurate + if (m <= nullAngle) + m = DAngle::fromDeg(1.); //Prevents lock. - if (m != 0) + if (m != nullAngle) { if (increase) Angle += m; @@ -266,12 +266,12 @@ void DBot::Dofire (ticcmd_t *cmd) Angle -= m; } - if (absangle(Angle, player->mo->Angles.Yaw) < 4.) + if (absangle(Angle, player->mo->Angles.Yaw) < DAngle::fromDeg(4.)) { increase = !increase; } - if (Check_LOS (enemy, (SHOOTFOV/2))) + if (Check_LOS (enemy, DAngle::fromDeg(SHOOTFOV/2))) no_fire = false; } if (!no_fire) //If going to fire weapon @@ -328,7 +328,7 @@ void FCajunMaster::BotTick(AActor *mo) { if (!players[i].Bot->missile && (mo->flags3 & MF3_WARNBOT)) { //warn for incoming missiles. - if (mo->target != players[i].mo && players[i].Bot->Check_LOS(mo, 90.)) + if (mo->target != players[i].mo && players[i].Bot->Check_LOS(mo, DAngle::fromDeg(90.))) players[i].Bot->missile = mo; } } @@ -425,9 +425,9 @@ AActor *DBot::Find_enemy () //Note: It's hard to ambush a bot who is not alone if (allround || mate) - vangle = 360.; + vangle = DAngle::fromDeg(360.); else - vangle = ENEMY_SCAN_FOV; + vangle = DAngle::fromDeg(ENEMY_SCAN_FOV); allround = false; target = NULL; @@ -537,7 +537,7 @@ DAngle DBot::FireRox (AActor *enemy, ticcmd_t *cmd) dist = actor->Distance2D (enemy); if (dist < SAFE_SELF_MISDIST) - return 0.; + return nullAngle; //Predict. m = ((dist+1) / GetDefaultByName("Rocket")->Speed); @@ -563,7 +563,7 @@ DAngle DBot::FireRox (AActor *enemy, ticcmd_t *cmd) return player->mo->AngleTo(enemy); } } - return 0.; + return nullAngle; } // [RH] We absolutely do not want to pick things up here. The bot code is diff --git a/src/playsim/bots/b_move.cpp b/src/playsim/bots/b_move.cpp index a22867af1..4d91839d8 100644 --- a/src/playsim/bots/b_move.cpp +++ b/src/playsim/bots/b_move.cpp @@ -77,9 +77,9 @@ void DBot::Roam (ticcmd_t *cmd) int delta = angle - (player->mo->movedir << 29); if (delta > 0) - Angle -= 45; + Angle -= DAngle::fromDeg(45); else if (delta < 0) - Angle += 45; + Angle += DAngle::fromDeg(45); } // chase towards destination. @@ -357,18 +357,18 @@ void DBot::TurnToAng () if(enemy) if(!dest) //happens when running after item in combat situations, or normal, prevents weak turns if(GetBotInfo(player->ReadyWeapon).projectileType == NULL && GetBotInfo(player->ReadyWeapon).MoveCombatDist > 0) - if(Check_LOS(enemy, SHOOTFOV+5)) + if(Check_LOS(enemy, DAngle::fromDeg(SHOOTFOV+5))) maxturn = 3; } DAngle distance = deltaangle(player->mo->Angles.Yaw, Angle); - if (fabs (distance) < OKAYRANGE && !enemy) + if (fabs (distance) < DAngle::fromDeg(OKAYRANGE) && !enemy) return; distance /= TURNSENS; - if (fabs (distance) > maxturn) - distance = distance < 0 ? -maxturn : maxturn; + if (fabs (distance) > DAngle::fromDeg(maxturn)) + distance = DAngle::fromDeg(distance < nullAngle ? -maxturn : maxturn); player->mo->Angles.Yaw += distance; } @@ -380,7 +380,7 @@ void DBot::Pitch (AActor *target) diff = target->Z() - player->mo->Z(); aim = g_atan(diff / player->mo->Distance2D(target)); - player->mo->Angles.Pitch = DAngle::ToDegrees(aim); + player->mo->Angles.Pitch = DAngle::fromRad(aim); } //Checks if a sector is dangerous. diff --git a/src/playsim/bots/b_think.cpp b/src/playsim/bots/b_think.cpp index 0d9f26647..12c7d4113 100644 --- a/src/playsim/bots/b_think.cpp +++ b/src/playsim/bots/b_think.cpp @@ -78,13 +78,13 @@ void DBot::Think () ThinkForMove (cmd); TurnToAng (); - cmd->ucmd.yaw = (short)((actor->Angles.Yaw - oldyaw).Degrees * (65536 / 360.f)) / ticdup; - cmd->ucmd.pitch = (short)((oldpitch - actor->Angles.Pitch).Degrees * (65536 / 360.f)); + cmd->ucmd.yaw = (short)((actor->Angles.Yaw - oldyaw).Degrees() * (65536 / 360.f)) / ticdup; + cmd->ucmd.pitch = (short)((oldpitch - actor->Angles.Pitch).Degrees() * (65536 / 360.f)); if (cmd->ucmd.pitch == -32768) cmd->ucmd.pitch = -32767; cmd->ucmd.pitch /= ticdup; - actor->Angles.Yaw = oldyaw + DAngle(cmd->ucmd.yaw * ticdup * (360 / 65536.f)); - actor->Angles.Pitch = oldpitch - DAngle(cmd->ucmd.pitch * ticdup * (360 / 65536.f)); + actor->Angles.Yaw = oldyaw + DAngle::fromDeg(cmd->ucmd.yaw * ticdup * (360 / 65536.f)); + actor->Angles.Pitch = oldpitch - DAngle::fromDeg(cmd->ucmd.pitch * ticdup * (360 / 65536.f)); } if (t_active) t_active--; @@ -118,7 +118,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd) dist = dest ? player->mo->Distance2D(dest) : 0; if (missile && - (!missile->Vel.X || !missile->Vel.Y || !Check_LOS(missile, SHOOTFOV*3/2))) + (!missile->Vel.X || !missile->Vel.Y || !Check_LOS(missile, DAngle::fromDeg(SHOOTFOV*3/2)))) { sleft = !sleft; missile = nullptr; //Probably ended its travel. @@ -147,7 +147,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd) } //If able to see enemy while avoiding missile, still fire at enemy. - if (enemy && Check_LOS (enemy, SHOOTFOV)) + if (enemy && Check_LOS (enemy, DAngle::fromDeg(SHOOTFOV))) Dofire (cmd); //Order bot to fire current weapon } else if (enemy && P_CheckSight (player->mo, enemy, 0)) //Fight! @@ -259,7 +259,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd) ///// roam: ///// - if (enemy && Check_LOS (enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it. + if (enemy && Check_LOS (enemy, DAngle::fromDeg(SHOOTFOV*3/2))) //If able to see enemy while avoiding missile , still fire at it. Dofire (cmd); //Order bot to fire current weapon if (dest && !(dest->flags&MF_SPECIAL) && dest->health < 0) diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index 3dc3acc16..4ee4cfeb7 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -122,6 +122,9 @@ typedef enum CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use 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_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. @@ -161,7 +164,7 @@ class FPlayerClass { public: FPlayerClass (); - FPlayerClass (const FPlayerClass &other); + FPlayerClass (const FPlayerClass &other) = default; ~FPlayerClass (); bool CheckSkin (int skin); @@ -224,6 +227,10 @@ struct userinfo_t : TMap { return *static_cast(*CheckKey(NAME_MoveBob)); } + bool GetFViewBob() const + { + return *static_cast(*CheckKey(NAME_FViewBob)); + } double GetStillBob() const { return *static_cast(*CheckKey(NAME_StillBob)); @@ -340,7 +347,7 @@ public: AActor *ReadyWeapon = nullptr; AActor *PendingWeapon = nullptr; // WP_NOCHANGE if not changing - TObjPtr psprites = nullptr; // view sprites (gun, etc) + TObjPtr psprites = MakeObjPtr(nullptr); // view sprites (gun, etc) int cheats = 0; // bit flags int timefreezer = 0; // Player has an active time freezer @@ -355,8 +362,8 @@ public: int poisoncount = 0; // screen flash for poison damage FName poisontype = NAME_None; // type of poison damage to apply FName poisonpaintype = NAME_None; // type of Pain state to enter for poison damage - TObjPtr poisoner = nullptr; // NULL for non-player actors - TObjPtr attacker = nullptr; // who did damage (NULL for floors) + TObjPtr poisoner = MakeObjPtr(nullptr); // NULL for non-player actors + TObjPtr attacker = MakeObjPtr(nullptr); // who did damage (NULL for floors) int extralight = 0; // so gun flashes light up areas short fixedcolormap = 0; // can be set to REDCOLORMAP, etc. short fixedlightlevel = 0; @@ -364,19 +371,19 @@ public: PClassActor *MorphedPlayerClass = nullptr; // [MH] (for SBARINFO) class # for this player instance when morphed int MorphStyle = 0; // which effects to apply for this player instance when morphed PClassActor *MorphExitFlash = nullptr; // flash to apply when demorphing (cache of value given to MorphPlayer) - TObjPtr PremorphWeapon = nullptr; // ready weapon before morphing + TObjPtr PremorphWeapon = MakeObjPtr(nullptr); // ready weapon before morphing 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 int respawn_time = 0; // [RH] delay respawning until this tic - TObjPtr camera = nullptr; // [RH] Whose eyes this player sees through + TObjPtr camera = MakeObjPtr(nullptr); // [RH] Whose eyes this player sees through int air_finished = 0; // [RH] Time when you start drowning FName LastDamageType = NAME_None; // [RH] For damage-specific pain and death sounds - TObjPtr MUSINFOactor = nullptr; // For MUSINFO purposes + TObjPtr MUSINFOactor = MakeObjPtr(nullptr); // For MUSINFO purposes int8_t MUSINFOtics = 0; bool settings_controller = false; // Player can control game settings. @@ -384,7 +391,7 @@ public: int8_t crouchdir = 0; //Added by MC: - TObjPtr Bot = nullptr; + TObjPtr Bot = MakeObjPtr(nullptr); float BlendR = 0; // [RH] Final blending values float BlendG = 0; @@ -396,8 +403,8 @@ public: FString SubtitleText; int SubtitleCounter; - DAngle MinPitch = 0.; // Viewpitch limits (negative is up, positive is down) - DAngle MaxPitch = 0.; + DAngle MinPitch = nullAngle; // Viewpitch limits (negative is up, positive is down) + DAngle MaxPitch = nullAngle; double crouchfactor = 0; double crouchoffset = 0; @@ -406,8 +413,8 @@ public: FWeaponSlots weapons; // [CW] I moved these here for multiplayer conversation support. - TObjPtr ConversationNPC = nullptr, ConversationPC = nullptr; - DAngle ConversationNPCAngle = 0.; + TObjPtr ConversationNPC = MakeObjPtr(nullptr), ConversationPC = MakeObjPtr(nullptr); + DAngle ConversationNPCAngle = nullAngle; bool ConversationFaceTalker = false; double GetDeltaViewHeight() const @@ -448,6 +455,10 @@ public: void SetFOV(float fov); bool HasWeaponsInSlot(int slot) const; bool Resurrect(); + + // Scaled angle adjustment info. Not for direct manipulation. + DRotator angleTargets; + DRotator angleAppliedAmounts; }; // Bookkeeping on players - state. @@ -480,4 +491,6 @@ inline bool AActor::IsNoClip2() const bool P_IsPlayerTotallyFrozen(const player_t *player); +bool P_NoInterpolation(player_t const *player, AActor const *actor); + #endif // __D_PLAYER_H__ diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index cabdf8668..86ef7918c 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -111,7 +111,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level) bool dolights; if ((gl_lights && vid_rendermode == 4) || (r_dynlights && vid_rendermode != 4)) { - dolights = Level->lights || (Level->flags3 & LEVEL3_LIGHTCREATED); + dolights = true;// Level->lights || (Level->flags3 & LEVEL3_LIGHTCREATED); } else { @@ -247,7 +247,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level) Printf(TEXTCOLOR_YELLOW "Total, ms Averg, ms Calls Actor class\n"); Printf(TEXTCOLOR_YELLOW "---------- ---------- ------ --------------------\n"); - const unsigned count = MIN(profilelimit > 0 ? profilelimit : UINT_MAX, sorted.Size()); + const unsigned count = min(profilelimit > 0 ? profilelimit : UINT_MAX, sorted.Size()); for (unsigned i = 0; i < count; ++i) { @@ -271,7 +271,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level) // //========================================================================== -void FThinkerCollection::DestroyAllThinkers() +void FThinkerCollection::DestroyAllThinkers(bool fullgc) { int i; bool error = false; @@ -285,11 +285,12 @@ void FThinkerCollection::DestroyAllThinkers() } } error |= Thinkers[MAX_STATNUM + 1].DoDestroyThinkers(); - GC::FullGC(); + if (fullgc) GC::FullGC(); if (error) { ClearGlobalVMStack(); - I_Error("DestroyAllThinkers failed"); + if (fullgc) I_Error("DestroyAllThinkers failed"); + else I_FatalError("DestroyAllThinkers failed"); } } @@ -537,7 +538,7 @@ bool FThinkerList::DoDestroyThinkers() { Printf("VM exception in DestroyThinkers:\n"); exception.MaybePrintMessage(); - Printf("%s", exception.stacktrace.GetChars()); + Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", exception.stacktrace.GetChars()); // forcibly delete this. Cleanup may be incomplete, though. node->ObjectFlags |= OF_YesReallyDelete; delete node; @@ -545,7 +546,7 @@ bool FThinkerList::DoDestroyThinkers() } catch (CRecoverableError &exception) { - Printf("Error in DestroyThinkers: %s\n", exception.GetMessage()); + Printf(PRINT_NONOTIFY | PRINT_BOLD, "Error in DestroyThinkers: %s\n", exception.GetMessage()); // forcibly delete this. Cleanup may be incomplete, though. node->ObjectFlags |= OF_YesReallyDelete; delete node; @@ -616,7 +617,6 @@ int FThinkerList::TickThinkers(FThinkerList *dest) ThinkCount++; node->CallTick(); node->ObjectFlags &= ~OF_JustSpawned; - GC::CheckGC(); } node = NextToThink; } @@ -667,7 +667,6 @@ int FThinkerList::ProfileThinkers(FThinkerList *dest) node->CallTick(); prof.timer.Unclock(); node->ObjectFlags &= ~OF_JustSpawned; - GC::CheckGC(); } node = NextToThink; } diff --git a/src/playsim/dthinker.h b/src/playsim/dthinker.h index 680afbc9a..78dcd1520 100644 --- a/src/playsim/dthinker.h +++ b/src/playsim/dthinker.h @@ -79,7 +79,7 @@ struct FThinkerCollection } void RunThinkers(FLevelLocals *Level); // The level is needed to tick the lights - void DestroyAllThinkers(); + void DestroyAllThinkers(bool fullgc = true); void SerializeThinkers(FSerializer &arc, bool keepPlayers); void MarkRoots(); DThinker *FirstThinker(int statnum); diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index e0d85cfab..549c330ae 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -34,7 +34,7 @@ //--------------------------------------------------------------------------- // -#include "templates.h" + #include "p_local.h" #include "t_script.h" #include "sbar.h" @@ -349,7 +349,7 @@ static FSoundID T_FindSound(const char * name) char buffer[40]; FSoundID so=S_FindSound(name); - if (so>0) return so; + if (so.isvalid()) return so; // Now it gets dirty! @@ -364,9 +364,9 @@ static FSoundID T_FindSound(const char * name) if (fileSystem.CheckNumForName(buffer, ns_sounds)<0) mysnprintf(buffer, countof(buffer), "DS%.35s", name); } - int id = S_AddSound(name, buffer); + FSoundID id = S_AddSound(name, buffer); soundEngine->HashSounds(); - return FSoundID(id); + return id; } @@ -827,7 +827,7 @@ void FParser::SF_Spawn(void) { DVector3 pos; PClassActor *pclass; - DAngle angle = 0.; + DAngle angle = nullAngle; if (CheckArgs(3)) { @@ -853,7 +853,7 @@ void FParser::SF_Spawn(void) if(t_argc >= 4) { - angle = floatvalue(t_argv[3]); + angle = DAngle::fromDeg(floatvalue(t_argv[3])); } t_return.type = svt_mobj; @@ -1013,7 +1013,7 @@ void FParser::SF_ObjAngle(void) mo = Script->trigger; } - t_return.setDouble(mo ? mo->Angles.Yaw.Degrees : 0.); + t_return.setDouble(mo ? mo->Angles.Yaw.Degrees() : 0.); } @@ -1217,7 +1217,7 @@ void FParser::SF_PushThing(void) AActor * mo = actorvalue(t_argv[0]); if(!mo) return; - DAngle angle = floatvalue(t_argv[1]); + DAngle angle = DAngle::fromDeg(floatvalue(t_argv[1])); double force = floatvalue(t_argv[2]); mo->Thrust(angle, force); } @@ -1273,7 +1273,7 @@ void FParser::SF_MobjTarget(void) } t_return.type = svt_mobj; - t_return.value.mobj = mo ? mo->target : NULL; + t_return.value.mobj = mo ? mo->target.Get() : nullptr; } } @@ -1364,7 +1364,7 @@ void FParser::SF_PointToAngle(void) double x2 = floatvalue(t_argv[2]); double y2 = floatvalue(t_argv[3]); - t_return.setDouble(DVector2(x2 - x1, y2 - y1).Angle().Normalized360().Degrees); + t_return.setDouble(DVector2(x2 - x1, y2 - y1).Angle().Normalized360().Degrees()); } } @@ -1415,15 +1415,15 @@ void FParser::SF_SetCamera(void) return; // nullptr check } - angle = t_argc < 2 ? newcamera->Angles.Yaw : floatvalue(t_argv[1]); + angle = t_argc < 2 ? newcamera->Angles.Yaw : DAngle::fromDeg(floatvalue(t_argv[1])); - newcamera->specialf1 = newcamera->Angles.Yaw.Degrees; + newcamera->specialf1 = newcamera->Angles.Yaw.Degrees(); newcamera->specialf2 = newcamera->Z(); double z = t_argc < 3 ? newcamera->Sector->floorplane.ZatPoint(newcamera) + 41 : floatvalue(t_argv[2]); newcamera->SetOrigin(newcamera->PosAtZ(z), false); newcamera->Angles.Yaw = angle; - if (t_argc < 4) newcamera->Angles.Pitch = 0.; - else newcamera->Angles.Pitch = clamp(floatvalue(t_argv[3]), -50., 50.) * (20. / 32.); + if (t_argc < 4) newcamera->Angles.Pitch = nullAngle; + else newcamera->Angles.Pitch = DAngle::fromDeg(clamp(floatvalue(t_argv[3]), -50., 50.) * (20. / 32.)); player->camera=newcamera; newcamera->renderflags |= RF_NOINTERPOLATEVIEW; } @@ -1445,7 +1445,7 @@ void FParser::SF_ClearCamera(void) if (cam) { player->camera=player->mo; - cam->Angles.Yaw = cam->specialf1; + cam->Angles.Yaw = DAngle::fromDeg(cam->specialf1); cam->SetZ(cam->specialf2); } @@ -2732,14 +2732,14 @@ void FParser::SF_MoveCamera(void) } else finishedmove = true; - DAngle targetangle = DAngle(floatvalue(t_argv[4])).Normalized360(); + DAngle targetangle = DAngle::fromDeg(floatvalue(t_argv[4])).Normalized360(); if (cam->Angles.Yaw != targetangle) { - DAngle anglespeed = floatvalue(t_argv[5]); + DAngle anglespeed = DAngle::fromDeg(floatvalue(t_argv[5])); DAngle anglenow = targetangle; const DAngle diffangle = deltaangle(cam->Angles.Yaw, targetangle); - if (movespeed > 0 && anglespeed == 0.) + if (movespeed > 0 && anglespeed == nullAngle) { if (!finishedmove) { @@ -2749,7 +2749,7 @@ void FParser::SF_MoveCamera(void) } else { - if (diffangle > 0) + if (diffangle > nullAngle) { anglenow = (cam->Angles.Yaw + anglespeed).Normalized360(); } @@ -2758,7 +2758,7 @@ void FParser::SF_MoveCamera(void) anglenow = (cam->Angles.Yaw - anglespeed).Normalized360(); } const DAngle diffangle2 = deltaangle(anglenow, targetangle); - if (diffangle.Degrees * diffangle2.Degrees <= 0) + if (diffangle.Degrees() * diffangle2.Degrees() <= 0) { anglenow = targetangle; finishedangle = true; @@ -2912,7 +2912,7 @@ void FParser::SF_SpawnExplosion() { spawn->ClearCounters(); t_return.value.i = spawn->SetState(spawn->FindState(NAME_Death)); - if(spawn->DeathSound) S_Sound (spawn, CHAN_BODY, 0, spawn->DeathSound, 1, ATTN_NORM); + if(spawn->DeathSound.isvalid()) S_Sound (spawn, CHAN_BODY, 0, spawn->DeathSound, 1, ATTN_NORM); } } } @@ -3307,7 +3307,7 @@ void FParser::SF_LineAttack() mo = actorvalue(t_argv[0]); damage = intvalue(t_argv[2]); - angle = floatvalue(t_argv[1]); + angle = DAngle::fromDeg(floatvalue(t_argv[1])); slope = P_AimLineAttack(mo, angle, MISSILERANGE); P_LineAttack(mo, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); diff --git a/src/playsim/fragglescript/t_load.cpp b/src/playsim/fragglescript/t_load.cpp index dd7ddd815..efd27a070 100644 --- a/src/playsim/fragglescript/t_load.cpp +++ b/src/playsim/fragglescript/t_load.cpp @@ -315,6 +315,6 @@ void T_AddSpawnedThing(FLevelLocals *Level, AActor * ac) if (Level->FraggleScriptThinker) { auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings; - SpawnedThings.Push(GC::ReadBarrier(ac)); + SpawnedThings.Push(MakeObjPtr(ac)); } } diff --git a/src/playsim/fragglescript/t_script.h b/src/playsim/fragglescript/t_script.h index fbe88db9a..94770645b 100644 --- a/src/playsim/fragglescript/t_script.h +++ b/src/playsim/fragglescript/t_script.h @@ -101,12 +101,7 @@ struct svalue_t value.i = 0; } - svalue_t(const svalue_t & other) - { - type = other.type; - string = other.string; - value = other.value; - } + svalue_t(const svalue_t & other) = default; void setInt(int ip) { diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 27dc1cf0e..330738494 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -40,6 +40,8 @@ #include "r_data/r_interpolate.h" #include "g_levellocals.h" #include "vm.h" +#include "r_utility.h" +#include "actorinlines.h" //========================================================================== // @@ -661,6 +663,8 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d // 1. Find 2-sided line with same sector side[0] (lowest numbered) // 2. Other side is the next sector to raise // 3. Unless already moving, or different texture, then stop building + validcount++; + sec->validcount = validcount; do { ok = 0; @@ -668,12 +672,13 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d if (usespecials & DFloor::stairUseSpecials) { // [RH] Find the next sector by scanning for Stairs_Special? - tsec = sec->NextSpecialSector ( + tsec = P_NextSpecialSectorVC(sec, sec->special == Stairs_Special1 ? - Stairs_Special2 : Stairs_Special1, prev); + Stairs_Special2 : Stairs_Special1); - if ( (ok = (tsec != NULL)) ) + if ( (ok = (tsec != nullptr)) ) { + tsec->validcount = validcount; height += stairstep; // if sector's floor already moving, look for another @@ -806,13 +811,12 @@ 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 (s2->PlaneMoving(sector_t::floor)) + if (!(compatflags2 & COMPATF2_FLOORMOVE) && s2->PlaneMoving(sector_t::floor)) continue; for (auto ln : s2->Lines) { - if (!(ln->flags & ML_TWOSIDED) || - (ln->backsector == s1)) + if (ln->backsector == nullptr || ln->backsector == s1) continue; s3 = ln->backsector; diff --git a/src/playsim/mapthinkers/a_lightning.cpp b/src/playsim/mapthinkers/a_lightning.cpp index 9f2504f09..854e26212 100644 --- a/src/playsim/mapthinkers/a_lightning.cpp +++ b/src/playsim/mapthinkers/a_lightning.cpp @@ -26,7 +26,7 @@ #include "doomstat.h" #include "p_lnspec.h" #include "m_random.h" -#include "templates.h" + #include "s_sound.h" #include "p_acs.h" #include "r_sky.h" @@ -157,11 +157,11 @@ void DLightningThinker::LightningFlash () LightningLightLevels[j] = tempSec->lightlevel; if (special == Light_IndoorLightning1) { - tempSec->SetLightLevel(MIN (tempSec->lightlevel+64, flashLight)); + tempSec->SetLightLevel(min (tempSec->lightlevel+64, flashLight)); } else if (special == Light_IndoorLightning2) { - tempSec->SetLightLevel(MIN (tempSec->lightlevel+32, flashLight)); + tempSec->SetLightLevel(min (tempSec->lightlevel+32, flashLight)); } else { diff --git a/src/playsim/mapthinkers/a_lights.cpp b/src/playsim/mapthinkers/a_lights.cpp index 68c417446..9cd7fb20f 100644 --- a/src/playsim/mapthinkers/a_lights.cpp +++ b/src/playsim/mapthinkers/a_lights.cpp @@ -26,7 +26,7 @@ //----------------------------------------------------------------------------- -#include "templates.h" + #include "m_random.h" #include "doomdef.h" @@ -521,7 +521,7 @@ int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev else l = Level->CreateThinker (sector, baselevel); - int numsteps = PhaseHelper (sector->NextSpecialSector ( + int numsteps = PhaseHelper (P_NextSpecialSector (sector, sector->special == LightSequenceSpecial1 ? LightSequenceSpecial2 : LightSequenceSpecial1, prev), index + 1, l->m_BaseLevel, sector); diff --git a/src/playsim/mapthinkers/a_pusher.cpp b/src/playsim/mapthinkers/a_pusher.cpp index 588ce338c..eefb427a1 100644 --- a/src/playsim/mapthinkers/a_pusher.cpp +++ b/src/playsim/mapthinkers/a_pusher.cpp @@ -232,7 +232,7 @@ void DPusher::Tick () if ((speed > 0) && (P_CheckSight (thing, m_Source, SF_IGNOREVISIBILITY))) { DAngle pushangle = pos.Angle(); - if (m_Source->GetClass()->TypeName == NAME_PointPuller) pushangle += 180; + if (m_Source->IsKindOf(NAME_PointPuller)) pushangle += DAngle::fromDeg(180); thing->Thrust(pushangle, speed); } } diff --git a/src/playsim/mapthinkers/a_pusher.h b/src/playsim/mapthinkers/a_pusher.h index c3cf30efa..36c9cfab6 100644 --- a/src/playsim/mapthinkers/a_pusher.h +++ b/src/playsim/mapthinkers/a_pusher.h @@ -26,7 +26,7 @@ public: int CheckForSectorMatch (EPusher type, int tag); void ChangeValues (int magnitude, int angle) { - DAngle ang = angle * (360. / 256.); + DAngle ang = DAngle::fromDeg(angle * (360. / 256.)); m_PushVec = ang.ToVector(magnitude); m_Magnitude = magnitude; } diff --git a/src/playsim/mapthinkers/a_quake.cpp b/src/playsim/mapthinkers/a_quake.cpp index b906665e8..35e979a49 100644 --- a/src/playsim/mapthinkers/a_quake.cpp +++ b/src/playsim/mapthinkers/a_quake.cpp @@ -22,7 +22,7 @@ // Hexen's earthquake system, significantly enhanced // -#include "templates.h" + #include "doomtype.h" #include "doomstat.h" #include "p_local.h" @@ -48,7 +48,7 @@ IMPLEMENT_POINTERS_END // //========================================================================== -void DEarthquake::Construct(AActor *center, int intensityX, int intensityY, int intensityZ, int duration, +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) @@ -121,25 +121,28 @@ void DEarthquake::Tick () if (m_DamageRadius > 0) { - for (i = 0; i < MAXPLAYERS; i++) + if (m_Flags & QF_AFFECTACTORS) { - if (Level->PlayerInGame(i) && !(Level->Players[i]->cheats & CF_NOCLIP)) - { - AActor *victim = Level->Players[i]->mo; - double dist; + auto iterator = m_Spot->Level->GetThinkerIterator(); + AActor* mo = nullptr; - dist = m_Spot->Distance2D(victim, true); - // Check if in damage radius - if (dist < m_DamageRadius && victim->Z() <= victim->floorz) + while ((mo = iterator.Next()) != NULL) + { + if (mo == m_Spot) //Ignore the earthquake origin. + continue; + + + DoQuakeDamage(this, mo); + } + } + else + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (Level->PlayerInGame(i) && !(Level->Players[i]->cheats & CF_NOCLIP)) { - if (pr_quake() < 50) - { - P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_Quake); - } - // Thrust player around - DAngle an = victim->Angles.Yaw + pr_quake(); - victim->Vel.X += m_Intensity.X * an.Cos() * 0.5; - victim->Vel.Y += m_Intensity.Y * an.Sin() * 0.5; + AActor* victim = Level->Players[i]->mo; + DoQuakeDamage(this, victim); } } } @@ -157,6 +160,39 @@ void DEarthquake::Tick () } } +//========================================================================== +// +// DEarthquake :: DoQuakeDamage +// +// Handles performing earthquake damage and thrust to the specified victim. +// +//========================================================================== + +void DEarthquake::DoQuakeDamage(DEarthquake *quake, AActor *victim) const +{ + double dist; + + if (!quake || !victim) return; + + dist = quake->m_Spot->Distance2D(victim, true); + // 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); + } + // Thrust player or thrustable actor around + if (victim->player || !(victim->flags7 & MF7_DONTTHRUST)) + { + 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; + } + } + return; +} + //========================================================================== // // DEarthquake :: GetModWave @@ -210,8 +246,8 @@ double DEarthquake::GetModIntensity(double intensity, bool fake) const { // Defaults to middle of the road. divider = m_CountdownStart; - scalar = (m_Flags & QF_MAX) ? MAX(m_Countdown, m_CountdownStart - m_Countdown) - : MIN(m_Countdown, m_CountdownStart - m_Countdown); + scalar = (m_Flags & QF_MAX) ? max(m_Countdown, m_CountdownStart - m_Countdown) + : min(m_Countdown, m_CountdownStart - m_Countdown); } scalar = (scalar > divider) ? divider : scalar; @@ -295,9 +331,13 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak while ( (quake = iterator.Next()) != nullptr) { - if (quake->m_Spot != nullptr) + if (quake->m_Spot != nullptr && !(quake->m_Flags & QF_GROUNDONLY && victim->Z() > victim->floorz)) { - const double dist = quake->m_Spot->Distance2D(victim, true); + double dist; + + if (quake->m_Flags & QF_3D) dist = quake->m_Spot->Distance3D(victim, true); + else dist = quake->m_Spot->Distance2D(victim, true); + if (dist < quake->m_TremorRadius) { ++count; @@ -311,20 +351,20 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak if (!(quake->m_Flags & QF_WAVE)) { - jiggers.RollIntensity = MAX(r, jiggers.RollIntensity) * falloff; + jiggers.RollIntensity = max(r, jiggers.RollIntensity) * falloff; intensity *= falloff; if (quake->m_Flags & QF_RELATIVE) { - jiggers.RelIntensity.X = MAX(intensity.X, jiggers.RelIntensity.X); - jiggers.RelIntensity.Y = MAX(intensity.Y, jiggers.RelIntensity.Y); - jiggers.RelIntensity.Z = MAX(intensity.Z, jiggers.RelIntensity.Z); + jiggers.RelIntensity.X = max(intensity.X, jiggers.RelIntensity.X); + jiggers.RelIntensity.Y = max(intensity.Y, jiggers.RelIntensity.Y); + jiggers.RelIntensity.Z = max(intensity.Z, jiggers.RelIntensity.Z); } else { - jiggers.Intensity.X = MAX(intensity.X, jiggers.Intensity.X); - jiggers.Intensity.Y = MAX(intensity.Y, jiggers.Intensity.Y); - jiggers.Intensity.Z = MAX(intensity.Z, jiggers.Intensity.Z); + jiggers.Intensity.X = max(intensity.X, jiggers.Intensity.X); + jiggers.Intensity.Y = max(intensity.Y, jiggers.Intensity.Y); + jiggers.Intensity.Z = max(intensity.Z, jiggers.Intensity.Z); } } else @@ -368,7 +408,7 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak // //========================================================================== -bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, +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) @@ -376,9 +416,9 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, int intens AActor *center; bool res = false; - if (intensityX) intensityX = clamp(intensityX, 1, 9); - if (intensityY) intensityY = clamp(intensityY, 1, 9); - if (intensityZ) intensityZ = clamp(intensityZ, 1, 9); + intensityX = clamp(intensityX, 0.0, 9.0); + intensityY = clamp(intensityY, 0.0, 9.0); + intensityZ = clamp(intensityZ, 0.0, 9.0); if (tid == 0) { @@ -403,7 +443,7 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, int intens return res; } -bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) +bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, int damrad, int 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); } diff --git a/src/playsim/mapthinkers/a_scroll.cpp b/src/playsim/mapthinkers/a_scroll.cpp index 6e5ba7ad0..e0a561ad8 100644 --- a/src/playsim/mapthinkers/a_scroll.cpp +++ b/src/playsim/mapthinkers/a_scroll.cpp @@ -119,7 +119,7 @@ void DScroller::Serialize(FSerializer &arc) static void RotationComp(const sector_t *sec, int which, double dx, double dy, double &tdx, double &tdy) { DAngle an = sec->GetAngle(which); - if (an == 0) + if (an == nullAngle) { tdx = dx; tdy = dy; diff --git a/src/playsim/mapthinkers/dsectoreffect.cpp b/src/playsim/mapthinkers/dsectoreffect.cpp index 25a8826e9..e14f628b4 100644 --- a/src/playsim/mapthinkers/dsectoreffect.cpp +++ b/src/playsim/mapthinkers/dsectoreffect.cpp @@ -319,7 +319,7 @@ EMoveResult sector_t::MoveCeiling(double speed, double dest, int crush, int dire ceilingplane.setD(dest); flag = P_ChangeSector (this, crush, move, 1, false); - if (flag) + if (flag && !(crush >= 0 && !hexencrush && movedest == dest)) { ceilingplane.setD(lastpos); P_ChangeSector (this, crush, -move, 1, true); diff --git a/src/playsim/mapthinkers/dsectoreffect.h b/src/playsim/mapthinkers/dsectoreffect.h index cbaff9efc..362702351 100644 --- a/src/playsim/mapthinkers/dsectoreffect.h +++ b/src/playsim/mapthinkers/dsectoreffect.h @@ -22,7 +22,7 @@ public: class DMover : public DSectorEffect { - DECLARE_ABSTRACT_CLASS (DMover, DSectorEffect) + DECLARE_CLASS (DMover, DSectorEffect) HAS_OBJECT_POINTERS protected: void Construct(sector_t *sector); @@ -39,14 +39,14 @@ protected: class DMovingFloor : public DMover { - DECLARE_ABSTRACT_CLASS (DMovingFloor, DMover) + DECLARE_CLASS (DMovingFloor, DMover) protected: void Construct(sector_t *sector); }; class DMovingCeiling : public DMover { - DECLARE_ABSTRACT_CLASS (DMovingCeiling, DMover) + DECLARE_CLASS (DMovingCeiling, DMover) protected: void Construct(sector_t *sector, bool interpolate = true); }; diff --git a/src/playsim/p_3dfloors.cpp b/src/playsim/p_3dfloors.cpp index ece17634b..dd5a2bb0a 100644 --- a/src/playsim/p_3dfloors.cpp +++ b/src/playsim/p_3dfloors.cpp @@ -35,7 +35,7 @@ ** */ -#include "templates.h" + #include "p_local.h" #include "p_lnspec.h" #include "p_maputl.h" @@ -780,7 +780,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li double low1 = (open.lowfloorthroughportal & 1) ? open.lowfloor : lowestfloor[0]; double low2 = (open.lowfloorthroughportal & 2) ? open.lowfloor : lowestfloor[1]; - open.lowfloor = MIN(low1, low2); + open.lowfloor = min(low1, low2); } } } diff --git a/src/playsim/p_3dmidtex.cpp b/src/playsim/p_3dmidtex.cpp index 5d764d4e0..315ded0c9 100644 --- a/src/playsim/p_3dmidtex.cpp +++ b/src/playsim/p_3dmidtex.cpp @@ -35,7 +35,7 @@ */ -#include "templates.h" + #include "p_3dmidtex.h" #include "p_local.h" #include "p_terrain.h" @@ -244,14 +244,14 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, double *ptextop, do if(line->flags & ML_DONTPEGBOTTOM) { *ptexbot = y_offset + - MAX(line->frontsector->GetPlaneTexZ(sector_t::floor), line->backsector->GetPlaneTexZ(sector_t::floor)); + max(line->frontsector->GetPlaneTexZ(sector_t::floor), line->backsector->GetPlaneTexZ(sector_t::floor)); *ptextop = *ptexbot + textureheight; } else { *ptextop = y_offset + - MIN(line->frontsector->GetPlaneTexZ(sector_t::ceiling), line->backsector->GetPlaneTexZ(sector_t::ceiling)); + min(line->frontsector->GetPlaneTexZ(sector_t::ceiling), line->backsector->GetPlaneTexZ(sector_t::ceiling)); *ptexbot = *ptextop - textureheight; } diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 674aad0f4..ff97c7484 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -535,6 +535,7 @@ PLAYERINFO_PLAYERCLASS, PLAYERINFO_FOV, PLAYERINFO_DESIREDFOV, + PLAYERINFO_FVIEWBOB, }; @@ -615,17 +616,17 @@ inline int DoubleToACS(double val) inline DAngle ACSToAngle(int acsval) { - return acsval * (360. / 65536.); + return DAngle::fromQ16(acsval); } inline int AngleToACS(DAngle ang) { - return ang.BAMs() >> 16; + return ang.Normalized360().Q16(); } inline int PitchToACS(DAngle ang) { - return int(ang.Normalized180().Degrees * (65536. / 360)); + return ang.Normalized180().Q16(); } struct CallReturn @@ -747,7 +748,7 @@ protected: int DoSpawnSpot(int type, int spot, int tid, int angle, bool forced); int DoSpawnSpotFacing(int type, int spot, int tid, bool forced); int DoClassifyActor(int tid); - int CallFunction(int argCount, int funcIndex, int32_t *args); + int CallFunction(int argCount, int funcIndex, int32_t *args, int &needCount); void DoFadeTo(int r, int g, int b, int a, int time); void DoFadeRange(int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2, int time); @@ -2454,7 +2455,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, // Use unsigned iterator here to avoid issue with GCC 4.9/5.x // optimizer. Might be some undefined behavior in this code, // but I don't know what it is. - unsigned int initsize = MIN (ArrayStore[arraynum].ArraySize, (LittleLong(chunk[1])-4)/4); + unsigned int initsize = min (ArrayStore[arraynum].ArraySize, (LittleLong(chunk[1])-4)/4); int32_t *elems = ArrayStore[arraynum].Elements; for (unsigned int j = 0; j < initsize; ++j) { @@ -2532,7 +2533,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, { int32_t *elems = ArrayStore[arraynum].Elements; // Ending zeros may be left out. - for (int j = MIN(LittleLong(chunk[1])-5, ArrayStore[arraynum].ArraySize); j > 0; --j, ++elems, ++chunkData) + for (int j = min(LittleLong(chunk[1])-5, ArrayStore[arraynum].ArraySize); j > 0; --j, ++elems, ++chunkData) { // For ATAG, a value of 0 = Integer, 1 = String, 2 = FunctionPtr // Our implementation uses the same tags for both String and FunctionPtr @@ -3791,7 +3792,7 @@ int DLevelScript::DoSpawn (int type, const DVector3 &pos, int tid, DAngle angle, int DLevelScript::DoSpawn(int type, int x, int y, int z, int tid, int angle, bool force) { - return DoSpawn(type, DVector3(ACSToDouble(x), ACSToDouble(y), ACSToDouble(z)), tid, angle * (360. / 256), force); + return DoSpawn(type, DVector3(ACSToDouble(x), ACSToDouble(y), ACSToDouble(z)), tid, DAngle::fromDeg(angle * (360. / 256)), force); } @@ -3806,12 +3807,12 @@ int DLevelScript::DoSpawnSpot (int type, int spot, int tid, int angle, bool forc while ( (aspot = iterator.Next ()) ) { - spawned += DoSpawn (type, aspot->Pos(), tid, angle * (360. / 256), force); + spawned += DoSpawn (type, aspot->Pos(), tid, DAngle::fromDeg(angle * (360. / 256)), force); } } else if (activator != NULL) { - spawned += DoSpawn (type, activator->Pos(), tid, angle * (360. / 256), force); + spawned += DoSpawn (type, activator->Pos(), tid, DAngle::fromDeg(angle * (360. / 256)), force); } return spawned; } @@ -3997,54 +3998,56 @@ int DoGetMasterTID (AActor *self) enum { - APROP_Health = 0, - APROP_Speed = 1, - APROP_Damage = 2, - APROP_Alpha = 3, - APROP_RenderStyle = 4, - APROP_SeeSound = 5, // Sounds can only be set, not gotten - APROP_AttackSound = 6, - APROP_PainSound = 7, - APROP_DeathSound = 8, - APROP_ActiveSound = 9, - APROP_Ambush = 10, - APROP_Invulnerable = 11, - APROP_JumpZ = 12, // [GRB] - APROP_ChaseGoal = 13, - APROP_Frightened = 14, - APROP_Gravity = 15, - APROP_Friendly = 16, - APROP_SpawnHealth = 17, - APROP_Dropped = 18, - APROP_Notarget = 19, - APROP_Species = 20, - APROP_NameTag = 21, - APROP_Score = 22, - APROP_Notrigger = 23, - APROP_DamageFactor = 24, - APROP_MasterTID = 25, - APROP_TargetTID = 26, - APROP_TracerTID = 27, - APROP_WaterLevel = 28, - APROP_ScaleX = 29, - APROP_ScaleY = 30, - APROP_Dormant = 31, - APROP_Mass = 32, - APROP_Accuracy = 33, - APROP_Stamina = 34, - APROP_Height = 35, - APROP_Radius = 36, - APROP_ReactionTime = 37, - APROP_MeleeRange = 38, - APROP_ViewHeight = 39, - APROP_AttackZOffset = 40, - APROP_StencilColor = 41, - APROP_Friction = 42, - APROP_DamageMultiplier=43, - APROP_MaxStepHeight = 44, - APROP_MaxDropOffHeight= 45, - APROP_DamageType = 46, - APROP_SoundClass = 47, + APROP_Health = 0, + APROP_Speed = 1, + APROP_Damage = 2, + APROP_Alpha = 3, + APROP_RenderStyle = 4, + APROP_SeeSound = 5, // Sounds can only be set, not gotten + APROP_AttackSound = 6, + APROP_PainSound = 7, + APROP_DeathSound = 8, + APROP_ActiveSound = 9, + APROP_Ambush = 10, + APROP_Invulnerable = 11, + APROP_JumpZ = 12, // [GRB] + APROP_ChaseGoal = 13, + APROP_Frightened = 14, + APROP_Gravity = 15, + APROP_Friendly = 16, + APROP_SpawnHealth = 17, + APROP_Dropped = 18, + APROP_Notarget = 19, + APROP_Species = 20, + APROP_NameTag = 21, + APROP_Score = 22, + APROP_Notrigger = 23, + APROP_DamageFactor = 24, + APROP_MasterTID = 25, + APROP_TargetTID = 26, + APROP_TracerTID = 27, + APROP_WaterLevel = 28, + APROP_ScaleX = 29, + APROP_ScaleY = 30, + APROP_Dormant = 31, + APROP_Mass = 32, + APROP_Accuracy = 33, + APROP_Stamina = 34, + APROP_Height = 35, + APROP_Radius = 36, + APROP_ReactionTime = 37, + APROP_MeleeRange = 38, + APROP_ViewHeight = 39, + APROP_AttackZOffset = 40, + APROP_StencilColor = 41, + APROP_Friction = 42, + APROP_DamageMultiplier = 43, + APROP_MaxStepHeight = 44, + APROP_MaxDropOffHeight = 45, + APROP_DamageType = 46, + APROP_SoundClass = 47, + APROP_FriendlySeeBlocks = 48, + APROP_WaterDepth = 49, }; // These are needed for ACS's APROP_RenderStyle @@ -4199,23 +4202,23 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) break; case APROP_SeeSound: - actor->SeeSound = Level->Behaviors.LookupString(value); + actor->SeeSound = S_FindSound(Level->Behaviors.LookupString(value)); break; case APROP_AttackSound: - actor->AttackSound = Level->Behaviors.LookupString(value); + actor->AttackSound = S_FindSound(Level->Behaviors.LookupString(value)); break; case APROP_PainSound: - actor->PainSound = Level->Behaviors.LookupString(value); + actor->PainSound = S_FindSound(Level->Behaviors.LookupString(value)); break; case APROP_DeathSound: - actor->DeathSound = Level->Behaviors.LookupString(value); + actor->DeathSound = S_FindSound(Level->Behaviors.LookupString(value)); break; case APROP_ActiveSound: - actor->ActiveSound = Level->Behaviors.LookupString(value); + actor->ActiveSound = S_FindSound(Level->Behaviors.LookupString(value)); break; case APROP_Species: @@ -4245,11 +4248,11 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) break; case APROP_ScaleX: - actor->Scale.X = ACSToDouble(value); + actor->Scale.X = (float)ACSToDouble(value); break; case APROP_ScaleY: - actor->Scale.Y = ACSToDouble(value); + actor->Scale.Y = (float)ACSToDouble(value); break; case APROP_Mass: @@ -4317,6 +4320,9 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) } } break; + case APROP_FriendlySeeBlocks: + actor->friendlyseeblocks = value; + break; default: // do nothing. @@ -4416,6 +4422,8 @@ int DLevelScript::GetActorProperty (int tid, int property) case APROP_MaxDropOffHeight: return DoubleToACS(actor->MaxDropOffHeight); case APROP_DamageType: return GlobalACSStrings.AddString(actor->DamageType.GetChars()); case APROP_SoundClass: return GlobalACSStrings.AddString(S_GetSoundClass(actor)); + case APROP_FriendlySeeBlocks: return actor->friendlyseeblocks; + case APROP_WaterDepth: return DoubleToACS(actor->waterdepth); default: return 0; } @@ -4465,6 +4473,8 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_MaxStepHeight: case APROP_MaxDropOffHeight: case APROP_StencilColor: + case APROP_FriendlySeeBlocks: + case APROP_WaterDepth: return (GetActorProperty(tid, property) == value); // Boolean values need to compare to a binary version of value @@ -4649,6 +4659,7 @@ enum SOUND_WallBounce, SOUND_CrushPain, SOUND_Howl, + SOUND_Push, }; static FSoundID GetActorSound(AActor *actor, int soundtype) @@ -4665,7 +4676,8 @@ static FSoundID GetActorSound(AActor *actor, int soundtype) case SOUND_WallBounce: return actor->WallBounceSound; case SOUND_CrushPain: return actor->CrushPainSound; case SOUND_Howl: return actor->SoundVar(NAME_HowlSound); - default: return 0; + case SOUND_Push: return actor->SoundVar(NAME_PushSound); + default: return NO_SOUND; } } @@ -5251,7 +5263,7 @@ int DLevelScript::SwapActorTeleFog(AActor *activator, int tid) } else if (argtype == TypeSound) { - params.Push(int(FSoundID(Level->Behaviors.LookupString(args[i])))); + params.Push(S_FindSound(Level->Behaviors.LookupString(args[i])).index()); } else { @@ -5284,7 +5296,7 @@ int DLevelScript::SwapActorTeleFog(AActor *activator, int tid) } else if (rettype == TypeSound) { - retval = GlobalACSStrings.AddString(S_GetSoundName(FSoundID(retval))); + retval = GlobalACSStrings.AddString(S_GetSoundName(FSoundID::fromInt(retval))); } } else if (rettype == TypeFloat64) @@ -5311,46 +5323,60 @@ int DLevelScript::SwapActorTeleFog(AActor *activator, int tid) return retval; } -int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) +// Macro for CallFunction. Checks passed number of arguments with minimum required. Sets needCount and returns if not enough. +#define MIN_ARG_COUNT(minCount) do { if (argCount < minCount) { needCount = minCount; return 0; } } while(0) + +int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int &needCount) { AActor *actor; switch(funcIndex) { case ACSF_GetLineUDMFInt: + MIN_ARG_COUNT(2); return GetUDMFInt(Level, UDMF_Line, LineFromID(args[0]), Level->Behaviors.LookupString(args[1])); case ACSF_GetLineUDMFFixed: + MIN_ARG_COUNT(2); return DoubleToACS(GetUDMFFloat(Level, UDMF_Line, LineFromID(args[0]), Level->Behaviors.LookupString(args[1]))); case ACSF_GetThingUDMFInt: case ACSF_GetThingUDMFFixed: + MIN_ARG_COUNT(2); return 0; // Not implemented yet case ACSF_GetSectorUDMFInt: + MIN_ARG_COUNT(2); return GetUDMFInt(Level, UDMF_Sector, Level->FindFirstSectorFromTag(args[0]), Level->Behaviors.LookupString(args[1])); case ACSF_GetSectorUDMFFixed: + MIN_ARG_COUNT(2); return DoubleToACS(GetUDMFFloat(Level, UDMF_Sector, Level->FindFirstSectorFromTag(args[0]), Level->Behaviors.LookupString(args[1]))); case ACSF_GetSideUDMFInt: + MIN_ARG_COUNT(3); return GetUDMFInt(Level, UDMF_Side, SideFromID(args[0], args[1]), Level->Behaviors.LookupString(args[2])); case ACSF_GetSideUDMFFixed: + MIN_ARG_COUNT(3); return DoubleToACS(GetUDMFFloat(Level, UDMF_Side, SideFromID(args[0], args[1]), Level->Behaviors.LookupString(args[2]))); case ACSF_GetActorVelX: + MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); return actor != NULL? DoubleToACS(actor->Vel.X) : 0; case ACSF_GetActorVelY: + MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); return actor != NULL? DoubleToACS(actor->Vel.Y) : 0; case ACSF_GetActorVelZ: + MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); return actor != NULL? DoubleToACS(actor->Vel.Z) : 0; case ACSF_SetPointer: + MIN_ARG_COUNT(2); if (activator) { AActor *ptr = Level->SingleActorFromTID(args[1], activator); @@ -5365,6 +5391,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return 0; case ACSF_SetActivator: + MIN_ARG_COUNT(1); if (argCount > 1 && args[1] != AAPTR_DEFAULT) // condition (x != AAPTR_DEFAULT) is essentially condition (x). { activator = COPY_AAPTREX(Level, Level->SingleActorFromTID(args[0], activator), args[1]); @@ -5376,6 +5403,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return activator != NULL; case ACSF_SetActivatorToTarget: + MIN_ARG_COUNT(1); // [KS] I revised this a little bit actor = Level->SingleActorFromTID(args[0], activator); if (actor != NULL) @@ -5399,6 +5427,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return 0; case ACSF_GetActorViewHeight: + MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); if (actor != NULL) { @@ -5414,6 +5443,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) else return 0; case ACSF_GetChar: + MIN_ARG_COUNT(2); { const char *p = Level->Behaviors.LookupString(args[0]); if (p != NULL && args[1] >= 0 && args[1] < int(strlen(p))) @@ -5427,6 +5457,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_GetAirSupply: + MIN_ARG_COUNT(1); { if (args[0] < 0 || args[0] >= MAXPLAYERS || !Level->PlayerInGame(args[0])) { @@ -5439,6 +5470,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SetAirSupply: + MIN_ARG_COUNT(2); { if (args[0] < 0 || args[0] >= MAXPLAYERS || !Level->PlayerInGame(args[0])) { @@ -5452,6 +5484,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SetSkyScrollSpeed: + MIN_ARG_COUNT(2); { if (args[0] == 1) Level->skyspeed1 = ACSToFloat(args[1]); else if (args[0] == 2) Level->skyspeed2 = ACSToFloat(args[1]); @@ -5459,6 +5492,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_GetArmorType: + MIN_ARG_COUNT(2); { if (args[1] < 0 || args[1] >= MAXPLAYERS || !Level->PlayerInGame(args[1])) { @@ -5474,6 +5508,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_GetArmorInfo: + MIN_ARG_COUNT(1); { if (activator == NULL || activator->player == NULL) return 0; @@ -5509,15 +5544,19 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SpawnSpotForced: + MIN_ARG_COUNT(4); return DoSpawnSpot(args[0], args[1], args[2], args[3], true); case ACSF_SpawnSpotFacingForced: + MIN_ARG_COUNT(3); return DoSpawnSpotFacing(args[0], args[1], args[2], true); case ACSF_CheckActorProperty: + MIN_ARG_COUNT(3); return (CheckActorProperty(args[0], args[1], args[2])); case ACSF_SetActorVelocity: + MIN_ARG_COUNT(6); { DVector3 vel(ACSToDouble(args[1]), ACSToDouble(args[2]), ACSToDouble(args[3])); if (args[0] == 0) @@ -5537,6 +5576,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SetUserVariable: + MIN_ARG_COUNT(3); { int cnt = 0; FName varname(Level->Behaviors.LookupString(args[1]), true); @@ -5565,6 +5605,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_GetUserVariable: + MIN_ARG_COUNT(2); { FName varname(Level->Behaviors.LookupString(args[1]), true); if (varname != NAME_None) @@ -5576,6 +5617,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SetUserArray: + MIN_ARG_COUNT(4); { int cnt = 0; FName varname(Level->Behaviors.LookupString(args[1]), true); @@ -5604,6 +5646,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_GetUserArray: + MIN_ARG_COUNT(3); { FName varname(Level->Behaviors.LookupString(args[1]), true); if (varname != NAME_None) @@ -5615,22 +5658,26 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_Radius_Quake2: - P_StartQuake(Level, activator, args[0], args[1], args[2], args[3], args[4], Level->Behaviors.LookupString(args[5])); + MIN_ARG_COUNT(6); + P_StartQuake(Level, activator, args[0], (double)args[1], args[2], args[3], args[4], S_FindSound(Level->Behaviors.LookupString(args[5]))); break; case ACSF_CheckActorClass: + MIN_ARG_COUNT(2); { AActor *a = Level->SingleActorFromTID(args[0], activator); return a == NULL ? false : a->GetClass()->TypeName == FName(Level->Behaviors.LookupString(args[1])); } case ACSF_GetActorClass: + MIN_ARG_COUNT(1); { AActor *a = Level->SingleActorFromTID(args[0], activator); return GlobalACSStrings.AddString(a == NULL ? "None" : a->GetClass()->TypeName.GetChars()); } case ACSF_SoundSequenceOnActor: + MIN_ARG_COUNT(2); { const char *seqname = Level->Behaviors.LookupString(args[1]); if (seqname != NULL) @@ -5657,6 +5704,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) break; case ACSF_SoundSequenceOnSector: + MIN_ARG_COUNT(3); { const char *seqname = Level->Behaviors.LookupString(args[1]); int space = args[2] < CHAN_FLOOR || args[2] > CHAN_INTERIOR ? CHAN_FULLHEIGHT : args[2]; @@ -5673,6 +5721,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) break; case ACSF_SoundSequenceOnPolyobj: + MIN_ARG_COUNT(2); { const char *seqname = Level->Behaviors.LookupString(args[1]); if (seqname != NULL) @@ -5687,6 +5736,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) break; case ACSF_GetPolyobjX: + MIN_ARG_COUNT(1); { FPolyObj *poly = Level->GetPolyobj(args[0]); if (poly != NULL) @@ -5697,6 +5747,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return FIXED_MAX; case ACSF_GetPolyobjY: + MIN_ARG_COUNT(1); { FPolyObj *poly = Level->GetPolyobj(args[0]); if (poly != NULL) @@ -5707,6 +5758,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return FIXED_MAX; case ACSF_CheckSight: + MIN_ARG_COUNT(3); { AActor *source; AActor *dest; @@ -5752,7 +5804,8 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) } case ACSF_SpawnForced: - return DoSpawn(args[0], args[1], args[2], args[3], args[4], args[5], true); + MIN_ARG_COUNT(4); + return DoSpawn(args[0], args[1], args[2], args[3], argCount > 4 ? args[4] : 0, argCount > 5 ? args[5] : 0, true); case ACSF_ACS_NamedExecute: case ACSF_ACS_NamedSuspend: @@ -5761,6 +5814,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) case ACSF_ACS_NamedLockedExecuteDoor: case ACSF_ACS_NamedExecuteWithResult: case ACSF_ACS_NamedExecuteAlways: + MIN_ARG_COUNT(1); { int scriptnum = -FName(Level->Behaviors.LookupString(args[0])).GetIndex(); int arg1 = argCount > 1 ? args[1] : 0; @@ -5777,15 +5831,19 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) return Level->FindUniqueTID(argCount > 0 ? args[0] : 0, (argCount > 1 && args[1] >= 0) ? args[1] : 0); case ACSF_IsTIDUsed: + MIN_ARG_COUNT(1); return Level->IsTIDUsed(args[0]); case ACSF_Sqrt: + MIN_ARG_COUNT(1); return xs_FloorToInt(g_sqrt(double(args[0]))); case ACSF_FixedSqrt: + MIN_ARG_COUNT(1); return DoubleToACS(g_sqrt(ACSToDouble(args[0]))); case ACSF_VectorLength: + MIN_ARG_COUNT(2); return DoubleToACS(DVector2(ACSToDouble(args[0]), ACSToDouble(args[1])).Length()); case ACSF_SetHUDClipRect: @@ -5802,56 +5860,36 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) break; case ACSF_GetCVarString: - if (argCount == 1) - { - return DoGetCVar(GetCVar(activator && activator->player ? int(activator->player - players) : -1, Level->Behaviors.LookupString(args[0])), true); - } - break; + MIN_ARG_COUNT(1); + return DoGetCVar(GetCVar(activator && activator->player ? int(activator->player - players) : -1, Level->Behaviors.LookupString(args[0])), true); case ACSF_SetCVar: - if (argCount == 2) - { - return SetCVar(activator, Level->Behaviors.LookupString(args[0]), args[1], false); - } - break; + MIN_ARG_COUNT(2); + return SetCVar(activator, Level->Behaviors.LookupString(args[0]), args[1], false); case ACSF_SetCVarString: - if (argCount == 2) - { - return SetCVar(activator, Level->Behaviors.LookupString(args[0]), args[1], true); - } - break; + MIN_ARG_COUNT(2); + return SetCVar(activator, Level->Behaviors.LookupString(args[0]), args[1], true); case ACSF_GetUserCVar: - if (argCount == 2) - { - return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), false); - } - break; + MIN_ARG_COUNT(2); + return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), false); case ACSF_GetUserCVarString: - if (argCount == 2) - { - return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), true); - } - break; + MIN_ARG_COUNT(2); + return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), true); case ACSF_SetUserCVar: - if (argCount == 3) - { - return SetUserCVar(args[0], Level->Behaviors.LookupString(args[1]), args[2], false); - } - break; + MIN_ARG_COUNT(3); + return SetUserCVar(args[0], Level->Behaviors.LookupString(args[1]), args[2], false); case ACSF_SetUserCVarString: - if (argCount == 3) - { - return SetUserCVar(args[0], Level->Behaviors.LookupString(args[1]), args[2], true); - } - break; + MIN_ARG_COUNT(3); + return SetUserCVar(args[0], Level->Behaviors.LookupString(args[1]), args[2], true); //[RC] A bullet firing function for ACS. Thanks to DavidPH. case ACSF_LineAttack: + MIN_ARG_COUNT(4); { DAngle angle = ACSToAngle(args[1]); DAngle pitch = ACSToAngle(args[2]); @@ -5894,18 +5932,19 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) case ACSF_PlaySound: case ACSF_PlayActorSound: // PlaySound(tid, "SoundName", channel, volume, looping, attenuation, local) + MIN_ARG_COUNT(2); { - FSoundID sid = 0; + FSoundID sid = NO_SOUND; if (funcIndex == ACSF_PlaySound) { const char *lookup = Level->Behaviors.LookupString(args[1]); if (lookup != NULL) { - sid = lookup; + sid = S_FindSound(lookup); } } - if (sid != 0 || funcIndex == ACSF_PlayActorSound) + if (sid != NO_SOUND || funcIndex == ACSF_PlayActorSound) { auto it = Level->GetActorIterator(args[0]); AActor *spot; @@ -5927,7 +5966,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) { sid = GetActorSound(spot, args[1]); } - if (sid != 0) + if (sid != NO_SOUND) { // What a mess. I think it's a given that this was used with sound flags so it will forever be restricted to the original 8 channels. if (local) chan |= CHANF_LOCAL; @@ -5940,6 +5979,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_StopSound: + MIN_ARG_COUNT(1); { int chan = argCount > 1 ? args[1] : CHAN_BODY; @@ -5962,6 +6002,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_SoundVolume: // SoundVolume(int tid, int channel, fixed volume) + MIN_ARG_COUNT(3); { int chan = args[1]; double volume = ACSToDouble(args[2]); @@ -5985,7 +6026,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_strcmp: case ACSF_stricmp: - if (argCount >= 2) + MIN_ARG_COUNT(2); { const char *a, *b; // If the string indicies are the same, then they are the same string. @@ -6014,7 +6055,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_StrLeft: case ACSF_StrRight: - if (argCount >= 2) + MIN_ARG_COUNT(2); { const char *oldstr = Level->Behaviors.LookupString(args[0]); if (oldstr == NULL || *oldstr == '\0') @@ -6034,7 +6075,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_StrMid: - if (argCount >= 3) + MIN_ARG_COUNT(3); { const char *oldstr = Level->Behaviors.LookupString(args[0]); if (oldstr == NULL || *oldstr == '\0') @@ -6071,6 +6112,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_SpawnDecal: // int SpawnDecal(int tid, str decalname, int flags, fixed angle, int|fixed zoffset, int|fixed distance) // Returns number of decals spawned (not including spreading) + MIN_ARG_COUNT(2); { int count = 0; const FDecalTemplate *tpl = DecalLibrary.GetDecalByName(Level->Behaviors.LookupString(args[1])); @@ -6105,9 +6147,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_CheckFont: // bool CheckFont(str fontname) + MIN_ARG_COUNT(1); return V_GetFont(Level->Behaviors.LookupString(args[0])) != NULL; case ACSF_DropItem: + MIN_ARG_COUNT(2); { const char *type = Level->Behaviors.LookupString(args[1]); int amount = argCount >= 3? args[2] : -1; @@ -6141,6 +6185,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_DropInventory: + MIN_ARG_COUNT(2); { const char *type = Level->Behaviors.LookupString(args[1]); AActor *inv; @@ -6177,6 +6222,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_CheckFlag: + MIN_ARG_COUNT(2); { AActor *actor = Level->SingleActorFromTID(args[0], activator); if (actor != NULL) @@ -6187,8 +6233,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_QuakeEx: + MIN_ARG_COUNT(8); { - return P_StartQuakeXYZ(Level, activator, args[0], args[1], args[2], args[3], args[4], args[5], args[6], Level->Behaviors.LookupString(args[7]), + return P_StartQuakeXYZ(Level, activator, args[0], args[1], args[2], args[3], args[4], args[5], args[6], S_FindSound(Level->Behaviors.LookupString(args[7])), argCount > 8 ? args[8] : 0, argCount > 9 ? ACSToDouble(args[9]) : 1.0, argCount > 10 ? ACSToDouble(args[10]) : 1.0, @@ -6200,19 +6247,22 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_SetLineActivation: - if (argCount >= 2) + MIN_ARG_COUNT(2); { int line; auto itr = Level->GetLineIdIterator(args[0]); + int repeat = argCount > 2 ? args[2] : -1; while ((line = itr.Next()) >= 0) { Level->lines[line].activation = args[1]; + if (repeat > 0) Level->lines[line].flags |= ML_REPEAT_SPECIAL; + else if (repeat == 0) Level->lines[line].flags &= ~ML_REPEAT_SPECIAL; } } break; case ACSF_GetLineActivation: - if (argCount > 0) + MIN_ARG_COUNT(1); { int line = Level->FindFirstLineFromID(args[0]); return line >= 0 ? Level->lines[line].activation : 0; @@ -6220,7 +6270,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_GetActorPowerupTics: - if (argCount >= 2) + MIN_ARG_COUNT(2); { PClassActor *powerupclass = PClass::FindActor(Level->Behaviors.LookupString(args[1])); if (powerupclass == NULL || !powerupclass->IsDescendantOf(NAME_Powerup)) @@ -6241,32 +6291,26 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_ChangeActorAngle: - if (argCount >= 2) - { - SetActorAngle(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); - } + MIN_ARG_COUNT(2); + SetActorAngle(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); break; case ACSF_ChangeActorPitch: - if (argCount >= 2) - { - SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); - } + MIN_ARG_COUNT(2); + SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); break; + case ACSF_SetActorTeleFog: - if (argCount >= 3) - { - SetActorTeleFog(activator, args[0], Level->Behaviors.LookupString(args[1]), Level->Behaviors.LookupString(args[2])); - } + MIN_ARG_COUNT(3); + SetActorTeleFog(activator, args[0], Level->Behaviors.LookupString(args[1]), Level->Behaviors.LookupString(args[2])); break; + case ACSF_SwapActorTeleFog: - if (argCount >= 1) - { - return SwapActorTeleFog(activator, args[0]); - } - break; + MIN_ARG_COUNT(1); + return SwapActorTeleFog(activator, args[0]); + case ACSF_PickActor: - if (argCount >= 5) + MIN_ARG_COUNT(5); { actor = Level->SingleActorFromTID(args[0], activator); if (actor == NULL) @@ -6311,6 +6355,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_IsPointerEqual: + MIN_ARG_COUNT(2); { int tid1 = 0, tid2 = 0; switch (argCount) @@ -6327,7 +6372,8 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_CanRaiseActor: - if (argCount >= 1) { + MIN_ARG_COUNT(1); + { if (args[0] == 0) { actor = Level->SingleActorFromTID(args[0], activator); if (actor != NULL) { @@ -6339,7 +6385,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) bool canraiseall = true; while ((actor = iterator.Next())) { - canraiseall = P_Thing_CanRaise(actor) & canraiseall; + canraiseall &= P_Thing_CanRaise(actor); } return canraiseall; @@ -6348,22 +6394,23 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) // [Nash] Actor roll functions. Let's roll! case ACSF_SetActorRoll: + MIN_ARG_COUNT(2); SetActorRoll(activator, args[0], args[1], false); - return 0; + break; case ACSF_ChangeActorRoll: - if (argCount >= 2) - { - SetActorRoll(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); - } + MIN_ARG_COUNT(2); + SetActorRoll(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); break; case ACSF_GetActorRoll: + MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); return actor != NULL? AngleToACS(actor->Angles.Roll) : 0; // [ZK] A_Warp in ACS case ACSF_Warp: + MIN_ARG_COUNT(6); { if (nullptr == activator) { @@ -6415,6 +6462,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) return true; } case ACSF_GetMaxInventory: + MIN_ARG_COUNT(2); actor = Level->SingleActorFromTID(args[0], activator); if (actor != NULL) { @@ -6423,7 +6471,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_SetSectorDamage: - if (argCount >= 2) + MIN_ARG_COUNT(2); { auto it = Level->GetSectorTagIterator(args[0]); int s; @@ -6440,7 +6488,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_SetSectorTerrain: - if (argCount >= 3) + MIN_ARG_COUNT(3); { if (args[1] == sector_t::floor || args[1] == sector_t::ceiling) { @@ -6456,6 +6504,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_SpawnParticle: + MIN_ARG_COUNT(1); { PalEntry color = args[0]; bool fullbright = argCount > 1 ? !!args[1] : false; @@ -6488,10 +6537,12 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; case ACSF_SetMusicVolume: + MIN_ARG_COUNT(1); Level->SetMusicVolume(ACSToFloat(args[0])); break; case ACSF_CheckProximity: + MIN_ARG_COUNT(3); { // [zombie] ACS version of A_CheckProximity actor = Level->SingleActorFromTID(args[0], activator); @@ -6504,6 +6555,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_CheckActorState: + MIN_ARG_COUNT(2); { actor = Level->SingleActorFromTID(args[0], activator); const char *statename = Level->Behaviors.LookupString(args[1]); @@ -6516,12 +6568,14 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_CheckClass: + MIN_ARG_COUNT(1); { const char *clsname = Level->Behaviors.LookupString(args[0]); return !!PClass::FindActor(clsname); } case ACSF_DamageActor: // [arookas] wrapper around P_DamageMobj + MIN_ARG_COUNT(6); { // (target, ptr_select1, inflictor, ptr_select2, amount, damagetype) AActor* target = COPY_AAPTREX(Level, Level->SingleActorFromTID(args[0], activator), args[1]); @@ -6531,6 +6585,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_SetActorFlag: + MIN_ARG_COUNT(3); { int tid = args[0]; FString flagname = Level->Behaviors.LookupString(args[1]); @@ -6559,6 +6614,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_SetTranslation: + MIN_ARG_COUNT(2); { int tid = args[0]; const char *trname = Level->Behaviors.LookupString(args[1]); @@ -6580,6 +6636,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) // OpenGL exclusive functions case ACSF_SetSectorGlow: + MIN_ARG_COUNT(6); { int which = !!args[1]; PalEntry color(args[2], args[3], args[4]); @@ -6597,6 +6654,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_SetFogDensity: + MIN_ARG_COUNT(2); { auto it = Level->GetSectorTagIterator(args[0]); int s; @@ -6609,6 +6667,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_GetActorFloorTexture: + MIN_ARG_COUNT(1); { auto a = Level->SingleActorFromTID(args[0], activator); if (a != nullptr) @@ -6623,6 +6682,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_GetActorFloorTerrain: + MIN_ARG_COUNT(1); { auto a = Level->SingleActorFromTID(args[0], activator); if (a != nullptr) @@ -6637,25 +6697,32 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_StrArg: + MIN_ARG_COUNT(1); return -FName(Level->Behaviors.LookupString(args[0])).GetIndex(); case ACSF_Floor: + MIN_ARG_COUNT(1); return args[0] & ~0xffff; case ACSF_Ceil: + MIN_ARG_COUNT(1); return (args[0] & ~0xffff) + 0x10000; case ACSF_Round: + MIN_ARG_COUNT(1); return (args[0] + 32768) & ~0xffff; case ACSF_ScriptCall: + MIN_ARG_COUNT(1); return ScriptCall(activator, argCount, args); case ACSF_StartSlideshow: + MIN_ARG_COUNT(1); G_StartSlideshow(Level, FName(Level->Behaviors.LookupString(args[0]))); break; case ACSF_GetSectorHealth: + MIN_ARG_COUNT(2); { int part = args[1]; auto it = Level->GetSectorTagIterator(args[0]); @@ -6683,6 +6750,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_GetLineHealth: + MIN_ARG_COUNT(1); { auto it = Level->GetLineIdIterator(args[0]); int l = it.Next(); @@ -6700,6 +6768,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_GetLineX: case ACSF_GetLineY: + MIN_ARG_COUNT(3); { auto it = Level->GetLineIdIterator(args[0]); int lineno = it.Next(); @@ -6715,22 +6784,20 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } case ACSF_SetSubtitleNumber: - if (argCount >= 2) + MIN_ARG_COUNT(2); + // only players allowed as activator + if (activator != nullptr && activator->player != nullptr) { - // only players allowed as activator - if (activator != nullptr && activator->player != nullptr) + int logNum = args[0]; + FSoundID sid = NO_SOUND; + + const char* lookup = Level->Behaviors.LookupString(args[1]); + if (lookup != nullptr) { - int logNum = args[0]; - FSoundID sid = 0; - - const char* lookup = Level->Behaviors.LookupString(args[1]); - if (lookup != nullptr) - { - sid = lookup; - } - - activator->player->SetSubtitle(logNum, sid); + sid = S_FindSound(lookup); } + + activator->player->SetSubtitle(logNum, sid); } break; @@ -6739,6 +6806,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } return 0; } +#undef MIN_ARG_COUNT enum { @@ -7152,7 +7220,12 @@ int DLevelScript::RunScript() int argCount = NEXTBYTE; int funcIndex = NEXTSHORT; - int retval = CallFunction(argCount, funcIndex, &STACK(argCount)); + int retval, minCount = 0; + retval = CallFunction(argCount, funcIndex, &STACK(argCount), minCount); + if (minCount != 0) + { + Printf("Called ACS function index %d with too few args: %d (need %d)\n", funcIndex, argCount, minCount); + } sp -= argCount-1; STACK(1) = retval; } @@ -8570,7 +8643,7 @@ scriptwait: int capacity, offset, a, c; if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTMAPCHRANGE)) { - while (capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0') + while (capacity-- && (c = activeBehavior->GetArrayVal (*activeBehavior->MapVars[a], offset)) != '\0') { work += (char)c; offset++; @@ -8757,8 +8830,8 @@ scriptwait: (type & HUDMSG_LAYER_MASK) >> HUDMSG_LAYER_SHIFT); if (type & HUDMSG_LOG) { - int consolecolor = color >= CR_BRICK && color <= CR_YELLOW ? color + 'A' : '-'; - Printf(PRINT_NONOTIFY, "\n" TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", consolecolor, console_bar, work.GetChars(), console_bar); + int consolecolor = color >= CR_BRICK && color < NUM_TEXT_COLORS && color != CR_UNTRANSLATED ? color + 'A' : '-'; + Printf(PRINT_HIGH | PRINT_NONOTIFY, "\n" TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", consolecolor, console_bar, work.GetChars(), console_bar); } } } @@ -8860,7 +8933,7 @@ scriptwait: S_Sound ( activationline->frontsector, CHAN_AUTO, 0, // Not CHAN_AREA, because that'd probably break existing scripts. - lookup, + S_FindSound(lookup), (float)(STACK(1)) / 127.f, ATTN_NORM); } @@ -9649,7 +9722,7 @@ scriptwait: break; case PCD_VECTORANGLE: - STACK(2) = AngleToACS(VecToAngle(STACK(2), STACK(1)).Degrees); + STACK(2) = AngleToACS(VecToAngle(STACK(2), STACK(1))); sp--; break; @@ -9750,14 +9823,14 @@ scriptwait: // Like Thing_Projectile(Gravity) specials, but you can give the // projectile a TID. // Thing_Projectile2 (tid, type, angle, speed, vspeed, gravity, newtid); - Level->EV_Thing_Projectile(STACK(7), activator, STACK(6), NULL, STACK(5) * (360. / 256.), + Level->EV_Thing_Projectile(STACK(7), activator, STACK(6), NULL, DAngle::fromDeg(STACK(5) * (360. / 256.)), STACK(4) / 8., STACK(3) / 8., 0, NULL, STACK(2), STACK(1), false); sp -= 7; break; case PCD_SPAWNPROJECTILE: // Same, but takes an actor name instead of a spawn ID. - Level->EV_Thing_Projectile(STACK(7), activator, 0, Level->Behaviors.LookupString(STACK(6)), STACK(5) * (360. / 256.), + Level->EV_Thing_Projectile(STACK(7), activator, 0, Level->Behaviors.LookupString(STACK(6)), DAngle::fromDeg(STACK(5) * (360. / 256.)), STACK(4) / 8., STACK(3) / 8., 0, NULL, STACK(2), STACK(1), false); sp -= 7; break; @@ -9947,6 +10020,7 @@ scriptwait: case PLAYERINFO_PLAYERCLASS: STACK(2) = userinfo->GetPlayerClassNum(); break; case PLAYERINFO_DESIREDFOV: STACK(2) = (int)pl->DesiredFOV; break; case PLAYERINFO_FOV: STACK(2) = (int)pl->FOV; break; + case PLAYERINFO_FVIEWBOB: STACK(2) = (bool)userinfo->GetFViewBob(); break; default: STACK(2) = 0; break; } } @@ -10309,7 +10383,7 @@ DLevelScript::DLevelScript (FLevelLocals *l, AActor *who, line_t *where, int num assert(code->VarCount >= code->ArgCount); Localvars.Resize(code->VarCount); memset(&Localvars[0], 0, code->VarCount * sizeof(int32_t)); - for (int i = 0; i < MIN(argcount, code->ArgCount); ++i) + for (int i = 0; i < min(argcount, code->ArgCount); ++i) { Localvars[i] = args[i]; } diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index af1c07e01..157ef9336 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -69,6 +69,7 @@ #include "sbar.h" #include "actorinlines.h" #include "types.h" +#include "model.h" static FRandom pr_camissile ("CustomActorfire"); static FRandom pr_cabullet ("CustomBullet"); @@ -764,7 +765,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SeekerMissile) { self->tracer = P_RoughMonsterSearch (self, distance, true); } - if (!P_SeekerMissile(self, clamp(ang1, 0, 90), clamp(ang2, 0, 90), !!(flags & SMF_PRECISE), !!(flags & SMF_CURSPEED))) + if (!P_SeekerMissile(self, DAngle::fromDeg(clamp(ang1, 0, 90)), DAngle::fromDeg(clamp(ang2, 0, 90)), !!(flags & SMF_PRECISE), !!(flags & SMF_CURSPEED))) { if (flags & SMF_LOOK) { // This monster is no longer seekable, so let us look for another one next time. @@ -794,7 +795,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack) S_Sound (self, CHAN_WEAPON, 0, self->AttackSound, 1, ATTN_NORM); for (i = self->GetMissileDamage (0, 1); i > 0; --i) { - DAngle angle = self->Angles.Yaw + pr_cabullet.Random2() * (5.625 / 256.); + DAngle angle = self->Angles.Yaw + DAngle::fromDeg(pr_cabullet.Random2() * (5.625 / 256.)); int damage = ((pr_cabullet()%5)+1)*3; P_LineAttack(self, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff); @@ -930,7 +931,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile) { if (ti) { - DAngle angle = self->Angles.Yaw - 90; + DAngle angle = self->Angles.Yaw - DAngle::fromDeg(90.); double x = Spawnofs_xy * angle.Cos(); double y = Spawnofs_xy * angle.Sin(); double z = Spawnheight + self->GetBobOffset() - 32 + (self->player? self->player->crouchoffset : 0.); @@ -1075,7 +1076,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack) A_FaceTarget (self); if (P_CheckMeleeRange(self)) { - if (meleesound) + if (meleesound.isvalid()) S_Sound (self, CHAN_WEAPON, 0, meleesound, 1, ATTN_NORM); int newdam = P_DamageMobj (self->target, self, self, damage, damagetype); if (bleed) @@ -1083,7 +1084,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMeleeAttack) } else { - if (misssound) + if (misssound.isvalid()) S_Sound (self, CHAN_WEAPON, 0, misssound, 1, ATTN_NORM); } return 0; @@ -1112,7 +1113,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomComboAttack) { if (damagetype == NAME_None) damagetype = NAME_Melee; // Melee is the default type - if (meleesound) + if (meleesound.isvalid()) S_Sound (self, CHAN_WEAPON, 0, meleesound, 1, ATTN_NORM); int newdam = P_DamageMobj (self->target, self, self, damage, damagetype); if (bleed) @@ -1201,7 +1202,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) { self->Angles.Yaw = self->AngleTo(self->target); } - self->Angles.Pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE, &t, 60., 0, aim ? self->target : NULL); + self->Angles.Pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE, &t, DAngle::fromDeg(60.), 0, aim ? self->target.Get() : nullptr); if (t.linetarget == NULL && aim) { // We probably won't hit the target, but aim at it anyway so we don't look stupid. @@ -1227,7 +1228,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun) if (self->target->flags & MF_SHADOW) { - DAngle rnd = pr_crailgun.Random2() * (45. / 256.); + DAngle rnd = DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); self->Angles.Yaw += rnd; } } @@ -1275,7 +1276,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Recoil) PARAM_SELF_PROLOGUE(AActor); PARAM_FLOAT(xyvel); - self->Thrust(self->Angles.Yaw + 180., xyvel); + self->Thrust(self->Angles.Yaw + DAngle::fromDeg(180.), xyvel); return 0; } @@ -1618,6 +1619,9 @@ enum SPFflag 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) @@ -1649,7 +1653,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticle) if (flags & SPF_RELANG) angle += self->Angles.Yaw; double s = angle.Sin(); double c = angle.Cos(); - DVector3 pos(xoff, yoff, zoff); + DVector3 pos(xoff, yoff, zoff + self->GetBobOffset()); DVector3 vel(xvel, yvel, zvel); DVector3 acc(accelx, accely, accelz); //[MC] Code ripped right out of A_SpawnItemEx. @@ -1675,6 +1679,75 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticle) return 0; } +DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticleEx) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_COLOR (color); + PARAM_INT (i_texid) + PARAM_INT (style) + PARAM_INT (flags) + PARAM_INT (lifetime) + PARAM_FLOAT (size) + PARAM_ANGLE (angle) + PARAM_FLOAT (xoff) + PARAM_FLOAT (yoff) + PARAM_FLOAT (zoff) + PARAM_FLOAT (xvel) + PARAM_FLOAT (yvel) + PARAM_FLOAT (zvel) + PARAM_FLOAT (accelx) + PARAM_FLOAT (accely) + PARAM_FLOAT (accelz) + PARAM_FLOAT (startalpha) + PARAM_FLOAT (fadestep) + PARAM_FLOAT (sizestep) + PARAM_FLOAT (startroll) + PARAM_FLOAT (rollvel) + PARAM_FLOAT (rollacc) + + startalpha = clamp(startalpha, 0., 1.); + if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); + size = fabs(size); + if (lifetime != 0) + { + if (flags & SPF_RELANG) angle += self->Angles.Yaw; + double s = angle.Sin(); + double c = angle.Cos(); + DVector3 pos(xoff, yoff, zoff + self->GetBobOffset()); + DVector3 vel(xvel, yvel, zvel); + DVector3 acc(accelx, accely, accelz); + //[MC] Code ripped right out of A_SpawnItemEx. + if (flags & SPF_RELPOS) + { + // in relative mode negative y values mean 'left' and positive ones mean 'right' + // This is the inverse orientation of the absolute mode! + pos.X = xoff * c + yoff * s; + pos.Y = xoff * s - yoff * c; + } + if (flags & SPF_RELVEL) + { + vel.X = xvel * c + yvel * s; + vel.Y = xvel * s - yvel * c; + } + if (flags & SPF_RELACCEL) + { + acc.X = accelx * c + accely * s; + acc.Y = accelx * s - accely * c; + } + + FTextureID texid; + texid.SetIndex(i_texid); + + if(style < 0 || style >= STYLE_Count) + { + style = STYLE_None; + } + + P_SpawnParticle(self->Level, self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, sizestep, flags, texid, ERenderStyle(style), startroll, rollvel, rollacc); + } + return 0; +} + //=========================================================================== // // A_CheckSight @@ -1921,9 +1994,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burst) // base the number of shards on the size of the dead thing, so bigger // things break up into more shards than smaller things. // An self with radius 20 and height 64 creates ~40 chunks. - numChunks = MAX (4, int(self->radius * self->Height)/32); + numChunks = max (4, int(self->radius * self->Height)/32); i = (pr_burst.Random2()) % (numChunks/4); - for (i = MAX (24, numChunks + i); i >= 0; i--) + for (i = max (24, numChunks + i); i >= 0; i--) { double xo = (pr_burst() - 128) * self->radius / 128; double yo = (pr_burst() - 128) * self->radius / 128; @@ -2422,7 +2495,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfTargetInLOS) else { // Does the player aim at something that can be shot? - P_AimLineAttack(self, self->Angles.Yaw, MISSILERANGE, &t, (flags & JLOSF_NOAUTOAIM) ? 0.5 : 0., ALF_PORTALRESTRICT); + P_AimLineAttack(self, self->Angles.Yaw, MISSILERANGE, &t, DAngle::fromDeg((flags & JLOSF_NOAUTOAIM) ? 0.5 : 0.), ALF_PORTALRESTRICT); if (!t.linetarget) { @@ -2434,14 +2507,14 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfTargetInLOS) { case JLOSF_TARGETLOS|JLOSF_FLIPFOV: // target makes sight check, player makes fov check; player has verified fov - fov = 0.; + fov = nullAngle; // fall-through case JLOSF_TARGETLOS: doCheckSight = !(flags & JLOSF_NOSIGHT); // The target is responsible for sight check and fov break; default: // player has verified sight and fov - fov = 0.; + fov = nullAngle; // fall-through case JLOSF_FLIPFOV: // Player has verified sight, but target must verify fov doCheckSight = false; @@ -2472,7 +2545,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfTargetInLOS) ACTION_RETURN_BOOL(false); } if (flags & JLOSF_CLOSENOFOV) - fov = 0.; + fov = nullAngle; if (flags & JLOSF_CLOSENOSIGHT) doCheckSight = false; @@ -2492,9 +2565,9 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfTargetInLOS) else { target = viewport; viewport = self; } } - fov = MIN(fov, 360.); + fov = min(fov, DAngle::fromDeg(360.)); - if (fov > 0) + if (fov > nullAngle) { DAngle an = absangle(viewport->AngleTo(target), viewport->Angles.Yaw); @@ -2566,13 +2639,13 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfInTargetLOS) ACTION_RETURN_BOOL(false); } if (flags & JLOSF_CLOSENOFOV) - fov = 0.; + fov = nullAngle; if (flags & JLOSF_CLOSENOSIGHT) doCheckSight = false; } - if (fov > 0 && (fov < 360.)) + if (fov > nullAngle && (fov < DAngle::fromDeg(360.))) { DAngle an = absangle(target->AngleTo(self), target->Angles.Yaw); @@ -2797,7 +2870,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRefire) DEFINE_ACTION_FUNCTION(AActor, A_SetAngle) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT(angle); + PARAM_ANGLE(angle); PARAM_INT(flags); PARAM_INT(ptr); @@ -2820,7 +2893,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetAngle) DEFINE_ACTION_FUNCTION(AActor, A_SetPitch) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT(pitch); + PARAM_ANGLE(pitch); PARAM_INT(flags); PARAM_INT(ptr); @@ -2844,7 +2917,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetPitch) DEFINE_ACTION_FUNCTION(AActor, A_SetRoll) { PARAM_SELF_PROLOGUE(AActor); - PARAM_FLOAT (roll); + PARAM_ANGLE (roll); PARAM_INT (flags); PARAM_INT (ptr) ; AActor *ref = COPY_AAPTR(self, ptr); @@ -2869,7 +2942,7 @@ static void SetViewAngleNative(AActor* self, double angle, int flags, int ptr) AActor *ref = COPY_AAPTR(self, ptr); if (ref != nullptr) { - ref->SetViewAngle(angle, flags); + ref->SetViewAngle(DAngle::fromDeg(angle), flags); } } @@ -2898,7 +2971,7 @@ static void SetViewPitchNative(AActor* self, double pitch, int flags, int ptr) AActor *ref = COPY_AAPTR(self, ptr); if (ref != nullptr) { - ref->SetViewPitch(pitch, flags); + ref->SetViewPitch(DAngle::fromDeg(pitch), flags); } } @@ -2927,7 +3000,7 @@ static void SetViewRollNative(AActor* self, double roll, int flags, int ptr) AActor *ref = COPY_AAPTR(self, ptr); if (ref != nullptr) { - ref->SetViewRoll(roll, flags); + ref->SetViewRoll(DAngle::fromDeg(roll), flags); } } @@ -3260,7 +3333,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport) DEFINE_ACTION_FUNCTION(AActor, A_Quake) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (intensity); + PARAM_FLOAT (intensity); PARAM_INT (duration); PARAM_INT (damrad); PARAM_INT (tremrad); @@ -3281,9 +3354,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Quake) DEFINE_ACTION_FUNCTION(AActor, A_QuakeEx) { PARAM_SELF_PROLOGUE(AActor); - PARAM_INT(intensityX); - PARAM_INT(intensityY); - PARAM_INT(intensityZ); + PARAM_FLOAT(intensityX); + PARAM_FLOAT(intensityY); + PARAM_FLOAT(intensityZ); PARAM_INT(duration); PARAM_INT(damrad); PARAM_INT(tremrad); @@ -3316,7 +3389,7 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist) weaveXY = self->WeaveIndexXY & 63; weaveZ = self->WeaveIndexZ & 63; - angle = self->Angles.Yaw + 90; + angle = self->Angles.Yaw + DAngle::fromDeg(90); if (xydist != 0 && xyspeed != 0) { @@ -3431,7 +3504,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 < 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); @@ -4750,16 +4823,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FaceMovementDirection) //Done because using anglelimit directly causes a signed/unsigned mismatch. //Code borrowed from A_Face*. - if (anglelimit > 0) + if (anglelimit > nullAngle) { DAngle delta = -deltaangle(current, angle); if (fabs(delta) > anglelimit) { - if (delta < 0) + if (delta < nullAngle) { current += anglelimit + offset; } - else if (delta > 0) + else if (delta > nullAngle) { current -= anglelimit + offset; } @@ -4777,19 +4850,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_FaceMovementDirection) DAngle current = mobj->Angles.Pitch; const DVector2 velocity = mobj->Vel.XY(); DAngle pitch = -VecToAngle(velocity.Length(), mobj->Vel.Z); - if (pitchlimit > 0) + if (pitchlimit > nullAngle) { DAngle pdelta = deltaangle(current, pitch); if (fabs(pdelta) > pitchlimit) { - if (pdelta > 0) + if (pdelta > nullAngle) { - current -= MIN(pitchlimit, pdelta); + current -= min(pitchlimit, pdelta); } else //if (pdelta < 0) { - current += MIN(pitchlimit, -pdelta); + current += min(pitchlimit, -pdelta); } mobj->SetPitch(current, !!(flags & FMDF_INTERPOLATE)); } @@ -4857,10 +4930,10 @@ enum VRFFlags DEFINE_ACTION_FUNCTION(AActor, A_SetVisibleRotation) { PARAM_SELF_PROLOGUE(AActor); - PARAM_ANGLE(anglestart) - PARAM_ANGLE(angleend) - PARAM_ANGLE(pitchstart) - PARAM_ANGLE(pitchend) + PARAM_FANGLE(anglestart) + PARAM_FANGLE(angleend) + PARAM_FANGLE(pitchstart) + PARAM_FANGLE(pitchend) PARAM_INT(flags) PARAM_INT(ptr) @@ -4873,19 +4946,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetVisibleRotation) if (!(flags & VRF_NOANGLESTART)) { - mobj->VisibleStartAngle = anglestart.Degrees; + mobj->VisibleStartAngle = anglestart; } if (!(flags & VRF_NOANGLEEND)) { - mobj->VisibleEndAngle = angleend.Degrees; + mobj->VisibleEndAngle = angleend; } if (!(flags & VRF_NOPITCHSTART)) { - mobj->VisibleStartPitch = pitchstart.Degrees; + mobj->VisibleStartPitch = pitchstart; } if (!(flags & VRF_NOPITCHEND)) { - mobj->VisibleEndPitch = pitchend.Degrees; + mobj->VisibleEndPitch = pitchend; } ACTION_RETURN_BOOL(true); @@ -4928,7 +5001,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain) { int anglespeed = self->Level->GetFirstSectorTag(sec) - 100; double speed = (anglespeed % 10) / 16.; - DAngle an = (anglespeed / 10) * (360 / 8.); + DAngle an = DAngle::fromDeg((anglespeed / 10) * (360 / 8.)); self->Thrust(an, speed); } } @@ -5020,6 +5093,174 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState) return 0; } +//========================================================================== +// +// A_ChangeModel(modeldef, modelpath, model, modelindex, skinpath, skin, skinid, flags) +// +// This function allows the changing of an actor's modeldef, or models and/or skins at a given index +//========================================================================== + +enum ChangeModelFlags +{ + CMDL_WEAPONTOPLAYER = 1, + CMDL_HIDEMODEL = 1 << 1, + CMDL_USESURFACESKIN = 1 << 2, +}; + +DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel) +{ + 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 == nullptr) + ACTION_RETURN_BOOL(false); + else if (modeldef != NAME_None && PClass::FindClass(modeldef.GetChars()) == nullptr) + { + Printf("Attempt to pass invalid modeldef name %s in %s.", modeldef.GetChars(), self->GetCharacterName()); + ACTION_RETURN_BOOL(false); + } + else if (modelindex < 0) + { + Printf("Attempt to pass invalid model index %d in %s, index must be non-negative.", modelindex, self->GetCharacterName()); + ACTION_RETURN_BOOL(false); + } + else if (skinindex < 0) + { + Printf("Attempt to pass invalid skin index %d in %s, index must be non-negative.", skinindex, self->GetCharacterName()); + ACTION_RETURN_BOOL(false); + } + else if (animationindex < 0) + { + Printf("Attempt to pass invalid animation index %d in %s, index must be non-negative.", animationindex, self->GetCharacterName()); + ACTION_RETURN_BOOL(false); + } + + AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : stateowner; + + if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/'; + if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/'; + if (animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/'; + + if (mobj->modelData == nullptr) + { + 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); + } + + 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(); + + int skinPosition = skinindex + modelindex * MD3_MAX_SURFACES; + + 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) + { + 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 + } + else + { + if (maxSkins > skinindex) + mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs[skinindex]); + } + + //[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()); + else + while ((int)mobj->modelData->skinIDs.Size() < skinindex) mobj->modelData->skinIDs.Push(FNullTextureID()); + + 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()); + + 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(); + } + + return 0; +} + // This needs to account for the fact that internally renderstyles are stored as a series of operations, // but the script side only cares about symbolic constants. DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 000cc0fee..a7588d1ba 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -51,7 +51,7 @@ #include "g_game.h" CVAR (Int, cl_rockettrails, 1, CVAR_ARCHIVE); -CVAR (Bool, r_rail_smartspiral, 0, CVAR_ARCHIVE); +CVAR (Bool, r_rail_smartspiral, false, CVAR_ARCHIVE); CVAR (Int, r_rail_spiralsparsity, 1, CVAR_ARCHIVE); CVAR (Int, r_rail_trailsparsity, 1, CVAR_ARCHIVE); CVAR (Bool, r_particles, true, 0); @@ -99,15 +99,63 @@ static const struct ColorList { {NULL, 0, 0, 0 } }; -inline particle_t *NewParticle (FLevelLocals *Level) +inline particle_t *NewParticle (FLevelLocals *Level, bool replace = false) { particle_t *result = nullptr; - if (Level->InactiveParticles != NO_PARTICLE) + // [MC] Thanks to RaveYard and randi for helping me with this addition. + // Array's filled up + if (Level->InactiveParticles == NO_PARTICLE) { - result = &Level->Particles[Level->InactiveParticles]; - Level->InactiveParticles = result->tnext; - result->tnext = Level->ActiveParticles; - Level->ActiveParticles = uint32_t(result - Level->Particles.Data()); + if (replace) + { + result = &Level->Particles[Level->OldestParticle]; + + // There should be NO_PARTICLE for the oldest's tnext + if (result->tprev != NO_PARTICLE) + { + // tnext: youngest to oldest + // tprev: oldest to youngest + + // 2nd oldest -> oldest + particle_t *nbottom = &Level->Particles[result->tprev]; + nbottom->tnext = NO_PARTICLE; + + // now oldest becomes youngest + Level->OldestParticle = result->tprev; + result->tnext = Level->ActiveParticles; + result->tprev = NO_PARTICLE; + Level->ActiveParticles = uint32_t(result - Level->Particles.Data()); + + // youngest -> 2nd youngest + particle_t* ntop = &Level->Particles[result->tnext]; + ntop->tprev = Level->ActiveParticles; + } + // [MC] Future proof this by resetting everything when replacing a particle. + auto tnext = result->tnext; + auto tprev = result->tprev; + *result = {}; + result->tnext = tnext; + result->tprev = tprev; + } + return result; + } + + // Array isn't full. + uint32_t current = Level->ActiveParticles; + result = &Level->Particles[Level->InactiveParticles]; + Level->InactiveParticles = result->tnext; + result->tnext = current; + result->tprev = NO_PARTICLE; + Level->ActiveParticles = uint32_t(result - Level->Particles.Data()); + + if (current != NO_PARTICLE) // More than one active particles + { + particle_t* next = &Level->Particles[current]; + next->tprev = Level->ActiveParticles; + } + else // Just one active particle + { + Level->OldestParticle = Level->ActiveParticles; } return result; } @@ -138,12 +186,17 @@ void P_InitParticles (FLevelLocals *Level) void P_ClearParticles (FLevelLocals *Level) { int i = 0; - memset (Level->Particles.Data(), 0, Level->Particles.Size() * sizeof(particle_t)); + Level->OldestParticle = NO_PARTICLE; Level->ActiveParticles = NO_PARTICLE; Level->InactiveParticles = 0; for (auto &p : Level->Particles) + { + p = {}; + p.tprev = i - 1; p.tnext = ++i; + } Level->Particles.Last().tnext = NO_PARTICLE; + Level->Particles.Data()->tprev = NO_PARTICLE; } // Group particles by subsectors. Because particles are always @@ -212,16 +265,13 @@ void P_InitEffects () void P_ThinkParticles (FLevelLocals *Level) { - int i; - particle_t *particle, *prev; - - i = Level->ActiveParticles; - prev = NULL; + int i = Level->ActiveParticles; + particle_t *particle = nullptr, *prev = nullptr; while (i != NO_PARTICLE) { particle = &Level->Particles[i]; i = particle->tnext; - if (!particle->notimefreeze && Level->isFrozen()) + if (Level->isFrozen() && !(particle->flags &PT_NOTIMEFREEZE)) { prev = particle; continue; @@ -232,11 +282,17 @@ void P_ThinkParticles (FLevelLocals *Level) particle->size += particle->sizestep; if (particle->alpha <= 0 || oldtrans < particle->alpha || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it - memset (particle, 0, sizeof(particle_t)); + *particle = {}; if (prev) prev->tnext = i; else Level->ActiveParticles = i; + + if (i != NO_PARTICLE) + { + particle_t *next = &Level->Particles[i]; + next->tprev = particle->tprev; + } particle->tnext = Level->InactiveParticles; Level->InactiveParticles = (int)(particle - Level->Particles.Data()); continue; @@ -248,6 +304,13 @@ void P_ThinkParticles (FLevelLocals *Level) particle->Pos.Y = newxy.Y; particle->Pos.Z += particle->Vel.Z; particle->Vel += particle->Acc; + + if(particle->flags & PT_DOROLL) + { + particle->Roll += particle->RollVel; + particle->RollVel += particle->RollAcc; + } + particle->subsector = Level->PointInRenderSubsector(particle->Pos); sector_t *s = particle->subsector->sector; // Handle crossing a sector portal. @@ -273,14 +336,17 @@ void P_ThinkParticles (FLevelLocals *Level) enum PSFlag { - PS_FULLBRIGHT = 1, - PS_NOTIMEFREEZE = 1 << 5, + 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) + double fadestep, double sizestep, int flags, FTextureID texture, ERenderStyle style, double startroll, double rollvel, double rollacc) { - particle_t *particle = NewParticle(Level); + particle_t *particle = NewParticle(Level, !!(flags & PS_REPLACE)); if (particle) { @@ -295,7 +361,23 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v particle->bright = !!(flags & PS_FULLBRIGHT); particle->size = size; particle->sizestep = sizestep; - particle->notimefreeze = !!(flags & PS_NOTIMEFREEZE); + particle->texture = texture; + particle->style = style; + 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 |= PT_NOXYBILLBOARD; + } } } @@ -341,7 +423,7 @@ static void MakeFountain (AActor *actor, int color1, int color2) if (particle) { - DAngle an = M_Random() * (360. / 256); + DAngle an = DAngle::fromDeg(M_Random() * (360. / 256)); double out = actor->radius * M_Random() / 256.; particle->Pos = actor->Vec3Angle(out, an, actor->Height + 1); @@ -374,7 +456,7 @@ void P_RunEffect (AActor *actor, int effects) double backy = -actor->radius * 2 * moveangle.Sin(); double backz = actor->Height * ((2. / 3) - actor->Vel.Z / 8); - DAngle an = moveangle + 90.; + DAngle an = moveangle + DAngle::fromDeg(90.); double speed; particle = JitterParticle (actor->Level, 3 + (M_Random() & 31)); @@ -423,7 +505,7 @@ void P_RunEffect (AActor *actor, int effects) DVector3 pos = actor->Vec3Angle(-actor->radius * 2, moveangle, -actor->Height * actor->Vel.Z / 8 + actor->Height * (2. / 3)); - P_DrawSplash2 (actor->Level, 6, pos, moveangle + 180, 2, 2); + P_DrawSplash2 (actor->Level, 6, pos, moveangle + DAngle::fromDeg(180), 2, 2); } if (actor->fountaincolor) { @@ -440,6 +522,7 @@ void P_RunEffect (AActor *actor, int effects) &grey4, &white }; int color = actor->fountaincolor*2; + if (color < 0 || color >= 16) color = 0; MakeFountain (actor, *fountainColors[color], *fountainColors[color+1]); } if (effects & FX_RESPAWNINVUL) @@ -453,7 +536,7 @@ void P_RunEffect (AActor *actor, int effects) particle = JitterParticle (actor->Level, 16); if (particle != NULL) { - DAngle ang = M_Random() * (360 / 256.); + DAngle ang = DAngle::fromDeg(M_Random() * (360 / 256.)); DVector3 pos = actor->Vec3Angle(actor->radius, ang, 0); particle->Pos = pos; particle->color = *protectColors[M_Random() & 1]; @@ -499,7 +582,7 @@ void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle a p->Acc.X += (M_Random () - 128) / 8192.; p->Acc.Y += (M_Random () - 128) / 8192.; p->Pos.Z = pos.Z - M_Random () / 64.; - angle += M_Random() * (45./256); + angle += DAngle::fromDeg(M_Random() * (45./256)); p->Pos.X = pos.X + (M_Random() & 15)*angle.Cos(); p->Pos.Y = pos.Y + (M_Random() & 15)*angle.Sin(); } @@ -551,13 +634,13 @@ void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle p->Acc.Z = -1 / 22.; if (kind) { - an = angle + ((M_Random() - 128) * (180 / 256.)); + an = angle + DAngle::fromDeg((M_Random() - 128) * (180 / 256.)); p->Vel.X = M_Random() * an.Cos() / 2048.; p->Vel.Y = M_Random() * an.Sin() / 2048.; p->Acc.X = p->Vel.X / 16.; p->Acc.Y = p->Vel.Y / 16.; } - an = angle + ((M_Random() - 128) * (90 / 256.)); + an = angle + DAngle::fromDeg((M_Random() - 128) * (90 / 256.)); p->Pos.X = pos.X + ((M_Random() & 31) - 15) * an.Cos(); p->Pos.Y = pos.Y + ((M_Random() & 31) - 15) * an.Sin(); p->Pos.Z = pos.Z + (M_Random() + zadd - 128) * zspread; @@ -647,8 +730,8 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, // Allow other sounds than 'weapons/railgf'! if (!source->player) sound = source->AttackSound; else if (source->player->ReadyWeapon) sound = source->player->ReadyWeapon->AttackSound; - else sound = 0; - if (!sound) sound = "weapons/railgf"; + else sound = NO_SOUND; + if (!sound.isvalid()) sound = S_FindSound("weapons/railgf"); // The railgun's sound is special. It gets played from the // point on the slug's trail that is closest to the hearing player. @@ -686,7 +769,7 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, color1 = color1 == 0 ? -1 : ParticleColor(color1); pos = trail[0].start; - deg = (double)SpiralOffset; + deg = DAngle::fromDeg(SpiralOffset); for (i = spiral_steps; i; i--) { particle_t *p = NewParticle (source->Level); @@ -707,7 +790,7 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, p->Vel = tempvec * drift / 16.; p->Pos = tempvec + pos; pos += trail[segment].dir * stepsize; - deg += double(r_rail_spiralsparsity * 14); + deg += DAngle::fromDeg(r_rail_spiralsparsity * 14); lencount -= stepsize; if (color1 == -1) { diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 56980c6e3..3b542c19e 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -35,33 +35,44 @@ #include "vectors.h" #include "doomdef.h" +#include "renderstyle.h" -#define FX_ROCKET 0x00000001 -#define FX_GRENADE 0x00000002 -#define FX_RESPAWNINVUL 0x00000020 -#define FX_VISIBILITYPULSE 0x00000040 +enum +{ + FX_ROCKET = 0x00000001, + FX_GRENADE = 0x00000002, + FX_RESPAWNINVUL = 0x00000020, + FX_VISIBILITYPULSE = 0x00000040 +}; struct subsector_t; struct FLevelLocals; // [RH] Particle details +enum EParticleFlags +{ + PT_NOTIMEFREEZE = 1, + PT_DOROLL = 1 << 1, + PT_NOXYBILLBOARD = 1 << 2, +}; + struct particle_t { - DVector3 Pos; - DVector3 Vel; - DVector3 Acc; - double size; - double sizestep; - subsector_t * subsector; - int32_t ttl; - uint8_t bright; - bool notimefreeze; - float fadestep; - float alpha; - int color; - uint16_t tnext; - uint16_t snext; + 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; }; const uint16_t NO_PARTICLE = 0xffff; @@ -77,7 +88,32 @@ particle_t *JitterParticle (FLevelLocals *Level, int ttl); particle_t *JitterParticle (FLevelLocals *Level, int ttl, double drift); void P_ThinkParticles (FLevelLocals *Level); -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 = 0); + +struct FSpawnParticleParams +{ + int color; + FTextureID texture; + int style; + int flags; + int lifetime; + + double size; + double sizestep; + + DVector3 pos; + DVector3 vel; + DVector3 accel; + + double startalpha; + double fadestep; + + double startroll; + double rollvel; + double rollacc; +}; + +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 = 0, FTextureID texture = FNullTextureID(), ERenderStyle style = STYLE_None, double startroll = 0, double rollvel = 0, double rollacc = 0); + void P_InitEffects (void); void P_RunEffect (AActor *actor, int effects); @@ -89,7 +125,8 @@ struct SPortalHit DVector3 OutDir; }; -void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = 0., int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = 0.); +void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = nullAngle, int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = nullAngle); void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int kind); void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); void P_DisconnectEffect (AActor *actor); + diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index b877bcd12..7eea4cefb 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -31,7 +31,7 @@ #include -#include "templates.h" + #include "m_random.h" #include "doomdef.h" @@ -268,10 +268,10 @@ int P_CheckMeleeRange (AActor* actor, double range) AActor *pl = actor->target; double dist; - - if (!pl || (actor->Sector->Flags & SECF_NOATTACK)) + + if (!pl) return false; - + dist = actor->Distance2D (pl); if (range < 0) range = actor->meleerange; @@ -282,6 +282,9 @@ int P_CheckMeleeRange (AActor* actor, double range) if (pl == actor->goal) return true; + if (actor->Sector->Flags & SECF_NOATTACK) + return false; + // [RH] Don't melee things too far above or below actor. if (!(actor->flags5 & MF5_NOVERTICALMELEERANGE)) { @@ -401,7 +404,7 @@ int P_HitFriend(AActor * self) { DAngle angle = self->AngleTo(self->target); double dist = self->Distance2D(self->target); - P_AimLineAttack (self, angle, dist, &t, 0., true); + P_AimLineAttack (self, angle, dist, &t, nullAngle, true); if (t.linetarget != NULL && t.linetarget != self->target) { return self->IsFriend (t.linetarget); @@ -595,7 +598,7 @@ static int P_Move (AActor *actor) { DAngle anglediff = deltaangle(oldangle, actor->Angles.Yaw); - if (anglediff != 0) + if (anglediff != nullAngle) { move = move.Rotated(anglediff); oldangle = actor->Angles.Yaw; @@ -994,7 +997,7 @@ void P_NewChaseDir(AActor * actor) } else if (front == actor->Z() && back < actor->Z() - actor->MaxDropOffHeight) { - angle = line->Delta().Angle() + 180.; // back side dropoff + angle = line->Delta().Angle() + DAngle::fromDeg(180.); // back side dropoff } else continue; @@ -1092,7 +1095,7 @@ void P_RandomChaseDir (AActor *actor) int turndir; // Friendly monsters like to head toward a player - if (actor->flags & MF_FRIENDLY) + if (actor->flags & MF_FRIENDLY && !(actor->flags8 & MF8_DONTFOLLOWPLAYERS)) { AActor *player; DVector2 delta; @@ -1263,7 +1266,7 @@ int P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams else { mindist = maxdist = 0; - fov = allaround ? 0. : 180.; + fov = DAngle::fromDeg(allaround ? 0. : 180.); } double dist = lookee->Distance2D (other); @@ -1274,7 +1277,7 @@ int P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams if (mindist && dist < mindist) return false; // [KS] too close - if (fov != 0) + if (fov != nullAngle) { DAngle an = absangle(lookee->AngleTo(other), lookee->Angles.Yaw); @@ -1555,25 +1558,32 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) continue; other = NULL; - if (link->flags & MF_FRIENDLY) + if (lookee->flags & MF_FRIENDLY) { - if (!lookee->IsFriend(link)) + if (link->flags & MF_FRIENDLY) { - // This is somebody else's friend, so go after it - other = link; - } - else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) - { - other = link->target; - if (!(other->flags & MF_SHOOTABLE) || - other->health <= 0 || - (other->flags2 & MF2_DORMANT)) + if (!lookee->IsFriend(link)) { - other = NULL;; + // This is somebody else's friend, so go after it + other = link; + } + else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) + { + other = link->target; + if (!(other->flags & MF_SHOOTABLE) || + other->health <= 0 || + (other->flags2 & MF2_DORMANT)) + { + other = NULL;; + } } } + else + { + other = link; + } } - else + else if (lookee->flags8 & MF8_SEEFRIENDLYMONSTERS && link->flags & MF_FRIENDLY) { other = link; } @@ -1617,7 +1627,7 @@ int P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) { AActor *other; - other = P_BlockmapSearch (actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params); + other = P_BlockmapSearch(actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params); if (other != NULL) { @@ -1726,6 +1736,12 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) } // [SP] if false, and in deathmatch, intentional fall-through + else if (actor->flags8 & MF8_SEEFRIENDLYMONSTERS) + { + bool result = P_LookForEnemies (actor, allaround, params); + + if (result) return true; + } if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) && actor->Level->isPrimaryLevel() && @@ -1947,7 +1963,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) if (self->reactiontime > self->Level->maptime) self->target = nullptr; } - else if (self->SeeSound) + else if (self->SeeSound.isvalid()) { if ((self->flags2 & MF2_BOSS) || (self->flags8 & MF8_FULLVOLSEE)) { // full volume @@ -1986,7 +2002,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) AActor *targ = NULL; // Shuts up gcc double dist; - if (fov == 0) fov = 180.; + if (fov == nullAngle) fov = DAngle::fromDeg(180.); FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate }; if (self->flags5 & MF5_INCONVERSATION) @@ -2129,7 +2145,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) if (self->reactiontime > self->Level->maptime) self->target = nullptr; } - else if (self->SeeSound && !(flags & LOF_NOSEESOUND)) + else if (self->SeeSound.isvalid() && !(flags & LOF_NOSEESOUND)) { if (flags & LOF_FULLVOLSEESOUND) { // full volume @@ -2189,6 +2205,7 @@ enum ChaseFlags CHF_NODIRECTIONTURN = 64, CHF_NOPOSTATTACKTURN = 128, CHF_STOPIFBLOCKED = 256, + CHF_DONTIDLE = 512, }; void A_Wander(AActor *self, int flags) @@ -2212,15 +2229,15 @@ void A_Wander(AActor *self, int flags) // turn towards movement direction if not there yet if (!(flags & CHF_NODIRECTIONTURN) && (self->movedir < DI_NODIR)) { - self->Angles.Yaw = floor(self->Angles.Yaw.Degrees / 45) * 45.; - DAngle delta = deltaangle(self->Angles.Yaw, (self->movedir * 45)); - if (delta < 0) + self->Angles.Yaw = DAngle::fromDeg(floor(self->Angles.Yaw.Degrees() / 45) * 45.); + DAngle delta = deltaangle(self->Angles.Yaw, DAngle::fromDeg(self->movedir * 45)); + if (delta < nullAngle) { - self->Angles.Yaw -= 45; + self->Angles.Yaw -= DAngle::fromDeg(45); } - else if (delta > 0) + else if (delta > nullAngle) { - self->Angles.Yaw += 45; + self->Angles.Yaw += DAngle::fromDeg(45); } } @@ -2365,15 +2382,15 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi } else if (!(flags & CHF_NODIRECTIONTURN) && actor->movedir < 8) { - actor->Angles.Yaw = floor(actor->Angles.Yaw.Degrees / 45) * 45.; - DAngle delta = deltaangle(actor->Angles.Yaw, (actor->movedir * 45)); - if (delta < 0) + actor->Angles.Yaw = DAngle::fromDeg(floor(actor->Angles.Yaw.Degrees() / 45) * 45.); + DAngle delta = deltaangle(actor->Angles.Yaw, DAngle::fromDeg(actor->movedir * 45)); + if (delta < nullAngle) { - actor->Angles.Yaw -= 45; + actor->Angles.Yaw -= DAngle::fromDeg(45); } - else if (delta > 0) + else if (delta > nullAngle) { - actor->Angles.Yaw += 45; + actor->Angles.Yaw += DAngle::fromDeg(45); } } @@ -2430,7 +2447,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi } if (actor->target == NULL) { - if (actor->flags & MF_FRIENDLY) + if (flags & CHF_DONTIDLE || actor->flags & MF_FRIENDLY) { //A_Look(actor); if (actor->target == NULL) @@ -2538,8 +2555,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi if (pr_chase() < 100) { DAngle ang = actor->AngleTo(actor->target); - if (pr_chase() < 128) ang += 90.; - else ang -= 90.; + if (pr_chase() < 128) ang += DAngle::fromDeg(90.); + else ang -= DAngle::fromDeg(90.); actor->VelFromAngle(13., ang); actor->FastChaseStrafeCount = 3; // strafe time } @@ -2557,7 +2574,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi // check for melee attack if (meleestate && P_CheckMeleeRange(actor)) { - if (actor->AttackSound) + if (actor->AttackSound.isvalid()) S_Sound (actor, CHAN_WEAPON, 0, actor->AttackSound, 1, ATTN_NORM); actor->SetState (meleestate); @@ -2718,7 +2735,7 @@ bool P_CanResurrect(AActor *raiser, AActor *thing) // //========================================================================== -bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nullptr, FSoundID sound = 0) +bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nullptr, FSoundID sound = NO_SOUND) { const AActor *info; AActor *temp; @@ -2819,7 +2836,7 @@ bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nu self->SetState(archvile->FindState(NAME_Heal)); } } - if (sound == 0) sound = "vile/raise"; + if (sound == NO_SOUND) sound = S_FindSound("vile/raise"); S_Sound(corpsehit, CHAN_BODY, 0, sound, 1, ATTN_IDLE); info = corpsehit->GetDefault(); @@ -2827,7 +2844,7 @@ bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nu { corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses } - if (self->Level->ib_compatflags & BCOMPATF_VILEGHOSTS) + if (self->Level->i_compatflags & COMPATF_VILEGHOSTS) { corpsehit->Height *= 4; // [GZ] This was a commented-out feature, so let's make use of it, @@ -2930,9 +2947,9 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng // 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms. // It also means that there is no need to check for going past the other. - if (max_turn != 0 && (max_turn < fabs(delta))) + if (max_turn != nullAngle && (max_turn < fabs(delta))) { - if (delta > 0) + if (delta > nullAngle) { self->Angles.Yaw -= max_turn + ang_offset; } @@ -2948,7 +2965,7 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng // [DH] Now set pitch. In order to maintain compatibility, this can be // disabled and is so by default. - if (max_pitch <= 180.) + if (max_pitch <= DAngle::fromDeg(180.)) { DVector2 dist = self->Vec2To(other); @@ -2981,18 +2998,18 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng double dist_z = target_z - source_z; double ddist = g_sqrt(dist.X*dist.X + dist.Y*dist.Y + dist_z*dist_z); - DAngle other_pitch = -DAngle::ToDegrees(g_asin(dist_z / ddist)).Normalized180(); + DAngle other_pitch = -DAngle::fromRad(g_asin(dist_z / ddist)).Normalized180(); - if (max_pitch != 0) + if (max_pitch != nullAngle) { if (self->Angles.Pitch > other_pitch) { - max_pitch = MIN(max_pitch, (self->Angles.Pitch - other_pitch).Normalized360()); + max_pitch = min(max_pitch, (self->Angles.Pitch - other_pitch).Normalized360()); self->Angles.Pitch -= max_pitch; } else { - max_pitch = MIN(max_pitch, (other_pitch - self->Angles.Pitch).Normalized360()); + max_pitch = min(max_pitch, (other_pitch - self->Angles.Pitch).Normalized360()); self->Angles.Pitch += max_pitch; } } @@ -3006,9 +3023,9 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng // This will never work well if the turn angle is limited. - if (max_turn == 0 && (self->Angles.Yaw == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) ) + if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) ) { - self->Angles.Yaw += pr_facetarget.Random2() * (45 / 256.); + self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); } } @@ -3044,7 +3061,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) self->Angles.Yaw = self->AngleTo(self->target); - self->Angles.Pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE, &t, 60., 0, self->target); + self->Angles.Pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE, &t, DAngle::fromDeg(60.), 0, self->target); if (t.linetarget == NULL) { // We probably won't hit the target, but aim at it anyway so we don't look stupid. @@ -3058,7 +3075,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE)) { - self->Angles.Yaw += pr_railface.Random2() * 45./256; + self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45./256); } FRailParams p; @@ -3097,7 +3114,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) if (self->player && self->player->morphTics == 0) { const char *pain_amount; - FSoundID sfx_id = 0; + FSoundID sfx_id = NO_SOUND; if (self->health < 25) pain_amount = "*pain25"; @@ -3114,23 +3131,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain) FString pain_sound = pain_amount; pain_sound += '-'; pain_sound += self->player->LastDamageType.GetChars(); - sfx_id = pain_sound; - if (sfx_id == 0) + sfx_id = S_FindSound(pain_sound); + if (sfx_id == NO_SOUND) { // Try again without a specific pain amount. pain_sound = "*pain-"; pain_sound += self->player->LastDamageType.GetChars(); - sfx_id = pain_sound; + sfx_id = S_FindSound(pain_sound); } } - if (sfx_id == 0) + if (sfx_id == NO_SOUND) { - sfx_id = pain_amount; + sfx_id = S_FindSound(pain_amount); } S_Sound (self, CHAN_VOICE, 0, sfx_id, 1, ATTN_NORM); } - else if (self->PainSound) + else if (self->PainSound.isvalid()) { S_Sound (self, CHAN_VOICE, 0, self->PainSound, 1, ATTN_NORM); } diff --git a/src/playsim/p_enemy.h b/src/playsim/p_enemy.h index dd38c3bf0..9f13128ff 100644 --- a/src/playsim/p_enemy.h +++ b/src/playsim/p_enemy.h @@ -72,7 +72,7 @@ void A_Wander(AActor *self, int flags = 0); void A_DoChase(AActor *actor, bool fastchase, FState *meleestate, FState *missilestate, bool playactive, bool nightmarefast, bool dontmove, int flags); void A_Chase(AActor *self); void A_FaceTarget(AActor *actor); -void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0); +void A_Face(AActor *self, AActor *other, DAngle max_turn = nullAngle, DAngle max_pitch = DAngle::fromDeg(270.), DAngle ang_offset = nullAngle, DAngle pitch_offset = nullAngle, int flags = 0, double z_add = 0); class FSoundID; int CheckBossDeath (AActor *); diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index a054b763c..2c89e3cc1 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -61,6 +61,7 @@ #include "g_levellocals.h" #include "events.h" #include "actorinlines.h" +#include "d_main.h" static FRandom pr_botrespawn ("BotRespawn"); static FRandom pr_killmobj ("ActorDie"); @@ -76,6 +77,7 @@ EXTERN_CVAR (Bool, show_obituaries) CVAR (Float, sv_damagefactormobj, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) CVAR (Float, sv_damagefactorfriendly, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) CVAR (Float, sv_damagefactorplayer, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) +CVAR (Float, sv_ammofactor, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) // used in the zscript ammo code // // GET STUFF @@ -90,7 +92,7 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher) // The pickup is at or above the toucher's feet OR // The pickup is below the toucher. - if (delta > toucher->Height || delta < MIN(-32., -special->Height)) + if (delta > toucher->Height || delta < min(-32., -special->Height)) { // out of reach return; } @@ -187,7 +189,7 @@ void PronounMessage (const char *from, char *to, int pronoun, const char *victim // void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgflags, FName MeansOfDeath) { - FString ret; + FString ret, lookup; char gendermessage[1024]; // No obituaries for non-players, voodoo dolls or when not wanted @@ -238,20 +240,30 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf messagename = "$OB_VOODOO"; } - if (attacker != NULL && message == NULL) + if (attacker != nullptr && message == nullptr) { if (attacker == self) { message = "$OB_KILLEDSELF"; } - else + else { - IFVIRTUALPTR(attacker, AActor, GetObituary) + lookup.Format("$Obituary_%s_%s", attacker->GetClass()->TypeName.GetChars(), mod.GetChars()); + if (GStrings[lookup.GetChars() + 1]) message = lookup; + else { - 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; + lookup.Format("$Obituary_%s", attacker->GetClass()->TypeName.GetChars()); + if (GStrings[lookup.GetChars() + 1]) message = lookup; + else + { + IFVIRTUALPTR(attacker, AActor, GetObituary) + { + 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; + } + } } } } @@ -1242,7 +1254,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da { IFVIRTUALPTR(target, AActor, ApplyKickback) { - VMValue params[] = { target, inflictor, source, damage, angle.Degrees, mod.GetIndex(), flags }; + VMValue params[] = { target, inflictor, source, damage, angle.Degrees(), mod.GetIndex(), flags }; VMCall(func, params, countof(params), nullptr, 0); } } @@ -1467,7 +1479,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da } } - const int realdamage = MAX(0, damage); + const int realdamage = max(0, damage); target->Level->localEventManager->WorldThingDamaged(target, inflictor, source, realdamage, mod, flags, angle); needevent = false; @@ -1475,7 +1487,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da return realdamage; } } - return MAX(0, damage); + return max(0, damage); } static int DoDamageMobj(AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, DAngle angle) @@ -1492,7 +1504,7 @@ static int DoDamageMobj(AActor *target, AActor *inflictor, AActor *source, int d target->Level->localEventManager->WorldThingDamaged(target, inflictor, source, realdamage, mod, flags, angle); } - return MAX(0, realdamage); + return max(0, realdamage); } DEFINE_ACTION_FUNCTION(AActor, DamageMobj) @@ -1503,7 +1515,7 @@ DEFINE_ACTION_FUNCTION(AActor, DamageMobj) PARAM_INT(damage); PARAM_NAME(mod); PARAM_INT(flags); - PARAM_FLOAT(angle); + PARAM_ANGLE(angle); ACTION_RETURN_INT(DoDamageMobj(self, inflictor, source, damage, mod, flags, angle)); } @@ -1511,7 +1523,7 @@ int P_DamageMobj(AActor *target, AActor *inflictor, AActor *source, int damage, { IFVIRTUALPTR(target, AActor, DamageMobj) { - VMValue params[7] = { target, inflictor, source, damage, mod.GetIndex(), flags, angle.Degrees }; + VMValue params[7] = { target, inflictor, source, damage, mod.GetIndex(), flags, angle.Degrees() }; VMReturn ret; int retval; ret.IntAt(&retval); diff --git a/src/playsim/p_linkedsectors.cpp b/src/playsim/p_linkedsectors.cpp index 5d327643e..1b5a958e5 100644 --- a/src/playsim/p_linkedsectors.cpp +++ b/src/playsim/p_linkedsectors.cpp @@ -33,7 +33,7 @@ ** */ -#include "templates.h" + #include "p_local.h" #include "p_lnspec.h" #include "p_spec.h" diff --git a/src/playsim/p_lnspec.cpp b/src/playsim/p_lnspec.cpp index 2dd6d9493..88b37f8c3 100644 --- a/src/playsim/p_lnspec.cpp +++ b/src/playsim/p_lnspec.cpp @@ -78,7 +78,7 @@ static const uint8_t ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 }; #define SPEED(a) ((a) / 8.) #define TICS(a) (((a)*TICRATE)/35) #define OCTICS(a) (((a)*TICRATE)/8) -#define BYTEANGLE(a) ((a) * (360./256.)) +#define BYTEANGLE(a) DAngle::fromDeg((a) * (360./256.)) #define CRUSH(a) ((a) > 0? (a) : -1) #define CHANGE(a) (((a) >= 0 && (a)<=7)? ChangeMap[a]:0) @@ -1736,13 +1736,13 @@ FUNC(LS_Thing_Hate) FUNC(LS_Thing_ProjectileAimed) // Thing_ProjectileAimed (tid, type, speed, target, newtid) { - return Level->EV_Thing_Projectile (arg0, it, arg1, NULL, 0., SPEED(arg2), 0, arg3, it, 0, arg4, false); + return Level->EV_Thing_Projectile (arg0, it, arg1, NULL, nullAngle, SPEED(arg2), 0, arg3, it, 0, arg4, false); } FUNC(LS_Thing_ProjectileIntercept) // Thing_ProjectileIntercept (tid, type, speed, target, newtid) { - return Level->EV_Thing_Projectile (arg0, it, arg1, NULL, 0., SPEED(arg2), 0, arg3, it, 0, arg4, true); + return Level->EV_Thing_Projectile (arg0, it, arg1, NULL, nullAngle, SPEED(arg2), 0, arg3, it, 0, arg4, true); } // [BC] added newtid for next two @@ -1761,7 +1761,7 @@ FUNC(LS_Thing_SpawnNoFog) FUNC(LS_Thing_SpawnFacing) // Thing_SpawnFacing (tid, type, nofog, newtid) { - return Level->EV_Thing_Spawn (arg0, it, arg1, 1000000., arg2 ? false : true, arg3); + return Level->EV_Thing_Spawn (arg0, it, arg1, DAngle::fromDeg(1000000.), arg2 ? false : true, arg3); } FUNC(LS_Thing_Raise) @@ -2161,7 +2161,7 @@ FUNC(LS_Light_Stop) FUNC(LS_Radius_Quake) // Radius_Quake (intensity, duration, damrad, tremrad, tid) { - return P_StartQuake (Level, it, arg4, arg0, arg1, arg2*64, arg3*64, "world/quake"); + return P_StartQuake (Level, it, arg4, (double)arg0, arg1, arg2*64, arg3*64, S_FindSound("world/quake")); } FUNC(LS_UsePuzzleItem) @@ -2583,8 +2583,8 @@ FUNC(LS_Sector_SetCeilingScale2) FUNC(LS_Sector_SetRotation) // Sector_SetRotation (tag, floor-angle, ceiling-angle) { - DAngle ceiling = (double)arg2; - DAngle floor = (double)arg1; + DAngle ceiling = DAngle::fromDeg(arg2); + DAngle floor = DAngle::fromDeg(arg1); auto itr = Level->GetSectorTagIterator(arg0); int secnum; @@ -2736,40 +2736,47 @@ FUNC(LS_Line_SetTextureScale) FUNC(LS_Line_SetBlocking) // Line_SetBlocking (id, setflags, clearflags) { - static const int flagtrans[] = - { - ML_BLOCKING, - ML_BLOCKMONSTERS, - ML_BLOCK_PLAYERS, - ML_BLOCK_FLOATERS, - ML_BLOCKPROJECTILE, - ML_BLOCKEVERYTHING, - ML_RAILING, - ML_BLOCKUSE, - ML_BLOCKSIGHT, - ML_BLOCKHITSCAN, - ML_SOUNDBLOCK, - -1 - }; + struct FlagTransEntry + { + int fieldIndex, bitmask; + }; - if (arg0 == 0) return false; + static const FlagTransEntry flagtrans[] = + { + {0, ML_BLOCKING}, + {0, ML_BLOCKMONSTERS}, + {0, ML_BLOCK_PLAYERS}, + {0, ML_BLOCK_FLOATERS}, + {0, ML_BLOCKPROJECTILE}, + {0, ML_BLOCKEVERYTHING}, + {0, ML_RAILING}, + {0, ML_BLOCKUSE}, + {0, ML_BLOCKSIGHT}, + {0, ML_BLOCKHITSCAN}, + {0, ML_SOUNDBLOCK}, + {1, ML2_BLOCKLANDMONSTERS}, + {-1, -1}, + }; - int setflags = 0; - int clearflags = 0; + if (arg0 == 0) return false; - for(int i = 0; flagtrans[i] != -1; i++, arg1 >>= 1, arg2 >>= 1) - { - if (arg1 & 1) setflags |= flagtrans[i]; - if (arg2 & 1) clearflags |= flagtrans[i]; - } + int setflags[2] = {}; + int clearflags[2] = {}; - auto itr = Level->GetLineIdIterator(arg0); - int line; - while ((line = itr.Next()) >= 0) - { - Level->lines[line].flags = (Level->lines[line].flags & ~clearflags) | setflags; - } - return true; + for (int i = 0; flagtrans[i].bitmask != -1; i++, arg1 >>= 1, arg2 >>= 1) + { + if (arg1 & 1) setflags[flagtrans[i].fieldIndex] |= flagtrans[i].bitmask; + if (arg2 & 1) clearflags[flagtrans[i].fieldIndex] |= flagtrans[i].bitmask; + } + + auto itr = Level->GetLineIdIterator(arg0); + int line; + while ((line = itr.Next()) >= 0) + { + Level->lines[line].flags = (Level->lines[line].flags & ~clearflags[0]) | setflags[0]; + Level->lines[line].flags2 = (Level->lines[line].flags2 & ~clearflags[1]) | setflags[1]; + } + return true; } FUNC(LS_Line_SetAutomapFlags) @@ -2907,7 +2914,14 @@ enum PROP_UNUSED1, PROP_UNUSED2, PROP_SPEED, + PROP_BUDDHA, + PROP_BUDDHA2, + PROP_FRIGHTENING, + PROP_NOCLIP, + PROP_NOCLIP2, + PROP_GODMODE, + PROP_GODMODE2, }; FUNC(LS_SetPlayerProperty) @@ -3028,24 +3042,43 @@ FUNC(LS_SetPlayerProperty) // Set or clear a flag switch (arg2) { - case PROP_BUDDHA: - mask = CF_BUDDHA; - break; - case PROP_FROZEN: - mask = CF_FROZEN; - break; - case PROP_NOTARGET: - mask = CF_NOTARGET; - break; - case PROP_INSTANTWEAPONSWITCH: - mask = CF_INSTANTWEAPSWITCH; - break; - case PROP_FLY: - //mask = CF_FLY; - break; - case PROP_TOTALLYFROZEN: - mask = CF_TOTALLYFROZEN; - break; + case PROP_BUDDHA: + mask = CF_BUDDHA; + break; + case PROP_BUDDHA2: + mask = CF_BUDDHA2; + break; + case PROP_FROZEN: + mask = CF_FROZEN; + break; + case PROP_NOTARGET: + mask = CF_NOTARGET; + break; + case PROP_INSTANTWEAPONSWITCH: + mask = CF_INSTANTWEAPSWITCH; + break; + //CF_FLY has special handling + case PROP_FLY: + //mask = CF_FLY; + break; + case PROP_TOTALLYFROZEN: + mask = CF_TOTALLYFROZEN; + break; + case PROP_FRIGHTENING: + mask = CF_FRIGHTENING; + break; + case PROP_NOCLIP: + mask = CF_NOCLIP; + break; + case PROP_NOCLIP2: + mask = CF_NOCLIP|CF_NOCLIP2; //Both must be on. + break; + case PROP_GODMODE: + mask = CF_GODMODE; + break; + case PROP_GODMODE2: + mask = CF_GODMODE2; + break; } if (arg0 == 0) @@ -3211,8 +3244,9 @@ FUNC(LS_SendToCommunicator) if (it->CheckLocalView()) { S_StopSound (CHAN_VOICE); - it->player->SetSubtitle(arg0, name); - S_Sound (CHAN_VOICE, 0, name, 1, ATTN_NORM); + auto snd = S_FindSound(name); + it->player->SetSubtitle(arg0, snd); + S_Sound (CHAN_VOICE, 0, snd, 1, ATTN_NORM); // Get the message from the LANGUAGE lump. FString msg; @@ -3234,7 +3268,7 @@ FUNC(LS_ForceField) if (it != NULL) { P_DamageMobj (it, NULL, NULL, 16, NAME_None); - it->Thrust(it->Angles.Yaw + 180, 7.8125); + it->Thrust(it->Angles.Yaw + DAngle::fromDeg(180), 7.8125); } return true; } @@ -3308,7 +3342,7 @@ FUNC(LS_GlassBreak) } if (glass != nullptr) { - glass->Angles.Yaw = pr_glass() * (360 / 256.); + glass->Angles.Yaw = DAngle::fromDeg(pr_glass() * (360 / 256.)); glass->VelFromAngle(pr_glass() & 3); glass->Vel.Z = (pr_glass() & 7); // [RH] Let the shards stick around longer than they did in Strife. diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 8b0012d68..e1fae8d62 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -50,6 +50,7 @@ struct secplane_t; struct FCheckPosition; struct FTranslatedLineTarget; struct FLinePortal; +class DViewPosition; #include @@ -91,8 +92,7 @@ void P_PredictionLerpReset(); #define SPF_TEMPPLAYER 1 // spawning a short-lived dummy player #define SPF_WEAPONFULLYUP 2 // spawn with weapon already raised -int P_FaceMobj (AActor *source, AActor *target, DAngle *delta); -bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise = false, bool usecurspeed=false); +bool P_SeekerMissile (AActor *actor, DAngle thresh, DAngle turnMax, bool precise = false, bool usecurspeed=false); enum EPuffFlags { @@ -218,6 +218,7 @@ enum SPF { SPF_FORCECLAMP = 1, // players always clamp SPF_INTERPOLATE = 2, + SPF_SCALEDNOLERP = 4, }; enum PCM @@ -298,7 +299,7 @@ void P_FindFloorCeiling (AActor *actor, int flags=0); bool P_ChangeSector (sector_t* sector, int crunch, double amt, int floorOrCeil, bool isreset, bool instant = false); -DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLineTarget *pLineTarget = NULL, DAngle vrange = 0., int flags = 0, AActor *target = NULL, AActor *friender = NULL); +DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLineTarget *pLineTarget = NULL, DAngle vrange = nullAngle, int flags = 0, AActor *target = NULL, AActor *friender = NULL); enum // P_AimLineAttack flags { @@ -309,6 +310,7 @@ enum // P_AimLineAttack flags ALF_NOFRIENDS = 16, ALF_PORTALRESTRICT = 32, // only work through portals with a global offset (to be used for stuff that cannot remember the calculated FTranslatedLineTarget info) ALF_NOWEAPONCHECK = 64, // ignore NOAUTOAIM flag on a player's weapon. + ALF_IGNORENOAUTOAIM = 128, // for informative stuff like 'linetarget' CCMD. }; enum // P_LineAttack flags @@ -361,8 +363,8 @@ struct FRailParams double maxdiff = 0; int flags = 0; PClassActor *puff = nullptr; - DAngle angleoffset = 0.; - DAngle pitchoffset = 0.; + DAngle angleoffset = nullAngle; + DAngle pitchoffset = nullAngle; double distance = 8192; int duration = 0; double sparsity = 1.0; @@ -392,6 +394,10 @@ 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] Means of death enum { @@ -426,7 +432,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move); // P_INTER // void P_TouchSpecialThing (AActor *special, AActor *toucher); -int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0, DAngle angle = 0.); +int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0, DAngle angle = nullAngle); void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type); bool P_GiveBody (AActor *actor, int num, int max=0); bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison); diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index a6784e00e..589376fea 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -61,7 +61,7 @@ #include #include -#include "templates.h" + #include "m_bbox.h" #include "m_random.h" @@ -111,6 +111,20 @@ static FRandom pr_crunch("DoCrunch"); TArray spechit; TArray portalhit; +//========================================================================== +// +// P_ShouldPassThroughPlayer +// Allows players to walk through and shoot through each other (useful in +// multiplayer) +// +//========================================================================== + +bool P_ShouldPassThroughPlayer(AActor *self, AActor *other) +{ + return (dmflags3 & DF3_NO_PLAYER_CLIP) && + other->player && other->player->mo == other && + self->IsFriend(other); +} //========================================================================== // @@ -155,6 +169,38 @@ bool P_CanCollideWith(AActor *tmthing, AActor *thing) return true; } +//========================================================================== +// +// CanCrossLine +// +// Checks if an actor can cross a line after all checks are processed. +// If false, the line blocks them. +//========================================================================== + +bool P_CanCrossLine(AActor *mo, line_t *line, DVector3 next) +{ + static unsigned VIndex = ~0u; + if (VIndex == ~0u) + { + VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCrossLine"); + assert(VIndex != ~0u); + } + + VMValue params[] = { mo, line, next.X, next.Y, next.Z, false }; + VMReturn ret; + int retval; + ret.IntAt(&retval); + + auto clss = mo->GetClass(); + VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr; + if (func != nullptr) + { + VMCall(func, params, countof(params), &ret, 1); + return retval; + } + return true; +} + //========================================================================== // // FindRefPoint @@ -480,6 +526,9 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi if ((thing->IsKindOf(NAME_Inventory) || (thing->flags2 & MF2_TELESTOMP)) && !(thing->flags & MF_SOLID) && ((th->flags3 & MF3_ISMONSTER) || th->player != nullptr)) continue; + if (tmf.thing->player && P_ShouldPassThroughPlayer(tmf.thing, th)) + continue; + // monsters don't stomp things except on boss level // [RH] Some Heretic/Hexen monsters can telestomp // ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them. @@ -490,6 +539,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi P_DamageMobj(th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS); continue; } + return false; } @@ -953,6 +1003,13 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec } } + if ((tm.thing->flags8 & MF8_CROSSLINECHECK) && !P_CanCrossLine(tm.thing, ld, tm.pos)) + { + if (wasfit) + tm.thing->BlockingLine = ld; + + return false; + } // If the floor planes on both sides match we should recalculate open.bottom at the actual position we are checking // This is to avoid bumpy movement when crossing a linedef with the same slope on both sides. // This should never narrow down the opening, though, only widen it. @@ -1332,6 +1389,9 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies())) return true; + if (tm.thing->player && P_ShouldPassThroughPlayer(tm.thing, thing)) + return true; + tm.thing->BlockingMobj = thing; topz = thing->Top(); @@ -1519,6 +1579,12 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch return true; } + if (tm.thing->target && tm.thing->target != thing && + tm.thing->target->player && P_ShouldPassThroughPlayer(tm.thing->target, thing)) + { + return true; + } + double clipheight; if (thing->projectilepassheight > 0) @@ -1645,6 +1711,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch { // Push thing if (thing->lastpush != tm.PushTime) { + thing->PlayPushSound(); thing->Vel += tm.thing->Vel.XY() * thing->pushfactor; thing->lastpush = tm.PushTime; } @@ -1993,7 +2060,7 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { AActor *onmobj = nullptr; if (pOnmobj) *pOnmobj = nullptr; - if (actor->flags & MF_NOCLIP) + if ((actor->flags & MF_NOCLIP) || (actor->flags2 & MF2_THRUACTORS)) { return true; } @@ -2011,7 +2078,7 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { continue; } - if ((actor->flags2 | thing->flags2) & MF2_THRUACTORS) + if (thing->flags2 & MF2_THRUACTORS) { continue; } @@ -2064,7 +2131,10 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { // If they cannot collide, they cannot block each other. continue; } - + if (actor->player && P_ShouldPassThroughPlayer(actor, thing)) + { + continue; + } onmobj = thing; if (quick) break; @@ -2102,7 +2172,7 @@ void P_FakeZMovement(AActor *mo) } if (mo->player && mo->flags&MF_NOGRAVITY && (mo->Z() > mo->floorz) && !mo->IsNoClip2()) { - mo->AddZ(DAngle(4.5 * mo->Level->maptime).Sin()); + mo->AddZ(DAngle::fromDeg(4.5 * mo->Level->maptime).Sin()); } // @@ -2357,7 +2427,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // This is so that it does not walk off of things onto a drop off. if (thing->flags2 & MF2_ONMOBJ) { - floorz = MAX(thing->Z(), tm.floorz); + floorz = max(thing->Z(), tm.floorz); } if (floorz - tm.dropoffz > thing->MaxDropOffHeight && @@ -2516,7 +2586,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (thing->Level->isCamera(thing)) { divline_t dl1 = { besthit.Oldrefpos.X,besthit.Oldrefpos.Y, besthit.Refpos.X - besthit.Oldrefpos.X, besthit.Refpos.Y - besthit.Oldrefpos.Y }; - DVector3a hit = { {dl1.x + dl1.dx * bestfrac, dl1.y + dl1.dy * bestfrac, 0.},0. }; + DVector3a hit = { {dl1.x + dl1.dx * bestfrac, dl1.y + dl1.dy * bestfrac, 0.},nullAngle }; R_AddInterpolationPoint(hit); if (port->mType == PORTT_LINKED) @@ -2922,16 +2992,16 @@ void FSlide::HitSlideLine(line_t* ld) lineangle = ld->Delta().Angle(); if (side == 1) - lineangle += 180.; + lineangle += DAngle::fromDeg(180.); moveangle = tmmove.Angle(); // prevents sudden path reversal due to rounding error | // phares - moveangle += 3600/65536.*65536.; // Boom added 10 to the angle here. + moveangle += DAngle::fromDeg(3600/65536.*65536.); // Boom added 10 to the angle here. deltaangle = ::deltaangle(lineangle, moveangle); // V movelen = tmmove.Length(); - if (icyfloor && (deltaangle > 45) && (deltaangle < 135)) + if (icyfloor && (deltaangle > DAngle::fromDeg(45)) && (deltaangle < DAngle::fromDeg(135))) { moveangle = ::deltaangle(deltaangle, lineangle); movelen /= 2; // absorb @@ -3449,7 +3519,7 @@ bool FSlide::BounceWall(AActor *mo) if (line->special == Line_Horizon || ((mo->BounceFlags & BOUNCE_NotOnSky) && line->hitSkyWall(mo))) { - mo->SeeSound = mo->BounceSound = 0; // it might make a sound otherwise + mo->SeeSound = mo->BounceSound = NO_SOUND; // it might make a sound otherwise mo->Destroy(); return true; } @@ -3480,7 +3550,7 @@ bool FSlide::BounceWall(AActor *mo) lineangle = line->Delta().Angle(); if (side == 1) { - lineangle += 180; + lineangle += DAngle::fromDeg(180); } moveangle = mo->Vel.Angle(); deltaangle = (lineangle * 2) - moveangle; @@ -3572,7 +3642,7 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) if (!ontop) { - DAngle angle = BlockingMobj->AngleTo(mo) + ((pr_bounce() % 16) - 8); + DAngle angle = BlockingMobj->AngleTo(mo) + DAngle::fromDeg((pr_bounce() % 16) - 8); double speed = mo->VelXYToSpeed() * GetWallBounceFactor(mo); // [GZ] was 0.75, using wallbouncefactor seems more consistent if (fabs(speed) < EQUAL_EPSILON) speed = 0; mo->Angles.Yaw = angle; @@ -4011,8 +4081,8 @@ struct aim_t lastfloorplane = lastceilingplane = NULL; // check the initial sector for 3D-floors and portals - bool ceilingportalstate = (aimdir & aim_t::aim_up) && toppitch < 0 && !lastsector->PortalBlocksMovement(sector_t::ceiling); - bool floorportalstate = (aimdir & aim_t::aim_down) && bottompitch > 0 && !lastsector->PortalBlocksMovement(sector_t::floor); + bool ceilingportalstate = (aimdir & aim_t::aim_up) && toppitch < nullAngle && !lastsector->PortalBlocksMovement(sector_t::ceiling); + bool floorportalstate = (aimdir & aim_t::aim_down) && bottompitch > nullAngle && !lastsector->PortalBlocksMovement(sector_t::floor); for (auto rover : lastsector->e->XFloor.ffloors) { @@ -4035,8 +4105,8 @@ struct aim_t floorportalstate = false; } } - if (ceilingportalstate) EnterSectorPortal(sector_t::ceiling, 0, lastsector, toppitch, MIN(0., bottompitch)); - if (floorportalstate) EnterSectorPortal(sector_t::floor, 0, lastsector, MAX(0., toppitch), bottompitch); + if (ceilingportalstate) EnterSectorPortal(sector_t::ceiling, 0, lastsector, toppitch, min(nullAngle, bottompitch)); + if (floorportalstate) EnterSectorPortal(sector_t::floor, 0, lastsector, max(nullAngle, toppitch), bottompitch); FPathTraverse it(lastsector->Level, startpos.X, startpos.Y, aimtrace.X, aimtrace.Y, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE | PT_DELTA, startfrac); intercept_t *in; @@ -4062,7 +4132,7 @@ struct aim_t int frontflag = P_PointOnLineSidePrecise(startpos, li); if (aimdebug) - Printf("Found line %d: toppitch = %f, bottompitch = %f\n", li->Index(), toppitch.Degrees, bottompitch.Degrees); + Printf("Found line %d: toppitch = %f, bottompitch = %f\n", li->Index(), toppitch.Degrees(), bottompitch.Degrees()); if (li->isLinePortal() && frontflag == 0) { @@ -4106,19 +4176,19 @@ struct aim_t return; if (aimdebug) - Printf("After line %d: toppitch = %f, bottompitch = %f, planestocheck = %d\n", li->Index(), toppitch.Degrees, bottompitch.Degrees, planestocheck); + Printf("After line %d: toppitch = %f, bottompitch = %f, planestocheck = %d\n", li->Index(), toppitch.Degrees(), bottompitch.Degrees(), planestocheck); sector_t *entersec = frontflag ? li->frontsector : li->backsector; sector_t *exitsec = frontflag ? li->backsector : li->frontsector; lastsector = entersec; // check portal in backsector when aiming up/downward is possible, the line doesn't have portals on both sides and there's actually a portal in the backsector - if ((planestocheck & aim_up) && toppitch < 0 && open.top != LINEOPEN_MAX && !entersec->PortalBlocksMovement(sector_t::ceiling)) + if ((planestocheck & aim_up) && toppitch < nullAngle && open.top != LINEOPEN_MAX && !entersec->PortalBlocksMovement(sector_t::ceiling)) { - EnterSectorPortal(sector_t::ceiling, in->frac, entersec, toppitch, MIN(0., bottompitch)); + EnterSectorPortal(sector_t::ceiling, in->frac, entersec, toppitch, min(nullAngle, bottompitch)); } - if ((planestocheck & aim_down) && bottompitch > 0 && open.bottom != LINEOPEN_MIN && !entersec->PortalBlocksMovement(sector_t::floor)) + if ((planestocheck & aim_down) && bottompitch > nullAngle && open.bottom != LINEOPEN_MIN && !entersec->PortalBlocksMovement(sector_t::floor)) { - EnterSectorPortal(sector_t::floor, in->frac, entersec, MAX(0., toppitch), bottompitch); + EnterSectorPortal(sector_t::floor, in->frac, entersec, max(nullAngle, toppitch), bottompitch); } continue; // shot continues } @@ -4131,6 +4201,9 @@ struct aim_t if (aimtarget != NULL && th != aimtarget) continue; // only care about target, and you're not it + if (shootthing->player && P_ShouldPassThroughPlayer(shootthing, th)) + continue; + // If we want to start a conversation anything that has one should be // found, regardless of other settings. if (!(flags & ALF_CHECKCONVERSATION) || th->Conversation == NULL) @@ -4153,7 +4226,7 @@ struct aim_t dist = attackrange * in->frac; // Don't autoaim certain special actors - if (!cl_doautoaim && th->flags6 & MF6_NOTAUTOAIMED) + if (!cl_doautoaim && !(flags & ALF_IGNORENOAUTOAIM) && th->flags6 & MF6_NOTAUTOAIMED) { continue; } @@ -4328,11 +4401,11 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin double shootz = t1->Center() - t1->Floorclip + t1->AttackOffset(); // can't shoot outside view angles - if (vrange == 0) + if (vrange == nullAngle) { if (t1->player == NULL || !t1->Level->IsFreelookAllowed()) { - vrange = 35.; + vrange = DAngle::fromDeg(35.); } else { @@ -4340,7 +4413,7 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin auto weapon = t1->player->ReadyWeapon; if ((weapon && (weapon->IntVar(NAME_WeaponFlags) & WIF_NOAUTOAIM)) && !(flags & ALF_NOWEAPONCHECK)) { - vrange = 0.5; + vrange = DAngle::fromDeg(0.5); } else { @@ -4348,7 +4421,7 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin // vrange of 0 degrees, because then toppitch and bottompitch will // be equal, and PTR_AimTraverse will never find anything to shoot at // if it crosses a line. - vrange = clamp(t1->player->userinfo.GetAimDist(), 0.5, 35.); + vrange = DAngle::fromDeg(clamp(t1->player->userinfo.GetAimDist(), 0.5, 35.)); } } } @@ -4416,19 +4489,20 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) // 3. MTHRUSPECIES on puff and the shooter has same species as the hit actor // 4. THRUSPECIES on puff and the puff has same species as the hit actor // 5. THRUGHOST on puff and the GHOST flag on the hit actor + // 6. Matching ThruBits + // 7. A player caller with no player clip enabled if ((data->ThruActors) || (!(data->Spectral) && res.Actor->flags4 & MF4_SPECTRAL) || (data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) || (data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) || - (data->hitGhosts && res.Actor->flags3 & MF3_GHOST)) + (data->hitGhosts && res.Actor->flags3 & MF3_GHOST) || + (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) || + (data->Caller->player && P_ShouldPassThroughPlayer(data->Caller, res.Actor))) { return TRACE_Skip; } - if (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) - return TRACE_Skip; - return TRACE_Stop; } @@ -4573,7 +4647,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (!Trace(tempos, t1->Sector, direction, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData)) { // hit nothing - if (!nointeract && puffDefaults && puffDefaults->ActiveSound) + if (!nointeract && puffDefaults && puffDefaults->ActiveSound.isvalid()) { // Play miss sound S_Sound(t1, CHAN_WEAPON, 0, puffDefaults->ActiveSound, 1, ATTN_NORM); } @@ -4614,7 +4688,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { DVector2 pos = t1->Level->GetPortalOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4); puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget, - trace.SrcAngleFromTarget - 90, 0, puffFlags); + trace.SrcAngleFromTarget - DAngle::fromDeg(90), 0, puffFlags); puff->radius = 1/65536.; if (nointeract) @@ -4678,7 +4752,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, puffFlags |= PF_HITTHINGBLEED; // We must pass the unreplaced puff type here - puff = P_SpawnPuff(t1, pufftype, bleedpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 2, puffFlags | PF_HITTHING, trace.Actor); + puff = P_SpawnPuff(t1, pufftype, bleedpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - DAngle::fromDeg(90), 2, puffFlags | PF_HITTHING, trace.Actor); } if (victim != NULL) { @@ -4716,7 +4790,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { // Since the puff is the damage inflictor we need it here // regardless of whether it is displayed or not. - puff = P_SpawnPuff(t1, pufftype, bleedpos, 0., 0., 2, puffFlags | PF_HITTHING | PF_TEMPORARY); + puff = P_SpawnPuff(t1, pufftype, bleedpos, nullAngle, nullAngle, 2, puffFlags | PF_HITTHING | PF_TEMPORARY); killPuff = true; } auto src = t1; @@ -4731,7 +4805,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { IFVIRTUALPTR(trace.Actor, AActor, SpawnLineAttackBlood) { - VMValue params[] = { trace.Actor, t1, bleedpos.X, bleedpos.Y, bleedpos.Z, trace.SrcAngleFromTarget.Degrees, damage, newdam }; + VMValue params[] = { trace.Actor, t1, bleedpos.X, bleedpos.Y, bleedpos.Z, trace.SrcAngleFromTarget.Degrees(), damage, newdam }; VMCall(func, params, countof(params), nullptr, 0); } if (damage) @@ -4746,7 +4820,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { if (puff == NULL) { // Spawn puff just to get a mass for the splash - puff = P_SpawnPuff(t1, pufftype, trace.HitPos, 0., 0., 2, puffFlags | PF_HITTHING | PF_TEMPORARY); + puff = P_SpawnPuff(t1, pufftype, trace.HitPos, nullAngle, nullAngle, 2, puffFlags | PF_HITTHING | PF_TEMPORARY); killPuff = true; } SpawnDeepSplash(t1, trace, puff); @@ -4767,10 +4841,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, PClassActor *type = PClass::FindActor(pufftype); if (type == NULL) { - if (victim != NULL) - { - memset(victim, 0, sizeof(*victim)); - } + if (victim != NULL) *victim = {}; Printf("Attempt to spawn unknown actor type '%s'\n", pufftype.GetChars()); return NULL; } @@ -5009,8 +5080,8 @@ void P_TraceBleed(int damage, const DVector3 &pos, AActor *actor, DAngle angle, { FTraceResults bleedtrace; - DAngle bleedang = angle + (pr_tracebleed() - 128) * noise; - DAngle bleedpitch = pitch + (pr_tracebleed() - 128) * noise; + DAngle bleedang = angle + DAngle::fromDeg((pr_tracebleed() - 128) * noise); + DAngle bleedpitch = pitch + DAngle::fromDeg((pr_tracebleed() - 128) * noise); double cosp = bleedpitch.Cos(); DVector3 vdir = DVector3(cosp * bleedang.Cos(), cosp * bleedang.Sin(), -bleedpitch.Sin()); @@ -5062,11 +5133,11 @@ void P_TraceBleed(int damage, AActor *target, AActor *missile) double aim; aim = g_atan(missile->Vel.Z / target->Distance2D(missile)); - pitch = -DAngle::ToDegrees(aim); + pitch = -DAngle::fromRad(aim); } else { - pitch = 0.; + pitch = nullAngle; } P_TraceBleed(damage, target->PosPlusZ(target->Height/2), target, missile->AngleTo(target), pitch); } @@ -5084,7 +5155,7 @@ void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff) return; } - DAngle pitch = (pr_tracebleed() - 128) * (360 / 65536.); + DAngle pitch = DAngle::fromDeg((pr_tracebleed() - 128) * (360 / 65536.)); P_TraceBleed(damage, t->linetarget->PosPlusZ(t->linetarget->Height/2), t->linetarget, t->angleFromSource, pitch); } @@ -5099,8 +5170,8 @@ void P_TraceBleed(int damage, AActor *target) { if (target != NULL) { - DAngle angle = pr_tracebleed() * (360 / 256.); - DAngle pitch = (pr_tracebleed() - 128) * (360 / 65536.); + DAngle angle = DAngle::fromDeg(pr_tracebleed() * (360 / 256.)); + DAngle pitch = DAngle::fromDeg((pr_tracebleed() - 128) * (360 / 65536.)); P_TraceBleed(damage, target->PosPlusZ(target->Height / 2), target, angle, pitch); } } @@ -5158,12 +5229,14 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) // 2. MTHRUSPECIES on puff and the shooter has same species as the hit actor // 3. THRUSPECIES on puff and the puff has same species as the hit actor // 4. THRUGHOST on puff and the GHOST flag on the hit actor + // 5. Skip through players in coop if sv_noplayerclip is enabled if ((data->ThruActors) || (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) || (data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) || (data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) || - (data->ThruGhosts && res.Actor->flags3 & MF3_GHOST)) + (data->ThruGhosts && res.Actor->flags3 & MF3_GHOST) || + (data->Caller->player && P_ShouldPassThroughPlayer(data->Caller, res.Actor))) { return TRACE_Skip; } @@ -5230,7 +5303,7 @@ void P_RailAttack(FRailParams *p) puffflags |= PF_NORANDOMZ; } - DVector2 xy = source->Vec2Angle(p->offset_xy, angle - 90.); + DVector2 xy = source->Vec2Angle(p->offset_xy, angle - DAngle::fromDeg(90.)); RailData rail_data; rail_data.Caller = source; @@ -5293,6 +5366,7 @@ void P_RailAttack(FRailParams *p) int actorpuffflags = puffflags | PF_HITTHING; AActor *hitactor = rail_data.RailHits[i].HitActor; + AActor *hitpuff = NULL; DVector3 &hitpos = rail_data.RailHits[i].HitPos; DAngle hitangle = rail_data.RailHits[i].HitAngle; @@ -5312,21 +5386,25 @@ void P_RailAttack(FRailParams *p) } if (spawnpuff) { - P_SpawnPuff(source, puffclass, hitpos, hitangle, hitangle - 90, 1, actorpuffflags, hitactor); + hitpuff = P_SpawnPuff(source, puffclass, hitpos, hitangle, hitangle - DAngle::fromDeg(90), 1, actorpuffflags, hitactor); } - + // https://github.com/coelckers/gzdoom/pull/1668#pullrequestreview-1039431156 + if (!hitpuff) { + hitpuff = thepuff; + } + int dmgFlagPass = DMG_INFLICTOR_IS_PUFF; if (puffDefaults != NULL) // is this even possible? { if (puffDefaults->PoisonDamage > 0 && puffDefaults->PoisonDuration != INT_MIN) { - P_PoisonMobj(hitactor, thepuff ? thepuff : source, source, puffDefaults->PoisonDamage, puffDefaults->PoisonDuration, puffDefaults->PoisonPeriod, puffDefaults->PoisonDamageType); + P_PoisonMobj(hitactor, hitpuff ? hitpuff : source, source, puffDefaults->PoisonDamage, puffDefaults->PoisonDuration, puffDefaults->PoisonPeriod, puffDefaults->PoisonDamageType); } if (puffDefaults->flags3 & MF3_FOILINVUL) dmgFlagPass |= DMG_FOILINVUL; if (puffDefaults->flags7 & MF7_FOILBUDDHA) dmgFlagPass |= DMG_FOILBUDDHA; } // [RK] If the attack source is a player, send the DMG_PLAYERATTACK flag. - int newdam = P_DamageMobj(hitactor, thepuff ? thepuff : source, source, p->damage, damagetype, dmgFlagPass | DMG_USEANGLE | (source->player ? DMG_PLAYERATTACK : 0), hitangle); + int newdam = P_DamageMobj(hitactor, hitpuff ? hitpuff : source, source, p->damage, damagetype, dmgFlagPass | DMG_USEANGLE | (source->player ? DMG_PLAYERATTACK : 0), hitangle); if (bleed) { @@ -5344,7 +5422,7 @@ void P_RailAttack(FRailParams *p) if (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) { - puff = P_SpawnPuff(source, puffclass, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 1, puffflags); + puff = P_SpawnPuff(source, puffclass, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - DAngle::fromDeg(90), 1, puffflags); if (puff && (trace.Line != NULL) && (trace.Line->special == Line_Horizon) && !(puff->flags3 & MF3_SKYEXPLODE)) puff->Destroy(); } @@ -5359,7 +5437,7 @@ void P_RailAttack(FRailParams *p) AActor* puff = NULL; if (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) { - puff = P_SpawnPuff(source, puffclass, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - 90, 1, puffflags); + puff = P_SpawnPuff(source, puffclass, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - DAngle::fromDeg(90), 1, puffflags); if (puff && !(puff->flags3 & MF3_SKYEXPLODE) && (((trace.HitType == TRACE_HitFloor) && (puff->floorpic == skyflatnum)) || ((trace.HitType == TRACE_HitCeiling) && (puff->ceilingpic == skyflatnum)))) @@ -5397,7 +5475,7 @@ CVAR(Float, chase_dist, 90.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&CameraSector, bool &unlinked) { double distance = clamp(chase_dist, 0, 30000); - DAngle angle = t1->Angles.Yaw - 180; + DAngle angle = t1->Angles.Yaw - DAngle::fromDeg(180); DAngle pitch = t1->Angles.Pitch; FTraceResults trace; DVector3 vvec; @@ -5420,9 +5498,30 @@ void P_AimCamera(AActor *t1, DVector3 &campos, DAngle &camangle, sector_t *&Came } CameraSector = trace.Sector; unlinked = trace.unlinked; - camangle = trace.SrcAngleFromTarget - 180.; + 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) + { + // Position camera slightly in front of hit thing + campos = orig + vvec.Unit() * (trace.Distance - 5); + } + else + { + campos = trace.HitPos - trace.HitVector * 1 / 256.; + } + CameraSector = trace.Sector; + unlinked = trace.unlinked; +} //========================================================================== // @@ -5440,7 +5539,7 @@ bool P_TalkFacing(AActor *player) for (double angle : angleofs) { - P_AimLineAttack(player, player->Angles.Yaw + angle, TALKRANGE, &t, 35., ALF_FORCENOSMART | ALF_CHECKCONVERSATION | ALF_PORTALRESTRICT); + P_AimLineAttack(player, player->Angles.Yaw + DAngle::fromDeg(angle), TALKRANGE, &t, DAngle::fromDeg(35.), ALF_FORCENOSMART | ALF_CHECKCONVERSATION | ALF_PORTALRESTRICT); if (t.linetarget != NULL) { if (t.linetarget->health > 0 && // Dead things can't talk. @@ -5951,6 +6050,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom if (thing->flags3 & MF3_NORADIUSDMG && !(bombspot->flags4 & MF4_FORCERADIUSDMG)) continue; + // allow rocket splash damage if (!(flags & RADF_HURTSOURCE) && (thing == bombsource || thing == bombspot)) { // don't damage the source of the explosion continue; @@ -5977,6 +6077,9 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom continue; } + if (bombsource && thing != bombsource && bombsource->player && P_ShouldPassThroughPlayer(bombsource, thing)) + continue; + targets.Push(thing); } @@ -6310,13 +6413,13 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos) if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } - DAngle an = (M_Random() - 128) * (360./256); + DAngle an = DAngle::fromDeg((M_Random() - 128) * (360./256)); if (cl_bloodtype >= 1) { P_DrawSplash2(thing->Level, 32, thing->PosPlusZ(thing->Height/2), an, 2, thing->BloodColor); } } - if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound)) + if (thing->CrushPainSound != NO_SOUND && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound)) { S_Sound(thing, CHAN_VOICE, 0, thing->CrushPainSound, 1.f, ATTN_NORM); } @@ -6364,6 +6467,9 @@ int P_PushUp(AActor *thing, FChangePosition *cpos) if (!P_CanCollideWith(thing, intersect)) continue; + if (thing->player && P_ShouldPassThroughPlayer(thing, intersect)) + continue; + if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) @@ -6428,6 +6534,9 @@ int P_PushDown(AActor *thing, FChangePosition *cpos) if (!P_CanCollideWith(thing, intersect)) continue; + if (thing->player && P_ShouldPassThroughPlayer(thing, intersect)) + continue; + if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) @@ -6663,7 +6772,7 @@ void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos) AActor *onmobj; if (!P_TestMobjZ(thing, true, &onmobj) && onmobj->Z() <= thing->Z()) { - thing->SetZ(MIN(thing->ceilingz - thing->Height, onmobj->Top())); + thing->SetZ(min(thing->ceilingz - thing->Height, onmobj->Top())); thing->UpdateRenderSectorList(); } } diff --git a/src/playsim/p_maputl.cpp b/src/playsim/p_maputl.cpp index 4f3af3c85..9c5bd14b1 100644 --- a/src/playsim/p_maputl.cpp +++ b/src/playsim/p_maputl.cpp @@ -415,11 +415,11 @@ bool AActor::FixMapthingPos() DAngle ang = ldef->Delta().Angle(); if (ldef->backsector != NULL && ldef->backsector == secstart) { - ang += 90.; + ang += DAngle::fromDeg(90.); } else { - ang -= 90.; + ang -= DAngle::fromDeg(90.); } // Get the distance we have to move the object away from the wall @@ -527,10 +527,10 @@ void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sec } else { // [RH] Link into every block this actor touches, not just the center one - x1 = MAX(0, x1); - y1 = MAX(0, y1); - x2 = MIN(Level->blockmap.bmapwidth - 1, x2); - y2 = MIN(Level->blockmap.bmapheight - 1, y2); + x1 = max(0, x1); + y1 = max(0, y1); + x2 = min(Level->blockmap.bmapwidth - 1, x2); + y2 = min(Level->blockmap.bmapheight - 1, y2); for (int y = y1; y <= y2; ++y) { for (int x = x1; x <= x2; ++x) @@ -1686,7 +1686,7 @@ FPathTraverse::~FPathTraverse() // int P_CheckFov(AActor* t1, AActor* t2, double fov) { - return absangle(t1->AngleTo(t2), t1->Angles.Yaw) <= fov; + return absangle(t1->AngleTo(t2), t1->Angles.Yaw) <= DAngle::fromDeg(fov); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFov, P_CheckFov) @@ -2092,3 +2092,42 @@ int BoxOnLineSide(const FBoundingBox &box, const line_t* ld) return (p1 == p2) ? p1 : -1; } +DEFINE_ACTION_FUNCTION(FLevelLocals, PointOnLineSide) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_POINTER(l, line_t); + PARAM_BOOL(precise); + + int res; + if (precise) // allow forceful overriding of compat flag + res = P_PointOnLineSidePrecise(x, y, l); + else + res = P_PointOnLineSide(x, y, l); + + ACTION_RETURN_INT(res); +} + +DEFINE_ACTION_FUNCTION(FLevelLocals, ActorOnLineSide) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_OBJECT(mo, AActor); + PARAM_POINTER(l, line_t); + + FBoundingBox box(mo->X(), mo->Y(), mo->radius); + ACTION_RETURN_INT(BoxOnLineSide(box, l)); +} + +DEFINE_ACTION_FUNCTION(FLevelLocals, BoxOnLineSide) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(radius); + PARAM_POINTER(l, line_t); + + FBoundingBox box(x, y, radius); + ACTION_RETURN_INT(BoxOnLineSide(box, l)); +} + diff --git a/src/playsim/p_maputl.h b/src/playsim/p_maputl.h index 0c93ab445..53984f1d3 100644 --- a/src/playsim/p_maputl.h +++ b/src/playsim/p_maputl.h @@ -39,12 +39,12 @@ struct intercept_t // //========================================================================== -inline int P_PointOnLineSidePrecise(double x, double y, const line_t *line) +inline int P_PointOnLineSidePrecise(double x, double y, const linebase_t *line) { return (y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - x) * line->Delta().Y > EQUAL_EPSILON; } -inline int P_PointOnLineSidePrecise(const DVector2 &pt, const line_t *line) +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; } diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index a9674122b..1c0052abe 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -58,7 +58,7 @@ // HEADER FILES ------------------------------------------------------------ #include -#include "templates.h" + #include "m_random.h" #include "doomdef.h" @@ -158,6 +158,7 @@ CVAR (Int, cl_bloodtype, 0, CVAR_ARCHIVE); // CODE -------------------------------------------------------------------- +IMPLEMENT_CLASS(DActorModelData, false, false); IMPLEMENT_CLASS(AActor, false, true) IMPLEMENT_POINTERS_START(AActor) @@ -171,23 +172,17 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(master) IMPLEMENT_POINTER(Poisoner) IMPLEMENT_POINTER(alternative) + IMPLEMENT_POINTER(ViewPos) + IMPLEMENT_POINTER(modelData) + IMPLEMENT_POINTER(boneComponentData) IMPLEMENT_POINTERS_END -AActor::~AActor () -{ - // Please avoid calling the destructor directly (or through delete)! - // Use Destroy() instead. -} - - //========================================================================== // // AActor :: Serialize // //========================================================================== - - #define A(a,b) ((a), (b), def->b) void AActor::Serialize(FSerializer &arc) @@ -204,6 +199,7 @@ void AActor::Serialize(FSerializer &arc) A("scale", Scale) A("renderstyle", RenderStyle) A("renderflags", renderflags) + A("renderflags2", renderflags2) A("picnum", picnum) A("floorpic", floorpic) A("ceilingpic", ceilingpic) @@ -328,6 +324,7 @@ void AActor::Serialize(FSerializer &arc) A("damagemultiply", DamageMultiply) A("waveindexxy", WeaveIndexXY) A("weaveindexz", WeaveIndexZ) + A("freezetics", freezetics) A("pdmgreceived", PoisonDamageReceived) A("pdurreceived", PoisonDurationReceived) A("ppreceived", PoisonPeriodReceived) @@ -353,10 +350,10 @@ void AActor::Serialize(FSerializer &arc) A("cameraheight", CameraHeight) A("camerafov", CameraFOV) A("tag", Tag) - A("visiblestartangle",VisibleStartAngle) - A("visibleendangle",VisibleEndAngle) - A("visiblestartpitch",VisibleStartPitch) - A("visibleendpitch",VisibleEndPitch) + A("visiblestartangle", VisibleStartAngle) + A("visibleendangle", VisibleEndAngle) + A("visiblestartpitch", VisibleStartPitch) + A("visibleendpitch", VisibleEndPitch) A("woundhealth", WoundHealth) A("rdfactor", RadiusDamageFactor) A("selfdamagefactor", SelfDamageFactor) @@ -369,7 +366,11 @@ void AActor::Serialize(FSerializer &arc) A("spawnorder", SpawnOrder) A("friction", Friction) A("SpriteOffset", SpriteOffset) - A("userlights", UserLights); + ("viewpos", ViewPos) + A("lightlevel", LightLevel) + A("userlights", UserLights) + A("WorldOffset", WorldOffset) + ("modelData", modelData); SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); SerializeArgs(arc, "args", args, def->args, special); @@ -406,17 +407,11 @@ void AActor::PostSerialize() } } ClearInterpolation(); + ClearFOVInterpolation(); UpdateWaterLevel(false); } - -AActor &AActor::operator= (const AActor &other) -{ - memcpy (&snext, &other.snext, (uint8_t *)&this[1] - (uint8_t *)&snext); - return *this; -} - //========================================================================== // // AActor::InStateSequence @@ -473,14 +468,14 @@ bool AActor::IsMapActor() // //========================================================================== -int AActor::GetTics(FState * newstate) +inline int GetTics(AActor* actor, FState * newstate) { int tics = newstate->GetTics(); - if (isFast() && newstate->GetFast()) + if (actor->isFast() && newstate->GetFast()) { return tics - (tics>>1); } - else if (isSlow() && newstate->GetSlow()) + else if (actor->isSlow() && newstate->GetSlow()) { return tics<<1; } @@ -527,7 +522,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) return false; } state = newstate; - tics = GetTics(newstate); + tics = GetTics(this, newstate); renderflags = (renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (newstate->GetFullbright()); newsprite = newstate->sprite; if (newsprite != SPR_FIXED) @@ -605,13 +600,14 @@ DEFINE_ACTION_FUNCTION(AActor, SetState) //============================================================================ // -// AActor :: DestroyAllInventory +// DestroyAllInventory +// Destroys all the inventory the actor is holding. // //============================================================================ -void AActor::DestroyAllInventory () +static void DestroyAllInventory(AActor* actor) { - AActor *inv = Inventory; + AActor *inv = PARAM_NULLCHECK(actor, self)->Inventory; if (inv != nullptr) { TArray toDelete; @@ -638,10 +634,10 @@ void AActor::DestroyAllInventory () } } -DEFINE_ACTION_FUNCTION(AActor, DestroyAllInventory) +DEFINE_ACTION_FUNCTION_NATIVE(AActor, DestroyAllInventory, DestroyAllInventory) { PARAM_SELF_PROLOGUE(AActor); - self->DestroyAllInventory(); + DestroyAllInventory(self); return 0; } //============================================================================ @@ -763,23 +759,6 @@ DEFINE_ACTION_FUNCTION(AActor, GiveInventoryType) ACTION_RETURN_OBJECT(self->GiveInventoryType(type)); } -//============================================================================ -// -// AActor :: ClearInventory -// -// Clears the inventory of a single actor. -// -//============================================================================ - -void AActor::ClearInventory() -{ - IFVIRTUAL(AActor, ClearInventory) - { - VMValue params[] = { this }; - VMCall(func, params, 1, nullptr, 0); - } -} - //============================================================================ // // AActor :: CopyFriendliness @@ -1007,10 +986,10 @@ bool AActor::IsInsideVisibleAngles() const if (p == nullptr || p->camera == nullptr) return true; - DAngle anglestart = VisibleStartAngle.Degrees; - DAngle angleend = VisibleEndAngle.Degrees; - DAngle pitchstart = VisibleStartPitch.Degrees; - DAngle pitchend = VisibleEndPitch.Degrees; + DAngle anglestart = DAngle::fromDeg(VisibleStartAngle.Degrees()); + DAngle angleend = DAngle::fromDeg(VisibleEndAngle.Degrees()); + DAngle pitchstart = DAngle::fromDeg(VisibleStartPitch.Degrees()); + DAngle pitchend = DAngle::fromDeg(VisibleEndPitch.Degrees()); if (anglestart > angleend) { @@ -1131,18 +1110,6 @@ void AActor::ConversationAnimation (int animnum) // //============================================================================ -void AActor::Touch (AActor *toucher) -{ -} - -DEFINE_ACTION_FUNCTION(AActor, Touch) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT_NOT_NULL(toucher, AActor); - self->Touch(toucher); - return 0; -} - void AActor::CallTouch(AActor *toucher) { IFVIRTUAL(AActor, Touch) @@ -1150,7 +1117,6 @@ void AActor::CallTouch(AActor *toucher) VMValue params[2] = { (DObject*)this, toucher }; VMCall(func, params, 2, nullptr, 0); } - else Touch(toucher); } //============================================================================ @@ -1163,20 +1129,22 @@ void AActor::CallTouch(AActor *toucher) // Bool items is true if it should destroy() dropped items, false otherwise. //============================================================================ -bool AActor::Grind(bool items) +static int Grind(AActor* actor, int items) { + PARAM_NULLCHECK(actor, actor); // crunch bodies to giblets - if ((flags & MF_CORPSE) && !(flags3 & MF3_DONTGIB) && (health <= 0)) + if ((actor->flags & MF_CORPSE) && !(actor->flags3 & MF3_DONTGIB) && (actor->health <= 0)) { - FState * state = FindState(NAME_Crush); + FState * state = actor->FindState(NAME_Crush); // In Heretic and Chex Quest we don't change the actor's sprite, just its size. if (state == NULL && gameinfo.dontcrunchcorpses) { - flags &= ~MF_SOLID; - flags3 |= MF3_DONTGIB; - Height = 0; - radius = 0; + actor->flags &= ~MF_SOLID; + actor->flags3 |= MF3_DONTGIB; + actor->Height = 0; + actor->radius = 0; + actor->Vel.Zero(); return false; } @@ -1185,46 +1153,46 @@ bool AActor::Grind(bool items) // The reason for the change was originally because of a problem with players, // see rh_log entry for February 21, 1999. Don't know if it is still relevant. if (state == NULL // Only use the default crushed state if: - && !(flags & MF_NOBLOOD) // 1. the monster bleeeds, - && (Level->i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, - && player == NULL) // 3. and the thing isn't a player. + && !(actor->flags & MF_NOBLOOD) // 1. the monster bleeeds, + && actor->player == NULL) // 3. and the thing isn't a player. { isgeneric = true; - state = FindState(NAME_GenericCrush); + state = actor->FindState(NAME_GenericCrush); if (state != NULL && (sprites[state->sprite].numframes <= 0)) state = NULL; // If one of these tests fails, do not use that state. } - if (state != NULL && !(flags & MF_ICECORPSE)) + if (state != NULL && !(actor->flags & MF_ICECORPSE)) { - if (this->flags4 & MF4_BOSSDEATH) + if (actor->flags4 & MF4_BOSSDEATH) { - A_BossDeath(this); + A_BossDeath(actor); } - flags &= ~MF_SOLID; - flags3 |= MF3_DONTGIB; - Height = 0; - radius = 0; - SetState (state); + actor->flags &= ~MF_SOLID; + actor->flags3 |= MF3_DONTGIB; + actor->Height = 0; + actor->radius = 0; + actor->Vel.Zero(); + actor->SetState (state); if (isgeneric) // Not a custom crush state, so colorize it appropriately. { - S_Sound (this, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); - Translation = BloodTranslation; + S_Sound (actor, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); + actor->Translation = actor->BloodTranslation; } - Level->localEventManager->WorldThingGround(this, state); + actor->Level->localEventManager->WorldThingGround(actor, state); return false; } - if (!(flags & MF_NOBLOOD)) + if (!(actor->flags & MF_NOBLOOD)) { - if (this->flags4 & MF4_BOSSDEATH) + if (actor->flags4 & MF4_BOSSDEATH) { - A_BossDeath(this); + A_BossDeath(actor); } PClassActor *i = PClass::FindActor("RealGibs"); if (i != NULL) { - i = i->GetReplacement(Level); + i = i->GetReplacement(actor->Level); const AActor *defaults = GetDefaultByType (i); if (defaults->SpawnState == NULL || @@ -1236,68 +1204,69 @@ bool AActor::Grind(bool items) if (i == NULL) { // if there's no gib sprite don't crunch it. - flags &= ~MF_SOLID; - flags3 |= MF3_DONTGIB; - Height = 0; - radius = 0; + actor->flags &= ~MF_SOLID; + actor->flags3 |= MF3_DONTGIB; + actor->Height = 0; + actor->radius = 0; + actor->Vel.Zero(); return false; } - AActor *gib = Spawn (Level, i, Pos(), ALLOW_REPLACE); + AActor *gib = Spawn (actor->Level, i, actor->Pos(), ALLOW_REPLACE); if (gib != NULL) { - gib->RenderStyle = RenderStyle; - gib->Alpha = Alpha; + gib->RenderStyle = actor->RenderStyle; + gib->Alpha = actor->Alpha; gib->Height = 0; gib->radius = 0; - gib->Translation = BloodTranslation; + gib->Translation = actor->BloodTranslation; } - S_Sound (this, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); - Level->localEventManager->WorldThingGround(this, nullptr); + S_Sound (actor, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); + actor->Level->localEventManager->WorldThingGround(actor, nullptr); } - if (flags & MF_ICECORPSE) + if (actor->flags & MF_ICECORPSE) { - tics = 1; - Vel.Zero(); + actor->tics = 1; + actor->Vel.Zero(); } - else if (player) + else if (actor->player) { - flags |= MF_NOCLIP; - flags3 |= MF3_DONTGIB; - renderflags |= RF_INVISIBLE; + actor->flags |= MF_NOCLIP; + actor->flags3 |= MF3_DONTGIB; + actor->renderflags |= RF_INVISIBLE; } else { - Destroy (); + actor->Destroy (); } return false; // keep checking } // killough 11/98: kill touchy things immediately - if (flags6 & MF6_TOUCHY && (flags6 & MF6_ARMED || IsSentient())) + if (actor->flags6 & MF6_TOUCHY && (actor->flags6 & MF6_ARMED || actor->IsSentient())) { - flags6 &= ~MF6_ARMED; // Disarm - P_DamageMobj (this, NULL, NULL, health, NAME_Crush, DMG_FORCED); // kill object + actor->flags6 &= ~MF6_ARMED; // Disarm + P_DamageMobj (actor, NULL, NULL, actor->health, NAME_Crush, DMG_FORCED); // kill object return true; // keep checking } - if (!(flags & MF_SOLID) || (flags & MF_NOCLIP)) + if (!(actor->flags & MF_SOLID) || (actor->flags & MF_NOCLIP)) { return false; } - if (!(flags & MF_SHOOTABLE)) + if (!(actor->flags & MF_SHOOTABLE)) { return false; // assume it is bloody gibs or something } return true; } -DEFINE_ACTION_FUNCTION(AActor, Grind) +DEFINE_ACTION_FUNCTION_NATIVE(AActor, Grind, Grind) { PARAM_SELF_PROLOGUE(AActor); PARAM_BOOL(items); - ACTION_RETURN_BOOL(self->Grind(items)); + ACTION_RETURN_BOOL(Grind(self, items)); } bool AActor::CallGrind(bool items) @@ -1310,7 +1279,7 @@ bool AActor::CallGrind(bool items) VMCall(func, params, 2, &ret, 1); return !!retv; } - return Grind(items); + return false; } //============================================================================ @@ -1349,6 +1318,24 @@ bool AActor::Massacre () return false; } +//---------------------------------------------------------------------------- +// +// Serialize DActorModelData +// +//---------------------------------------------------------------------------- + +void DActorModelData::Serialize(FSerializer& arc) +{ + Super::Serialize(arc); + arc("modelDef", modelDef) + ("modelIDs", modelIDs) + ("skinIDs", skinIDs) + ("surfaceSkinIDs", surfaceSkinIDs) + ("animationIDs", animationIDs) + ("modelFrameGenerators", modelFrameGenerators) + ("hasModel", hasModel); +} + //---------------------------------------------------------------------------- // // PROC P_ExplodeMissile @@ -1450,7 +1437,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target, bool onsky, FNa } // play the sound before changing the state, so that AActor::OnDestroy can call S_RelinkSounds on it and the death state can override it. - if (mo->DeathSound) + if (mo->DeathSound.isvalid()) { S_Sound (mo, CHAN_VOICE, 0, mo->DeathSound, 1, (mo->flags3 & MF3_FULLVOLDEATH) ? ATTN_NONE : ATTN_NORM); @@ -1518,7 +1505,7 @@ void AActor::PlayBounceSound(bool onfloor) { S_Sound (this, CHAN_VOICE, 0, SeeSound, 1, ATTN_IDLE); } - else if (onfloor || WallBounceSound <= 0) + else if (onfloor || !WallBounceSound.isvalid()) { S_Sound (this, CHAN_VOICE, 0, BounceSound, 1, ATTN_IDLE); } @@ -1663,12 +1650,12 @@ bool AActor::FloorBounceMissile (secplane_t &plane) // //---------------------------------------------------------------------------- -int P_FaceMobj (AActor *source, AActor *target, DAngle *delta) +static int P_FaceMobj (AActor *source, AActor *target, DAngle *delta) { DAngle diff; diff = deltaangle(source->Angles.Yaw, source->AngleTo(target)); - if (diff > 0) + if (diff > nullAngle) { *delta = diff; return 1; @@ -1716,7 +1703,7 @@ DEFINE_ACTION_FUNCTION(AActor, CanSeek) // //---------------------------------------------------------------------------- -bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise, bool usecurspeed) +bool P_SeekerMissile (AActor *actor, DAngle thresh, DAngle turnMax, bool precise, bool usecurspeed) { int dir; DAngle delta; @@ -1771,10 +1758,10 @@ bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise } else { - DAngle pitch = 0.; + DAngle pitch = nullAngle; if (!(actor->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) { // Need to seek vertically - double dist = MAX(1., actor->Distance2D(target)); + double dist = max(1., actor->Distance2D(target)); // Aim at a player's eyes and at the middle of the actor for everything else. double aimheight = target->Height/2; if (target->player) @@ -1798,7 +1785,7 @@ bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise #define STOPSPEED (0x1000/65536.) #define CARRYSTOPSPEED ((0x1000*32/3)/65536.) -double P_XYMovement (AActor *mo, DVector2 scroll) +static double P_XYMovement (AActor *mo, DVector2 scroll) { static int pushtime = 0; bool bForceSlide = !scroll.isZero(); @@ -1821,16 +1808,16 @@ double P_XYMovement (AActor *mo, DVector2 scroll) switch (special) { case 40: case 41: case 42: // Wind_East - mo->Thrust(0., windTab[special-40]); + mo->Thrust(DAngle::fromDeg(0.), windTab[special-40]); break; case 43: case 44: case 45: // Wind_North - mo->Thrust(90., windTab[special-43]); + mo->Thrust(DAngle::fromDeg(90.), windTab[special-43]); break; case 46: case 47: case 48: // Wind_South - mo->Thrust(270., windTab[special-46]); + mo->Thrust(DAngle::fromDeg(270.), windTab[special-46]); break; case 49: case 50: case 51: // Wind_West - mo->Thrust(180., windTab[special-49]); + mo->Thrust(DAngle::fromDeg(180.), windTab[special-49]); break; } } @@ -1849,7 +1836,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) // preserve the direction instead of clamping x and y independently. double cx = mo->Vel.X == 0 ? 1. : clamp(mo->Vel.X, -maxmove, maxmove) / mo->Vel.X; double cy = mo->Vel.Y == 0 ? 1. : clamp(mo->Vel.Y, -maxmove, maxmove) / mo->Vel.Y; - double fac = MIN(cx, cy); + double fac = min(cx, cy); mo->Vel.X *= fac; mo->Vel.Y *= fac; @@ -2010,7 +1997,9 @@ double P_XYMovement (AActor *mo, DVector2 scroll) (mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove) && mo->BlockingLine->sidedef[1] != NULL) { - mo->Vel.Z = WATER_JUMP_SPEED; + double spd = mo->FloatVar(NAME_WaterClimbSpeed); + if (fabs(spd) >= EQUAL_EPSILON) + mo->Vel.Z = spd; } // If the blocked move executed any push specials that changed the // actor's velocity, do not attempt to slide. @@ -2131,7 +2120,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) { if ((BlockingMobj->flags7 & MF7_MIRRORREFLECT) && (tg | blockingtg)) { - mo->Angles.Yaw += 180.; + mo->Angles.Yaw += DAngle::fromDeg(180.); mo->Vel *= -.5; } else @@ -2213,7 +2202,7 @@ explode: // For that we need to adjust the start point, and the movement vector. DAngle anglediff = deltaangle(oldangle, mo->Angles.Yaw); - if (anglediff != 0) + if (anglediff != nullAngle) { move = move.Rotated(anglediff); oldangle = mo->Angles.Yaw; @@ -2349,8 +2338,8 @@ explode: return Oldfloorz; } -// Move this to p_inter *** -void P_MonsterFallingDamage (AActor *mo) + +static void P_MonsterFallingDamage (AActor *mo) { int damage; double vel; @@ -2377,7 +2366,7 @@ void P_MonsterFallingDamage (AActor *mo) // P_ZMovement // -void P_ZMovement (AActor *mo, double oldfloorz) +static void P_ZMovement (AActor *mo, double oldfloorz) { double dist; double delta; @@ -2395,84 +2384,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) mo->AddZ(mo->Vel.Z); -// -// apply gravity -// - if (mo->Z() > mo->floorz && !(mo->flags & MF_NOGRAVITY)) - { - double startvelz = mo->Vel.Z; - - if (mo->waterlevel == 0 || (mo->player && - !(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove))) - { - // [RH] Double gravity only if running off a ledge. Coming down from - // an upward thrust (e.g. a jump) should not double it. - if (mo->Vel.Z == 0 && oldfloorz > mo->floorz && mo->Z() == oldfloorz) - { - mo->Vel.Z -= grav + grav; - } - else - { - mo->Vel.Z -= grav; - } - } - if (mo->player == NULL) - { - if (mo->waterlevel >= 1) - { - double sinkspeed; - - if ((mo->flags & MF_SPECIAL) && !(mo->flags3 & MF3_ISMONSTER)) - { // Pickup items don't sink if placed and drop slowly if dropped - sinkspeed = (mo->flags & MF_DROPPED) ? -WATER_SINK_SPEED / 8 : 0; - } - else - { - sinkspeed = -WATER_SINK_SPEED; - - // If it's not a player, scale sinkspeed by its mass, with - // 100 being equivalent to a player. - if (mo->player == NULL) - { - sinkspeed = sinkspeed * clamp(mo->Mass, 1, 4000) / 100; - } - } - if (mo->Vel.Z < sinkspeed) - { // Dropping too fast, so slow down toward sinkspeed. - mo->Vel.Z -= MAX(sinkspeed*2, -8.); - if (mo->Vel.Z > sinkspeed) - { - mo->Vel.Z = sinkspeed; - } - } - else if (mo->Vel.Z > sinkspeed) - { // Dropping too slow/going up, so trend toward sinkspeed. - mo->Vel.Z = startvelz + MAX(sinkspeed/3, -8.); - if (mo->Vel.Z < sinkspeed) - { - mo->Vel.Z = sinkspeed; - } - } - } - } - else - { - if (mo->waterlevel > 1) - { - double sinkspeed = -WATER_SINK_SPEED; - - if (mo->Vel.Z < sinkspeed) - { - mo->Vel.Z = (startvelz < sinkspeed) ? startvelz : sinkspeed; - } - else - { - mo->Vel.Z = startvelz + ((mo->Vel.Z - startvelz) * - (mo->waterlevel == 1 ? WATER_SINK_SMALL_FACTOR : WATER_SINK_FACTOR)); - } - } - } - } + mo->CallFallAndSink(grav, oldfloorz); // Hexen compatibility handling for floatbobbing. Ugh... // Hexen yanked all items to the floor, except those being spawned at map start in the air. @@ -2501,9 +2413,12 @@ void P_ZMovement (AActor *mo, double oldfloorz) } if (mo->player && (mo->flags & MF_NOGRAVITY) && (mo->Z() > mo->floorz)) { - if (!mo->IsNoClip2()) + FBaseCVar* const fViewBobCvar = G_GetUserCVar(int(mo->player - players),"FViewBob"); + bool const fViewBob = fViewBobCvar->GetGenericRep(fViewBobCvar->GetRealType()).Bool; + + if (!mo->IsNoClip2() && fViewBob) { - mo->AddZ(DAngle(360 / 80.f * mo->Level->maptime).Sin() / 8); + mo->AddZ(DAngle::fromDeg(360 / 80.f * mo->Level->maptime).Sin() / 8 * mo->FloatVar(NAME_FlyBob)); } if (!(mo->flags8 & MF8_NOFRICTION)) @@ -2777,10 +2692,17 @@ DEFINE_ACTION_FUNCTION(AActor, CheckFakeFloorTriggers) // //=========================================================================== +static void PlayerLandedMakeGruntSound(AActor* self, AActor *onmobj) +{ + IFVIRTUALPTR(self, AActor, PlayerLandedMakeGruntSound) + { + VMValue params[2] = { self, onmobj }; + VMCall(func, params, 2, nullptr, 0); + } +} + static void PlayerLandedOnThing (AActor *mo, AActor *onmobj) { - bool grunted; - if (!mo->player) return; @@ -2794,28 +2716,117 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj) P_FallingDamage (mo); - // [RH] only make noise if alive - if (mo->health > 0 && !mo->player->morphTics) - { - grunted = false; - // Why should this number vary by gravity? - if (mo->Vel.Z < -mo->player->mo->FloatVar(NAME_GruntSpeed)) - { - S_Sound (mo, CHAN_VOICE, 0, "*grunt", 1, ATTN_NORM); - grunted = true; - } - if (onmobj != NULL || !Terrains[P_GetThingFloorType (mo)].IsLiquid) - { - if (!grunted || !S_AreSoundsEquivalent (mo, "*grunt", "*land")) - { - S_Sound (mo, CHAN_AUTO, 0, "*land", 1, ATTN_NORM); - } - } - } + PlayerLandedMakeGruntSound(mo, onmobj); + // mo->player->centering = true; } +//========================================================================== +// +// AActor :: FallAndSink +// +//========================================================================== +void AActor::FallAndSink(double grav, double oldfloorz) +{ + if (Z() > floorz && !(flags & MF_NOGRAVITY)) + { + double startvelz = Vel.Z; + + if (waterlevel == 0 || (player && + !(player->cmd.ucmd.forwardmove | player->cmd.ucmd.sidemove))) + { + // [RH] Double gravity only if running off a ledge. Coming down from + // an upward thrust (e.g. a jump) should not double it. + if (Vel.Z == 0 && oldfloorz > floorz && Z() == oldfloorz) + { + Vel.Z -= grav + grav; + } + else + { + Vel.Z -= grav; + } + } + if (player == NULL) + { + if (waterlevel >= 1) + { + double sinkspeed; + + if ((flags & MF_SPECIAL) && !(flags3 & MF3_ISMONSTER)) + { // Pickup items don't sink if placed and drop slowly if dropped + sinkspeed = (flags & MF_DROPPED) ? -WATER_SINK_SPEED / 8 : 0; + } + else + { + sinkspeed = -WATER_SINK_SPEED; + + // If it's not a player, scale sinkspeed by its mass, with + // 100 being equivalent to a player. + if (player == NULL) + { + sinkspeed = sinkspeed * clamp(Mass, 1, 4000) / 100; + } + } + if (Vel.Z < sinkspeed) + { // Dropping too fast, so slow down toward sinkspeed. + Vel.Z -= max(sinkspeed * 2, -8.); + if (Vel.Z > sinkspeed) + { + Vel.Z = sinkspeed; + } + } + else if (Vel.Z > sinkspeed) + { // Dropping too slow/going up, so trend toward sinkspeed. + Vel.Z = startvelz + max(sinkspeed / 3, -8.); + if (Vel.Z < sinkspeed) + { + Vel.Z = sinkspeed; + } + } + } + } + else + { + if (waterlevel > 1) + { + double sinkspeed = -WATER_SINK_SPEED; + + if (Vel.Z < sinkspeed) + { + Vel.Z = (startvelz < sinkspeed) ? startvelz : sinkspeed; + } + else + { + Vel.Z = startvelz + ((Vel.Z - startvelz) * + (waterlevel == 1 ? WATER_SINK_SMALL_FACTOR : WATER_SINK_FACTOR)); + } + } + } + } +} + +DEFINE_ACTION_FUNCTION(AActor, FallAndSink) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(grav); + PARAM_FLOAT(oldfloorz); + self->FallAndSink(grav, oldfloorz); + return 0; +} + +void AActor::CallFallAndSink(double grav, double oldfloorz) +{ + IFVIRTUAL(AActor, FallAndSink) + { + VMValue params[3] = { (DObject*)this, grav, oldfloorz }; + VMCall(func, params, 3, nullptr, 0); + } + else + { + FallAndSink(grav, oldfloorz); + } +} // // P_NightmareRespawn @@ -2893,7 +2904,7 @@ void P_NightmareRespawn (AActor *mobj) mo->SpawnPoint = mobj->SpawnPoint; mo->SpawnAngle = mobj->SpawnAngle; mo->SpawnFlags = mobj->SpawnFlags & ~MTF_DORMANT; // It wasn't dormant when it died, so it's not dormant now, either. - mo->Angles.Yaw = (double)mobj->SpawnAngle; + mo->Angles.Yaw = DAngle::fromDeg(mobj->SpawnAngle); mo->HandleSpawnFlags (); mo->reactiontime = 18; @@ -3135,6 +3146,12 @@ DEFINE_ACTION_FUNCTION(AActor, Howl) bool AActor::Slam (AActor *thing) { + if ((flags8 & MF8_ONLYSLAMSOLID) + && !(thing->flags & MF_SOLID) && !(thing->flags & MF_SHOOTABLE)) + { + return true; + } + flags &= ~MF_SKULLFLY; Vel.Zero(); if (health > 0) @@ -3147,8 +3164,13 @@ bool AActor::Slam (AActor *thing) // The charging monster may have died by the target's actions here. if (health > 0) { - if (SeeState != NULL && !(flags8 & MF8_RETARGETAFTERSLAM)) SetState (SeeState); - else SetIdle(); + FState *slam = FindState(NAME_Slam); + if (slam != NULL) + SetState(slam); + else if (SeeState != NULL && !(flags8 & MF8_RETARGETAFTERSLAM)) + SetState (SeeState); + else + SetIdle(); } } else @@ -3207,28 +3229,28 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) if (thing->flags4&MF4_SHIELDREFLECT) { // Shield reflection (from the Centaur) - if (absangle(angle, thing->Angles.Yaw) > 45) + if (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 += 45; + angle += DAngle::fromDeg(45); else - angle -= 45; + angle -= DAngle::fromDeg(45); } else if (thing->flags4&MF4_DEFLECT) { // deflect (like the Heresiarch) if(pr_reflect() < 128) - angle += 45; + angle += DAngle::fromDeg(45); else - angle -= 45; + angle -= DAngle::fromDeg(45); } else { - angle += ((pr_reflect() % 16) - 8); + angle += DAngle::fromDeg((pr_reflect() % 16) - 8); } //Always check for AIMREFLECT, no matter what else is checked above. if (thing->flags7 & MF7_AIMREFLECT) @@ -3283,7 +3305,7 @@ void AActor::AlterWeaponSprite(visstyle_t *vis) void AActor::PlayActiveSound () { - if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1)) + if (ActiveSound.isvalid() && !S_IsActorPlayingSomething(this, CHAN_VOICE)) { S_Sound (this, CHAN_VOICE, 0, ActiveSound, 1, (flags3 & MF3_FULLVOLACTIVE) ? ATTN_NONE : ATTN_IDLE); @@ -3297,6 +3319,22 @@ DEFINE_ACTION_FUNCTION(AActor, PlayActiveSound) return 0; } +void AActor::PlayPushSound() +{ + FSoundID push = SoundVar(NAME_PushSound); + if (!S_IsActorPlayingSomething(this, CHAN_BODY, push)) + { + S_Sound(this, CHAN_BODY, 0, push, 1, ATTN_NORM); + } +} + +DEFINE_ACTION_FUNCTION(AActor, PlayPushSound) +{ + PARAM_SELF_PROLOGUE(AActor); + self->PlayPushSound(); + return 0; +} + bool AActor::IsOkayToAttack (AActor *link) { // Standard things to eliminate: an actor shouldn't attack itself, @@ -3331,11 +3369,11 @@ bool AActor::IsOkayToAttack (AActor *link) if (P_CheckSight (this, link)) { // AMageStaffFX2::IsOkayToAttack had an extra check here, generalized with a flag, - // to only allow the check to succeed if the enemy was in a ~84� FOV of the player + // to only allow the check to succeed if the enemy was in a ~84 FOV of the player if (flags3 & MF3_SCREENSEEKER) { DAngle angle = absangle(Friend->AngleTo(link), Friend->Angles.Yaw); - if (angle < 30 * (256./360.)) + if (angle < DAngle::fromDeg(30 * (256./360.))) { return true; } @@ -3379,8 +3417,8 @@ DAngle AActor::ClampPitch(DAngle p) } else { - min = -89.; - max = 89.; + min = DAngle::fromDeg(-89.); + max = DAngle::fromDeg(89.); } p = clamp(p, min, max); return p; @@ -3395,10 +3433,29 @@ void AActor::SetPitch(DAngle p, int fflags) if (p != Angles.Pitch) { - Angles.Pitch = p; - if (player != nullptr && (fflags & SPF_INTERPOLATE)) + if (player != nullptr) { - player->cheats |= CF_INTERPVIEW; + 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) + { + player->angleTargets.Pitch = deltaangle(Angles.Pitch, p); + player->angleAppliedAmounts.Pitch = nullAngle; + player->cheats |= CF_SCALEDNOLERP; + } + else + { + Angles.Pitch = p; + } + } + else + { + Angles.Pitch = p; } } @@ -3408,10 +3465,29 @@ void AActor::SetAngle(DAngle ang, int fflags) { if (ang != Angles.Yaw) { - Angles.Yaw = ang; - if (player != nullptr && (fflags & SPF_INTERPOLATE)) + if (player != nullptr) { - player->cheats |= CF_INTERPVIEW; + 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) + { + player->angleTargets.Yaw = deltaangle(Angles.Yaw, ang); + player->angleAppliedAmounts.Yaw = nullAngle; + player->cheats |= CF_SCALEDNOLERP; + } + else + { + Angles.Yaw = ang; + } + } + else + { + Angles.Yaw = ang; } } @@ -3421,10 +3497,29 @@ void AActor::SetRoll(DAngle r, int fflags) { if (r != Angles.Roll) { - Angles.Roll = r; - if (player != nullptr && (fflags & SPF_INTERPOLATE)) + if (player != nullptr) { - player->cheats |= CF_INTERPVIEW; + 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) + { + player->angleTargets.Roll = deltaangle(Angles.Roll, r); + player->angleAppliedAmounts.Roll = nullAngle; + player->cheats |= CF_SCALEDNOLERP; + } + else + { + Angles.Roll = r; + } + } + else + { + Angles.Roll = r; } } } @@ -3441,7 +3536,7 @@ void AActor::SetViewPitch(DAngle p, int fflags) ViewAngles.Pitch = p; if (player != nullptr && (fflags & SPF_INTERPOLATE)) { - player->cheats |= CF_INTERPVIEW; + player->cheats |= CF_INTERPVIEWANGLES; } } @@ -3454,12 +3549,34 @@ void AActor::SetViewAngle(DAngle ang, int fflags) ViewAngles.Yaw = ang; if (player != nullptr && (fflags & SPF_INTERPOLATE)) { - player->cheats |= CF_INTERPVIEW; + player->cheats |= CF_INTERPVIEWANGLES; } } } +double AActor::GetFOV(double ticFrac) +{ + // [B] Disable interpolation when playing online, otherwise it gets vomit inducing + if (netgame) + return player ? player->FOV : CameraFOV; + + double fov; + if (player) + { + if (player->cheats & CF_NOFOVINTERP) + return player->FOV; + + fov = player->FOV; + } + else + { + fov = CameraFOV; + } + + return PrevFOV.Degrees() * (1 - ticFrac) + fov * ticFrac; +} + void AActor::SetViewRoll(DAngle r, int fflags) { if (r != ViewAngles.Roll) @@ -3467,7 +3584,7 @@ void AActor::SetViewRoll(DAngle r, int fflags) ViewAngles.Roll = r; if (player != nullptr && (fflags & SPF_INTERPOLATE)) { - player->cheats |= CF_INTERPVIEW; + player->cheats |= CF_INTERPVIEWANGLES; } } } @@ -3590,6 +3707,11 @@ void AActor::Tick () static const uint8_t HereticScrollDirs[4] = { 6, 9, 1, 4 }; static const uint8_t HereticSpeedMuls[5] = { 5, 10, 25, 30, 35 }; + if (freezetics > 0) + { + freezetics--; + return; + } AActor *onmo; @@ -3859,7 +3981,7 @@ void AActor::Tick () { // Strife scroll special int anglespeed = Level->GetFirstSectorTag(sec) - 100; double carryspeed = (anglespeed % 10) / (16 * CARRYFACTOR); - DAngle angle = ((anglespeed / 10) * 45.); + DAngle angle = DAngle::fromDeg(((anglespeed / 10) * 45.)); scrollv += angle.ToVector(carryspeed); } } @@ -4238,6 +4360,101 @@ void AActor::CheckSectorTransition(sector_t *oldsec) } } +//========================================================================== +// +// UpdateWaterDepth +// +// Updates the actor's current waterlevel and waterdepth. +// Consolidates common code in UpdateWaterLevel and SplashCheck. +// +// Returns the floor height used for the depth check, or -FLT_MAX +// if the actor wasn't in a sector. +// +//========================================================================== + +static double UpdateWaterDepth(AActor* actor, bool splash) +{ + double fh = -FLT_MAX; + bool reset = false; + + actor->waterlevel = 0; + actor->waterdepth = 0; + + if (actor->Sector == NULL) + { + return fh; + } + + if (actor->Sector->MoreFlags & SECMF_UNDERWATER) // intentionally not SECMF_UNDERWATERMASK + { + actor->waterdepth = actor->Height; + } + else + { + const sector_t *hsec = actor->Sector->GetHeightSec(); + if (hsec != NULL) + { + fh = hsec->floorplane.ZatPoint(actor); + + // splash checks also check Boom-style non-swimmable sectors + // as well as non-solid, visible 3D floors (below) + if (splash || hsec->MoreFlags & SECMF_UNDERWATERMASK) + { + actor->waterdepth = fh - actor->Z(); + + if (actor->waterdepth <= 0 && !(hsec->MoreFlags & SECMF_FAKEFLOORONLY) && (actor->Top() > hsec->ceilingplane.ZatPoint(actor))) + { + actor->waterdepth = actor->Height; + } + } + } + else + { + // Check 3D floors as well! + for (auto rover : actor->Sector->e->XFloor.ffloors) + { + if (!(rover->flags & FF_EXISTS)) continue; + if (rover->flags & FF_SOLID) continue; + + bool reset = !(rover->flags & FF_SWIMMABLE); + if (splash) { reset &= rover->alpha == 0; } + if (reset) continue; + + double ff_bottom = rover->bottom.plane->ZatPoint(actor); + double ff_top = rover->top.plane->ZatPoint(actor); + + if (ff_top <= actor->Z() || ff_bottom > actor->Center()) continue; + + fh = ff_top; + actor->waterdepth = ff_top - actor->Z(); + break; + } + } + } + + if (actor->waterdepth < 0) { actor->waterdepth = 0; } + + if (actor->waterdepth > (actor->Height / 2)) + { + // When noclipping around and going from low to high sector, your view height + // can go negative, which is why this is nested inside here + if ((actor->player && (actor->waterdepth >= actor->player->viewheight)) || (actor->waterdepth >= actor->Height)) + { + actor->waterlevel = 3; + } + else + { + actor->waterlevel = 2; + } + } + else if (actor->waterdepth > 0) + { + actor->waterlevel = 1; + } + + return fh; +} + //========================================================================== // // AActor::SplashCheck @@ -4248,85 +4465,7 @@ void AActor::CheckSectorTransition(sector_t *oldsec) void AActor::SplashCheck() { - double fh = -FLT_MAX; - bool reset = false; - - waterlevel = 0; - - if (Sector == NULL) - { - return; - } - - if (Sector->MoreFlags & SECMF_UNDERWATER) // intentionally not SECMF_UNDERWATERMASK - { - waterlevel = 3; - } - else - { - const sector_t *hsec = Sector->GetHeightSec(); - if (hsec != NULL) - { - fh = hsec->floorplane.ZatPoint(this); - //if (hsec->MoreFlags & SECMF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors - { - if (Z() < fh) - { - waterlevel = 1; - if (Center() < fh) - { - waterlevel = 2; - if ((player && Z() + player->viewheight <= fh) || - (Top() <= fh)) - { - waterlevel = 3; - } - } - } - else if (!(hsec->MoreFlags & SECMF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this))) - { - waterlevel = 3; - } - else - { - waterlevel = 0; - } - } - } - else - { - // Check 3D floors as well! - for (auto rover : Sector->e->XFloor.ffloors) - { - if (!(rover->flags & FF_EXISTS)) continue; - if (rover->flags & FF_SOLID) continue; - - bool reset = !(rover->flags & FF_SWIMMABLE); - if (reset && rover->alpha == 0) continue; - double ff_bottom = rover->bottom.plane->ZatPoint(this); - double ff_top = rover->top.plane->ZatPoint(this); - - if (ff_top <= Z() || ff_bottom > (Center())) continue; - - fh = ff_top; - if (Z() < fh) - { - waterlevel = 1; - if (Center() < fh) - { - waterlevel = 2; - if ((player && Z() + player->viewheight <= fh) || - (Top() <= fh)) - { - waterlevel = 3; - } - } - } - - break; - } - } - } + double fh = UpdateWaterDepth(this, true); // some additional checks to make deep sectors like Boom's splash without setting // the water flags. @@ -4351,103 +4490,33 @@ bool AActor::UpdateWaterLevel(bool dosplash) int oldlevel = waterlevel; if (dosplash) SplashCheck(); + UpdateWaterDepth(this, false); - double fh = -FLT_MAX; - bool reset = false; + // Play surfacing and diving sounds, as appropriate. + // + // (used to be that this code was wrapped around a "Sector != nullptr" check, + // but actors should always be within a sector, and besides, this is just + // sound stuff) - waterlevel = 0; - - if (Sector != nullptr) + if (player != nullptr) { - if (Sector->MoreFlags & SECMF_UNDERWATER) // intentionally not SECMF_UNDERWATERMASK + if (oldlevel < 3 && waterlevel == 3) { - waterlevel = 3; + // Our head just went under. + S_Sound(this, CHAN_VOICE, 0, "*dive", 1, ATTN_NORM); } - else + else if (oldlevel == 3 && waterlevel < 3) { - const sector_t *hsec = Sector->GetHeightSec(); - if (hsec != NULL) + // Our head just came up. + if (player->air_finished > Level->maptime) { - fh = hsec->floorplane.ZatPoint(this); - if (hsec->MoreFlags & SECMF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors - { - if (Z() < fh) - { - waterlevel = 1; - if (Center() < fh) - { - waterlevel = 2; - if ((player && Z() + player->viewheight <= fh) || - (Top() <= fh)) - { - waterlevel = 3; - } - } - } - else if (!(hsec->MoreFlags & SECMF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this))) - { - waterlevel = 3; - } - else - { - waterlevel = 0; - } - } - } - else - { - // Check 3D floors as well! - for (auto rover : Sector->e->XFloor.ffloors) - { - if (!(rover->flags & FF_EXISTS)) continue; - if (rover->flags & FF_SOLID) continue; - if (!(rover->flags & FF_SWIMMABLE)) continue; - - double ff_bottom = rover->bottom.plane->ZatPoint(this); - double ff_top = rover->top.plane->ZatPoint(this); - - if (ff_top <= Z() || ff_bottom > (Center())) continue; - - fh = ff_top; - if (Z() < fh) - { - waterlevel = 1; - if (Center() < fh) - { - waterlevel = 2; - if ((player && Z() + player->viewheight <= fh) || - (Top() <= fh)) - { - waterlevel = 3; - } - } - } - - break; - } - } - } - - // Play surfacing and diving sounds, as appropriate. - if (player != nullptr) - { - if (oldlevel < 3 && waterlevel == 3) - { - // Our head just went under. - S_Sound(this, CHAN_VOICE, 0, "*dive", 1, ATTN_NORM); - } - else if (oldlevel == 3 && waterlevel < 3) - { - // Our head just came up. - if (player->air_finished > Level->maptime) - { - // We hadn't run out of air yet. - S_Sound(this, CHAN_VOICE, 0, "*surface", 1, ATTN_NORM); - } - // If we were running out of air, then ResetAirSupply() will play *gasp. + // We hadn't run out of air yet. + S_Sound(this, CHAN_VOICE, 0, "*surface", 1, ATTN_NORM); } + // If we were running out of air, then ResetAirSupply() will play *gasp. } } + return false; // we did the splash ourselves } @@ -4522,6 +4591,7 @@ void ConstructActor(AActor *actor, const DVector3 &pos, bool SpawningMapThing) // set subsector and/or block links actor->LinkToWorld (nullptr, SpawningMapThing); actor->ClearInterpolation(); + actor->ClearFOVInterpolation(); actor->dropoffz = actor->floorz = actor->Sector->floorplane.ZatPoint(pos); actor->ceilingz = actor->Sector->ceilingplane.ZatPoint(pos); @@ -4943,7 +5013,7 @@ void AActor::OnDestroy () ClearRenderLineList(); // [RH] Destroy any inventory this actor is carrying - DestroyAllInventory (); + DestroyAllInventory (this); // [RH] Unlink from tid chain RemoveFromHash (); @@ -4952,6 +5022,12 @@ void AActor::OnDestroy () UnlinkFromWorld (nullptr); flags |= MF_NOSECTOR|MF_NOBLOCKMAP; + if (ViewPos != nullptr) + { + ViewPos->Destroy(); + ViewPos = nullptr; + } + // Transform any playing sound into positioned, non-actor sounds. S_RelinkSound (this, NULL); @@ -5176,10 +5252,10 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag spawn.Y = mthing->pos.Y; // Allow full angular precision - SpawnAngle = (double)mthing->angle; + SpawnAngle = DAngle::fromDeg(mthing->angle); if (i_compatflags2 & COMPATF2_BADANGLES) { - SpawnAngle += 0.01; + SpawnAngle += DAngle::fromDeg(0.01); } if (GetDefaultByType(p->cls)->flags & MF_SPAWNCEILING) @@ -5234,7 +5310,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag } mobj->Angles.Yaw = SpawnAngle; - mobj->Angles.Pitch = mobj->Angles.Roll = 0.; + mobj->Angles.Pitch = mobj->Angles.Roll = nullAngle; mobj->health = p->health; // [RH] Set player sprite based on skin @@ -5264,7 +5340,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag p->lastkilltime = 0; p->BlendR = p->BlendG = p->BlendB = p->BlendA = 0.f; p->Uncrouch(); - p->MinPitch = p->MaxPitch = 0.; // will be filled in by PostBeginPlay()/netcode + p->MinPitch = p->MaxPitch = nullAngle; // will be filled in by PostBeginPlay()/netcode p->MUSINFOactor = nullptr; p->MUSINFOtics = -1; p->Vel.Zero(); // killough 10/98: initialize bobbing to 0. @@ -5313,7 +5389,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag if (oldactor != NULL) { // Remove any inventory left from the old actor. Coop handles // it above, but the other modes don't. - oldactor->DestroyAllInventory(); + DestroyAllInventory(oldactor); } // [BC] Handle temporary invulnerability when respawned if (state == PST_REBORN || state == PST_ENTER) @@ -5700,7 +5776,7 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) // [RH] Add ThingID to mobj and link it in with the others mobj->SetTID(mthing->thingid); - mobj->PrevAngles.Yaw = mobj->Angles.Yaw = (double)mthing->angle; + mobj->PrevAngles.Yaw = mobj->Angles.Yaw = DAngle::fromDeg(mthing->angle); // Check if this actor's mapthing has a conversation defined if (mthing->Conversation > 0) @@ -5724,9 +5800,9 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) if (mthing->Scale.Y != 0) mobj->Scale.Y = mthing->Scale.Y * mobj->Scale.Y; if (mthing->pitch) - mobj->Angles.Pitch = (double)mthing->pitch; + mobj->Angles.Pitch = DAngle::fromDeg(mthing->pitch); if (mthing->roll) - mobj->Angles.Roll = (double)mthing->roll; + mobj->Angles.Roll = DAngle::fromDeg(mthing->roll); if (mthing->score) mobj->Score = mthing->score; if (mthing->fillcolor) @@ -5752,8 +5828,8 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) if (mobj->IntVar(NAME_lightflags) & LF_SPOT) { - mobj->AngleVar(NAME_SpotInnerAngle) = double(mthing->args[1]); - mobj->AngleVar(NAME_SpotOuterAngle) = double(mthing->args[2]); + mobj->AngleVar(NAME_SpotInnerAngle) = DAngle::fromDeg(mthing->args[1]); + mobj->AngleVar(NAME_SpotOuterAngle) = DAngle::fromDeg(mthing->args[2]); } } @@ -5768,7 +5844,12 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) else mobj->health = -int(mthing->Health); if (mthing->Health == 0) - mobj->CallDie(NULL, NULL); + { + // We cannot call 'Die' here directly because the level is not yet fully set up. + // This needs to be delayed by one tic. + auto state = mobj->FindState(NAME_DieFromSpawn); + if (state) mobj->SetState(state, true); + } else if (mthing->Health != 1) mobj->StartHealth = mobj->health; @@ -5836,7 +5917,7 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 puff->target = source; // Angle is the opposite of the hit direction (i.e. the puff faces the source.) - puff->Angles.Yaw = hitdir + 180; + puff->Angles.Yaw = hitdir + DAngle::fromDeg(180); // If a puff has a crash state and an actor was not hit, // it will enter the crash state. This is used by the StrifeSpark @@ -5869,11 +5950,11 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 if (cl_pufftype == 1) puff->renderflags |= RF_INVISIBLE; } - if ((flags & PF_HITTHING) && puff->SeeSound) + if ((flags & PF_HITTHING) && puff->SeeSound.isvalid()) { // Hit thing sound S_Sound (puff, CHAN_BODY, 0, puff->SeeSound, 1, ATTN_NORM); } - else if (puff->AttackSound) + else if (puff->AttackSound.isvalid()) { S_Sound (puff, CHAN_BODY, 0, puff->AttackSound, 1, ATTN_NORM); } @@ -6040,7 +6121,7 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle) } if (bloodtype >= 1) { - P_DrawSplash2 (originator->Level, 40, pos, hitangle-180., 2, originator->BloodColor); + P_DrawSplash2 (originator->Level, 40, pos, hitangle - DAngle::fromDeg(180.), 2, originator->BloodColor); } } @@ -6081,7 +6162,7 @@ void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle) } if (bloodtype >= 1) { - P_DrawSplash2(originator->Level, 40, pos + add, hitangle - 180., 2, originator->BloodColor); + P_DrawSplash2(originator->Level, 40, pos + add, hitangle - DAngle::fromDeg(180.), 2, originator->BloodColor); } } @@ -6141,7 +6222,7 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) } if (bloodtype >= 1) { - P_DrawSplash2(bleeder->Level, 28, pos, bleeder->AngleTo(mo) + 180., 0, bleeder->BloodColor); + P_DrawSplash2(bleeder->Level, 28, pos, bleeder->AngleTo(mo) + DAngle::fromDeg(180.), 0, bleeder->BloodColor); } } @@ -6273,6 +6354,7 @@ foundone: if (smallsplash && splash->SmallSplash) { mo = Spawn(sec->Level, splash->SmallSplash, pos, ALLOW_REPLACE); + mo->target = thing; if (mo) mo->Floorclip += splash->SmallSplashClip; } else @@ -6294,6 +6376,7 @@ foundone: if (splash->SplashBase) { mo = Spawn(sec->Level, splash->SplashBase, pos, ALLOW_REPLACE); + mo->target = thing; } if (thing->player && !splash->NoAlert && alert) { @@ -6501,7 +6584,7 @@ DEFINE_ACTION_FUNCTION(AActor, CheckMissileSpawn) void P_PlaySpawnSound(AActor *missile, AActor *spawner) { - if (missile->SeeSound != 0) + if (missile->SeeSound != NO_SOUND) { if (!(missile->flags & MF_SPAWNSOUNDSOURCE)) { @@ -6606,7 +6689,7 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct // [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 = pr_spawnmissile.Random2() * (22.5 / 256); + DAngle an = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)); double c = an.Cos(); double s = an.Sin(); @@ -6693,7 +6776,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct th->VelFromAngle(); - double dist = source->DistanceBySpeed(dest, MAX(1., th->Speed)); + double dist = source->DistanceBySpeed(dest, max(1., th->Speed)); th->Vel.Z = (dest->Z() - source->Z()) / dist; if (th->flags4 & MF4_SPECTRAL) @@ -6739,7 +6822,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActo if (dest->flags & MF_SHADOW) { - an += pr_spawnmissile.Random2() * (16. / 360.); + an += DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)); } dist = source->Distance2D (dest); speed = GetDefaultSpeed (type); @@ -6869,13 +6952,14 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, { return nullptr; } + aimflags &= ~ALF_IGNORENOAUTOAIM; // just to be safe. static const double angdiff[3] = { -5.625, 5.625, 0 }; DAngle an = angle; DAngle pitch; FTranslatedLineTarget scratch; AActor *defaultobject = GetDefaultByType(type); - DAngle vrange = nofreeaim ? 35. : 0.; + DAngle vrange = DAngle::fromDeg(nofreeaim ? 35. : 0.); if (!pLineTarget) pLineTarget = &scratch; if (!(aimflags & ALF_NOWEAPONCHECK) && source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->IntVar(NAME_WeaponFlags) & WIF_NOAUTOAIM) || noautoaim)) @@ -6895,7 +6979,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, int i = 2; do { - an = angle + angdiff[i]; + an = angle + DAngle::fromDeg(angdiff[i]); pitch = P_AimLineAttack (source, an, linetargetrange, pLineTarget, vrange, aimflags); if (source->player != NULL && @@ -6912,7 +6996,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, double x, double y, double z, an = angle; if (nofreeaim || !source->Level->IsFreelookAllowed()) { - pitch = 0.; + pitch = nullAngle; } } } @@ -6966,7 +7050,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile) PARAM_BOOL(noautoaim); PARAM_INT(aimflags); AActor *missileactor; - if (angle == 1e37) angle = self->Angles.Yaw; + if (angle == DAngle::fromDeg(1e37)) angle = self->Angles.Yaw; AActor *misl = P_SpawnPlayerMissile(self, x, y, z, type, angle, lt, &missileactor, nofreeaim, noautoaim, aimflags); if (numret > 0) ret[0].SetObject(misl); if (numret > 1) ret[1].SetObject(missileactor), numret = 2; diff --git a/src/playsim/p_pspr.cpp b/src/playsim/p_pspr.cpp index 91a07d8ec..b32ce67e6 100644 --- a/src/playsim/p_pspr.cpp +++ b/src/playsim/p_pspr.cpp @@ -36,7 +36,7 @@ #include "s_sound.h" #include "doomstat.h" #include "p_pspr.h" -#include "templates.h" + #include "g_level.h" #include "d_player.h" #include "serializer_doom.h" @@ -90,7 +90,7 @@ enum EWRF_Options // [SO] 1=Weapons states are all 1 tick // 2=states with a function 1 tick, others 0 ticks. -CVAR(Int, sv_fastweapons, false, CVAR_SERVERINFO); +CVAR(Int, sv_fastweapons, 0, CVAR_SERVERINFO); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -132,6 +132,7 @@ DEFINE_FIELD(DPSprite, x) DEFINE_FIELD(DPSprite, y) DEFINE_FIELD(DPSprite, oldx) DEFINE_FIELD(DPSprite, oldy) +DEFINE_FIELD(DPSprite, baseScale) DEFINE_FIELD(DPSprite, pivot) DEFINE_FIELD(DPSprite, scale) DEFINE_FIELD(DPSprite, rotation) @@ -172,7 +173,6 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) Tics(0), Translation(0), Flags(0), - Caller(caller), Owner(owner), State(nullptr), Sprite(0), @@ -180,7 +180,9 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) ID(id), processPending(true) { - rotation = 0.; + Caller = caller; + baseScale = {1.0, 1.2}; + rotation = nullAngle; scale = {1.0, 1.0}; pivot = {0.0, 0.0}; for (int i = 0; i < 4; i++) @@ -250,6 +252,26 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, FindPSprite) // the underscore is needed to } +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +static DPSprite *P_CreatePsprite(player_t *player, AActor *caller, int layer) +{ + DPSprite *pspr = Create(player, caller, layer); + + // [XA] apply WeaponScaleX/WeaponScaleY properties for weapon psprites + if (caller != nullptr && caller->IsKindOf(NAME_Weapon)) + { + pspr->baseScale.X = caller->FloatVar(NAME_WeaponScaleX); + pspr->baseScale.Y = caller->FloatVar(NAME_WeaponScaleY); + } + + return pspr; +} + //------------------------------------------------------------------------ // // @@ -294,12 +316,12 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) newcaller = ReadyWeapon; } - if (newcaller == nullptr) return nullptr; // Error case was not handled properly. This function cannot give a guarantee to always succeed! + if (newcaller == nullptr || layer == PSP_CALLERID) return nullptr; // Error case was not handled properly. This function cannot give a guarantee to always succeed! DPSprite *pspr = FindPSprite(layer); if (pspr == nullptr) { - pspr = Create(this, newcaller, layer); + pspr = P_CreatePsprite(this, newcaller, layer); } else { @@ -619,6 +641,26 @@ 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) { + IFVIRTUALPTRNAME(player->mo, NAME_PlayerPawn, BobWeapon3D) + { + VMValue param[] = { player->mo, ticfrac }; + DVector3 t, r; + VMReturn returns[2]; + returns[0].Vec3At(&t); + returns[1].Vec3At(&r); + VMCall(func, param, 2, returns, 2); + translation->X = (float)t.X; + translation->Y = (float)t.Y; + translation->Z = (float)t.Z; + rotation->X = (float)r.X; + rotation->Y = (float)r.Y; + rotation->Z = (float)r.Z; + return; + } + *translation = *rotation = {}; +} + //--------------------------------------------------------------------------- // // PROC P_CheckWeaponButtons @@ -1110,7 +1152,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Overlay) } DPSprite *pspr; - pspr = Create(player, stateowner, layer); + pspr = P_CreatePsprite(player, stateowner, layer); pspr->SetState(state); ACTION_RETURN_BOOL(true); } @@ -1176,13 +1218,14 @@ DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget, int aimfla DAngle pitch; FTranslatedLineTarget scratch; + aimflags &= ~ALF_IGNORENOAUTOAIM; // just to be safe. if (pLineTarget == NULL) pLineTarget = &scratch; // see which target is to be aimed at i = 2; do { - an = mo->Angles.Yaw + angdiff[i]; - pitch = P_AimLineAttack (mo, an, 16.*64, pLineTarget, 0., aimflags); + an = mo->Angles.Yaw + DAngle::fromDeg(angdiff[i]); + pitch = P_AimLineAttack (mo, an, 16.*64, pLineTarget, nullAngle, aimflags); if (mo->player != nullptr && mo->Level->IsFreelookAllowed() && @@ -1200,7 +1243,7 @@ DEFINE_ACTION_FUNCTION(AActor, BulletSlope) PARAM_SELF_PROLOGUE(AActor); PARAM_POINTER(t, FTranslatedLineTarget); PARAM_INT(aimflags); - ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees); + ACTION_RETURN_FLOAT(P_BulletSlope(self, t, aimflags).Degrees()); } //------------------------------------------------------------------------ @@ -1251,7 +1294,8 @@ void DPSprite::Serialize(FSerializer &arc) ("rotation", rotation) ("halign", HAlign) ("valign", VAlign) - ("renderstyle_", Renderstyle); // The underscore is intentional to avoid problems with old savegames which had this as an ERenderStyle (which is not future proof.) + ("renderstyle_", Renderstyle) // The underscore is intentional to avoid problems with old savegames which had this as an ERenderStyle (which is not future proof.) + ("baseScale", baseScale); } //------------------------------------------------------------------------ diff --git a/src/playsim/p_pspr.h b/src/playsim/p_pspr.h index df5b45f54..85add7b6b 100644 --- a/src/playsim/p_pspr.h +++ b/src/playsim/p_pspr.h @@ -51,6 +51,7 @@ class player_t; enum PSPLayers { PSP_STRIFEHANDS = -1, + PSP_CALLERID = 0, PSP_WEAPON = 1, PSP_FLASH = 1000, PSP_TARGETCENTER = INT_MAX - 2, @@ -114,9 +115,10 @@ public: float GetYAdjust(bool fullscreen); int HAlign, VAlign; // Horizontal and vertical alignment + DVector2 baseScale; // Base scale (set by weapon); defaults to (1.0, 1.2) since that's Doom's native aspect ratio DAngle rotation; // How much rotation to apply. DVector2 pivot; // pivot points - DVector2 scale; // Scale + DVector2 scale; // Dynamic scale (set by A_Overlay functions) double x, y, alpha; double oldx, oldy; bool InterpolateTic; // One tic interpolation (WOF_INTERPOLATE) @@ -154,6 +156,7 @@ void P_SetPsprite(player_t *player, PSPLayers id, FState *state, bool pending = void P_BringUpWeapon (player_t *player); void P_FireWeapon (player_t *player); void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac); +void P_BobWeapon3D (player_t *player, FVector3 *translation, FVector3 *rotation, double ticfrac); DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0); AActor *P_AimTarget(AActor *mo); diff --git a/src/playsim/p_secnodes.cpp b/src/playsim/p_secnodes.cpp index 3e479e77c..f43b0e30e 100644 --- a/src/playsim/p_secnodes.cpp +++ b/src/playsim/p_secnodes.cpp @@ -390,7 +390,7 @@ void AActor::UpdateRenderSectorList() { int bx = Level->blockmap.GetBlockX(X()); int by = Level->blockmap.GetBlockY(Y()); - FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors + FBoundingBox bb(X(), Y(), min(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors // Are there any portals near the actor's position? if (Level->blockmap.isValidBlock(bx, by) && Level->PortalBlockmap(bx, by).neighborContainsLines) { diff --git a/src/playsim/p_sectors.cpp b/src/playsim/p_sectors.cpp index 448808265..a194f177a 100644 --- a/src/playsim/p_sectors.cpp +++ b/src/playsim/p_sectors.cpp @@ -78,7 +78,7 @@ // //========================================================================== -CUSTOM_CVAR(Int, r_fakecontrast, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, r_fakecontrast, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (self < 0) self = 1; else if (self > 2) self = 2; @@ -89,27 +89,44 @@ CUSTOM_CVAR(Int, r_fakecontrast, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // // Returns the next special sector attached to this sector // with a certain special. -sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const + +sector_t* P_NextSpecialSectorVC(sector_t* sec, int type) +{ + sector_t* tsec; + for (auto ln : sec->Lines) + { + if (nullptr != (tsec = getNextSector(ln, sec)) && + tsec->validcount != validcount && + tsec->special == type) + { + return tsec; + } + } + return nullptr; +} + + +sector_t *P_NextSpecialSector (sector_t* sec, int type, sector_t *nogood) { sector_t *tsec; - for (auto ln : Lines) + for (auto ln : sec->Lines) { - if (NULL != (tsec = getNextSector (ln, this)) && + if (nullptr != (tsec = getNextSector (ln, sec)) && tsec != nogood && tsec->special == type) { return tsec; } } - return NULL; + return nullptr; } -DEFINE_ACTION_FUNCTION(_Sector, NextSpecialSector) +DEFINE_ACTION_FUNCTION_NATIVE(_Sector, NextSpecialSector, P_NextSpecialSector) { PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(type); PARAM_POINTER(nogood, sector_t); - ACTION_RETURN_POINTER(self->NextSpecialSector(type, nogood)); + ACTION_RETURN_POINTER(P_NextSpecialSector(self, type, nogood)); } // @@ -921,7 +938,12 @@ int GetTerrain(const sector_t *sector, int pos) return sector->terrainnum[pos] >= 0 ? sector->terrainnum[pos] : TerrainTypes[sector->GetTexture(pos)]; } - //===================================================================================== +FTerrainDef *GetFloorTerrain_S(const sector_t* sec, int pos) +{ + return &Terrains[GetTerrain(sec, pos)]; +} + +//===================================================================================== // // //===================================================================================== @@ -1379,12 +1401,12 @@ bool FLevelLocals::AlignFlat (int linenum, int side, int fc) return false; DAngle angle = line->Delta().Angle(); - DAngle norm = angle - 90; + DAngle norm = angle - DAngle::fromDeg(90.); double dist = -(norm.Cos() * line->v1->fX() + norm.Sin() * line->v1->fY()); if (side) { - angle += 180.; + angle += DAngle::fromDeg(180.); dist = -dist; } @@ -1475,6 +1497,12 @@ void subsector_t::BuildPolyBSP() BSP->Subsectors[i].sector = sector; BSP->Subsectors[i].section = section; } + for (unsigned i = 0; i < BSP->Segs.Size(); i++) + { + BSP->Segs[i].Subsector = this; + BSP->Segs[i].PartnerSeg = nullptr; + } + } //=========================================================================== @@ -1516,11 +1544,18 @@ void line_t::AdjustLine() // //========================================================================== -int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfakecontrast) const +int side_t::GetLightLevel (bool foggy, int baselight, int which, bool is3dlight, int *pfakecontrast) const { - if (!is3dlight && (Flags & WALLF_ABSLIGHTING)) + if (!is3dlight) { - baselight = Light; + if (Flags & (WALLF_ABSLIGHTING_TIER << which)) + { + baselight = TierLights[which]; + } + else if (Flags & WALLF_ABSLIGHTING) + { + baselight = Light + TierLights[which]; + } } if (pfakecontrast != NULL) @@ -1559,9 +1594,9 @@ int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfake } } } - if (!is3dlight && !(Flags & WALLF_ABSLIGHTING) && (!foggy || (Flags & WALLF_LIGHT_FOG))) + if (!is3dlight && !(Flags & WALLF_ABSLIGHTING) && !(Flags & (WALLF_ABSLIGHTING_TIER << which)) && (!foggy || (Flags & WALLF_LIGHT_FOG))) { - baselight += this->Light; + baselight += this->Light + this->TierLights[which]; } return baselight; } @@ -1602,4 +1637,3 @@ 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 0f1738f38..f75b1f61d 100644 --- a/src/playsim/p_sight.cpp +++ b/src/playsim/p_sight.cpp @@ -192,8 +192,8 @@ void SightCheck::P_SightOpening(SightOpening &open, const line_t *linedef, doubl if (ff == 0) ff = front->floorplane.ZatPoint(x, y); if (bf == 0) bf = back->floorplane.ZatPoint(x, y); - open.bottom = MAX(ff, bf); - open.top = MIN(fc, bc); + open.bottom = max(ff, bf); + open.top = min(fc, bc); // we only want to know if there is an opening, not how large it is. open.range = open.bottom < open.top; diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 147a34db1..52760d935 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -67,7 +67,7 @@ #include -#include "templates.h" + #include "doomdef.h" #include "doomstat.h" #include "d_event.h" @@ -622,7 +622,7 @@ void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool pl C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]); if (showsecretsector && sectornum >= 0) { - Printf(PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum); + Printf(PRINT_HIGH | PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum); } } if (playsound) S_Sound (CHAN_AUTO, CHANF_UI, "misc/secret", 1, ATTN_NORM); diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index 9508dd225..a0918da91 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, int intensityX, int intensityY, int 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, int 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, 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); #endif diff --git a/src/playsim/p_switch.cpp b/src/playsim/p_switch.cpp index 51dda852c..73aa95daa 100644 --- a/src/playsim/p_switch.cpp +++ b/src/playsim/p_switch.cpp @@ -32,7 +32,7 @@ ** */ -#include "templates.h" + #include "doomdef.h" #include "p_local.h" @@ -250,7 +250,7 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno, const DVector3 * bool P_ChangeSwitchTexture (side_t *side, int useAgain, uint8_t special, bool *quest) { int texture; - int sound; + FSoundID sound; FSwitchDef *Switch; if ((Switch = TexAnim.FindSwitch (side->GetTexture(side_t::top))) != NULL) @@ -275,7 +275,7 @@ bool P_ChangeSwitchTexture (side_t *side, int useAgain, uint8_t special, bool *q } // EXIT SWITCH? - if (Switch->Sound != 0) + if (Switch->Sound != NO_SOUND) { sound = Switch->Sound; } @@ -404,7 +404,7 @@ void DActiveButton::Tick () { m_Frame = -1; S_Sound (Level, DVector3(m_Pos, 0), CHAN_VOICE, CHANF_LISTENERZ, - def->Sound != 0 ? FSoundID(def->Sound) : FSoundID("switches/normbutn"), + def->Sound != NO_SOUND ? FSoundID(def->Sound) : S_FindSound("switches/normbutn"), 1, ATTN_STATIC); bFlippable = false; } diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index a5cec345a..fb2217ef0 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -154,7 +154,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) int nocancel = 1; IFVIRTUALPTR(thing, AActor, PreTeleport) { - VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees, flags }; + VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees(), flags }; VMReturn ret; ret.IntAt(&nocancel); VMCall(func, params, countof(params), &ret, 1); @@ -170,7 +170,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) player->viewz = thing->Z() + player->viewheight; if (resetpitch) { - player->mo->Angles.Pitch = 0.; + player->mo->Angles.Pitch = nullAngle; } } if (!(flags & TELF_KEEPORIENTATION)) @@ -200,7 +200,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && !(flags & TELF_KEEPVELOCITY)) - thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); + thing->player->FOV = min (175.f, thing->player->DesiredFOV + 45.f); } } // [BC] && bHaltVelocity. @@ -230,7 +230,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) { IFVIRTUALPTR(thing, AActor, PostTeleport) { - VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees, flags }; + VMValue params[] = { thing, pos.X, pos.Y, pos.Z, angle.Degrees(), flags }; VMCall(func, params, countof(params), nullptr, 1); } } @@ -359,10 +359,10 @@ bool FLevelLocals::EV_Teleport (int tid, int tag, line_t *line, int side, AActor { AActor *searcher; double z; - DAngle angle = 0.; + DAngle angle = nullAngle; double s = 0, c = 0; double vx = 0, vy = 0; - DAngle badangle = 0.; + DAngle badangle = nullAngle; if (thing == NULL) { // Teleport function called with an invalid actor @@ -389,7 +389,7 @@ bool FLevelLocals::EV_Teleport (int tid, int tag, line_t *line, int side, AActor // Rotate 90 degrees, so that walking perpendicularly across // teleporter linedef causes thing to exit in the direction // indicated by the exit thing. - angle = line->Delta().Angle() - searcher->Angles.Yaw + 90.; + angle = line->Delta().Angle() - searcher->Angles.Yaw + DAngle::fromDeg(90.); if (flags & TELF_ROTATEBOOMINVERSE) angle = -angle; // Sine, cosine of angle adjustment @@ -412,7 +412,7 @@ bool FLevelLocals::EV_Teleport (int tid, int tag, line_t *line, int side, AActor } if ((i_compatflags2 & COMPATF2_BADANGLES) && (thing->player != NULL)) { - badangle = 0.01; + badangle = DAngle::fromDeg(0.01); } if (P_Teleport (thing, DVector3(searcher->Pos(), z), searcher->Angles.Yaw + badangle, flags)) { @@ -502,7 +502,7 @@ bool FLevelLocals::EV_SilentLineTeleport (line_t *line, int side, AActor *thing, if (!reverse) { - angle += 180.; + angle += DAngle::fromDeg(180.); pos = 1 - pos; } @@ -662,10 +662,11 @@ bool DoGroupForOne (AActor *victim, AActor *source, AActor *dest, bool floorz, b 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(); + int flags = fog ? (TELF_DESTFOG | TELF_SOURCEFOG | TELF_KEEPORIENTATION) : TELF_KEEPORIENTATION; bool res = P_Teleport (victim, DVector3(dest->Pos().XY() + newp, z), - 0., fog ? (TELF_DESTFOG | TELF_SOURCEFOG) : TELF_KEEPORIENTATION); + nullAngle, flags); // P_Teleport only changes angle if fog is true victim->Angles.Yaw = (dest->Angles.Yaw + victim->Angles.Yaw - source->Angles.Yaw).Normalized360(); @@ -724,7 +725,7 @@ bool FLevelLocals::EV_TeleportGroup (int group_tid, AActor *victim, int source_t if (moveSource && didSomething) { didSomething |= - P_Teleport (sourceOrigin, destOrigin->PosAtZ(floorz ? ONFLOORZ : destOrigin->Z()), 0., TELF_KEEPORIENTATION); + P_Teleport (sourceOrigin, destOrigin->PosAtZ(floorz ? ONFLOORZ : destOrigin->Z()), nullAngle, TELF_KEEPORIENTATION); sourceOrigin->Angles.Yaw = destOrigin->Angles.Yaw; } diff --git a/src/playsim/p_things.cpp b/src/playsim/p_things.cpp index c818fb618..0089a29c2 100644 --- a/src/playsim/p_things.cpp +++ b/src/playsim/p_things.cpp @@ -87,7 +87,7 @@ bool FLevelLocals::EV_Thing_Spawn (int tid, AActor *source, int type, DAngle ang if (P_TestMobjLocation (mobj)) { rtn++; - mobj->Angles.Yaw = (angle != 1000000. ? angle : spot->Angles.Yaw); + mobj->Angles.Yaw = (angle != DAngle::fromDeg(1000000.) ? angle : spot->Angles.Yaw); if (fog) { P_SpawnTeleportFog(mobj, spot->Pos(), false, true); @@ -776,7 +776,7 @@ int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, do if (flags & WARPF_COPYPITCH) caller->SetPitch(reference->Angles.Pitch, false); - if (pitch != 0) + if (pitch != nullAngle) caller->SetPitch(caller->Angles.Pitch + pitch, false); if (flags & WARPF_COPYVELOCITY) diff --git a/src/playsim/p_trace.cpp b/src/playsim/p_trace.cpp index 9cff0ffb2..d8b362ca7 100644 --- a/src/playsim/p_trace.cpp +++ b/src/playsim/p_trace.cpp @@ -894,9 +894,14 @@ bool FTraceInfo::TraceTraverse (int ptflags) } Results = res; } - if (Results->HitType == TRACE_HitNone && Results->Distance == 0) + if (Results->HitType == TRACE_HitNone) { - Results->HitPos = Start + Vec * MaxDist; + // [MK] If we didn't cross anything, it's an easy guess, + // otherwise, complete the line using the remaining distance + if (Results->Distance == 0) + Results->HitPos = Start + Vec * MaxDist; + else + Results->HitPos += Vec * (MaxDist - Results->Distance); SetSourcePosition(); Results->Distance = MaxDist; Results->Fraction = 1.; @@ -1063,10 +1068,14 @@ DEFINE_ACTION_FUNCTION(DLineTracer, Trace) PARAM_FLOAT(direction_y); PARAM_FLOAT(direction_z); PARAM_FLOAT(maxDist); - // actor flags and wall flags are not supported due to how flags are implemented on the ZScript side. + // actor flags are not supported due to how flags are implemented on the ZScript side. // say thanks to oversimplifying the user API. PARAM_INT(traceFlags); + PARAM_UINT(wallMask); + PARAM_BOOL(ignoreAllActors); + PARAM_OBJECT(ignore, AActor); + // these are internal hacks. traceFlags &= ~(TRACE_PCross | TRACE_Impact); // this too @@ -1074,7 +1083,7 @@ DEFINE_ACTION_FUNCTION(DLineTracer, Trace) // Trace(vector3 start, Sector sector, vector3 direction, double maxDist, ETraceFlags traceFlags) bool res = Trace(DVector3(start_x, start_y, start_z), sector, DVector3(direction_x, direction_y, direction_z), maxDist, - (ActorFlag)0xFFFFFFFF, 0xFFFFFFFF, nullptr, self->Results, traceFlags, &DLineTracer::TraceCallback, self); + (ActorFlag)(ignoreAllActors ? 0x0 : 0xFFFFFFFF), wallMask, ignore, self->Results, traceFlags, &DLineTracer::TraceCallback, self); ACTION_RETURN_BOOL(res); } diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 9d976431b..87633398c 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -58,7 +58,7 @@ ** */ -#include "templates.h" + #include "doomdef.h" #include "d_event.h" #include "p_local.h" @@ -159,13 +159,6 @@ FPlayerClass::FPlayerClass () Flags = 0; } -FPlayerClass::FPlayerClass (const FPlayerClass &other) -{ - Type = other.Type; - Flags = other.Flags; - Skins = other.Skins; -} - FPlayerClass::~FPlayerClass () { } @@ -429,7 +422,7 @@ void player_t::SetLogText (const char *text) if (mo && mo->CheckLocalView()) { // Print log text to console - Printf(PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text); + Printf(PRINT_HIGH | PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text); } } @@ -453,7 +446,7 @@ void player_t::SetSubtitle(int num, FSoundID soundid) if (text != nullptr) { SubtitleText = lumpname; - int sl = soundid == 0 ? 7000 : std::max(7000, S_GetMSLength(soundid)); + int sl = soundid == NO_SOUND ? 7000 : max(7000, S_GetMSLength(soundid)); SubtitleCounter = sl * TICRATE / 1000; } } @@ -623,8 +616,8 @@ EXTERN_CVAR(Bool, cl_oldfreelooklimit); static int GetSoftPitch(bool down) { - int MAX_DN_ANGLE = MIN(56, (int)maxviewpitch); // Max looking down angle - int MAX_UP_ANGLE = MIN(32, (int)maxviewpitch); // Max looking up angle + int MAX_DN_ANGLE = min(56, (int)maxviewpitch); // Max looking down angle + int MAX_UP_ANGLE = min(32, (int)maxviewpitch); // Max looking up angle return (down ? MAX_DN_ANGLE : ((cl_oldfreelooklimit) ? MAX_UP_ANGLE : MAX_DN_ANGLE)); } @@ -803,6 +796,12 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, GetMoveBob) ACTION_RETURN_FLOAT(self->userinfo.GetMoveBob()); } +DEFINE_ACTION_FUNCTION(_PlayerInfo, GetFViewBob) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + ACTION_RETURN_BOOL(self->userinfo.GetFViewBob()); +} + DEFINE_ACTION_FUNCTION(_PlayerInfo, GetStillBob) { PARAM_SELF_STRUCT_PROLOGUE(player_t); @@ -894,12 +893,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) { PARAM_SELF_PROLOGUE(AActor); - int sound = 0; + FSoundID sound = NO_SOUND; int chan = CHAN_VOICE; - if (self->player == NULL || self->DeathSound != 0) + if (self->player == NULL || self->DeathSound != NO_SOUND) { - if (self->DeathSound != 0) + if (self->DeathSound != NO_SOUND) { S_Sound (self, CHAN_VOICE, 0, self->DeathSound, 1, ATTN_NORM); } @@ -915,31 +914,31 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream) (DF_FORCE_FALLINGZD | DF_FORCE_FALLINGHX)) && self->Vel.Z <= -39) { - sound = S_FindSkinnedSound (self, "*splat"); + sound = S_FindSkinnedSound (self, S_FindSound("*splat")); chan = CHAN_BODY; } - if (!sound && self->special1<10) + if (!sound.isvalid() && self->special1<10) { // Wimpy death sound sound = S_FindSkinnedSoundEx (self, "*wimpydeath", self->player->LastDamageType.GetChars()); } - if (!sound && self->health <= -50) + if (!sound.isvalid() && self->health <= -50) { if (self->health > -100) { // Crazy death sound sound = S_FindSkinnedSoundEx (self, "*crazydeath", self->player->LastDamageType.GetChars()); } - if (!sound) + if (!sound.isvalid()) { // Extreme death sound sound = S_FindSkinnedSoundEx (self, "*xdeath", self->player->LastDamageType.GetChars()); - if (!sound) + if (!sound.isvalid()) { sound = S_FindSkinnedSoundEx (self, "*gibbed", self->player->LastDamageType.GetChars()); chan = CHAN_BODY; } } } - if (!sound) + if (!sound.isvalid()) { // Normal death sound sound = S_FindSkinnedSoundEx (self, "*death", self->player->LastDamageType.GetChars()); } @@ -978,8 +977,8 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale) { // Convert from default scale to skin scale. DVector2 defscale = actor->GetDefault()->Scale; - scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / defscale.X; - scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y; + scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / double(defscale.X); + scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / double(defscale.Y); } // Set the crouch sprite? @@ -1176,8 +1175,8 @@ void P_CheckEnvironment(player_t *player) player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && !player->morphTics && player->mo->waterlevel == 0) { - int id = S_FindSkinnedSound(player->mo, "*falling"); - if (id != 0 && !S_IsActorPlayingSomething(player->mo, CHAN_VOICE, id)) + auto id = S_FindSkinnedSound(player->mo, S_FindSound("*falling")); + if (id != NO_SOUND && !S_IsActorPlayingSomething(player->mo, CHAN_VOICE, id)) { S_Sound(player->mo, CHAN_VOICE, 0, id, 1, ATTN_NORM); } @@ -1255,7 +1254,7 @@ void P_PlayerThink (player_t *player) { fprintf (debugfile, "tic %d for pl %d: (%f, %f, %f, %f) b:%02x p:%d y:%d f:%d s:%d u:%d\n", gametic, (int)(player-players), player->mo->X(), player->mo->Y(), player->mo->Z(), - player->mo->Angles.Yaw.Degrees, player->cmd.ucmd.buttons, + player->mo->Angles.Yaw.Degrees(), player->cmd.ucmd.buttons, player->cmd.ucmd.pitch, player->cmd.ucmd.yaw, player->cmd.ucmd.forwardmove, player->cmd.ucmd.sidemove, player->cmd.ucmd.upmove); } @@ -1265,6 +1264,9 @@ void P_PlayerThink (player_t *player) player->original_cmd = cmd->ucmd; // Don't interpolate the view for more than one tic player->cheats &= ~CF_INTERPVIEW; + player->cheats &= ~CF_INTERPVIEWANGLES; + player->cheats &= ~CF_SCALEDNOLERP; + player->cheats &= ~CF_NOFOVINTERP; player->mo->FloatVar("prevBob") = player->bob; IFVIRTUALPTRNAME(player->mo, NAME_PlayerPawn, PlayerThink) diff --git a/src/playsim/po_man.cpp b/src/playsim/po_man.cpp index 8d100bb71..f29001b9f 100644 --- a/src/playsim/po_man.cpp +++ b/src/playsim/po_man.cpp @@ -226,7 +226,7 @@ void DMovePoly::Serialize(FSerializer &arc) void DMovePoly::Construct(FPolyObj *polyNum) { Super::Construct(polyNum); - m_Angle = 0.; + m_Angle = nullAngle; m_Speedv = { 0,0 }; } @@ -275,7 +275,7 @@ void DPolyDoor::Construct (FPolyObj * polyNum, podoortype_t type) { Super::Construct(polyNum); m_Type = type; - m_Direction = 0.; + m_Direction = nullAngle; m_TotalDist = 0; m_Tics = 0; m_WaitTics = 0; @@ -300,7 +300,7 @@ void DRotatePoly::Tick () m_Speed = m_Speed < 0 ? -m_Dist : m_Dist; } - if (m_PolyObj->RotatePolyobj (m_Speed)) + if (m_PolyObj->RotatePolyobj (DAngle::fromDeg(m_Speed))) { if (m_Dist == -1) { // perpetual polyobj @@ -442,7 +442,7 @@ bool EV_MovePoly (FLevelLocals *Level, line_t *line, int polyNum, double speed, pe->StopInterpolation (); } - angle += 180.; // Reverse the angle. + angle += DAngle::fromDeg(180.); // Reverse the angle. } return pe != nullptr; // Return true if something started moving. } @@ -585,7 +585,7 @@ void DPolyDoor::Tick () break; case PODOOR_SWING: - if (m_Dist <= 0 || m_PolyObj->RotatePolyobj (m_Speed)) + if (m_Dist <= 0 || m_PolyObj->RotatePolyobj(DAngle::fromDeg(m_Speed))) { double absSpeed = fabs (m_Speed); m_Dist -= absSpeed; @@ -668,14 +668,14 @@ bool EV_OpenPolyDoor(FLevelLocals *Level, line_t *line, int polyNum, double spee pd->m_Direction = angle; pd->m_Speedv = angle.ToVector(speed); SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); - angle += 180.; // reverse the angle + angle += DAngle::fromDeg(180.); // reverse the angle } else if (type == PODOOR_SWING) { pd->m_WaitTics = delay; - pd->m_Direction.Degrees = swingdir; + pd->m_Direction = DAngle::fromDeg(swingdir); pd->m_Speed = (speed*swingdir*(90. / 64)) / 8; - pd->m_Dist = pd->m_TotalDist = angle.Degrees; + pd->m_Dist = pd->m_TotalDist = angle.Degrees(); SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); swingdir = -swingdir; // reverse the direction } @@ -718,7 +718,7 @@ bool EV_StopPoly(FLevelLocals *Level, int polynum) FPolyObj::FPolyObj() { StartSpot.pos = { 0,0 }; - Angle = 0.; + Angle = nullAngle; tag = 0; memset(bbox, 0, sizeof(bbox)); validcount = 0; @@ -762,7 +762,7 @@ void FPolyObj::ThrustMobj (AActor *actor, side_t *side) } vertex_t *v1 = side->V1(); vertex_t *v2 = side->V2(); - thrustAngle = (v2->fPos() - v1->fPos()).Angle() - 90.; + thrustAngle = (v2->fPos() - v1->fPos()).Angle() - DAngle::fromDeg(90.); pe = static_cast(specialdata); if (pe) diff --git a/src/playsim/portal.cpp b/src/playsim/portal.cpp index bc5a170cc..f94f7f914 100644 --- a/src/playsim/portal.cpp +++ b/src/playsim/portal.cpp @@ -51,6 +51,17 @@ DEFINE_FIELD(FSectorPortal, mDisplacement); DEFINE_FIELD(FSectorPortal, mPlaneZ); DEFINE_FIELD(FSectorPortal, mSkybox); +DEFINE_FIELD(FLinePortal, mOrigin); +DEFINE_FIELD(FLinePortal, mDestination); +DEFINE_FIELD(FLinePortal, mDisplacement); +DEFINE_FIELD(FLinePortal, mType); +DEFINE_FIELD(FLinePortal, mFlags); +DEFINE_FIELD(FLinePortal, mDefFlags); +DEFINE_FIELD(FLinePortal, mAlign); +DEFINE_FIELD(FLinePortal, mAngleDiff); +DEFINE_FIELD(FLinePortal, mSinRot); +DEFINE_FIELD(FLinePortal, mCosRot); + //============================================================================ // // BuildBlockmap @@ -208,9 +219,9 @@ static void SetPortalRotation(FLinePortal *port) { line_t *dst = port->mDestination; line_t *line = port->mOrigin; - DAngle angle = dst->Delta().Angle() - line->Delta().Angle() + 180.; - port->mSinRot = sindeg(angle.Degrees); // Here precision matters so use the slower but more precise versions. - port->mCosRot = cosdeg(angle.Degrees); + DAngle angle = dst->Delta().Angle() - line->Delta().Angle() + DAngle::fromDeg(180.); + port->mSinRot = sindeg(angle.Degrees()); // Here precision matters so use the slower but more precise versions. + port->mCosRot = cosdeg(angle.Degrees()); port->mAngleDiff = angle; if ((line->sidedef[0]->Flags & WALLF_POLYOBJ) || (dst->sidedef[0]->Flags & WALLF_POLYOBJ)) { @@ -226,7 +237,7 @@ static void SetPortalRotation(FLinePortal *port) // Linked portals have no angular difference. port->mSinRot = 0.; port->mCosRot = 1.; - port->mAngleDiff = 0.; + port->mAngleDiff = nullAngle; } } } @@ -388,13 +399,13 @@ bool FLevelLocals::ChangePortal(line_t *ln, int thisid, int destid) // //============================================================================ -inline int P_GetLineSide(const DVector2 &pos, const line_t *line) +inline int P_GetLineSide(const DVector2 &pos, const linebase_t *line) { double v = (pos.Y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - pos.X) * line->Delta().Y; return v < -1. / 65536. ? -1 : v > 1. / 65536 ? 1 : 0; } -bool P_ClipLineToPortal(line_t* line, line_t* portal, DVector2 view, bool partial, bool samebehind) +bool P_ClipLineToPortal(linebase_t* line, linebase_t* portal, DVector2 view, bool partial, bool samebehind) { int behind1 = P_GetLineSide(line->v1->fPos(), portal); int behind2 = P_GetLineSide(line->v2->fPos(), portal); diff --git a/src/playsim/portal.h b/src/playsim/portal.h index 164593daf..ca5e98427 100644 --- a/src/playsim/portal.h +++ b/src/playsim/portal.h @@ -4,6 +4,7 @@ #include "basics.h" #include "m_bbox.h" +struct linebase_t; struct line_t; struct sector_t; @@ -278,7 +279,7 @@ struct FSectorPortalGroup /* code ported from prototype */ -bool P_ClipLineToPortal(line_t* line, line_t* portal, DVector2 view, bool partial = true, bool samebehind = true); +bool P_ClipLineToPortal(linebase_t* line, linebase_t* portal, DVector2 view, bool partial = true, bool samebehind = true); void P_TranslatePortalXY(line_t* src, double& vx, double& vy); void P_TranslatePortalVXVY(line_t* src, double &velx, double &vely); void P_TranslatePortalAngle(line_t* src, DAngle& angle); diff --git a/src/posix/i_steam.cpp b/src/posix/i_steam.cpp index e0baa472f..15265a6e0 100644 --- a/src/posix/i_steam.cpp +++ b/src/posix/i_steam.cpp @@ -160,7 +160,10 @@ static struct SteamAppInfo {"Hexen Deathkings of the Dark Citadel/base", 2370}, {"Ultimate Doom/base", 2280}, {"DOOM 3 BFG Edition/base/wads", 208200}, - {"Strife", 317040} + {"Strife", 317040}, + {"Ultimate Doom/rerelease/DOOM_Data/StreamingAssets", 2280}, + {"Doom 2/rerelease/DOOM II_Data/StreamingAssets", 2300}, + {"Doom 2/finaldoombase", 2300} }; TArray I_GetSteamPath() @@ -225,3 +228,9 @@ TArray I_GetSteamPath() return result; } + +TArray I_GetGogPaths() +{ + // GOG's Doom games are Windows only at the moment + return TArray(); +} diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index b46a9b49c..2ee96133a 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -41,8 +41,9 @@ #include "filesystem.h" #include "r_sky.h" +#include "textures.h" #include "colormaps.h" -#include "templates.h" + #include "c_cvars.h" CUSTOM_CVAR(Bool, cl_customizeinvulmap, false, CVAR_ARCHIVE|CVAR_NOINITCALL) @@ -156,7 +157,7 @@ void R_InitColormaps (bool allowCustomColormap) g /= 256; b /= 256; // The calculated average is too dark so brighten it according to the palettes's overall brightness - int maxcol = MAX(MAX(palette_brightness, r), MAX(g, b)); + int maxcol = max(max(palette_brightness, r), max(g, b)); fakecmaps[j].blend = PalEntry (255, r * 255 / maxcol, g * 255 / maxcol, b * 255 / maxcol); } diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 6be82c77d..9718c77ec 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -35,7 +35,7 @@ #include #include "sc_man.h" -#include "templates.h" + #include "filesystem.h" #include "gi.h" #include "r_state.h" @@ -48,6 +48,8 @@ #include "hwrenderer/postprocessing/hw_postprocessshader.h" #include "hw_material.h" #include "texturemanager.h" +#include "gameconfigfile.h" +#include "m_argv.h" void AddLightDefaults(FLightDefaults *defaults, double attnFactor); void AddLightAssociation(const char *actor, const char *frame, const char *light); @@ -57,6 +59,50 @@ void ParseColorization(FScanner& sc); extern TDeletingArray LightDefaults; extern int AttenuationIsSet; +bool addedcvars = false; + +struct ExtraUniformCVARData +{ + FString Shader; + FString Uniform; + double* vec4 = nullptr; + ExtraUniformCVARData* Next = nullptr; +}; + +static void do_uniform_set(float value, ExtraUniformCVARData* data) +{ + if (!(data->vec4)) + { + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader& shader = PostProcessShaders[i]; + if (strcmp(shader.Name, data->Shader) == 0) + { + data->vec4 = shader.Uniforms[data->Uniform].Values; + } + } + } + double* vec4 = data->vec4; + if (vec4) + { + vec4[0] = value; + vec4[1] = 0.0; + vec4[2] = 0.0; + vec4[3] = 1.0; + } + if (data->Next) + do_uniform_set(value, data->Next); +} + +void uniform_callback_int(FIntCVar &self) +{ + do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); +} + +void uniform_callback_float(FFloatCVar &self) +{ + do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); +} //----------------------------------------------------------------------------- // @@ -143,6 +189,8 @@ static const char *LightTags[]= "dontlightactors", "spot", "noshadowmap", + "dontlightothers", + "dontlightmap", nullptr }; @@ -167,6 +215,8 @@ enum { LIGHTTAG_DONTLIGHTACTORS, LIGHTTAG_SPOT, LIGHTTAG_NOSHADOWMAP, + LIGHTTAG_DONTLIGHTOTHERS, + LIGHTTAG_DONTLIGHTMAP, }; //========================================================================== @@ -467,6 +517,12 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTACTORS: defaults->SetDontLightActors(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTOTHERS: + defaults->SetDontLightOthers(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTMAP: + defaults->SetDontLightMap(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -563,6 +619,12 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTACTORS: defaults->SetDontLightActors(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTOTHERS: + defaults->SetDontLightOthers(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTMAP: + defaults->SetDontLightMap(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -662,6 +724,12 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTACTORS: defaults->SetDontLightActors(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTOTHERS: + defaults->SetDontLightOthers(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTMAP: + defaults->SetDontLightMap(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -760,6 +828,12 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTACTORS: defaults->SetDontLightActors(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTOTHERS: + defaults->SetDontLightOthers(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTMAP: + defaults->SetDontLightMap(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -855,6 +929,12 @@ class GLDefsParser case LIGHTTAG_DONTLIGHTACTORS: defaults->SetDontLightActors(ParseInt(sc) != 0); break; + case LIGHTTAG_DONTLIGHTOTHERS: + defaults->SetDontLightOthers(ParseInt(sc) != 0); + break; + case LIGHTTAG_DONTLIGHTMAP: + defaults->SetDontLightMap(ParseInt(sc) != 0); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -1365,12 +1445,12 @@ class GLDefsParser if (usershader.shader.IsNotEmpty()) { int firstUserTexture; - if ((mlay.Normal || tex->Normal.get()) && (mlay.Specular || tex->Specular.get())) + if ((mlay.Normal || tex->GetNormalmap()) && (mlay.Specular || tex->GetSpecularmap())) { usershader.shaderType = SHADER_Specular; firstUserTexture = 7; } - else if ((mlay.Normal || tex->Normal.get()) && (mlay.Metallic || tex->Metallic.get()) && (mlay.Roughness || tex->Roughness.get()) && (mlay.AmbientOcclusion || tex->AmbientOcclusion.get())) + else if ((mlay.Normal || tex->GetNormalmap()) && (mlay.Metallic || tex->GetMetallic()) && (mlay.Roughness || tex->GetRoughness()) && (mlay.AmbientOcclusion || tex->GetAmbientOcclusion())) { usershader.shaderType = SHADER_PBR; firstUserTexture = 9; @@ -1452,8 +1532,10 @@ class GLDefsParser sc.MustGetString(); shaderdesc.Name = sc.String; } - else if (sc.Compare("uniform")) + else if (sc.Compare("uniform") || sc.Compare("cvar_uniform")) { + bool is_cvar = sc.Compare("cvar_uniform"); + sc.MustGetString(); FString uniformType = sc.String; uniformType.ToLower(); @@ -1474,8 +1556,96 @@ class GLDefsParser else sc.ScriptError("Unrecognized uniform type '%s'", sc.String); + auto strUniformType = sc.String; + if (parsedType != PostProcessUniformType::Undefined) shaderdesc.Uniforms[uniformName].Type = parsedType; + + if (is_cvar) + { + addedcvars = true; + if (!shaderdesc.Name.GetChars()) + sc.ScriptError("Shader must have a name to use cvar uniforms"); + + ECVarType cvartype = CVAR_Dummy; + int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL; + FBaseCVar *cvar; + void (*callback)(FBaseCVar&) = NULL; + FString cvarname; + switch (parsedType) + { + case PostProcessUniformType::Int: + cvartype = CVAR_Int; + callback = (void (*)(FBaseCVar&))uniform_callback_int; + break; + case PostProcessUniformType::Float: + cvartype = CVAR_Float; + callback = (void (*)(FBaseCVar&))uniform_callback_float; + break; + default: + sc.ScriptError("'%s' not supported for CVAR uniforms!", strUniformType); + break; + } + sc.MustGetString(); + cvarname = sc.String; + cvar = FindCVar(cvarname, NULL); + + UCVarValue oldval; + UCVarValue val; + ExtraUniformCVARData* oldextra = nullptr; + sc.MustGetFloat(); + + val.Float = oldval.Float = (float)sc.Float; + + if (!Args->CheckParm ("-shaderuniformtest")) + { + // these aren't really release-ready, so lock them behind a command-line argument for now. + sc.ScriptMessage("Warning - Use -shaderuniformtest to enable shader uniforms!"); + } + else + { + if (!cvar) + { + cvar = C_CreateCVar(cvarname, cvartype, cvarflags); + } + else if (cvar && (((cvar->GetFlags()) & CVAR_MOD) == CVAR_MOD)) + { + // this value may have been previously loaded + oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; + oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); + } + + if (!(cvar->GetFlags() & CVAR_MOD)) + { + if (!((cvar->GetFlags() & (CVAR_AUTO | CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE))) + sc.ScriptError("CVAR '%s' already in use!", cvarname.GetChars()); + } + + // must've picked this up from an autoexec.cfg, handle accordingly + if (cvar && ((cvar->GetFlags() & (CVAR_MOD|CVAR_AUTO|CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE))) + { + oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; + delete cvar; + cvar = C_CreateCVar(cvarname, cvartype, cvarflags); + oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); + } + + shaderdesc.Uniforms[uniformName].Values[0] = oldval.Float; + + cvar->SetGenericRepDefault(val, CVAR_Float); + + if (val.Float != oldval.Float) // it's not default anymore + cvar->SetGenericRep(oldval.Float, CVAR_Float); + + if (callback) + cvar->SetCallback(callback); + ExtraUniformCVARData* extra = new ExtraUniformCVARData; + extra->Shader = shaderdesc.Name.GetChars(); + extra->Uniform = uniformName.GetChars(); + extra->Next = oldextra; + cvar->SetExtraDataPointer(extra); + } + } } else if (sc.Compare("texture")) { @@ -1733,6 +1903,8 @@ public: sc.SavePos(); if (!sc.GetToken ()) { + if (addedcvars) + GameConfig->DoModSetup (gameinfo.ConfigName); return; } type = sc.MatchString(CoreKeywords); diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index c626a13eb..fd7d0c06c 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -55,7 +55,7 @@ EXTERN_CVAR (Bool, r_drawvoxels) 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); +void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, const PClass* ti, int translation, AActor* actor); void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac) @@ -78,7 +78,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod angles = actor->InterpolatedAngles(ticFrac); else angles = actor->Angles; - float angle = angles.Yaw.Degrees; + float angle = angles.Yaw.Degrees(); // [BB] Workaround for the missing pitch information. if ((smf->flags & MDL_PITCHFROMMOMENTUM)) @@ -119,11 +119,11 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod // 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) { - double d = angles.Pitch.Degrees; + double d = angles.Pitch.Degrees(); 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(); @@ -132,20 +132,31 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod objectToWorldMatrix.translate(x, z, y); // [Nash] take SpriteRotation into account - angle += actor->SpriteRotation.Degrees; + angle += actor->SpriteRotation.Degrees(); + + // consider the pixel stretching. For non-voxels this must be factored out here + float stretch = 1.f; + + // [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) + { + 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); + } // Applying model transformations: // 1) Applying actor angle, pitch and roll to the model if (smf->flags & MDL_USEROTATIONCENTER) { - objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ, smf->rotationCenterY); + 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) { - objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ, -smf->rotationCenterY); + objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ/stretch, -smf->rotationCenterY); } // 2) Applying Doomsday like rotation of the weapon pickup models @@ -153,37 +164,38 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod if (smf->flags & MDL_ROTATING) { - objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY, smf->rotationCenterZ); + objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY/stretch, smf->rotationCenterZ); objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate); - objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY, -smf->rotationCenterZ); + objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterY/stretch, -smf->rotationCenterZ); } // 3) Scaling model. objectToWorldMatrix.scale(scaleFactorX, scaleFactorZ, scaleFactorY); // 4) 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); + objectToWorldMatrix.translate(smf->xoffset / smf->xscale, smf->zoffset / (smf->zscale*stretch), smf->yoffset / smf->yscale); // 5) Applying model rotations. objectToWorldMatrix.rotate(-smf->angleoffset, 0, 1, 0); objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1); objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0); - // consider the pixel stretching. For non-voxels this must be factored out here - float 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); + 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); + } float orientation = scaleFactorX * scaleFactorY * scaleFactorZ; renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0); - RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->GetClass(), translation); + 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); } -void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float ofsY) +void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf) { AActor * playermo = players[consoleplayer].camera; - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; // [BB] No model found for this sprite, so we can't render anything. if (smf == nullptr) @@ -193,15 +205,34 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float o // but we need to position it correctly in the world for light to work properly. VSMatrix objectToWorldMatrix = renderer->GetViewToWorldMatrix(); + // [Nash] Optional scale weapon FOV + float fovscale = 1.0f; + 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); + objectToWorldMatrix.scale(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); // [BB] Weapon bob, very similar to the normal Doom weapon bob. - objectToWorldMatrix.rotate(ofsX / 4, 0, 1, 0); - objectToWorldMatrix.rotate((ofsY - WEAPONTOP) / -4., 1, 0, 0); + + + + objectToWorldMatrix.translate(rotation_pivot.X, rotation_pivot.Y, rotation_pivot.Z); + + objectToWorldMatrix.rotate(rotation.X, 0, 1, 0); + objectToWorldMatrix.rotate(rotation.Y, 1, 0, 0); + objectToWorldMatrix.rotate(rotation.Z, 0, 0, 1); + + objectToWorldMatrix.translate(-rotation_pivot.X, -rotation_pivot.Y, -rotation_pivot.Z); + + objectToWorldMatrix.translate(translation.X, translation.Y, translation.Z); + // [BB] For some reason the jDoom models need to be rotated. objectToWorldMatrix.rotate(90.f, 0, 1, 0); @@ -216,11 +247,11 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float o renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0); uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0; if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation; - RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->GetClass(), trans); + 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); } -void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation) +void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int 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. @@ -268,20 +299,117 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr } } - for (int i = 0; i < smf->modelsAmount; i++) + int 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 (smf->modelIDs[i] != -1) + if (actor->modelData->modelIDs.Size() > (unsigned)modelsamount) + modelsamount = actor->modelData->modelIDs.Size(); + } + + TArray surfaceskinids; + + TArray boneData = TArray(); + int boneStartingPosition = 0; + bool evaluatedSingle = false; + + for (int i = 0; i < modelsamount; i++) + { + int modelid = -1; + int animationid = -1; + int modelframe = -1; + int modelframenext = -1; + FTextureID skinid; skinid.SetInvalid(); + + surfaceskinids.Clear(); + if (actor->modelData != nullptr) { - FModel * mdl = Models[smf->modelIDs[i]]; - auto tex = smf->skinIDs[i].isValid() ? TexMan.GetGameTexture(smf->skinIDs[i], true) : nullptr; + if (i < (int)actor->modelData->modelIDs.Size()) + modelid = actor->modelData->modelIDs[i]; + + if (i < (int)actor->modelData->animationIDs.Size()) + animationid = actor->modelData->animationIDs[i]; + + if (i < (int)actor->modelData->modelFrameGenerators.Size()) + { + //[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) + { + modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]]; + if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]]; + } + } + if (i < (int)actor->modelData->skinIDs.Size()) + { + if (actor->modelData->skinIDs[i].isValid()) + skinid = actor->modelData->skinIDs[i]; + } + for (int surface = i * MD3_MAX_SURFACES; surface < (i + 1) * MD3_MAX_SURFACES; surface++) + { + if (surface < (int)actor->modelData->surfaceSkinIDs.Size()) + { + if (actor->modelData->surfaceSkinIDs[surface].isValid()) + { + // only make a copy of the surfaceskinIDs array if really needed + if (surfaceskinids.Size() == 0) surfaceskinids = smf->surfaceskinIDs; + surfaceskinids[surface] = actor->modelData->surfaceSkinIDs[surface]; + } + } + } + } + if (i < smf->modelsAmount) + { + 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]; + } + + if (modelid >= 0) + { + FModel * mdl = Models[modelid]; + auto tex = skinid.isValid() ? TexMan.GetGameTexture(skinid, true) : nullptr; mdl->BuildVertexBuffer(renderer); - mdl->PushSpriteMDLFrame(smf, i); + auto& ssids = surfaceskinids.Size() > 0 ? surfaceskinids : smf->surfaceskinIDs; + auto ssidp = (unsigned)(i * MD3_MAX_SURFACES) < ssids.Size() ? &ssids[i * MD3_MAX_SURFACES] : nullptr; - if (smfNext && smf->modelframes[i] != smfNext->modelframes[i]) - mdl->RenderFrame(renderer, tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation); + + bool nextFrame = smfNext && modelframe != modelframenext; + + if (actor->boneComponentData == nullptr) + { + auto ptr = Create(); + ptr->trscomponents.Resize(modelsamount); + ptr->trsmatrix.Resize(modelsamount); + actor->boneComponentData = ptr; + GC::WriteBarrier(actor, ptr); + } + + if (animationid >= 0) + { + FModel* animation = Models[animationid]; + const TArray* animationData = animation->AttachAnimationData(); + + if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) + { + boneData = animation->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.f, animationData, actor->boneComponentData, i); + boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1); + evaluatedSingle = true; + } + } else - mdl->RenderFrame(renderer, tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation); + { + if (!(smf->flags & MDL_MODELSAREATTACHMENTS) || evaluatedSingle == false) + { + boneData = mdl->CalculateBones(modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : 0.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); } } } @@ -324,8 +452,15 @@ void InitModels() smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; smf.skinIDs.Alloc(1); smf.skinIDs[0] = md->GetPaletteTexture(); + smf.animationIDs.Alloc(1); + smf.animationIDs[0] = -1; smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; - smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; + smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees(); + // this helps catching uninitialized data. + assert(VoxelDefs[i]->PitchFromMomentum == true || VoxelDefs[i]->PitchFromMomentum == false); + if (VoxelDefs[i]->PitchFromMomentum) smf.flags |= MDL_PITCHFROMMOMENTUM; + if (VoxelDefs[i]->UseActorPitch) smf.flags |= MDL_USEACTORPITCH; + if (VoxelDefs[i]->UseActorRoll) smf.flags |= MDL_USEACTORROLL; if (VoxelDefs[i]->PlacedSpin != 0) { smf.yrotate = 1.f; @@ -423,6 +558,7 @@ static void ParseModelDefLump(int Lump) initArray(smf.modelIDs, smf.modelsAmount, -1); initArray(smf.skinIDs, smf.modelsAmount, FNullTextureID()); initArray(smf.surfaceskinIDs, smf.modelsAmount * MD3_MAX_SURFACES, FNullTextureID()); + initArray(smf.animationIDs, smf.modelsAmount, -1); initArray(smf.modelframes, smf.modelsAmount, 0); sc.RestorePos(scPos); @@ -457,6 +593,26 @@ static void ParseModelDefLump(int Lump) Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } } + else if (sc.Compare("animation")) + { + sc.MustGetNumber(); + index = sc.Number; + if (index < 0) + { + sc.ScriptError("Animation index must be 0 or greater in %s", type->TypeName.GetChars()); + } + else if (index >= smf.modelsAmount) + { + sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); + } + sc.MustGetString(); + FixPathSeperator(sc.String); + smf.animationIDs[index] = FindModel(path.GetChars(), sc.String); + if (smf.animationIDs[index] == -1) + { + Printf("%s: animation model not found in %s\n", sc.String, path.GetChars()); + } + } else if (sc.Compare("scale")) { sc.MustGetFloat(); @@ -528,6 +684,14 @@ static void ParseModelDefLump(int Lump) { smf.flags |= MDL_NOPERPIXELLIGHTING; } + else if (sc.Compare("scaleweaponfov")) + { + smf.flags |= MDL_SCALEWEAPONFOV; + } + else if (sc.Compare("modelsareattachments")) + { + smf.flags |= MDL_MODELSAREATTACHMENTS; + } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; @@ -666,6 +830,10 @@ static void ParseModelDefLump(int Lump) if (smf.modelIDs[index] != -1) { FModel *model = Models[smf.modelIDs[index]]; + if (smf.animationIDs[index] != -1) + { + model = Models[smf.animationIDs[index]]; + } smf.modelframes[index] = model->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, type->TypeName.GetChars()); } @@ -704,6 +872,10 @@ static void ParseModelDefLump(int Lump) smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; } + else if (sc.Compare("correctpixelstretch")) + { + smf.flags |= MDL_CORRECTPIXELSTRETCH; + } else { sc.ScriptMessage("Unrecognized string \"%s\"", sc.String); @@ -787,7 +959,7 @@ 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->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; + 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; } return false; diff --git a/src/r_data/models.h b/src/r_data/models.h index 2ce9744ca..568ad5399 100644 --- a/src/r_data/models.h +++ b/src/r_data/models.h @@ -1,4 +1,4 @@ -// +// //--------------------------------------------------------------------------- // // Copyright(C) 2005-2016 Christoph Oelckers @@ -56,6 +56,9 @@ enum 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 }; FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped); @@ -107,6 +110,8 @@ void BSPWalkCircle(FLevelLocals *Level, float x, float y, float radiusSquared, c } void RenderModel(FModelRenderer* renderer, float x, float y, float z, FSpriteModelFrame* smf, AActor* actor, double ticFrac); -void RenderHUDModel(FModelRenderer* renderer, DPSprite* psp, float ofsX, float ofsY); +void RenderHUDModel(FModelRenderer* renderer, DPSprite* psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf); + +EXTERN_CVAR(Float, cl_scaleweaponfov) #endif diff --git a/src/r_data/r_canvastexture.h b/src/r_data/r_canvastexture.h index b69c46687..22f5a730f 100644 --- a/src/r_data/r_canvastexture.h +++ b/src/r_data/r_canvastexture.h @@ -1,6 +1,8 @@ #pragma once +class FCanvas; class FCanvasTexture; + // This list keeps track of the cameras that draw into canvas textures. struct FCanvasTextureEntry { diff --git a/src/r_data/r_interpolate.h b/src/r_data/r_interpolate.h index 888f387c5..29f3f56df 100644 --- a/src/r_data/r_interpolate.h +++ b/src/r_data/r_interpolate.h @@ -17,8 +17,8 @@ class DInterpolation : public DObject DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) HAS_OBJECT_POINTERS - TObjPtr Next = nullptr; - TObjPtr Prev = nullptr; + TObjPtr Next; + TObjPtr Prev; protected: FLevelLocals *Level; @@ -46,7 +46,7 @@ public: struct FInterpolator { - TObjPtr Head = nullptr; + TObjPtr Head = MakeObjPtr(nullptr); bool didInterp = false; int count = 0; diff --git a/src/r_data/r_sections.h b/src/r_data/r_sections.h index 221d19e63..fd13a80e7 100644 --- a/src/r_data/r_sections.h +++ b/src/r_data/r_sections.h @@ -72,8 +72,8 @@ struct BoundingRect double distanceTo(const BoundingRect &other) const { if (intersects(other)) return 0; - return std::max(std::min(fabs(left - other.right), fabs(right - other.left)), - std::min(fabs(top - other.bottom), fabs(bottom - other.top))); + return max(min(fabs(left - other.right), fabs(right - other.left)), + min(fabs(top - other.bottom), fabs(bottom - other.top))); } void addVertex(double x, double y) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index cc847a963..0f130e30a 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -34,7 +34,7 @@ #include -#include "templates.h" + #include "r_data/r_translate.h" #include "v_video.h" #include "g_game.h" @@ -144,7 +144,7 @@ int CreateBloodTranslation(PalEntry color) trans.Remap[0] = 0; for (i = 1; i < 256; i++) { - int bright = std::max(std::max(GPalette.BaseColors[i].r, GPalette.BaseColors[i].g), GPalette.BaseColors[i].b); + int bright = max(std::max(GPalette.BaseColors[i].r, GPalette.BaseColors[i].g), GPalette.BaseColors[i].b); PalEntry pe = PalEntry(255, color.r*bright/255, color.g*bright/255, color.b*bright/255); int entry = ColorMatcher.Pick(pe.r, pe.g, pe.b); @@ -484,7 +484,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC // Build player sprite translation //h = 45.f; - v = MAX (0.1f, v); + v = max (0.1f, v); for (i = start; i <= end; i++) { @@ -498,7 +498,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC float mv[18] = { .16f, .19f, .22f, .25f, .31f, .35f, .38f, .41f, .47f, .54f, .60f, .65f, .71f, .77f, .83f, .89f, .94f, 1.f }; // Build player sprite translation - v = MAX (0.1f, v); + v = max (0.1f, v); for (i = start; i <= end; i++) { @@ -513,12 +513,12 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC if (gameinfo.gametype == GAME_Heretic) { // Build rain/lifegem translation - bases = MIN(bases * 1.3f, 1.f); - basev = MIN(basev * 1.3f, 1.f); + bases = min(bases * 1.3f, 1.f); + basev = min(basev * 1.3f, 1.f); for (i = 145; i <= 168; i++) { - s = MIN(bases, 0.8965f - 0.0962f * (float)(i - 161)); - v = MIN(1.f, (0.2102f + 0.0489f * (float)(i - 144)) * basev); + s = min(bases, 0.8965f - 0.0962f * (float)(i - 161)); + v = min(1.f, (0.2102f + 0.0489f * (float)(i - 144)) * basev); HSVtoRGB(&r, &g, &b, h, s, v); SetRemap(alttable, i, r, g, b); SetPillarRemap(pillartable, i, h, s, v); diff --git a/src/r_data/r_vanillatrans.cpp b/src/r_data/r_vanillatrans.cpp index e969dd3d8..f63d7ee32 100644 --- a/src/r_data/r_vanillatrans.cpp +++ b/src/r_data/r_vanillatrans.cpp @@ -36,7 +36,7 @@ ** **/ -#include "templates.h" + #include "c_cvars.h" #include "filesystem.h" #include "doomtype.h" diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 3b88669e8..07a106e65 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -77,19 +77,19 @@ FTextureID spritedef_t::GetSpriteFrame(int frame, int rot, DAngle ang, bool *mir { if ((sprframe->Texture[0] == sprframe->Texture[1]) && flipagain) { - rot = (360.0 - ang + 45.0 / 2 * 9).BAMs() >> 28; + rot = (- ang + DAngle::fromDeg(360.0 + 45.0 / 2 * 9)).BAMs() >> 28; } else if (sprframe->Texture[0] == sprframe->Texture[1]) { - rot = (ang + 45.0 / 2 * 9).BAMs() >> 28; + rot = (ang + DAngle::fromDeg(45.0 / 2 * 9)).BAMs() >> 28; } else if (flipagain) { - rot = (360.0 - ang + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (- ang + DAngle::fromDeg(360.0 + (45.0 / 2 * 9 - 180.0 / 16))).BAMs() >> 28; } else { - rot = (ang + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (ang + DAngle::fromDeg(45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; } } if (mirror) *mirror = !!(sprframe->Flip&(1 << rot)); @@ -452,7 +452,7 @@ void R_InitSpriteDefs () { // voxel applies to a specific frame j = vh->Frame - 'A'; sprtemp[j].Voxel = voxdef; - maxframe = MAX(maxframe, j); + maxframe = max(maxframe, j); } } } @@ -573,7 +573,7 @@ void R_InitSkins (void) unsigned i; int j, k, base; int lastlump; - int aliasid; + FSoundID aliasid; bool remove; PClassActor *basetype, *transtype; @@ -583,7 +583,7 @@ void R_InitSkins (void) for (j = 0; j < NUMSKINSOUNDS; ++j) { - playersoundrefs[j] = skinsoundnames[j][1]; + playersoundrefs[j] = S_FindSound(skinsoundnames[j][1]); } while ((base = fileSystem.FindLump ("S_SKIN", &lastlump, true)) != -1) @@ -651,7 +651,7 @@ void R_InitSkins (void) } else if (0 == stricmp (key, "scale")) { - Skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.); + Skins[i].Scale.X = clamp((float)atof (sc.String), 1.f/65536, 256.f); Skins[i].Scale.Y = Skins[i].Scale.X; } else if (0 == stricmp (key, "game")) @@ -733,8 +733,8 @@ void R_InitSkins (void) } else { - int sndref = soundEngine->FindSoundNoHash (key); - if (sndref != 0) + auto sndref = soundEngine->FindSoundNoHash (key); + if (sndref.isvalid()) { S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true); } @@ -886,7 +886,7 @@ void R_InitSkins (void) } // Register any sounds this skin provides - aliasid = 0; + aliasid = NO_SOUND; for (j = 0; j < NUMSKINSOUNDS; j++) { if (sndlumps[j] != -1) diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 1c757e29e..333cb7579 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -34,7 +34,7 @@ #include "g_level.h" -#include "templates.h" + #include "v_video.h" #include "filesystem.h" #include "i_video.h" @@ -65,9 +65,11 @@ void InitPalette () FileData cmap = fileSystem.ReadFile(lump); const unsigned char* cmapdata = (const unsigned char*)cmap.GetMem(); GPalette.GenerateGlobalBrightmapFromColormap(cmapdata, 32); + MakeGoodRemap((uint32_t*)GPalette.BaseColors, GPalette.Remap, cmapdata + 7936); // last entry in colormap } + else + MakeGoodRemap ((uint32_t*)GPalette.BaseColors, GPalette.Remap); - MakeGoodRemap ((uint32_t*)GPalette.BaseColors, GPalette.Remap); ColorMatcher.SetPalette ((uint32_t *)GPalette.BaseColors); if (GPalette.Remap[0] == 0) @@ -84,35 +86,3 @@ void InitPalette () } -CCMD (testblend) -{ - FString colorstring; - int color; - float amt; - - if (argv.argc() < 3) - { - Printf ("testblend \n"); - } - else - { - if ( !(colorstring = V_GetColorStringByName (argv[1])).IsEmpty() ) - { - color = V_GetColorFromString (colorstring); - } - else - { - color = V_GetColorFromString (argv[1]); - } - amt = (float)atof (argv[2]); - if (amt > 1.0f) - amt = 1.0f; - else if (amt < 0.0f) - amt = 0.0f; - BaseBlendR = RPART(color); - BaseBlendG = GPART(color); - BaseBlendB = BPART(color); - BaseBlendA = amt; - } -} - diff --git a/src/r_data/voxeldef.cpp b/src/r_data/voxeldef.cpp index 300872ffc..128862178 100644 --- a/src/r_data/voxeldef.cpp +++ b/src/r_data/voxeldef.cpp @@ -52,15 +52,14 @@ struct VoxelOptions { - VoxelOptions() - : DroppedSpin(0), PlacedSpin(0), Scale(1.), AngleOffset(90.), OverridePalette(false) - {} - - int DroppedSpin; - int PlacedSpin; - double Scale; - DAngle AngleOffset; - bool OverridePalette; + int DroppedSpin = 0; + int PlacedSpin = 0; + double Scale = 1; + DAngle AngleOffset = DAngle90; + bool OverridePalette = false; + bool PitchFromMomentum = false; + bool UseActorPitch = false; + bool UseActorRoll = false; }; void VOX_AddVoxel(int sprnum, int frame, FVoxelDef* def); @@ -174,12 +173,24 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts) { sc.TokenMustBe(TK_FloatConst); } - opts.AngleOffset = mul * sc.Float + 90.; + opts.AngleOffset = DAngle::fromDeg(mul * sc.Float + 90.); } else if (sc.Compare("overridepalette")) { opts.OverridePalette = true; } + else if (sc.Compare("pitchfrommomentum")) + { + opts.PitchFromMomentum = true; + } + else if (sc.Compare("useactorpitch")) + { + opts.UseActorPitch = true; + } + else if (sc.Compare("useactorroll")) + { + opts.UseActorRoll = true; + } else { sc.ScriptMessage("Unknown voxel option '%s'\n", sc.String); @@ -249,6 +260,9 @@ void R_InitVoxels() def->DroppedSpin = opts.DroppedSpin; def->PlacedSpin = opts.PlacedSpin; def->AngleOffset = opts.AngleOffset; + def->PitchFromMomentum = opts.PitchFromMomentum; + def->UseActorPitch = opts.UseActorPitch; + def->UseActorRoll = opts.UseActorRoll; VoxelDefs.Push(def); for (unsigned i = 0; i < vsprites.Size(); ++i) diff --git a/src/rendering/2d/f_wipe.h b/src/rendering/2d/f_wipe.h deleted file mode 100644 index 9b16b4d38..000000000 --- a/src/rendering/2d/f_wipe.h +++ /dev/null @@ -1,60 +0,0 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// -// 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 3 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. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- -// -// DESCRIPTION: -// Mission start screen wipe/melt, special effects. -// -//----------------------------------------------------------------------------- - - -#ifndef __F_WIPE_H__ -#define __F_WIPE_H__ - -#include "stdint.h" - -class FTexture; -int wipe_CalcBurn(uint8_t *buffer, int width, int height, int density); - -enum -{ - wipe_None, // don't bother - wipe_Melt, // weird screen melt - wipe_Burn, // fade in shape of fire - wipe_Fade, // crossfade from old to new - wipe_NUMWIPES -}; - -class Wiper -{ -protected: - FGameTexture *startScreen = nullptr, *endScreen = nullptr; -public: - virtual ~Wiper(); - virtual bool Run(int ticks) = 0; - virtual void SetTextures(FGameTexture *startscreen, FGameTexture *endscreen) - { - startScreen = startscreen; - endScreen = endscreen; - } - - static Wiper *Create(int type); -}; - - -#endif diff --git a/src/rendering/2d/v_blend.cpp b/src/rendering/2d/v_blend.cpp index 88476cfc9..9fdba4179 100644 --- a/src/rendering/2d/v_blend.cpp +++ b/src/rendering/2d/v_blend.cpp @@ -34,7 +34,7 @@ #include -#include "templates.h" + #include "sbar.h" #include "c_cvars.h" #include "c_dispatch.h" @@ -141,7 +141,7 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (painFlash.a != 0) { - cnt = DamageToAlpha[MIN (CPlayer->damagecount * painFlash.a / 255, (uint32_t)113)]; + cnt = DamageToAlpha[min (CPlayer->damagecount * painFlash.a / 255, (uint32_t)113)]; // [BC] Allow users to tone down the intensity of the blood on the screen. cnt = (int)( cnt * blood_fade_scalar ); @@ -164,7 +164,7 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int if (CPlayer->poisoncount) { - cnt = MIN (CPlayer->poisoncount, 64); + cnt = min (CPlayer->poisoncount, 64); if (paletteflash & PF_POISON) { V_AddBlend(44/255.f, 92/255.f, 36/255.f, ((cnt + 7) >> 3) * 0.1f, blend); @@ -190,7 +190,7 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int } else { - cnt= MIN(CPlayer->hazardcount/8, 64); + cnt= min(CPlayer->hazardcount/8, 64); float r = ((Level->hazardcolor & 0xff0000) >> 16) / 255.f; float g = ((Level->hazardcolor & 0xff00) >> 8) / 255.f; float b = ((Level->hazardcolor & 0xff)) / 255.f; diff --git a/src/rendering/hwrenderer/doom_aabbtree.cpp b/src/rendering/hwrenderer/doom_aabbtree.cpp index 21256271d..718040b8e 100644 --- a/src/rendering/hwrenderer/doom_aabbtree.cpp +++ b/src/rendering/hwrenderer/doom_aabbtree.cpp @@ -57,10 +57,10 @@ DoomLevelAABBTree::DoomLevelAABBTree(FLevelLocals *lev) FVector2 aabb_min, aabb_max; const auto &left = nodes[staticroot]; const auto &right = nodes[dynamicroot]; - aabb_min.X = MIN(left.aabb_left, right.aabb_left); - aabb_min.Y = MIN(left.aabb_top, right.aabb_top); - aabb_max.X = MAX(left.aabb_right, right.aabb_right); - aabb_max.Y = MAX(left.aabb_bottom, right.aabb_bottom); + aabb_min.X = min(left.aabb_left, right.aabb_left); + aabb_min.Y = min(left.aabb_top, right.aabb_top); + aabb_max.X = max(left.aabb_right, right.aabb_right); + aabb_max.Y = max(left.aabb_bottom, right.aabb_bottom); nodes.Push({ aabb_min, aabb_max, staticroot, dynamicroot }); } @@ -137,20 +137,20 @@ bool DoomLevelAABBTree::Update() float y2 = (float)line.v2->fY(); int nodeIndex = path[0]; - nodes[nodeIndex].aabb_left = MIN(x1, x2); - nodes[nodeIndex].aabb_right = MAX(x1, x2); - nodes[nodeIndex].aabb_top = MIN(y1, y2); - nodes[nodeIndex].aabb_bottom = MAX(y1, y2); + nodes[nodeIndex].aabb_left = min(x1, x2); + nodes[nodeIndex].aabb_right = max(x1, x2); + nodes[nodeIndex].aabb_top = min(y1, y2); + nodes[nodeIndex].aabb_bottom = max(y1, y2); for (unsigned int j = 1; j < path.Size(); j++) { auto &cur = nodes[path[j]]; const auto &left = nodes[cur.left_node]; const auto &right = nodes[cur.right_node]; - cur.aabb_left = MIN(left.aabb_left, right.aabb_left); - cur.aabb_top = MIN(left.aabb_top, right.aabb_top); - cur.aabb_right = MAX(left.aabb_right, right.aabb_right); - cur.aabb_bottom = MAX(left.aabb_bottom, right.aabb_bottom); + cur.aabb_left = min(left.aabb_left, right.aabb_left); + cur.aabb_top = min(left.aabb_top, right.aabb_top); + cur.aabb_right = max(left.aabb_right, right.aabb_right); + cur.aabb_bottom = max(left.aabb_bottom, right.aabb_bottom); } treelines[i] = treeline; @@ -181,14 +181,14 @@ int DoomLevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector float x2 = (float)maplines[mapLines[lines[i]]].v2->fX(); float y2 = (float)maplines[mapLines[lines[i]]].v2->fY(); - aabb_min.X = MIN(aabb_min.X, x1); - aabb_min.X = MIN(aabb_min.X, x2); - aabb_min.Y = MIN(aabb_min.Y, y1); - aabb_min.Y = MIN(aabb_min.Y, y2); - aabb_max.X = MAX(aabb_max.X, x1); - aabb_max.X = MAX(aabb_max.X, x2); - aabb_max.Y = MAX(aabb_max.Y, y1); - aabb_max.Y = MAX(aabb_max.Y, y2); + aabb_min.X = min(aabb_min.X, x1); + aabb_min.X = min(aabb_min.X, x2); + aabb_min.Y = min(aabb_min.Y, y1); + aabb_min.Y = min(aabb_min.Y, y2); + aabb_max.X = max(aabb_max.X, x1); + aabb_max.X = max(aabb_max.X, x2); + aabb_max.Y = max(aabb_max.Y, y1); + aabb_max.Y = max(aabb_max.Y, y2); median += centroids[mapLines[lines[i]]]; } diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp new file mode 100644 index 000000000..ea8aa314d --- /dev/null +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -0,0 +1,387 @@ + +#include "templates.h" +#include "doom_levelmesh.h" +#include "g_levellocals.h" +#include "texturemanager.h" + +DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap) +{ + for (unsigned int i = 0; i < doomMap.sides.Size(); i++) + { + CreateSideSurfaces(doomMap, &doomMap.sides[i]); + } + + CreateSubsectorSurfaces(doomMap); + + for (size_t i = 0; i < Surfaces.Size(); i++) + { + const Surface &s = Surfaces[i]; + int numVerts = s.numVerts; + unsigned int pos = s.startVertIndex; + FVector3* verts = &MeshVertices[pos]; + + for (int j = 0; j < numVerts; j++) + { + MeshUVIndex.Push(j); + } + + if (s.type == ST_FLOOR || s.type == ST_CEILING) + { + for (int j = 2; j < numVerts; j++) + { + if (!IsDegenerate(verts[0], verts[j - 1], verts[j])) + { + MeshElements.Push(pos); + MeshElements.Push(pos + j - 1); + MeshElements.Push(pos + j); + MeshSurfaces.Push((int)i); + } + } + } + else if (s.type == ST_MIDDLEWALL || s.type == ST_UPPERWALL || s.type == ST_LOWERWALL) + { + 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); + } + } + } +} + +void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side) +{ + sector_t *front; + sector_t *back; + + front = side->sector; + back = (side->linedef->frontsector == front) ? side->linedef->backsector : side->linedef->frontsector; + + if (IsControlSector(front)) + return; + + FVector2 v1 = ToFVector2(side->V1()->fPos()); + FVector2 v2 = ToFVector2(side->V2()->fPos()); + + 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); + + int typeIndex = side->Index(); + + FVector2 dx(v2.X - v1.X, v2.Y - v1.Y); + float distance = dx.Length(); + + if (back) + { + for (unsigned int j = 0; j < front->e->XFloor.ffloors.Size(); j++) + { + F3DFloor *xfloor = front->e->XFloor.ffloors[j]; + + // 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++) + { + if (back->e->XFloor.ffloors[k] == xfloor) + { + bothSides = true; + break; + } + } + 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); + } + + 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); + + if (v1Top == v1TopBack && v1Bottom == v1BottomBack && v2Top == v2TopBack && v2Bottom == v2BottomBack) + { + return; + } + + // bottom seg + if (v1Bottom < v1BottomBack || v2Bottom < v2BottomBack) + { + if (IsBottomSideVisible(side)) + { + 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); + } + + v1Bottom = v1BottomBack; + v2Bottom = v2BottomBack; + } + + // top seg + if (v1Top > v1TopBack || v2Top > v2TopBack) + { + bool bSky = IsTopSideSky(front, back, side); + if (bSky || IsTopSideVisible(side)) + { + 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); + } + + v1Top = v1TopBack; + v2Top = v2TopBack; + } + } + + // middle seg + if (back == nullptr) + { + 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 = 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_MIDDLEWALL; + surf.typeIndex = typeIndex; + surf.controlSector = nullptr; + + Surfaces.Push(surf); + } +} + +void DoomLevelMesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor) +{ + Surface surf; + + if (!is3DFloor) + { + surf.plane = sector->floorplane; + } + else + { + surf.plane = sector->ceilingplane; + surf.plane.FlipVert(); + } + + 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++) + { + 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]); + } + + surf.type = ST_FLOOR; + surf.typeIndex = typeIndex; + surf.controlSector = is3DFloor ? sector : nullptr; + + Surfaces.Push(surf); +} + +void DoomLevelMesh::CreateCeilingSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor) +{ + Surface surf; + surf.bSky = IsSkySector(sector); + + if (!is3DFloor) + { + surf.plane = sector->ceilingplane; + } + else + { + surf.plane = sector->floorplane; + surf.plane.FlipVert(); + } + + 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++) + { + seg_t *seg = &sub->firstline[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]); + } + + surf.type = ST_CEILING; + surf.typeIndex = typeIndex; + surf.controlSector = is3DFloor ? sector : nullptr; + + Surfaces.Push(surf); +} + +void DoomLevelMesh::CreateSubsectorSurfaces(FLevelLocals &doomMap) +{ + for (unsigned int i = 0; i < doomMap.subsectors.Size(); i++) + { + subsector_t *sub = &doomMap.subsectors[i]; + + if (sub->numlines < 3) + { + continue; + } + + sector_t *sector = sub->sector; + if (!sector || IsControlSector(sector)) + continue; + + CreateFloorSurface(doomMap, sub, sector, i, false); + CreateCeilingSurface(doomMap, sub, sector, i, false); + + 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); + } + } +} + +bool DoomLevelMesh::IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side) +{ + return IsSkySector(frontsector) && IsSkySector(backsector); +} + +bool DoomLevelMesh::IsTopSideVisible(side_t* side) +{ + auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::top), true); + return tex && tex->isValid(); +} + +bool DoomLevelMesh::IsBottomSideVisible(side_t* side) +{ + auto tex = TexMan.GetGameTexture(side->GetTexture(side_t::bottom), true); + return tex && tex->isValid(); +} + +bool DoomLevelMesh::IsSkySector(sector_t* sector) +{ + return sector->GetTexture(sector_t::ceiling) == skyflatnum; +} + +bool DoomLevelMesh::IsControlSector(sector_t* sector) +{ + //return sector->controlsector; + return false; +} + +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; +} diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h new file mode 100644 index 000000000..73dc1a5bf --- /dev/null +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -0,0 +1,55 @@ + +#pragma once + +#include "hw_levelmesh.h" +#include "tarray.h" +#include "vectors.h" +#include "r_defs.h" + +struct FLevelLocals; + +struct Surface +{ + SurfaceType type; + int typeIndex; + int numVerts; + unsigned int startVertIndex; + secplane_t plane; + sector_t *controlSector; + bool bSky; +}; + +class DoomLevelMesh : public hwrenderer::LevelMesh +{ +public: + DoomLevelMesh(FLevelLocals &doomMap); + + TArray Surfaces; + +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); +}; diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index b3ef82afd..e80d7ef66 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -41,8 +41,10 @@ #include "v_palette.h" #include "d_main.h" #include "g_cvars.h" +#include "v_draw.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "hw_cvars.h" #include "hwrenderer/data/hw_viewpointbuffer.h" #include "hwrenderer/scene/hw_fakeflat.h" @@ -123,6 +125,8 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou screen->mShadowMap.SetCollectLights(nullptr); } + screen->SetLevelMesh(camera->Level->levelMesh); + // 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)); @@ -156,12 +160,12 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou // Only used by the GLES2 renderer RenderState.SetSpecialColormap(cm, flash); - di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) + di->Viewpoint.FieldOfView = DAngle::fromDeg(fov); // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) // Stereo mode specific perspective projection di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio); // Stereo mode specific viewpoint adjustment - vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees); + 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); @@ -269,24 +273,24 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) screen->SetSaveBuffers(true); screen->ImageTransitionScene(true); + hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); hw_ClearFakeFlat(); screen->mVertexData->Reset(); RenderState.SetVertexBuffer(screen->mVertexData); screen->mLights->Clear(); + screen->mBones->Clear(); screen->mViewpoints->Clear(); // This shouldn't overwrite the global viewpoint even for a short time. FRenderViewpoint savevp; - sector_t* viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); + sector_t* viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees(), 1.6f, 1.6f, true, false); RenderState.EnableStencil(false); RenderState.SetNoSoftLightLevel(); - int numpixels = width * height; - uint8_t* scr = (uint8_t*)M_Malloc(numpixels * 3); - screen->CopyScreenToBuffer(width, height, scr); + TArray scr(width * height * 3, true); + screen->CopyScreenToBuffer(width, height, scr.Data()); - DoWriteSavePic(file, SS_RGB, scr, width, height, viewsector, screen->FlipSavePic()); - M_Free(scr); + DoWriteSavePic(file, SS_RGB, scr.Data(), width, height, viewsector, screen->FlipSavePic()); // Switch back the screen render buffers screen->SetViewportRects(nullptr); @@ -314,6 +318,7 @@ sector_t* RenderView(player_t* player) auto RenderState = screen->RenderState(); RenderState->SetVertexBuffer(screen->mVertexData); screen->mVertexData->Reset(); + hw_postprocess.SetTonemapMode(level.info ? level.info->tonemap : ETonemapMode::None); sector_t* retsec; if (!V_IsHardwareRenderer()) @@ -339,6 +344,7 @@ sector_t* RenderView(player_t* player) else r_viewpoint.TicFrac = I_GetTimeFrac(); screen->mLights->Clear(); + screen->mBones->Clear(); screen->mViewpoints->Clear(); // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. @@ -348,6 +354,22 @@ sector_t* RenderView(player_t* player) // Shader start time does not need to be handled per level. Just use the one from the camera to render from. if (player->camera) CheckTimer(*RenderState, player->camera->Level->ShaderStartTime); + + // Draw all canvases that changed + for (FCanvas* canvas : AllCanvases) + { + if (canvas->Tex->CheckNeedsUpdate()) + { + screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) + { + screen->SetViewportRects(&bounds); + Draw2D(&canvas->Drawer, *screen->RenderState(), 0, 0, canvas->Tex->GetWidth(), canvas->Tex->GetHeight()); + canvas->Drawer.Clear(); + }); + canvas->Tex->SetUpdated(true); + } + } + // prepare all camera textures that have been used in the last frame. // This must be done for all levels, not just the primary one! for (auto Level : AllLevels()) @@ -378,7 +400,7 @@ sector_t* RenderView(player_t* player) screen->ImageTransitionScene(true); // Only relevant for Vulkan. - retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); + retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees(), ratio, fovratio, true, true); } All.Unclock(); return retsec; diff --git a/src/rendering/hwrenderer/hw_models.cpp b/src/rendering/hwrenderer/hw_models.cpp index ff99702f0..b22eca3c7 100644 --- a/src/rendering/hwrenderer/hw_models.cpp +++ b/src/rendering/hwrenderer/hw_models.cpp @@ -41,6 +41,7 @@ #include "hwrenderer/scene/hw_drawinfo.h" #include "hw_renderstate.h" #include "hwrenderer/scene/hw_portal.h" +#include "hw_bonebuffer.h" #include "hw_models.h" CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE) @@ -71,6 +72,7 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf void FHWModelRenderer::EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) { + state.SetBoneIndexBase(-1); state.EnableModelMatrix(false); state.SetDepthFunc(DF_Less); if (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) @@ -95,6 +97,7 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj void FHWModelRenderer::EndDrawHUDModel(FRenderStyle style) { + state.SetBoneIndexBase(-1); state.EnableModelMatrix(false); state.SetDepthFunc(DF_Less); @@ -134,10 +137,16 @@ void FHWModelRenderer::DrawElements(int numIndices, size_t offset) // //=========================================================================== -void FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size) +int FHWModelRenderer::SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { auto mdbuff = static_cast(model->GetVertexBuffer(GetType())); - state.SetVertexBuffer(mdbuff->vertexBuffer(), frame1, frame2); - if (mdbuff->indexBuffer()) state.SetIndexBuffer(mdbuff->indexBuffer()); + boneIndexBase = boneStartIndex >= 0 ? boneStartIndex : screen->mBones->UploadBones(bones); + state.SetBoneIndexBase(boneIndexBase); + if (mdbuff) + { + state.SetVertexBuffer(mdbuff->vertexBuffer(), frame1, frame2); + if (mdbuff->indexBuffer()) state.SetIndexBuffer(mdbuff->indexBuffer()); + } + return boneIndexBase; } diff --git a/src/rendering/hwrenderer/hw_models.h b/src/rendering/hwrenderer/hw_models.h index 28026905e..32248152b 100644 --- a/src/rendering/hwrenderer/hw_models.h +++ b/src/rendering/hwrenderer/hw_models.h @@ -39,6 +39,7 @@ class FHWModelRenderer : public FModelRenderer { friend class FModelVertexBuffer; int modellightindex = -1; + int boneIndexBase = -1; HWDrawInfo *di; FRenderState &state; public: @@ -55,7 +56,7 @@ public: void SetMaterial(FGameTexture *skin, bool clampNoFilter, int translation) override; void DrawArrays(int start, int count) override; void DrawElements(int numIndices, size_t offset) override; - void SetupFrame(FModel *model, unsigned int frame1, unsigned int frame2, unsigned int size) 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_postprocessshader.cpp b/src/rendering/hwrenderer/hw_postprocessshader.cpp deleted file mode 100644 index f8e6e3e8b..000000000 --- a/src/rendering/hwrenderer/hw_postprocessshader.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -** Postprocessing framework -** 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 "vm.h" -#include "d_player.h" -#include "hwrenderer/postprocessing/hw_postprocessshader.h" -#include "g_levellocals.h" -#include "hwrenderer/postprocessing/hw_postprocess.h" - -static bool IsConsolePlayer(player_t *player) -{ - AActor *activator = player ? player->mo : nullptr; - if (activator == nullptr || activator->player == nullptr) - return false; - return activator->player == activator->Level->GetConsolePlayer(); -} - -static void ShaderSetEnabled(player_t *player, const FString &shaderName, bool value) -{ - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - shader.Enabled = value; - } - } -} - -DEFINE_ACTION_FUNCTION_NATIVE(_Shader, SetEnabled, ShaderSetEnabled) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_BOOL(value); - ShaderSetEnabled(player, shaderName, value); - - return 0; -} - -static void ShaderSetUniform1f(player_t *player, const FString &shaderName, const FString &uniformName, double value) -{ - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } -} - -DEFINE_ACTION_FUNCTION_NATIVE(_Shader, SetUniform1f, ShaderSetUniform1f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(value); - ShaderSetUniform1f(player, shaderName, uniformName, value); - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform2f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(x); - PARAM_FLOAT(y); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform3f) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_FLOAT(x); - PARAM_FLOAT(y); - PARAM_FLOAT(z); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = z; - vec4[3] = 1.0; - } - } - } - return 0; -} - -DEFINE_ACTION_FUNCTION(_Shader, SetUniform1i) -{ - PARAM_PROLOGUE; - PARAM_POINTER(player, player_t); - PARAM_STRING(shaderName); - PARAM_STRING(uniformName); - PARAM_INT(value); - - if (IsConsolePlayer(player)) - { - for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) - { - PostProcessShader &shader = PostProcessShaders[i]; - if (shader.Name == shaderName) - { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = (double)value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; - } - } - } - return 0; -} diff --git a/src/rendering/hwrenderer/hw_precache.cpp b/src/rendering/hwrenderer/hw_precache.cpp index 7ad9192bc..7ea1ecb38 100644 --- a/src/rendering/hwrenderer/hw_precache.cpp +++ b/src/rendering/hwrenderer/hw_precache.cpp @@ -170,8 +170,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl } else if (smf->modelIDs[i] != -1) { - Models[smf->modelIDs[i]]->PushSpriteMDLFrame(smf, i); - Models[smf->modelIDs[i]]->AddSkins(texhitlist); + Models[smf->modelIDs[i]]->AddSkins(texhitlist, (unsigned)(i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr); } if (smf->modelIDs[i] != -1) { diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.cpp b/src/rendering/hwrenderer/hw_vertexbuilder.cpp index c4b980d65..718528afe 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.cpp +++ b/src/rendering/hwrenderer/hw_vertexbuilder.cpp @@ -160,13 +160,18 @@ TArray BuildVertices(TArray §ors) // //========================================================================== -static F3DFloor* Find3DFloor(sector_t* target, sector_t* model) +static F3DFloor *Find3DFloor(sector_t* target, sector_t* model, int &ffloorIndex) { for (unsigned i = 0; i < target->e->XFloor.ffloors.Size(); i++) { F3DFloor* ffloor = target->e->XFloor.ffloors[i]; - if (ffloor->model == model && !(ffloor->flags & FF_THISINSIDE)) return ffloor; + if (ffloor->model == model && !(ffloor->flags & FF_THISINSIDE)) + { + ffloorIndex = i; + return ffloor; + } } + ffloorIndex = -1; return NULL; } @@ -183,12 +188,99 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan ffv.z = (float)plane.ZatPoint(vt); ffv.u = (float)vt->fX() / 64.f; ffv.v = -(float)vt->fY() / 64.f; + ffv.lindex = -1.0f; } - - -static int CreateIndexedSectorVertices(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts) +static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, int llindex) { + ffv.x = (float)vt->fX(); + ffv.y = (float)vt->fY(); + ffv.z = (float)plane.ZatPoint(vt); + ffv.u = (float)vt->fX() / 64.f; + ffv.v = -(float)vt->fY() / 64.f; + ffv.lu = llu; + ffv.lv = llv; + ffv.lindex = (float)llindex; +} + +//========================================================================== +// +// Creates the vertices for one plane in one subsector w/lightmap support. +// Sectors with lightmaps cannot share subsector vertices. +// +//========================================================================== + +static int CreateIndexedSectorVerticesLM(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, int h, int lightmapIndex) +{ + int i, pos; + float diff; + + auto& ibo_data = fvb->ibo_data; + + int rt = ibo_data.Size(); + if (sec->transdoor && floor) diff = -1.f; + else diff = 0.f; + + // Allocate space + for (i = 0, pos = 0; i < sec->subsectorcount; i++) + { + pos += sec->subsectors[i]->numlines; + } + + auto& vbo_shadowdata = fvb->vbo_shadowdata; + int vi = vbo_shadowdata.Reserve(pos); + int idx = ibo_data.Reserve((pos - 2 * sec->subsectorcount) * 3); + + // Create the actual vertices. + for (i = 0, pos = 0; i < sec->subsectorcount; i++) + { + subsector_t* sub = sec->subsectors[i]; + LightmapSurface* lightmap = &sub->lightmap[h][lightmapIndex]; + if (lightmap->Type != ST_NULL) + { + float* luvs = lightmap->TexCoords; + int lindex = lightmap->LightmapNum; + for (unsigned int j = 0; j < sub->numlines; j++) + { + 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++; + } + } + else + { + 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++) + { + subsector_t* sub = sec->subsectors[i]; + 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 += sec->subsectors[i]->numlines; + } + + sec->ibocount = ibo_data.Size() - rt; + return rt; +} + +static int CreateIndexedSectorVertices(FFlatVertexBuffer* fvb, sector_t* sec, const secplane_t& plane, int floor, VertexContainer& verts, int h, int lightmapIndex) +{ + if (sec->HasLightmaps && lightmapIndex != -1) + return CreateIndexedSectorVerticesLM(fvb, sec, plane, floor, h, lightmapIndex); + auto& vbo_shadowdata = fvb->vbo_shadowdata; unsigned vi = vbo_shadowdata.Reserve(verts.vertices.Size()); float diff; @@ -225,14 +317,14 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c for (int n = 0; n < screen->mPipelineNbr; n++) sec->vboheight[n][h] = sec->GetPlaneTexZ(h); sec->ibocount = verts[sec->Index()].indices.Size(); - sec->iboindex[h] = CreateIndexedSectorVertices(fvb, sec, plane, floor, verts[sec->Index()]); + sec->iboindex[h] = CreateIndexedSectorVertices(fvb, 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(fvb, fsec, plane, false, verts[fsec->Index()]); + fsec->iboindex[2 + h] = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()], h, -1); } // and finally all attached 3D floors @@ -240,7 +332,8 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c for (unsigned g = 0; g < xf.Size(); g++) { sector_t* fsec = xf[g]; - F3DFloor* ffloor = Find3DFloor(fsec, sec); + int ffloorIndex; + F3DFloor* ffloor = Find3DFloor(fsec, sec, ffloorIndex); if (ffloor != NULL && ffloor->flags & FF_RENDERPLANES) { @@ -249,7 +342,7 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c if (dotop || dobottom) { - auto ndx = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()]); + auto ndx = CreateIndexedSectorVertices(fvb, fsec, plane, false, verts[fsec->Index()], h, ffloorIndex + 1); if (dotop) ffloor->top.vindex = ndx; if (dobottom) ffloor->bottom.vindex = ndx; } diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 8a1a63a33..822f7c2ca 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -429,11 +429,6 @@ void HWDrawInfo::AddPolyobjs(subsector_t *sub) if (sub->BSP == nullptr || sub->BSP->bDirty) { sub->BuildPolyBSP(); - for (unsigned i = 0; i < sub->BSP->Segs.Size(); i++) - { - sub->BSP->Segs[i].Subsector = sub; - sub->BSP->Segs[i].PartnerSeg = nullptr; - } } if (sub->BSP->Nodes.Size() == 0) { @@ -490,13 +485,13 @@ void HWDrawInfo::AddLines(subsector_t * sub, sector_t * sector) // //========================================================================== -inline bool PointOnLine(const DVector2 &pos, const line_t *line) +inline bool PointOnLine(const DVector2 &pos, const linebase_t *line) { double v = (pos.Y - line->v1->fY()) * line->Delta().X + (line->v1->fX() - pos.X) * line->Delta().Y; return fabs(v) <= EQUAL_EPSILON; } -void HWDrawInfo::AddSpecialPortalLines(subsector_t * sub, sector_t * sector, line_t *line) +void HWDrawInfo::AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line) { currentsector = sector; currentsubsector = sub; @@ -658,7 +653,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) int clipres = mClipPortal->ClipSubsector(sub); if (clipres == PClip_InFront) { - line_t *line = mClipPortal->ClipLine(); + auto line = mClipPortal->ClipLine(); // The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts. if (line) AddSpecialPortalLines(sub, fakesector, line); return; diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp index a2ee40d70..980fc52a5 100644 --- a/src/rendering/hwrenderer/scene/hw_decal.cpp +++ b/src/rendering/hwrenderer/scene/hw_decal.cpp @@ -61,6 +61,19 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) state.SetObjectColor(DecalColor); state.SetLightIndex(dynlightindex); + + // add light probe contribution + if (di->Level->LightProbes.Size() > 0) + { + double x, y; + decal->GetXY(decal->Side, x, y); + LightProbe *probe = FindLightProbe(di->Level, x, y, decal->GetRealZ(decal->Side) * 0.5); + if (probe) + { + state.SetDynLight(probe->Red, probe->Green, probe->Blue); + } + } + state.SetTextureMode(decal->RenderStyle); state.SetRenderStyle(decal->RenderStyle); state.SetMaterial(texture, UF_Sprite, 0, CLAMP_XY, decal->Translation, -1); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 427a91dfd..613132ebe 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -41,9 +41,14 @@ #include "hw_viewpointbuffer.h" #include "flatvertices.h" #include "hw_lightbuffer.h" +#include "hw_bonebuffer.h" #include "hw_vrmodes.h" #include "hw_clipper.h" #include "v_draw.h" +#include "a_corona.h" +#include "texturemanager.h" +#include "actorinlines.h" +#include "g_levellocals.h" EXTERN_CVAR(Float, r_visibility) CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE) @@ -55,6 +60,8 @@ CVAR(Bool, gl_texture, true, 0) CVAR(Float, gl_mask_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, gl_mask_sprite_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, gl_coronas, true, CVAR_ARCHIVE); + sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); //========================================================================== @@ -158,6 +165,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni } VPUniforms.mClipLine.X = -10000000.0f; VPUniforms.mShadowmapFilter = gl_shadowmap_filter; + VPUniforms.mLightBlendMode = (level.info ? (int)level.info->lightblendmode : 0); } mClipper->SetViewpoint(Viewpoint); @@ -165,6 +173,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset(); hudsprites.Clear(); +// Coronas.Clear(); vpIndex = 0; // Fullbright information needs to be propagated from the main view. @@ -341,15 +350,15 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player) angle_t HWDrawInfo::FrustumAngle() { - float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees); + float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees()); // If the pitch is larger than this you can look all around at a FOV of 90° if (tilt > 46.0f) return 0xffffffff; // ok, this is a gross hack that barely works... // but at least it doesn't overestimate too much... - double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; - angle_t a1 = DAngle(floatangle).BAMs(); + double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees() * 48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; + angle_t a1 = DAngle::fromDeg(floatangle).BAMs(); if (a1 >= ANGLE_180) return 0xffffffff; return a1; } @@ -366,9 +375,9 @@ void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float float planemult = planemirror ? -Level->info->pixelstretch : Level->info->pixelstretch; VPUniforms.mViewMatrix.loadIdentity(); - VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees, 0.0f, 0.0f, 1.0f); - VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees, 1.0f, 0.0f, 0.0f); - VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees, 0.0f, mult, 0.0f); + VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees(), 0.0f, 0.0f, 1.0f); + VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees(), 1.0f, 0.0f, 0.0f); + VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees(), 0.0f, mult, 0.0f); VPUniforms.mViewMatrix.translate(vx * mult, -vz * planemult, -vy); VPUniforms.mViewMatrix.scale(-mult, planemult, 1); } @@ -439,6 +448,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites) // clip the scene and fill the drawlists screen->mVertexData->Map(); screen->mLights->Map(); + screen->mBones->Map(); RenderBSP(Level->HeadNode(), drawpsprites); @@ -451,6 +461,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites) PrepareUnhandledMissingTextures(); DispatchRenderHacks(); screen->mLights->Unmap(); + screen->mBones->Unmap(); screen->mVertexData->Unmap(); ProcessAll.Unclock(); @@ -569,6 +580,134 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil) } +void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) +{ +#if 0 + spriteframe_t* sprframe = &SpriteFrames[sprites[corona->sprite].spriteframes + (size_t)corona->SpawnState->GetFrame()]; + FTextureID patch = sprframe->Texture[0]; + if (!patch.isValid()) return; + auto tex = TexMan.GetGameTexture(patch, false); + if (!tex || !tex->isValid()) return; + + // Project the corona sprite center + FVector4 worldPos((float)corona->X(), (float)corona->Z(), (float)corona->Y(), 1.0f); + FVector4 viewPos, clipPos; + VPUniforms.mViewMatrix.multMatrixPoint(&worldPos[0], &viewPos[0]); + VPUniforms.mProjectionMatrix.multMatrixPoint(&viewPos[0], &clipPos[0]); + if (clipPos.W < -1.0f) return; // clip z nearest + float halfViewportWidth = screen->GetWidth() * 0.5f; + float halfViewportHeight = screen->GetHeight() * 0.5f; + float invW = 1.0f / clipPos.W; + float screenX = halfViewportWidth + clipPos.X * invW * halfViewportWidth; + float screenY = halfViewportHeight - clipPos.Y * invW * halfViewportHeight; + + float alpha = corona->CoronaFade * float(corona->Alpha); + + // distance-based fade - looks better IMO + float distNearFadeStart = float(corona->RenderRadius()) * 0.1f; + float distFarFadeStart = float(corona->RenderRadius()) * 0.5f; + float distFade = 1.0f; + + if (float(dist) < distNearFadeStart) + distFade -= abs(((float(dist) - distNearFadeStart) / distNearFadeStart)); + else if (float(dist) >= distFarFadeStart) + distFade -= (float(dist) - distFarFadeStart) / distFarFadeStart; + + alpha *= distFade; + + state.SetColorAlpha(0xffffff, alpha, 0); + if (isSoftwareLighting()) state.SetSoftLightLevel(255); + else state.SetNoSoftLightLevel(); + + state.SetLightIndex(-1); + state.SetRenderStyle(corona->RenderStyle); + state.SetTextureMode(corona->RenderStyle); + + state.SetMaterial(tex, UF_Sprite, CTF_Expand, CLAMP_XY_NOMIP, 0, 0); + + float scale = screen->GetHeight() / 1000.0f; + float tileWidth = corona->Scale.X * tex->GetDisplayWidth() * scale; + float tileHeight = corona->Scale.Y * tex->GetDisplayHeight() * scale; + float x0 = screenX - tileWidth, y0 = screenY - tileHeight; + float x1 = screenX + tileWidth, y1 = screenY + tileHeight; + + float u0 = 0.0f, v0 = 0.0f; + float u1 = 1.0f, v1 = 1.0f; + + auto vert = screen->mVertexData->AllocVertices(4); + auto vp = vert.first; + unsigned int vertexindex = vert.second; + + vp[0].Set(x0, y0, 1.0f, u0, v0); + vp[1].Set(x1, y0, 1.0f, u1, v0); + vp[2].Set(x0, y1, 1.0f, u0, v1); + vp[3].Set(x1, y1, 1.0f, u1, v1); + + state.Draw(DT_TriangleStrip, vertexindex, 4); +#endif +} + +static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata) +{ + FRenderViewpoint* data = (FRenderViewpoint*)userdata; + if (res.HitType == TRACE_HitActor && res.Actor && res.Actor == data->ViewActor) + { + return TRACE_Skip; + } + + return TRACE_Stop; +} + + +void HWDrawInfo::DrawCoronas(FRenderState& state) +{ + state.EnableDepthTest(false); + state.SetDepthMask(false); + + HWViewpointUniforms vp = VPUniforms; + vp.mViewMatrix.loadIdentity(); + vp.mProjectionMatrix = VRMode::GetVRMode(true)->GetHUDSpriteProjection(); + screen->mViewpoints->SetViewpoint(state, &vp); + + float timeElapsed = (screen->FrameTime - LastFrameTime) / 1000.0f; + LastFrameTime = screen->FrameTime; + +#if 0 + for (ACorona* corona : Coronas) + { + auto cPos = corona->Vec3Offset(0., 0., corona->Height * 0.5); + DVector3 direction = Viewpoint.Pos - cPos; + double dist = direction.Length(); + + // skip coronas that are too far + if (dist > corona->RenderRadius()) + continue; + + static const float fadeSpeed = 9.0f; + + direction.MakeUnit(); + 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); + } + else + { + corona->CoronaFade = std::max(corona->CoronaFade - timeElapsed * fadeSpeed, 0.0f); + } + + if (corona->CoronaFade > 0.0f) + DrawCorona(state, corona, dist); + } +#endif + + state.SetTextureMode(TM_NORMAL); + screen->mViewpoints->Bind(state, vpIndex); + state.EnableDepthTest(true); + state.SetDepthMask(true); +} + + //----------------------------------------------------------------------------- // // Draws player sprites and color blend @@ -580,6 +719,11 @@ void HWDrawInfo::EndDrawScene(sector_t * viewsector, FRenderState &state) { state.EnableFog(false); + /*if (gl_coronas && Coronas.Size() > 0) + { + DrawCoronas(state); + }*/ + // [BB] HUD models need to be rendered here. const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); if (renderHUDModel) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 4d92c1cbc..68afcb246 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -29,6 +29,7 @@ class IShadowMap; struct particle_t; struct FDynLightData; struct HUDSprite; +class ACorona; class Clipper; class HWPortal; class FFlatVertexBuffer; @@ -150,6 +151,8 @@ struct HWDrawInfo 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; + uint64_t LastFrameTime = 0; TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -197,7 +200,7 @@ private: 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, line_t *line); + void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line); public: void RenderThings(subsector_t * sub, sector_t * sector); void RenderParticles(subsector_t *sub, sector_t *front); @@ -213,6 +216,9 @@ private: 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); + void PreparePlayerSprites3D(sector_t * viewsector, area_t in_area); public: void SetCameraPos(const DVector3 &pos) @@ -300,6 +306,8 @@ public: 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 ProcessLowerMinisegs(TArray &lowersegs); void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub); diff --git a/src/rendering/hwrenderer/scene/hw_drawlist.cpp b/src/rendering/hwrenderer/scene/hw_drawlist.cpp index 872d5d419..1d729e110 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlist.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlist.cpp @@ -287,6 +287,7 @@ void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, SortNode * head, SortNode * s { 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 @@ -295,11 +296,13 @@ void HWDrawList::SortWallIntoPlane(HWDrawInfo* di, SortNode * head, SortNode * s { 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, false); ws->MakeVertices(di, false); @@ -433,6 +436,7 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sor float ix=(float)(ws->glseg.x1+r*(ws->glseg.x2-ws->glseg.x1)); float iy=(float)(ws->glseg.y1+r*(ws->glseg.y2-ws->glseg.y1)); float iu=(float)(ws->tcs[HWWall::UPLFT].u + r * (ws->tcs[HWWall::UPRGT].u - ws->tcs[HWWall::UPLFT].u)); + float ilmu=(float)(ws->lightuv[HWWall::UPLFT].u + r * (ws->lightuv[HWWall::UPRGT].u - ws->lightuv[HWWall::UPLFT].u)); float izt=(float)(ws->ztop[0]+r*(ws->ztop[1]-ws->ztop[0])); float izb=(float)(ws->zbottom[0]+r*(ws->zbottom[1]-ws->zbottom[0])); @@ -446,6 +450,7 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sor w->ztop[0]=ws->ztop[1]=izt; 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, false); w->MakeVertices(di, false); diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 205f225d3..1ccd2603d 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -84,7 +84,7 @@ struct HWSectorPlane Offs.Y = (float)sec->GetYOffset(ceiling); Scale.X = (float)sec->GetXScale(ceiling); Scale.Y = (float)sec->GetYScale(ceiling); - Angle = (float)sec->GetAngle(ceiling).Degrees; + Angle = (float)sec->GetAngle(ceiling).Degrees(); texture = sec->GetTexture(ceiling); plane = sec->GetSecPlane(ceiling); Texheight = (float)((ceiling == sector_t::ceiling)? plane.fD() : -plane.fD()); @@ -154,10 +154,13 @@ public: vertex_t * vertexes[2]; // required for polygon splitting FGameTexture *texture; TArray *lightlist; + LightmapSurface *lightmap; HWSeg glseg; float ztop[2],zbottom[2]; texcoord tcs[4]; + texcoord lightuv[4]; + float lindex; float alpha; FColormap Colormap; @@ -238,13 +241,13 @@ public: void GetPlanePos(F3DFloor::planeref * planeref, float & left, float & right); - void BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, + void BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, int roverIndex, float ff_topleft, float ff_topright, float ff_bottomleft, float ff_bottomright); void InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, float topleft, float topright, float bottomleft, float bottomright); - void ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, sector_t * frontsector, + void ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector, float topleft, float topright, float bottomleft, float bottomright); void DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, sector_t * backsector, @@ -430,6 +433,7 @@ inline float Dist2(float x1,float y1,float x2,float y2) bool hw_SetPlaneTextureRotation(const HWSectorPlane * secplane, FGameTexture * gltexture, VSMatrix &mat); void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata); +LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z); extern const float LARGE_VALUE; diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 77ad93649..5b57c9f94 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -161,7 +161,7 @@ void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &light { FDynamicLight * light = node->lightsource; - if (!light->IsActive()) + if (!light->IsActive() || light->DontLightMap()) { node = node->nextLight; continue; diff --git a/src/rendering/hwrenderer/scene/hw_lighting.h b/src/rendering/hwrenderer/scene/hw_lighting.h index 2fd972b88..f4cc44380 100644 --- a/src/rendering/hwrenderer/scene/hw_lighting.h +++ b/src/rendering/hwrenderer/scene/hw_lighting.h @@ -2,7 +2,7 @@ #include "c_cvars.h" #include "v_palette.h" -#include "templates.h" + #include "r_utility.h" struct Colormap; diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index c5efff0ab..aaf7ae06c 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -415,7 +415,7 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset; DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset; - if (deltaangle(endAngle, startAngle) < 0) + if (deltaangle(endAngle, startAngle) < nullAngle) { clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); } @@ -447,7 +447,7 @@ int HWLinePortal::ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; // should be handled properly. } - return P_ClipLineToPortal(linedef, line(), viewpos) ? PClip_InFront : PClip_Inside; + return P_ClipLineToPortal(linedef, this, viewpos) ? PClip_InFront : PClip_Inside; } int HWLinePortal::ClipSubsector(subsector_t *sub) @@ -455,14 +455,14 @@ int HWLinePortal::ClipSubsector(subsector_t *sub) // this seg is completely behind the mirror for (unsigned int i = 0; inumlines; i++) { - if (P_PointOnLineSidePrecise(sub->firstline[i].v1->fPos(), line()) == 0) return PClip_Inside; + if (P_PointOnLineSidePrecise(sub->firstline[i].v1->fPos(), this) == 0) return PClip_Inside; } return PClip_InFront; } int HWLinePortal::ClipPoint(const DVector2 &pos) { - if (P_PointOnLineSidePrecise(pos, line())) + if (P_PointOnLineSidePrecise(pos, this)) { return PClip_InFront; } @@ -779,6 +779,11 @@ void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di) bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mState; + if (state->renderdepth > 100) // energency abort in case a map manages to set up a recursion. + { + return false; + } + FSectorPortalGroup *portal = origin; auto &vp = di->Viewpoint; diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 6a3b46170..3eebaee2d 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -74,7 +74,7 @@ public: virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; } virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; } - virtual line_t *ClipLine() { return nullptr; } + virtual linebase_t *ClipLine() { return nullptr; } virtual void * GetSource() const = 0; // GetSource MUST be implemented! virtual const char *GetName() = 0; virtual bool AllowSSAO() { return true; } @@ -156,14 +156,8 @@ public: virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {} }; -struct HWLinePortal : public HWScenePortalBase +struct HWLinePortal : public HWScenePortalBase, public linebase_t { - uint32_t PAD; // This fixes walls not being drawn in portals in 32bit machines..seems to be OK this is here for 64bit also.. - - // this must be the same as at the start of line_t, so that we can pass in this structure directly to P_ClipLineToPortal. - vertex_t *v1, *v2; // vertices, from v1 to v2 - DVector2 delta; // precalculated v2 - v1 for side checking - angle_t angv1, angv2; // for quick comparisons with a line or subsector HWLinePortal(FPortalSceneState *state, line_t *line) : HWScenePortalBase(state) @@ -196,12 +190,6 @@ struct HWLinePortal : public HWScenePortalBase delta = v2->fPos() - v1->fPos(); } - line_t *line() - { - vertex_t **pv = &v1; - return reinterpret_cast(pv); - } - int ClipSeg(seg_t *seg, const DVector3 &viewpos) override; int ClipSubsector(subsector_t *sub) override; int ClipPoint(const DVector2 &pos); @@ -236,7 +224,7 @@ protected: bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; virtual void * GetSource() const override { return glport; } virtual const char *GetName() override; - virtual line_t *ClipLine() override { return line(); } + virtual linebase_t *ClipLine() override { return this; } virtual void RenderAttached(HWDrawInfo *di) override; public: diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 71b486888..f9998398a 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -37,6 +37,7 @@ #include "hwrenderer/scene/hw_drawinfo.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "models.h" +#include // needed for std::floor on mac template T smoothstep(const T edge0, const T edge1, const T x) @@ -45,6 +46,61 @@ T smoothstep(const T edge0, const T edge1, const T x) return t * t * (3.0 - 2.0 * t); } +LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z) +{ + LightProbe* foundprobe = nullptr; + if (level->LightProbes.Size() > 0) + { +#if 1 + double rcpCellSize = 1.0 / level->LPCellSize; + int gridCenterX = (int)std::floor(x * rcpCellSize) - level->LPMinX; + int gridCenterY = (int)std::floor(y * rcpCellSize) - level->LPMinY; + int gridWidth = level->LPWidth; + int gridHeight = level->LPHeight; + float lastdist = 0.0f; + for (int gridY = gridCenterY - 1; gridY <= gridCenterY + 1; gridY++) + { + for (int gridX = gridCenterX - 1; gridX <= gridCenterX + 1; gridX++) + { + if (gridX >= 0 && gridY >= 0 && gridX < gridWidth && gridY < gridHeight) + { + const LightProbeCell& cell = level->LPCells[gridX + (size_t)gridY * gridWidth]; + for (int i = 0; i < cell.NumProbes; i++) + { + LightProbe* probe = cell.FirstProbe + i; + float dx = probe->X - x; + float dy = probe->Y - y; + float dz = probe->Z - z; + float dist = dx * dx + dy * dy + dz * dz; + if (!foundprobe || dist < lastdist) + { + foundprobe = probe; + lastdist = dist; + } + } + } + } + } +#else + float lastdist = 0.0f; + for (unsigned int i = 0; i < level->LightProbes.Size(); i++) + { + LightProbe *probe = &level->LightProbes[i]; + float dx = probe->X - x; + float dy = probe->Y - y; + float dz = probe->Z - z; + float dist = dx * dx + dy * dy + dz * dz; + if (i == 0 || dist < lastdist) + { + foundprobe = probe; + lastdist = dist; + } + } +#endif + } + return foundprobe; +} + //========================================================================== // // Sets a single light value from all dynamic lights affecting the specified location @@ -58,6 +114,15 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig float radius; out[0] = out[1] = out[2] = 0.f; + + LightProbe* probe = FindLightProbe(Level, x, y, z); + if (probe) + { + out[0] = probe->Red; + out[1] = probe->Green; + out[2] = probe->Blue; + } + // Go through both light lists while (node) { diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index d66074f6d..c11878c11 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -33,6 +33,7 @@ #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" @@ -101,6 +102,8 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) int rel = fullbright ? 0 : getExtraLight(); auto &vp = di->Viewpoint; + const bool UseActorLight = (actor && actor->LightLevel > -1); + if (translucent) { // The translucent pass requires special setup for the various modes. @@ -240,7 +243,6 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) // set up the light slice secplane_t *topplane = i == 0 ? &topp : &(*lightlist)[i].plane; secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane; - int thislight = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; int thisll = actor == nullptr ? thislight : (uint8_t)actor->Sector->CheckSpriteGlow(thislight, actor->InterpolatedPosition(vp.TicFrac)); @@ -292,6 +294,13 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) } else { + if (actor && di->Level->LightProbes.Size() > 0) + { + LightProbe* probe = FindLightProbe(di->Level, actor->X(), actor->Y(), actor->Center()); + if (probe) + state.SetDynLight(probe->Red, probe->Green, probe->Blue); + } + FHWModelRenderer renderer(di, state, dynlightindex); RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac); state.SetVertexBuffer(screen->mVertexData); @@ -343,12 +352,12 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // Tilt the actor up or down based on pitch (increase 'somersaults' forward). // Then counteract the roll and DO A BARREL ROLL. - FAngle pitch = (float)-Angles.Pitch.Degrees; + FAngle pitch = FAngle::fromDeg(-Angles.Pitch.Degrees()); pitch.Normalized180(); mat.Translate(x, z, y); - mat.Rotate(0, 1, 0, 270. - Angles.Yaw.Degrees); - mat.Rotate(1, 0, 0, pitch.Degrees); + mat.Rotate(0, 1, 0, 270. - Angles.Yaw.Degrees()); + mat.Rotate(1, 0, 0, pitch.Degrees()); if (actor->renderflags & RF_ROLLCENTER) { @@ -356,12 +365,12 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) float cy = (y1 + y2) * 0.5; mat.Translate(cx - x, 0, cy - y); - mat.Rotate(0, 1, 0, - Angles.Roll.Degrees); + mat.Rotate(0, 1, 0, - Angles.Roll.Degrees()); mat.Translate(-cx, -z, -cy); } else { - mat.Rotate(0, 1, 0, - Angles.Roll.Degrees); + mat.Rotate(0, 1, 0, - Angles.Roll.Degrees()); mat.Translate(-x, -z, -y); } v[0] = mat * FVector3(x2, z, y2); @@ -373,7 +382,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) } // [BB] Billboard stuff - const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD) + const bool drawWithXYBillboard = ((particle && gl_billboard_particles && !(particle->flags & PT_NOXYBILLBOARD)) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD) //&& di->mViewActor != nullptr && (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD)))); @@ -381,6 +390,8 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); + const bool drawRollParticle = (particle != nullptr && particle->flags & PT_DOROLL); + // [fgsfds] check sprite type mask uint32_t spritetype = (uint32_t)-1; @@ -391,7 +402,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER); // [Nash] check for special sprite drawing modes - if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || isFlatSprite) + if (drawWithXYBillboard || drawBillboardFacingCamera || drawRollSpriteActor || drawRollParticle || isFlatSprite) { // Compute center of sprite float xcenter = (x1 + x2)*0.5; @@ -412,7 +423,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) float xrel = xcenter - vp->X; float yrel = ycenter - vp->Y; float absAngleDeg = RAD2DEG(atan2(-yrel, xrel)); - float counterRotationDeg = 270. - HWAngles.Yaw.Degrees; // counteracts existing sprite rotation + float counterRotationDeg = 270. - HWAngles.Yaw.Degrees(); // counteracts existing sprite rotation float relAngleDeg = counterRotationDeg + absAngleDeg; mat.Rotate(0, 1, 0, relAngleDeg); @@ -420,8 +431,8 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // [fgsfds] calculate yaw vectors float yawvecX = 0, yawvecY = 0, rollDegrees = 0; - float angleRad = (270. - HWAngles.Yaw).Radians(); - if (actor) rollDegrees = Angles.Roll.Degrees; + float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians(); + if (actor || drawRollParticle) rollDegrees = Angles.Roll.Degrees(); if (isFlatSprite) { yawvecX = Angles.Yaw.Cos(); @@ -439,12 +450,12 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) if (useOffsets) mat.Translate(-xx, -zz, -yy); } } - else if (drawRollSpriteActor) + else if (drawRollSpriteActor || drawRollParticle) { if (useOffsets) mat.Translate(xx, zz, yy); if (drawWithXYBillboard) { - mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees); + mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees()); } mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees); if (useOffsets) mat.Translate(-xx, -zz, -yy); @@ -454,7 +465,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // Rotate the sprite about the vector starting at the center of the sprite // triangle strip and with direction orthogonal to where the player is looking // in the x/y plane. - mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees); + mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees()); } mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center @@ -695,7 +706,15 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; } - const auto &vp = di->Viewpoint; +#if 0 + if (thing->IsKindOf(NAME_Corona)) + { + di->Coronas.Push(static_cast(thing)); + return; + } +#endif + + const auto &vp = di->Viewpoint; AActor *camera = vp.camera; if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha)) @@ -711,7 +730,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; int spritenum = thing->sprite; - DVector2 sprscale = thing->Scale; + DVector2 sprscale(thing->Scale.X, thing->Scale.Y); if (thing->player != nullptr) { P_CheckPlayerSprite(thing, spritenum, sprscale); @@ -721,17 +740,36 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t DVector3 thingpos = thing->InterpolatedPosition(vp.TicFrac); if (thruportal == 1) thingpos += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); - // 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 (thing == camera && !vp.showviewer) + AActor *viewmaster = thing; + if ((thing->flags8 & MF8_MASTERNOSEE) && thing->master != nullptr) { - DVector3 thingorigin = thing->Pos(); - if (thruportal == 1) thingorigin += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); - if (fabs(thingorigin.X - vp.ActorPos.X) < 2 && fabs(thingorigin.Y - vp.ActorPos.Y) < 2) return; + viewmaster = thing->master; + } + + // [Nash] filter visibility in mirrors + bool isInMirror = di->mCurrentPortal && (di->mCurrentPortal->mState->MirrorFlag > 0 || di->mCurrentPortal->mState->PlaneMirrorFlag > 0); + if (thing->renderflags2 & RF2_INVISIBLEINMIRRORS && isInMirror) + { + return; + } + else if (thing->renderflags2 & RF2_ONLYVISIBLEINMIRRORS && !isInMirror) + { + 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) + { + 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; } // Thing is invisible if close to the camera. - if (thing->renderflags & RF_MAYBEINVISIBLE) + if (viewmaster->renderflags & RF_MAYBEINVISIBLE) { - if (fabs(thingpos.X - vp.Pos.X) < 32 && fabs(thingpos.Y - vp.Pos.Y) < 32) return; + DVector3 viewpos = viewmaster->InterpolatedPosition(vp.TicFrac); + if (thruportal == 1) viewpos += di->Level->Displacements.getOffset(viewmaster->Sector->PortalGroup, sector->PortalGroup); + if (fabs(viewpos.X - vp.Pos.X) < 32 && fabs(viewpos.Y - vp.Pos.Y) < 32) return; } // Too close to the camera. This doesn't look good if it is a sprite. @@ -790,9 +828,9 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t bottomclip = rendersector->PortalBlocksMovement(sector_t::floor) ? -LARGE_VALUE : rendersector->GetPortalPlaneZ(sector_t::floor); uint32_t spritetype = (thing->renderflags & RF_SPRITETYPEMASK); - x = thingpos.X; - z = thingpos.Z; - y = thingpos.Y; + x = thingpos.X + thing->WorldOffset.X; + z = thingpos.Z + thing->WorldOffset.Z; + y = thingpos.Y + thing->WorldOffset.Y; if (spritetype == RF_FACESPRITE) z -= thing->Floorclip; // wall and flat sprites are to be considered di->Level-> geometry so this may not apply. // snap shadow Z to the floor @@ -807,7 +845,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t z += fz; } - modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); + 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) @@ -836,16 +874,16 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t if (sprframe->Texture[0] == sprframe->Texture[1]) { if (thing->flags7 & MF7_SPRITEANGLE) - rot = (thing->SpriteAngle + 45.0 / 2 * 9).BAMs() >> 28; + rot = (thing->SpriteAngle + DAngle::fromDeg(45.0 / 2 * 9)).BAMs() >> 28; else - rot = (sprang - (thing->Angles.Yaw + thing->SpriteRotation) + 45.0 / 2 * 9).BAMs() >> 28; + rot = (sprang - (thing->Angles.Yaw + thing->SpriteRotation) + DAngle::fromDeg(45.0 / 2 * 9)).BAMs() >> 28; } else { if (thing->flags7 & MF7_SPRITEANGLE) - rot = (thing->SpriteAngle + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (thing->SpriteAngle + DAngle::fromDeg(45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; else - rot = (sprang - (thing->Angles.Yaw + thing->SpriteRotation) + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (sprang - (thing->Angles.Yaw + thing->SpriteRotation) + DAngle::fromDeg(45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; } auto picnum = sprframe->Texture[rot]; if (sprframe->Flip & (1 << rot)) @@ -868,7 +906,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t else { // Flat sprites cannot rotate in a predictable manner. - sprangle = 0.; + sprangle = nullAngle; rot = 0; } patch = sprites[spritenum].GetSpriteFrame(thing->frame, rot, sprangle, &mirror, !!(thing->renderflags & RF_SPRITEFLIP)); @@ -910,7 +948,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t thing->renderflags ^= RF_XFLIP; r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y); - + float SpriteOffY = thing->SpriteOffset.Y; float rightfac = -r.left - thing->SpriteOffset.X; float leftfac = rightfac - r.width; @@ -987,10 +1025,10 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t fullbright = (thing->flags5 & MF5_BRIGHT) || ((thing->renderflags & RF_FULLBRIGHT) && (!texture || !texture->isFullbrightDisabled())); - lightlevel = fullbright ? 255 : - hw_ClampLight(rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? - rendersector->GetCeilingLight() : rendersector->GetFloorLight()); - foglevel = (uint8_t)clamp(rendersector->lightlevel, 0, 255); + if (fullbright) lightlevel = 255; + else lightlevel = hw_ClampLight(thing->GetLightLevel(rendersector)); + + foglevel = (uint8_t)clamp(rendersector->lightlevel, 0, 255); // this *must* use the sector's light level or the fog will just look bad. lightlevel = rendersector->CheckSpriteGlow(lightlevel, thingpos); @@ -1203,8 +1241,7 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * { if (particle->alpha==0) return; - lightlevel = hw_ClampLight(sector->GetTexture(sector_t::ceiling) == skyflatnum ? - sector->GetCeilingLight() : sector->GetFloorLight()); + lightlevel = hw_ClampLight(sector->GetSpriteLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); if (di->isFullbrightScene()) @@ -1242,7 +1279,16 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * } trans=particle->alpha; - RenderStyle = STYLE_Translucent; + + if(particle->style != STYLE_None) + { + RenderStyle = particle->style; + } + else + { + RenderStyle = STYLE_Translucent; + } + OverrideShader = 0; ThingColor = particle->color; @@ -1254,17 +1300,21 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * 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 + // [BB] Load the texture for round or smooth particles - if (gl_particles_style) + if (particle_style) { FTextureID lump; - if (gl_particles_style == 1) + if (particle_style == 1) { lump = TexMan.glPart2; } - else if (gl_particles_style == 2) + else if (particle_style == 2) { - lump = TexMan.glPart; + lump = has_texture ? particle -> texture : TexMan.glPart; } else lump.SetNull(); @@ -1277,7 +1327,7 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * ur = 1; vt = 0; vb = 1; - texture = TexMan.GetGameTexture(lump, false); + texture = TexMan.GetGameTexture(lump, true); } } @@ -1292,10 +1342,16 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * x = float(particle->Pos.X) + xvf; y = float(particle->Pos.Y) + yvf; z = float(particle->Pos.Z) + zvf; + + if(particle->flags & PT_DOROLL) + { + float rvf = (particle->RollVel) * timefrac; + Angles.Roll = TAngle::fromDeg(particle->Roll + rvf); + } float factor; - if (gl_particles_style == 1) factor = 1.3f / 7.f; - else if (gl_particles_style == 2) factor = 2.5f / 7.f; + 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; @@ -1316,7 +1372,7 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * fullbright = !!particle->bright; // [BB] Translucent particles have to be rendered without the alpha test. - if (gl_particles_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; + 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) @@ -1363,11 +1419,33 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area) DVector3 newpos = savedpos; sector_t fakesector; - if (!vp.showviewer && th == vp.camera) + if (!vp.showviewer) { - if (fabs(savedpos.X - vp.ActorPos.X) < 2 && fabs(savedpos.Y - vp.ActorPos.Y) < 2) + AActor *viewmaster = th; + if ((th->flags8 & MF8_MASTERNOSEE) && th->master != nullptr) { - continue; + viewmaster = th->master; + } + + if (viewmaster == vp.camera) + { + DVector3 vieworigin = viewmaster->Pos(); + + if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2) + { + // Same as the original position + continue; + } + + P_TranslatePortalXY(line, vieworigin.X, vieworigin.Y); + P_TranslatePortalZ(line, vieworigin.Z); + + if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2) + { + // Same as the translated position + // (This is required for MASTERNOSEE actors with 3D models) + continue; + } } } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index f3ea5a2df..88ed52068 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -208,7 +208,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) } #endif - if (flags & HWWall::HWF_CLAMPY && (type == RENDERWALL_M2S || type == RENDERWALL_M2SNF)) + if (flags & HWWall::HWF_CLAMPY && (type == RENDERWALL_M2S || type == RENDERWALL_M2SNF) && !texture->isWarped()) { state.SetTextureClamp(true); } @@ -420,7 +420,7 @@ void HWWall::SetupLights(HWDrawInfo *di, FDynLightData &lightdata) // Iterate through all dynamic lights which touch this wall and render them while (node) { - if (node->lightsource->IsActive()) + if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) { iter_dlight++; @@ -705,7 +705,7 @@ bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool trans if ((maplightbottomleftztop[1]) || (maplightbottomleft>ztop[0] && maplightbottomright(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); + float clen = max(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); float dch = ztop[1] - ztop[0]; float dfh = maplightbottomright - maplightbottomleft; @@ -734,6 +734,10 @@ bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool trans 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, frontsector, translucent); copyWall2.SplitWall(di, frontsector, translucent); @@ -745,7 +749,7 @@ bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool trans if ((maplightbottomleftzbottom[1]) || (maplightbottomleft>zbottom[0] && maplightbottomright(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); + float clen = max(fabsf(glseg.x2 - glseg.x1), fabsf(glseg.y2 - glseg.y1)); float dch = zbottom[1] - zbottom[0]; float dfh = maplightbottomright - maplightbottomleft; @@ -775,6 +779,10 @@ bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool trans 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, frontsector, translucent); copyWall2.SplitWall(di, frontsector, translucent); @@ -870,6 +878,10 @@ void HWWall::SplitWall(HWDrawInfo *di, sector_t * frontsector, bool translucent) (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, &lightlist[i], translucent); } if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1]) @@ -967,6 +979,8 @@ bool HWWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, return true; } +static float ZeroLightmapUVs[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + //========================================================================== // // @@ -997,6 +1011,17 @@ 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; + } // // @@ -1014,6 +1039,9 @@ 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 { @@ -1034,6 +1062,9 @@ 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); } // @@ -1052,6 +1083,9 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop); } + + lightuv[UPRGT].v = srclightuv[UPRGT].v; + lightuv[LORGT].v = srclightuv[LORGT].v; } else { @@ -1071,11 +1105,19 @@ bool HWWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto { tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); } + + 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; @@ -1216,6 +1258,15 @@ void HWWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg, type = _type; + if (seg->sidedef->lightmap && type >= RENDERWALL_TOP && type <= RENDERWALL_BOTTOM) + { + lightmap = &seg->sidedef->lightmap[type - RENDERWALL_TOP]; + } + else + { + lightmap = nullptr; + } + float floatceilingref = ceilingrefheight + tci.RowOffset(seg->sidedef->GetTextureYOffset(texpos)); if (peg) floatceilingref += tci.mRenderHeight - flh - v_offset; @@ -1283,12 +1334,12 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, rowoffset = tci.RowOffset(seg->sidedef->GetTextureYOffset(side_t::mid)); if ((seg->linedef->flags & ML_DONTPEGBOTTOM) >0) { - texturebottom = MAX(realfront->GetPlaneTexZ(sector_t::floor), realback->GetPlaneTexZ(sector_t::floor) + zalign) + rowoffset; + texturebottom = max(realfront->GetPlaneTexZ(sector_t::floor), realback->GetPlaneTexZ(sector_t::floor) + zalign) + rowoffset; texturetop = texturebottom + tci.mRenderHeight; } else { - texturetop = MIN(realfront->GetPlaneTexZ(sector_t::ceiling), realback->GetPlaneTexZ(sector_t::ceiling) + zalign) + rowoffset; + texturetop = min(realfront->GetPlaneTexZ(sector_t::ceiling), realback->GetPlaneTexZ(sector_t::ceiling) + zalign) + rowoffset; texturebottom = texturetop - tci.mRenderHeight; } } @@ -1319,8 +1370,8 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, else { // texture is missing - use the higher plane - topleft = MAX(bch1,fch1); - topright = MAX(bch2,fch2); + topleft = max(bch1,fch1); + topright = max(bch2,fch2); } } else if ((bch1>fch1 || bch2>fch2) && @@ -1334,8 +1385,8 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, else { // But not if there can be visual artifacts. - topleft = MIN(bch1,fch1); - topright = MIN(bch2,fch2); + topleft = min(bch1,fch1); + topright = min(bch2,fch2); } // @@ -1347,8 +1398,8 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, if (!tex || !tex->isValid()) { // texture is missing - use the lower plane - bottomleft = MIN(bfh1,ffh1); - bottomright = MIN(bfh2,ffh2); + bottomleft = min(bfh1,ffh1); + bottomright = min(bfh2,ffh2); } else if (bfh1=ffh1 && bfh2>=ffh2))) { @@ -1360,8 +1411,8 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, else { // normal case - use the higher plane - bottomleft = MAX(bfh1,ffh1); - bottomright = MAX(bfh2,ffh2); + bottomleft = max(bfh1,ffh1); + bottomright = max(bfh2,ffh2); } // @@ -1514,8 +1565,8 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary, int i,t=0; float v_factor=(zbottom[0]-ztop[0])/(tcs[LOLFT].v-tcs[UPLFT].v); // only split the vertical area of the polygon that does not contain slopes. - float splittopv = MAX(tcs[UPLFT].v, tcs[UPRGT].v); - float splitbotv = MIN(tcs[LOLFT].v, tcs[LORGT].v); + float splittopv = max(tcs[UPLFT].v, tcs[UPRGT].v); + float splitbotv = min(tcs[LOLFT].v, tcs[LORGT].v); // this is split vertically into sections. for(i=0;isidedef == seg->linedef->sidedef[0]) + lightmap = seg->linedef->sidedef[1]->lightmap; + else + lightmap = seg->linedef->sidedef[0]->lightmap; + + if (lightmap) + lightmap += 4 + roverIndex; + if (rover->flags&FF_FOG) { if (!di->isFullbrightScene()) @@ -1655,6 +1715,28 @@ void HWWall::BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, 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; @@ -1744,7 +1826,7 @@ void HWWall::InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, } if (ff_topleft < ff_bottomleft || ff_topright < ff_bottomright) continue; - BuildFFBlock(di, seg, rover, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); + BuildFFBlock(di, seg, rover, i, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); topleft = ff_bottomleft; topright = ff_bottomright; @@ -1757,7 +1839,7 @@ void HWWall::InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, // // //========================================================================== -void HWWall::ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, sector_t * frontsector, +void HWWall::ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector, float topleft, float topright, float bottomleft, float bottomright) { @@ -1808,7 +1890,7 @@ void HWWall::ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, sector_ } else if (ff_topleft <= topleft && ff_topright <= topright) { - BuildFFBlock(di, seg, ffloor, topleft, topright, ff_topleft, ff_topright); + BuildFFBlock(di, seg, ffloor, ffloorIndex, topleft, topright, ff_topleft, ff_topright); if (ff_bottomleft <= bottomleft && ff_bottomright <= bottomright) return; topleft = ff_bottomleft; topright = ff_bottomright; @@ -1823,7 +1905,7 @@ void HWWall::ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, sector_ done: // if the program reaches here there is one block left to draw - BuildFFBlock(di, seg, ffloor, topleft, topright, bottomleft, bottomright); + BuildFFBlock(di, seg, ffloor, ffloorIndex, topleft, topright, bottomleft, bottomright); } //========================================================================== @@ -1897,9 +1979,9 @@ void HWWall::DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, // if translucent or liquid clip away adjoining parts of the same type of FFloors on the other side if (rover->flags&(FF_SWIMMABLE | FF_TRANSLUCENT)) - ClipFFloors(di, seg, rover, frontsector, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); + ClipFFloors(di, seg, rover, i, frontsector, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); else - BuildFFBlock(di, seg, rover, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); + BuildFFBlock(di, seg, rover, i, ff_topleft, ff_topright, ff_bottomleft, ff_bottomright); topleft = ff_bottomleft; topright = ff_bottomright; @@ -1914,7 +1996,23 @@ void HWWall::DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, InverseFloors(di, seg, frontsector, topleft, topright, bottomleft, bottomright); } } - + +inline int CalcRelLight(int lightlevel, int orglightlevel, int rel) +{ + if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this. + { + return 0; + } + else if (lightlevel - rel > 256) // the brighter part of fake contrast will be clamped so also clamp the darker part by the same amount for better looks + { + return 256 - lightlevel + rel; + } + else + { + return rel; + } +} + //========================================================================== // // @@ -1940,6 +2038,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ } #endif + lightmap = nullptr; + // note: we always have a valid sidedef and linedef reference when getting here. this->seg = seg; @@ -2019,19 +2119,6 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ int rel = 0; int orglightlevel = hw_ClampLight(frontsector->lightlevel); bool foggy = (!Colormap.FadeColor.isBlack() || di->Level->flags&LEVEL_HASFADETABLE); // fog disables fake contrast - lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel)); - if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this. - { - rellight = 0; - } - else if (lightlevel - rel > 256) // the brighter part of fake contrast will be clamped so also clamp the darker part by the same amount for better looks - { - rellight = 256 - lightlevel + rel; - } - else - { - rellight = rel; - } alpha = 1.0f; RenderStyle = STYLE_Normal; @@ -2077,6 +2164,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ else { // normal texture + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel)); + rellight = CalcRelLight(lightlevel, orglightlevel, rel); texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true); if (texture && texture->isValid()) { @@ -2145,6 +2234,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ if (bch1a < fch1 || bch2a < fch2) { + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::top, false, &rel)); + rellight = CalcRelLight(lightlevel, orglightlevel, rel); texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::top), true); if (texture && texture->isValid()) { @@ -2195,6 +2286,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ texture = tex; } else texture = nullptr; + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel)); + rellight = CalcRelLight(lightlevel, orglightlevel, rel); if (isportal) { @@ -2213,6 +2306,7 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ } else { + if (texture || drawfogboundary) { DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback, @@ -2221,6 +2315,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size()) { + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::top, false, &rel)); + rellight = CalcRelLight(lightlevel, orglightlevel, rel); DoFFloorBlocks(di, seg, frontsector, backsector, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2); } } @@ -2235,6 +2331,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ if (bfh1 > ffh1 || bfh2 > ffh2) { + lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::bottom, false, &rel)); + rellight = CalcRelLight(lightlevel, orglightlevel, rel); texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::bottom), true); if (texture && texture->isValid()) { diff --git a/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp b/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp index 751dbde64..e6cd1896f 100644 --- a/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls_vertex.cpp @@ -43,6 +43,8 @@ void HWWall::SplitUpperEdge(FFlatVertex *&ptr) float fact = (ztop[1] - ztop[0]) / polyw; float facc = (zceil[1] - zceil[0]) / polyw; float facf = (zfloor[1] - zfloor[0]) / polyw; + float faclu = (lightuv[UPRGT].u - lightuv[UPLFT].u) / polyw; + float faclv = (lightuv[UPRGT].v - lightuv[UPLFT].v) / polyw; for (int i = 0; i < sidedef->numsegs - 1; i++) { @@ -58,6 +60,9 @@ void HWWall::SplitUpperEdge(FFlatVertex *&ptr) ptr->z = ztop[0] + fact * fracfac; ptr->u = tcs[UPLFT].u + facu * fracfac; ptr->v = tcs[UPLFT].v + facv * fracfac; + ptr->lu = lightuv[UPLFT].u + faclu * fracfac; + ptr->lv = lightuv[UPLFT].v + faclv * fracfac; + ptr->lindex = lindex; ptr++; } } @@ -77,6 +82,8 @@ void HWWall::SplitLowerEdge(FFlatVertex *&ptr) float facb = (zbottom[1] - zbottom[0]) / polyw; float facc = (zceil[1] - zceil[0]) / polyw; float facf = (zfloor[1] - zfloor[0]) / polyw; + float faclu = (lightuv[LORGT].u - lightuv[LOLFT].u) / polyw; + float faclv = (lightuv[LORGT].v - lightuv[LOLFT].v) / polyw; for (int i = sidedef->numsegs - 2; i >= 0; i--) { @@ -92,6 +99,9 @@ void HWWall::SplitLowerEdge(FFlatVertex *&ptr) ptr->z = zbottom[0] + facb * fracfac; ptr->u = tcs[LOLFT].u + facu * fracfac; ptr->v = tcs[LOLFT].v + facv * fracfac; + ptr->lu = lightuv[LOLFT].u + faclu * fracfac; + ptr->lv = lightuv[LOLFT].v + faclv * fracfac; + ptr->lindex = lindex; ptr++; } } @@ -115,6 +125,8 @@ void HWWall::SplitLeftEdge(FFlatVertex *&ptr) float polyh1 = ztop[0] - zbottom[0]; float factv1 = polyh1 ? (tcs[UPLFT].v - tcs[LOLFT].v) / polyh1 : 0; float factu1 = polyh1 ? (tcs[UPLFT].u - tcs[LOLFT].u) / polyh1 : 0; + float factlv1 = polyh1 ? (lightuv[UPLFT].v - lightuv[LOLFT].v) / polyh1 : 0; + float factlu1 = polyh1 ? (lightuv[UPLFT].u - lightuv[LOLFT].u) / polyh1 : 0; while (inumheights && vi->heightlist[i] <= zbottom[0]) i++; while (inumheights && vi->heightlist[i] < ztop[0]) @@ -124,6 +136,9 @@ void HWWall::SplitLeftEdge(FFlatVertex *&ptr) ptr->z = vi->heightlist[i]; ptr->u = factu1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].u; ptr->v = factv1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].v; + ptr->lu = factlu1 * (vi->heightlist[i] - ztop[0]) + lightuv[UPLFT].u; + ptr->lv = factlv1 * (vi->heightlist[i] - ztop[0]) + lightuv[UPLFT].v; + ptr->lindex = lindex; ptr++; i++; } @@ -149,6 +164,8 @@ void HWWall::SplitRightEdge(FFlatVertex *&ptr) float polyh2 = ztop[1] - zbottom[1]; float factv2 = polyh2 ? (tcs[UPRGT].v - tcs[LORGT].v) / polyh2 : 0; float factu2 = polyh2 ? (tcs[UPRGT].u - tcs[LORGT].u) / polyh2 : 0; + float factlv2 = polyh2 ? (lightuv[UPRGT].v - lightuv[LORGT].v) / polyh2 : 0; + float factlu2 = polyh2 ? (lightuv[UPRGT].u - lightuv[LORGT].u) / polyh2 : 0; while (i>0 && vi->heightlist[i] >= ztop[1]) i--; while (i>0 && vi->heightlist[i] > zbottom[1]) @@ -158,6 +175,9 @@ void HWWall::SplitRightEdge(FFlatVertex *&ptr) ptr->z = vi->heightlist[i]; ptr->u = factu2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].u; ptr->v = factv2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].v; + ptr->lu = factlu2 * (vi->heightlist[i] - ztop[1]) + lightuv[UPRGT].u; + ptr->lv = factlv2 * (vi->heightlist[i] - ztop[1]) + lightuv[UPRGT].v; + ptr->lindex = lindex; ptr++; i--; } @@ -173,16 +193,16 @@ void HWWall::SplitRightEdge(FFlatVertex *&ptr) int HWWall::CreateVertices(FFlatVertex *&ptr, bool split) { auto oo = ptr; - ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); + ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v, lightuv[LOLFT].u, lightuv[LOLFT].v, lindex); ptr++; if (split && glseg.fracleft == 0) SplitLeftEdge(ptr); - ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v); + ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v, lightuv[UPLFT].u, lightuv[UPLFT].v, lindex); ptr++; if (split && !(flags & HWF_NOSPLITUPPER && seg->sidedef->numsegs > 1)) SplitUpperEdge(ptr); - ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v); + ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v, lightuv[UPRGT].u, lightuv[UPRGT].v, lindex); ptr++; if (split && glseg.fracright == 1) SplitRightEdge(ptr); - ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); + ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v, lightuv[LORGT].u, lightuv[LORGT].v, lindex); ptr++; if (split && !(flags & HWF_NOSPLITLOWER) && seg->sidedef->numsegs > 1) SplitLowerEdge(ptr); return int(ptr - oo); diff --git a/src/rendering/hwrenderer/scene/hw_weapon.cpp b/src/rendering/hwrenderer/scene/hw_weapon.cpp index f90ff4fd9..5d9f44d7c 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.cpp +++ b/src/rendering/hwrenderer/scene/hw_weapon.cpp @@ -89,7 +89,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) state.AlphaFunc(Alpha_GEqual, 0); FHWModelRenderer renderer(this, state, huds->lightindex); - RenderHUDModel(&renderer, huds->weapon, huds->mx, huds->my); + RenderHUDModel(&renderer, huds->weapon, huds->translation, huds->rotation + FVector3(huds->mx / 4., (huds->my - WEAPONTOP) / -4., 0), huds->pivot, huds->mframe); state.SetVertexBuffer(screen->mVertexData); } else @@ -140,7 +140,7 @@ static bool isBright(DPSprite *psp) if (psp != nullptr && psp->GetState() != nullptr) { bool disablefullbright = false; - FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, 0., nullptr); + FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, nullAngle, nullptr); if (lump.isValid()) { auto tex = TexMan.GetGameTexture(lump, true); @@ -157,9 +157,9 @@ static bool isBright(DPSprite *psp) // //========================================================================== -static WeaponPosition GetWeaponPosition(player_t *player, double ticFrac) +static WeaponPosition2D GetWeaponPosition2D(player_t *player, double ticFrac) { - WeaponPosition w; + WeaponPosition2D w; P_BobWeapon(player, &w.bobx, &w.boby, ticFrac); // Interpolate the main weapon layer once so as to be able to add it to other layers. @@ -184,13 +184,55 @@ static WeaponPosition GetWeaponPosition(player_t *player, double ticFrac) return w; } +static WeaponPosition3D GetWeaponPosition3D(player_t *player, double ticFrac) +{ + WeaponPosition3D w; + P_BobWeapon3D(player, &w.translation, &w.rotation, ticFrac); + + // Interpolate the main weapon layer once so as to be able to add it to other layers. + if ((w.weapon = player->FindPSprite(PSP_WEAPON)) != nullptr) + { + if (w.weapon->firstTic) + { + w.wx = (float)w.weapon->x; + w.wy = (float)w.weapon->y; + } + else + { + w.wx = (float)(w.weapon->oldx + (w.weapon->x - w.weapon->oldx) * ticFrac); + w.wy = (float)(w.weapon->oldy + (w.weapon->y - w.weapon->oldy) * ticFrac); + } + + auto weaponActor = w.weapon->GetCaller(); + + if (weaponActor && weaponActor->IsKindOf(NAME_Weapon)) + { + DVector3 *dPivot = (DVector3*) weaponActor->ScriptVar(NAME_BobPivot3D, nullptr); + w.pivot.X = (float) dPivot->X; + w.pivot.Y = (float) dPivot->Y; + w.pivot.Z = (float) dPivot->Z; + } + else + { + w.pivot = FVector3(0,0,0); + } + } + else + { + w.wx = 0; + w.wy = 0; + w.pivot = FVector3(0,0,0); + } + return w; +} + //========================================================================== // // Bobbing // //========================================================================== -static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp, double ticFrac) +static FVector2 BobWeapon2D(WeaponPosition2D &weap, DPSprite *psp, double ticFrac) { if (psp->firstTic) { // Can't interpolate the first tic. @@ -215,6 +257,46 @@ static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp, double ticFrac) return { sx, sy }; } +static FVector2 BobWeapon3D(WeaponPosition3D &weap, DPSprite *psp, FVector3 &translation, FVector3 &rotation, FVector3 &pivot, double ticFrac) +{ + if (psp->firstTic) + { // Can't interpolate the first tic. + psp->firstTic = false; + psp->ResetInterpolation(); + } + + float sx = float(psp->oldx + (psp->x - psp->oldx) * ticFrac); + float sy = float(psp->oldy + (psp->y - psp->oldy) * ticFrac); + float sz = 0; + + if (psp->Flags & PSPF_ADDBOB) + { + if (psp->Flags & PSPF_MIRROR) + { + translation = FVector3(-weap.translation.X, weap.translation.Y, weap.translation.Z); + rotation = FVector3(-weap.rotation.X, weap.rotation.Y, weap.rotation.Z); + pivot = FVector3(-weap.pivot.X, weap.pivot.Y, weap.pivot.Z); + } + else + { + translation = weap.translation ; + rotation = weap.rotation ; + pivot = weap.pivot ; + } + } + else + { + translation = rotation = pivot = FVector3(0,0,0); + } + + if (psp->Flags & PSPF_ADDWEAPON && psp->GetID() != PSP_WEAPON) + { + sx += weap.wx; + sy += weap.wy; + } + return { sx, sy }; +} + //========================================================================== // // Lighting @@ -411,11 +493,12 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, float tx; float scale; float scalex; + float ftextureadj; float ftexturemid; // decide which patch to use bool mirror; - FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, 0., &mirror); + FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, nullAngle, &mirror); if (!lump.isValid()) return false; auto tex = TexMan.GetGameTexture(lump, false); @@ -428,7 +511,7 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, FloatRect r = spi.GetSpriteRect(); // calculate edges of the shape - scalex = (320.0f / (240.0f * r_viewwindow.WidescreenRatio)) * vw / 320; + scalex = psp->baseScale.X * (320.0f / (240.0f * r_viewwindow.WidescreenRatio)) * (vw / 320); float x1, y1, x2, y2, u1, v1, u2, v2; @@ -445,9 +528,13 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, x2 += viewwindowx; // killough 12/98: fix psprite positioning problem - ftexturemid = 100.f - sy - r.top - psp->GetYAdjust(screenblocks >= 11); + ftextureadj = (120.0f / psp->baseScale.Y) - 100.0f; // [XA] scale relative to weapon baseline + ftexturemid = 100.f - sy - r.top - psp->GetYAdjust(screenblocks >= 11) - ftextureadj; - scale = (SCREENHEIGHT*vw) / (SCREENWIDTH * 200.0f); + // [XA] note: Doom's native 1.2x aspect ratio was originally + // handled here by multiplying SCREENWIDTH by 200 instead of + // 240, but now the baseScale var defines this from now on. + scale = psp->baseScale.Y * (SCREENHEIGHT*vw) / (SCREENWIDTH * 240.0f); y1 = viewwindowy + vh / 2 - (ftexturemid * scale); y2 = y1 + (r.height * scale) + 1; @@ -481,7 +568,7 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, const float cx = (flip) ? -psp->Coord[i].X : psp->Coord[i].X; Vert.v[i] += FVector2(cx * scalex, psp->Coord[i].Y * scale); } - if (psp->rotation != 0.0 || !psp->scale.isZero()) + if (psp->rotation != nullAngle || !psp->scale.isZero()) { // [MC] Sets up the alignment for starting the pivot at, in a corner. float anchorx, anchory; @@ -503,7 +590,7 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, // Handle PSPF_FLIP. if (flip) anchorx = 1.0 - anchorx; - FAngle rot = float((flip) ? -psp->rotation.Degrees : psp->rotation.Degrees); + FAngle rot = FAngle::fromDeg(float((flip) ? -psp->rotation.Degrees() : psp->rotation.Degrees())); const float cosang = rot.Cos(); const float sinang = rot.Sin(); @@ -582,11 +669,119 @@ bool HUDSprite::GetWeaponRect(HWDrawInfo *di, DPSprite *psp, float sx, float sy, // R_DrawPlayerSprites // //========================================================================== +void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area) +{ + AActor * playermo = players[consoleplayer].camera; + player_t * player = playermo->player; + + const auto &vp = Viewpoint; + + AActor *camera = vp.camera; + + WeaponPosition2D weap = GetWeaponPosition2D(camera->player, vp.TicFrac); + WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos()); + + // 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(); + + 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; + + // 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; + + HUDSprite hudsprite; + hudsprite.owner = playermo; + hudsprite.mframe = smf; + hudsprite.weapon = psp; + + if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue; + + FVector2 spos = BobWeapon2D(weap, psp, vp.TicFrac); + + hudsprite.dynrgb[0] = hudsprite.dynrgb[1] = hudsprite.dynrgb[2] = 0; + hudsprite.lightindex = -1; + // set the lighting parameters + if (hudsprite.RenderStyle.BlendOp != STYLEOP_Shadow && Level->HasDynamicLights && !isFullbrightScene() && gl_light_sprites) + { + GetDynSpriteLight(playermo, nullptr, hudsprite.dynrgb); + } + + if (!hudsprite.GetWeaponRect(this, psp, spos.X, spos.Y, player, vp.TicFrac)) continue; + hudsprites.Push(hudsprite); + } + lightmode = oldlightmode; +} + +void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area) +{ + AActor * playermo = players[consoleplayer].camera; + player_t * player = playermo->player; + + const auto &vp = Viewpoint; + + AActor *camera = vp.camera; + + WeaponPosition3D weap = GetWeaponPosition3D(camera->player, vp.TicFrac); + WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos()); + + // 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(); + + 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; + + // 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; + + HUDSprite hudsprite; + hudsprite.owner = playermo; + hudsprite.mframe = smf; + hudsprite.weapon = psp; + + if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue; + + //FVector2 spos = BobWeapon3D(weap, psp, hudsprite.translation, hudsprite.rotation, hudsprite.pivot, vp.TicFrac); + + FVector2 spos = BobWeapon3D(weap, psp, hudsprite.translation, hudsprite.rotation, hudsprite.pivot, vp.TicFrac); + + hudsprite.dynrgb[0] = hudsprite.dynrgb[1] = hudsprite.dynrgb[2] = 0; + hudsprite.lightindex = -1; + // set the lighting parameters + if (hudsprite.RenderStyle.BlendOp != STYLEOP_Shadow && Level->HasDynamicLights && !isFullbrightScene() && gl_light_sprites) + { + hw_GetDynModelLight(playermo, lightdata); + hudsprite.lightindex = screen->mLights->UploadLights(lightdata); + LightProbe* probe = FindLightProbe(playermo->Level, playermo->X(), playermo->Y(), playermo->Center()); + if (probe) + { + hudsprite.dynrgb[0] = probe->Red; + hudsprite.dynrgb[1] = probe->Green; + hudsprite.dynrgb[2] = probe->Blue; + } + } + + // [BB] In the HUD model step we just render the model and break out. + hudsprite.mx = spos.X; + hudsprite.my = spos.Y; + + hudsprites.Push(hudsprite); + } + lightmode = oldlightmode; +} void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) { - bool brightflash = false; AActor * playermo = players[consoleplayer].camera; player_t * player = playermo->player; @@ -603,60 +798,16 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) return; const bool hudModelStep = IsHUDModelForPlayerAvailable(camera->player); - WeaponPosition weap = GetWeaponPosition(camera->player, vp.TicFrac); - WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos()); - - // 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(); - - for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) + + if(hudModelStep) { - if (!psp->GetState()) continue; - FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr; - // 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 && !hudModelStep) continue; - if (!smf && hudModelStep) continue; - - HUDSprite hudsprite; - hudsprite.owner = playermo; - hudsprite.mframe = smf; - hudsprite.weapon = psp; - - if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue; - - FVector2 spos = BobWeapon(weap, psp, vp.TicFrac); - - hudsprite.dynrgb[0] = hudsprite.dynrgb[1] = hudsprite.dynrgb[2] = 0; - hudsprite.lightindex = -1; - // set the lighting parameters - if (hudsprite.RenderStyle.BlendOp != STYLEOP_Shadow && Level->HasDynamicLights && !isFullbrightScene() && gl_light_sprites) - { - if (!hudModelStep) - { - GetDynSpriteLight(playermo, nullptr, hudsprite.dynrgb); - } - else - { - hw_GetDynModelLight(playermo, lightdata); - hudsprite.lightindex = screen->mLights->UploadLights(lightdata); - } - } - - // [BB] In the HUD model step we just render the model and break out. - if (hudModelStep) - { - hudsprite.mx = spos.X; - hudsprite.my = spos.Y; - } - else - { - if (!hudsprite.GetWeaponRect(this, psp, spos.X, spos.Y, player, vp.TicFrac)) continue; - } - hudsprites.Push(hudsprite); + PreparePlayerSprites3D(viewsector,in_area); } - lightmode = oldlightmode; + else + { + PreparePlayerSprites2D(viewsector,in_area); + } + PrepareTargeterSprites(vp.TicFrac); } diff --git a/src/rendering/hwrenderer/scene/hw_weapon.h b/src/rendering/hwrenderer/scene/hw_weapon.h index 76df17d6c..97f39ad8e 100644 --- a/src/rendering/hwrenderer/scene/hw_weapon.h +++ b/src/rendering/hwrenderer/scene/hw_weapon.h @@ -11,13 +11,25 @@ struct HWDrawInfo; class FGameTexture; -struct WeaponPosition +struct WeaponPosition2D { float wx, wy; float bobx, boby; DPSprite *weapon; }; +struct WeaponPosition3D +{ + float wx, + wy; + + FVector3 translation, + rotation, + pivot; + + DPSprite *weapon; +}; + struct WeaponLighting { FColormap cm; @@ -43,6 +55,8 @@ struct HUDSprite float mx, my; float dynrgb[3]; + FVector3 rotation, translation, pivot; + int lightindex; void SetBright(bool isbelow); diff --git a/src/rendering/r_sky.h b/src/rendering/r_sky.h index fa36e535b..5d7236dc8 100644 --- a/src/rendering/r_sky.h +++ b/src/rendering/r_sky.h @@ -29,7 +29,8 @@ #define __R_SKY_H__ #include -#include "textures.h" +#include +#include "textureid.h" struct FLevelLocals; @@ -42,7 +43,6 @@ extern int freelookviewheight; void InitSkyMap(FLevelLocals *Level); void R_InitSkyMap(); void R_UpdateSky (uint64_t mstime); -std::pair& R_GetSkyCapColor(FGameTexture* tex); #endif //__R_SKY_H__ diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 908b1646a..1fe4aa1da 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -32,7 +32,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "d_net.h" #include "doomstat.h" @@ -65,6 +65,7 @@ #include "g_game.h" #include "i_system.h" #include "v_draw.h" +#include "i_interface.h" // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -79,6 +80,7 @@ struct InterpolationViewer { DVector3 Pos; DRotator Angles; + DRotator ViewAngles; }; AActor *ViewActor; @@ -130,7 +132,7 @@ FRenderViewpoint::FRenderViewpoint() player = nullptr; Pos = { 0.0, 0.0, 0.0 }; ActorPos = { 0.0, 0.0, 0.0 }; - Angles = { 0.0, 0.0, 0.0 }; + Angles = { nullAngle, nullAngle, nullAngle }; Path[0] = { 0.0, 0.0, 0.0 }; Path[1] = { 0.0, 0.0, 0.0 }; Cos = 0.0; @@ -139,7 +141,7 @@ FRenderViewpoint::FRenderViewpoint() TanSin = 0.0; camera = nullptr; sector = nullptr; - FieldOfView = 90.; // Angles in the SCREENWIDTH wide window + FieldOfView = DAngle::fromDeg(90.); // Angles in the SCREENWIDTH wide window TicFrac = 0.0; FrameTime = 0; extralight = 0; @@ -180,8 +182,8 @@ DEFINE_GLOBAL(LocalViewPitch); void R_SetFOV (FRenderViewpoint &viewpoint, DAngle fov) { - if (fov < 5.) fov = 5.; - else if (fov > 170.) fov = 170.; + if (fov < DAngle::fromDeg(5.)) fov = DAngle::fromDeg(5.); + else if (fov > DAngle::fromDeg(170.)) fov = DAngle::fromDeg(170.); if (fov != viewpoint.FieldOfView) { viewpoint.FieldOfView = fov; @@ -262,8 +264,8 @@ void R_SetWindow (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, int wind // screen that would be visible on a 4:3 display has the requested FOV. if (viewwindow.centerxwide != viewwindow.centerx) { // centerxwide is what centerx would be if the display was not widescreen - fov = DAngle::ToDegrees(2 * atan(viewwindow.centerx * tan(fov.Radians()/2) / double(viewwindow.centerxwide))); - if (fov > 170.) fov = 170.; + fov = DAngle::fromRad(2 * atan(viewwindow.centerx * tan(fov.Radians()/2) / double(viewwindow.centerxwide))); + if (fov > DAngle::fromDeg(170.)) fov = DAngle::fromDeg(170.); } viewwindow.FocalTangent = tan(fov.Radians() / 2); } @@ -393,7 +395,6 @@ FRenderer* SWRenderer; void R_Init () { - StartScreen->Progress(); R_InitTranslationTables (); R_SetViewSize (screenblocks); @@ -419,13 +420,35 @@ void R_Shutdown () //========================================================================== // -// R_InterpolateView +// P_NoInterpolation // //========================================================================== //CVAR (Int, tf, 0, 0) 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; +} + +//========================================================================== +// +// R_InterpolateView +// +//========================================================================== + void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Frac, InterpolationViewer *iview) { if (NoInterpolateView) @@ -449,18 +472,18 @@ void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Fr // 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. - if (!viewpoint.showviewer) + // Needless to say, this doesn't work for chasecam mode or viewpos. + if (!viewpoint.showviewer && !viewpoint.NoPortalPath) { double pathlen = 0; double zdiff = 0; double totalzdiff = 0; - DAngle adiff = 0.; - DAngle totaladiff = 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 }, 0. }; - DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, 0. }; + 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) @@ -513,23 +536,12 @@ void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Fr viewpoint.Pos = iview->New.Pos; viewpoint.Path[0] = viewpoint.Path[1] = iview->New.Pos; } - if (player != NULL && - !(player->cheats & CF_INTERPVIEW) && - player - players == consoleplayer && - viewpoint.camera == player->mo && - !demoplayback && + if (P_NoInterpolation(player, viewpoint.camera) && iview->New.Pos.X == viewpoint.camera->X() && - iview->New.Pos.Y == viewpoint.camera->Y() && - !(player->cheats & (CF_TOTALLYFROZEN|CF_FROZEN)) && - player->playerstate == PST_LIVE && - player->mo->reactiontime == 0 && - !NoInterpolateView && - !paused && - (!netgame || !cl_noprediction) && - !LocalKeyboardTurner) + iview->New.Pos.Y == viewpoint.camera->Y()) { - viewpoint.Angles.Yaw = (nviewangle + AngleToFloat(LocalViewAngle & 0xFFFF0000)).Normalized180(); - DAngle delta = player->centering ? DAngle(0.) : AngleToFloat(int(LocalViewPitch & 0xFFFF0000)); + 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(); } @@ -539,7 +551,13 @@ void R_InterpolateView (FRenderViewpoint &viewpoint, player_t *player, double Fr 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; + } + // Due to interpolation this is not necessarily the same as the sector the camera is in. viewpoint.sector = Level->PointInRenderSubsector(viewpoint.Pos)->sector; bool moved = false; @@ -600,7 +618,7 @@ void FRenderViewpoint::SetViewAngle (const FViewWindow &viewwindow) DVector2 v = Angles.Yaw.ToVector(); ViewVector.X = v.X; ViewVector.Y = v.Y; - HWAngles.Yaw = float(270.0 - Angles.Yaw.Degrees); + HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees()); } @@ -744,6 +762,35 @@ static double QuakePower(double factor, double intensity, double offset) return factor * (offset + randumb); } +//========================================================================== +// +// R_DoActorTickerAngleChanges +// +//========================================================================== + +static void R_DoActorTickerAngleChanges(player_t* const player, AActor* const actor, 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; + } + } +} + //========================================================================== // // R_SetupFrame @@ -781,6 +828,15 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor I_Error ("You lost your body. Bad dehacked work is likely to blame."); } + // [MR] Get the input fraction, even if we don't need it this frame. Must run every frame. + const auto scaleAdjust = I_GetInputFrac(false); + + // [MR] Process player angle changes if permitted to do so. + if (player && (player->cheats & CF_SCALEDNOLERP) && P_NoInterpolation(player, viewpoint.camera)) + { + R_DoActorTickerAngleChanges(player, viewpoint.camera, scaleAdjust); + } + iview = FindPastViewer (viewpoint.camera); int nowtic = I_GetTime (); @@ -789,47 +845,119 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor iview->otic = nowtic; iview->Old = iview->New; } - - if (player != NULL && gamestate != GS_TITLELEVEL && - ((player->cheats & CF_CHASECAM) || (r_deathcamera && viewpoint.camera->health <= 0))) + //============================================================================================== + // Handles offsetting the camera with ChaseCam and/or viewpos. { + 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; - // [RH] Use chasecam view - 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 (gamestate != GS_TITLELEVEL && + ((player && (player->cheats & CF_CHASECAM)) || (r_deathcamera && viewpoint.camera->health <= 0))) { - iview->otic = nowtic; - iview->Old = iview->New; - r_NoInterpolate = true; + // [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)) + { + iview->otic = nowtic; + iview->Old = iview->New; + r_NoInterpolate = true; + } + viewpoint.ActorPos = campos; + } + else if (VP) // No chase/death cam and player is alive, wants viewpos. + { + viewpoint.sector = viewpoint.ViewLevel->PointInRenderSubsector(iview->New.Pos.XY())->sector; + viewpoint.showviewer = false; + + // [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) + { + iview->New.Pos = VP->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; + } + } + } + + if (DefaultDraw) + { + iview->New.Pos = orig; + viewpoint.sector = viewpoint.camera->Sector; + viewpoint.showviewer = viewpoint.NoPortalPath = false; } - viewpoint.ActorPos = campos; - } - else - { - viewpoint.ActorPos = iview->New.Pos = { viewpoint.camera->Pos().XY(), viewpoint.camera->player ? viewpoint.camera->player->viewz : viewpoint.camera->Z() + viewpoint.camera->GetCameraHeight() }; - viewpoint.sector = viewpoint.camera->Sector; - viewpoint.showviewer = false; } - // [MC] Apply the view angles first, which is the offsets. If the absolute isn't desired, - // add the standard angles on top of it. - viewpoint.Angles = viewpoint.camera->ViewAngles; + // [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 (!(viewpoint.camera->flags8 & MF8_ABSVIEWANGLES)) - { - viewpoint.Angles += viewpoint.camera->Angles; - } - - iview->New.Angles = viewpoint.Angles; if (viewpoint.camera->player != 0) { player = viewpoint.camera->player; @@ -881,7 +1009,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor DVector3 pos; pos.Zero(); if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0) { - viewpoint.Angles.Roll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave); + viewpoint.Angles.Roll += DAngle::fromDeg(QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave)); } if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0) { @@ -980,18 +1108,6 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor if (R_OldBlend != newblend) { R_OldBlend = newblend; - if (APART(newblend)) - { - BaseBlendR = RPART(newblend); - BaseBlendG = GPART(newblend); - BaseBlendB = BPART(newblend); - BaseBlendA = APART(newblend) / 255.f; - } - else - { - BaseBlendR = BaseBlendG = BaseBlendB = 0; - BaseBlendA = 0.f; - } } validcount++; @@ -1038,9 +1154,9 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor double angx = cos(radPitch); double angy = sin(radPitch) * actor->Level->info->pixelstretch; double alen = sqrt(angx*angx + angy*angy); - viewpoint.HWAngles.Pitch = RAD2DEG((float)asin(angy / alen)); + viewpoint.HWAngles.Pitch = FAngle::fromRad((float)asin(angy / alen)); - viewpoint.HWAngles.Roll.Degrees = (float)viewpoint.Angles.Roll.Degrees; // copied for convenience. + 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 && diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index b4ac93c9b..77254ebec 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -43,7 +43,7 @@ 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); diff --git a/src/rendering/swrenderer/drawers/r_draw.cpp b/src/rendering/swrenderer/drawers/r_draw.cpp index 797f65626..4e8a66732 100644 --- a/src/rendering/swrenderer/drawers/r_draw.cpp +++ b/src/rendering/swrenderer/drawers/r_draw.cpp @@ -35,7 +35,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "filesystem.h" @@ -53,10 +53,9 @@ #include "r_thread.h" #include "swrenderer/scene/r_light.h" #include "playsim/a_dynlight.h" -#include "polyrenderer/drawers/poly_thread.h" -CVAR(Bool, r_dynlights, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -CVAR(Bool, r_fuzzscale, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, r_dynlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, r_fuzzscale, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); namespace swrenderer { @@ -109,7 +108,7 @@ namespace swrenderer for (int k = 0; k < 256; ++k) { uint8_t v = (((k + 2) * a) + 256) >> 14; - table[k] = MIN(v, 64); + table[k] = min(v, 64); } table += 256; } @@ -212,8 +211,8 @@ namespace swrenderer { if (!r_fuzzscale) { - int yl = MAX(args.FuzzY1(), 1); - int yh = MIN(args.FuzzY2(), fuzzviewheight); + int yl = max(args.FuzzY1(), 1); + int yh = min(args.FuzzY2(), fuzzviewheight); if (yl <= yh) fuzzpos = (fuzzpos + yh - yl + 1) % FUZZTABLE; } @@ -221,44 +220,6 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////// - void SWPixelFormatDrawers::DrawDepthColumn(const WallColumnDrawerArgs& args, float idepth) - { - int x, y, count; - - auto rendertarget = args.Viewport()->RenderTarget; - if (rendertarget->IsBgra()) - { - uint32_t* destorg = (uint32_t*)rendertarget->GetPixels(); - destorg += viewwindowx + viewwindowy * rendertarget->GetPitch(); - uint32_t* dest = (uint32_t*)args.Dest(); - int offset = (int)(ptrdiff_t)(dest - destorg); - x = offset % rendertarget->GetPitch(); - y = offset / rendertarget->GetPitch(); - } - else - { - uint8_t* destorg = rendertarget->GetPixels(); - destorg += viewwindowx + viewwindowy * rendertarget->GetPitch(); - uint8_t* dest = (uint8_t*)args.Dest(); - int offset = (int)(ptrdiff_t)(dest - destorg); - x = offset % rendertarget->GetPitch(); - y = offset / rendertarget->GetPitch(); - } - count = args.Count(); - - auto zbuffer = thread->Poly->depthstencil; - int pitch = zbuffer->Width(); - float* values = zbuffer->DepthValues() + y * pitch + x; - int cnt = count; - - float depth = idepth; - for (int i = 0; i < cnt; i++) - { - *values = depth; - values += pitch; - } - } - void SWPixelFormatDrawers::SetLights(WallColumnDrawerArgs& drawerargs, int x, int y1, const WallDrawerArgs& wallargs) { bool mirror = !!(wallargs.PortalMirrorFlags & RF_XFLIP); @@ -323,76 +284,4 @@ namespace swrenderer } } - ///////////////////////////////////////////////////////////////////////// - - void SWPixelFormatDrawers::DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth) - { - int x, y, count; - auto rendertarget = args.Viewport()->RenderTarget; - if (rendertarget->IsBgra()) - { - uint32_t* destorg = (uint32_t*)rendertarget->GetPixels(); - destorg += viewwindowx + viewwindowy * rendertarget->GetPitch(); - uint32_t* dest = (uint32_t*)args.Dest(); - int offset = (int)(ptrdiff_t)(dest - destorg); - x = offset % rendertarget->GetPitch(); - y = offset / rendertarget->GetPitch(); - } - else - { - uint8_t* destorg = rendertarget->GetPixels(); - destorg += viewwindowx + viewwindowy * rendertarget->GetPitch(); - uint8_t* dest = (uint8_t*)args.Dest(); - int offset = (int)(ptrdiff_t)(dest - destorg); - x = offset % rendertarget->GetPitch(); - y = offset / rendertarget->GetPitch(); - } - count = args.Count(); - - auto zbuffer = thread->Poly->depthstencil; - int pitch = zbuffer->Width(); - float* values = zbuffer->DepthValues() + y * pitch + x; - int cnt = count; - - float depth = idepth; - for (int i = 0; i < cnt; i++) - { - *values = depth; - values += pitch; - } - } - - void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2) - { - int y = args.DestY(); - int x1 = args.DestX1(); - int x2 = args.DestX2(); - - auto zbuffer = thread->Poly->depthstencil; - int pitch = zbuffer->Width(); - float *values = zbuffer->DepthValues() + x1 + y * pitch; - - int count = x2 - x1 + 1; - - if (idepth1 == idepth2) - { - float depth = idepth1; - for (int i = 0; i < count; i++) - { - *values = depth; - values++; - } - } - else - { - float depth = idepth1; - float step = (idepth2 - idepth1) / (x2 - x1 + 1); - for (int i = 0; i < count; i++) - { - *values = depth; - values++; - depth += step; - } - } - } } diff --git a/src/rendering/swrenderer/drawers/r_draw.h b/src/rendering/swrenderer/drawers/r_draw.h index be2619595..133c2b182 100644 --- a/src/rendering/swrenderer/drawers/r_draw.h +++ b/src/rendering/swrenderer/drawers/r_draw.h @@ -94,10 +94,6 @@ namespace swrenderer virtual void DrawFogBoundaryLine(const SpanDrawerArgs &args) = 0; virtual void DrawParticleColumn(int x, int yl, int ycount, uint32_t fg, uint32_t alpha, uint32_t fracposx) = 0; - void DrawDepthColumn(const WallColumnDrawerArgs& args, float idepth); - void DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth); - void DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2); - void SetLights(WallColumnDrawerArgs& drawerargs, int x, int y1, const WallDrawerArgs& wallargs); RenderThread* thread = nullptr; diff --git a/src/rendering/swrenderer/drawers/r_draw_pal.cpp b/src/rendering/swrenderer/drawers/r_draw_pal.cpp index 8cc7a0fc8..22d89cb93 100644 --- a/src/rendering/swrenderer/drawers/r_draw_pal.cpp +++ b/src/rendering/swrenderer/drawers/r_draw_pal.cpp @@ -36,7 +36,7 @@ #ifndef NO_SSE #include #endif -#include "templates.h" + #include "doomtype.h" #include "doomdef.h" #include "r_defs.h" @@ -107,7 +107,7 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + // distance_attenuation = 1 - min(dist * (1/radius), 1) float Lxy2 = lights[i].x; // L.x*L.x + L.y*L.y float Lz = lights[i].z - viewpos_z; float dist2 = Lxy2 + Lz * Lz; @@ -117,7 +117,7 @@ namespace swrenderer float rcp_dist = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(dist2))); #endif float dist = dist2 * rcp_dist; - float distance_attenuation = (256.0f - MIN(dist * lights[i].radius, 256.0f)); + float distance_attenuation = (256.0f - min(dist * lights[i].radius, 256.0f)); // The simple light type float simple_attenuation = distance_attenuation; @@ -139,9 +139,9 @@ namespace swrenderer uint32_t material_g = GPalette.BaseColors[material].g; uint32_t material_b = GPalette.BaseColors[material].b; - lit_r = MIN(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); - lit_g = MIN(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); - lit_b = MIN(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); + lit_r = min(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); + lit_g = min(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); + lit_b = min(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); return RGB256k.All[((lit_r >> 2) << 12) | ((lit_g >> 2) << 6) | (lit_b >> 2)]; } @@ -286,9 +286,9 @@ namespace swrenderer { uint8_t lit = colormap[pix]; - uint32_t r = MIN(GPalette.BaseColors[lit].r + GPalette.BaseColors[*dest].r, 255); - uint32_t g = MIN(GPalette.BaseColors[lit].g + GPalette.BaseColors[*dest].g, 255); - uint32_t b = MIN(GPalette.BaseColors[lit].b + GPalette.BaseColors[*dest].b, 255); + uint32_t r = min(GPalette.BaseColors[lit].r + GPalette.BaseColors[*dest].r, 255); + uint32_t g = min(GPalette.BaseColors[lit].g + GPalette.BaseColors[*dest].g, 255); + uint32_t b = min(GPalette.BaseColors[lit].b + GPalette.BaseColors[*dest].b, 255); *dest = RGB256k.RGB[r>>2][g>>2][b>>2]; } frac += fracstep; @@ -352,9 +352,9 @@ namespace swrenderer { uint8_t lit = num_dynlights != 0 ? AddLightsColumn(dynlights, num_dynlights, viewpos_z, colormap[pix], pix) : colormap[pix]; - uint32_t r = MIN(GPalette.BaseColors[lit].r + GPalette.BaseColors[*dest].r, 255); - uint32_t g = MIN(GPalette.BaseColors[lit].g + GPalette.BaseColors[*dest].g, 255); - uint32_t b = MIN(GPalette.BaseColors[lit].b + GPalette.BaseColors[*dest].b, 255); + uint32_t r = min(GPalette.BaseColors[lit].r + GPalette.BaseColors[*dest].r, 255); + uint32_t g = min(GPalette.BaseColors[lit].g + GPalette.BaseColors[*dest].g, 255); + uint32_t b = min(GPalette.BaseColors[lit].b + GPalette.BaseColors[*dest].b, 255); *dest = RGB256k.RGB[r>>2][g>>2][b>>2]; } viewpos_z += step_viewpos_z; @@ -567,7 +567,7 @@ namespace swrenderer uint8_t fg = source0[sample_index]; uint32_t c = palette[fg]; - int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_top = max(min(frac >> (16 - start_fade), 256), 0); int inv_alpha_top = 256 - alpha_top; int c_red = RPART(c); int c_green = GPART(c); @@ -600,7 +600,7 @@ namespace swrenderer uint8_t fg = source0[sample_index]; uint32_t c = palette[fg]; - int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + int alpha_bottom = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0); int inv_alpha_bottom = 256 - alpha_bottom; int c_red = RPART(c); int c_green = GPART(c); @@ -645,7 +645,7 @@ namespace swrenderer uint8_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } @@ -701,12 +701,12 @@ namespace swrenderer uint8_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } uint32_t c = palette[fg]; - int alpha_top = MAX(MIN(frac >> (16 - start_fade), 256), 0); + int alpha_top = max(min(frac >> (16 - start_fade), 256), 0); int inv_alpha_top = 256 - alpha_top; int c_red = RPART(c); int c_green = GPART(c); @@ -728,7 +728,7 @@ namespace swrenderer uint8_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } *dest = fg; @@ -745,12 +745,12 @@ namespace swrenderer uint8_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } uint32_t c = palette[fg]; - int alpha_bottom = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + int alpha_bottom = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0); int inv_alpha_bottom = 256 - alpha_bottom; int c_red = RPART(c); int c_green = GPART(c); @@ -785,9 +785,9 @@ namespace swrenderer uint32_t material_g = GPalette.BaseColors[material].g; uint32_t material_b = GPalette.BaseColors[material].b; - lit_r = MIN(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); - lit_g = MIN(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); - lit_b = MIN(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); + lit_r = min(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); + lit_g = min(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); + lit_b = min(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); return RGB256k.All[((lit_r >> 2) << 12) | ((lit_g >> 2) << 6) | (lit_b >> 2)]; } @@ -836,9 +836,9 @@ namespace swrenderer uint32_t lit_g = GPART(dynlight); uint32_t lit_b = BPART(dynlight); uint32_t light = 256 - (args.Light() >> (FRACBITS - 8)); - lit_r = MIN(light + lit_r, 256); - lit_g = MIN(light + lit_g, 256); - lit_b = MIN(light + lit_b, 256); + lit_r = min(light + lit_r, 256); + lit_g = min(light + lit_g, 256); + lit_b = min(light + lit_b, 256); lit_r = lit_r - light; lit_g = lit_g - light; lit_b = lit_b - light; @@ -1011,9 +1011,9 @@ namespace swrenderer int src_g = ((srccolor >> 0) & 0xff) * srcalpha; int src_b = ((srccolor >> 8) & 0xff) * srcalpha; int bg = *dest; - int r = MAX((-src_r + palette[bg].r * destalpha)>>18, 0); - int g = MAX((-src_g + palette[bg].g * destalpha)>>18, 0); - int b = MAX((-src_b + palette[bg].b * destalpha)>>18, 0); + int r = max((-src_r + palette[bg].r * destalpha)>>18, 0); + int g = max((-src_g + palette[bg].g * destalpha)>>18, 0); + int b = max((-src_b + palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; @@ -1061,9 +1061,9 @@ namespace swrenderer int src_g = ((srccolor >> 0) & 0xff) * srcalpha; int src_b = ((srccolor >> 8) & 0xff) * srcalpha; int bg = *dest; - int r = MAX((src_r - palette[bg].r * destalpha)>>18, 0); - int g = MAX((src_g - palette[bg].g * destalpha)>>18, 0); - int b = MAX((src_b - palette[bg].b * destalpha)>>18, 0); + int r = max((src_r - palette[bg].r * destalpha)>>18, 0); + int g = max((src_g - palette[bg].g * destalpha)>>18, 0); + int b = max((src_b - palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; @@ -1113,9 +1113,9 @@ namespace swrenderer { uint32_t fg = colormap[source[frac >> FRACBITS]]; uint32_t bg = *dest; - uint32_t r = MIN((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); - uint32_t g = MIN((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); - uint32_t b = MIN((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); + uint32_t r = min((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); + uint32_t g = min((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); + uint32_t b = min((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1192,9 +1192,9 @@ namespace swrenderer { uint32_t fg = colormap[translation[source[frac >> FRACBITS]]]; uint32_t bg = *dest; - uint32_t r = MIN((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); - uint32_t g = MIN((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); - uint32_t b = MIN((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); + uint32_t r = min((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); + uint32_t g = min((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); + uint32_t b = min((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1331,9 +1331,9 @@ namespace swrenderer { int fg = colormap[source[frac >> FRACBITS]]; int bg = *dest; - int r = MIN((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); - int g = MIN((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); - int b = MIN((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); + int r = min((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); + int g = min((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); + int b = min((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1385,9 +1385,9 @@ namespace swrenderer { int fg = colormap[translation[source[frac >> FRACBITS]]]; int bg = *dest; - int r = MIN((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); - int g = MIN((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); - int b = MIN((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); + int r = min((palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 63); + int g = min((palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 63); + int b = min((palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 63); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1437,9 +1437,9 @@ namespace swrenderer { int fg = colormap[source[frac >> FRACBITS]]; int bg = *dest; - int r = MAX((palette[fg].r * srcalpha - palette[bg].r * destalpha)>>18, 0); - int g = MAX((palette[fg].g * srcalpha - palette[bg].g * destalpha)>>18, 0); - int b = MAX((palette[fg].b * srcalpha - palette[bg].b * destalpha)>>18, 0); + int r = max((palette[fg].r * srcalpha - palette[bg].r * destalpha)>>18, 0); + int g = max((palette[fg].g * srcalpha - palette[bg].g * destalpha)>>18, 0); + int b = max((palette[fg].b * srcalpha - palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1490,9 +1490,9 @@ namespace swrenderer { int fg = colormap[translation[source[frac >> FRACBITS]]]; int bg = *dest; - int r = MAX((palette[fg].r * srcalpha - palette[bg].r * destalpha)>>18, 0); - int g = MAX((palette[fg].g * srcalpha - palette[bg].g * destalpha)>>18, 0); - int b = MAX((palette[fg].b * srcalpha - palette[bg].b * destalpha)>>18, 0); + int r = max((palette[fg].r * srcalpha - palette[bg].r * destalpha)>>18, 0); + int g = max((palette[fg].g * srcalpha - palette[bg].g * destalpha)>>18, 0); + int b = max((palette[fg].b * srcalpha - palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1542,9 +1542,9 @@ namespace swrenderer { int fg = colormap[source[frac >> FRACBITS]]; int bg = *dest; - int r = MAX((-palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 0); - int g = MAX((-palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 0); - int b = MAX((-palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 0); + int r = max((-palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 0); + int g = max((-palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 0); + int b = max((-palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1595,9 +1595,9 @@ namespace swrenderer { int fg = colormap[translation[source[frac >> FRACBITS]]]; int bg = *dest; - int r = MAX((-palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 0); - int g = MAX((-palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 0); - int b = MAX((-palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 0); + int r = max((-palette[fg].r * srcalpha + palette[bg].r * destalpha)>>18, 0); + int g = max((-palette[fg].g * srcalpha + palette[bg].g * destalpha)>>18, 0); + int b = max((-palette[fg].b * srcalpha + palette[bg].b * destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; dest += pitch; frac += fracstep; @@ -1618,8 +1618,8 @@ namespace swrenderer int _fuzzviewheight = fuzzviewheight; int x = _x; - int yl = MAX(_yl, 1); - int yh = MIN(_yh, _fuzzviewheight); + int yl = max(_yl, 1); + int yh = min(_yh, _fuzzviewheight); int count = yh - yl + 1; if (count <= 0) return; @@ -1661,8 +1661,8 @@ namespace swrenderer int _fuzzpos = fuzzpos; int _fuzzviewheight = fuzzviewheight; - int yl = MAX(_yl, 1); - int yh = MIN(_yh, _fuzzviewheight); + int yl = max(_yl, 1); + int yh = min(_yh, _fuzzviewheight); int count = yh - yl + 1; @@ -1687,7 +1687,7 @@ namespace swrenderer if (available % fuzzstep != 0) next_wrap++; - int cnt = MIN(count, next_wrap); + int cnt = min(count, next_wrap); count -= cnt; do { @@ -1733,7 +1733,7 @@ namespace swrenderer if (available % fuzzstep != 0) next_wrap++; - int cnt = MIN(count, next_wrap); + int cnt = min(count, next_wrap); count -= cnt; do { @@ -1775,7 +1775,7 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // attenuation = 1 - MIN(dist * (1/radius), 1) + // attenuation = 1 - min(dist * (1/radius), 1) float Lyz2 = lights[i].y; // L.y*L.y + L.z*L.z float Lx = lights[i].x - viewpos_x; float dist2 = Lyz2 + Lx * Lx; @@ -1785,7 +1785,7 @@ namespace swrenderer float rcp_dist = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_load_ss(&dist2))); #endif float dist = dist2 * rcp_dist; - float distance_attenuation = (256.0f - MIN(dist * lights[i].radius, 256.0f)); + float distance_attenuation = (256.0f - min(dist * lights[i].radius, 256.0f)); // The simple light type float simple_attenuation = distance_attenuation; @@ -1807,9 +1807,9 @@ namespace swrenderer uint32_t material_g = GPalette.BaseColors[material].g; uint32_t material_b = GPalette.BaseColors[material].b; - lit_r = MIN(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); - lit_g = MIN(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); - lit_b = MIN(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); + lit_r = min(GPalette.BaseColors[fg].r + ((lit_r * material_r) >> 8), 255); + lit_g = min(GPalette.BaseColors[fg].g + ((lit_g * material_g) >> 8), 255); + lit_b = min(GPalette.BaseColors[fg].b + ((lit_b * material_b) >> 8), 255); return RGB256k.All[((lit_r >> 2) << 12) | ((lit_g >> 2) << 6) | (lit_b >> 2)]; } @@ -2113,9 +2113,9 @@ namespace swrenderer spot = ((xfrac >> (32 - 6 - 6))&(63 * 64)) + (yfrac >> (32 - 6)); uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[source[spot]], source[spot]) : colormap[source[spot]]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest++ = RGB256k.RGB[r][g][b]; xfrac += xstep; @@ -2133,9 +2133,9 @@ namespace swrenderer spot = (((xfrac >> 16) * srcwidth) >> 16) * srcheight + (((yfrac >> 16) * srcheight) >> 16); uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[source[spot]], source[spot]) : colormap[source[spot]]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest++ = RGB256k.RGB[r][g][b]; xfrac += xstep; @@ -2267,9 +2267,9 @@ namespace swrenderer { uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[texdata], texdata) : colormap[texdata]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; } dest++; @@ -2293,9 +2293,9 @@ namespace swrenderer { uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[texdata], texdata) : colormap[texdata]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; } dest++; @@ -2416,9 +2416,9 @@ namespace swrenderer spot = ((xfrac >> (32 - 6 - 6))&(63 * 64)) + (yfrac >> (32 - 6)); uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[source[spot]], source[spot]) : colormap[source[spot]]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest++ = RGB256k.RGB[r][g][b]; xfrac += xstep; @@ -2436,9 +2436,9 @@ namespace swrenderer spot = (((xfrac >> 16) * srcwidth) >> 16) * srcheight + (((yfrac >> 16) * srcheight) >> 16); uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[source[spot]], source[spot]) : colormap[source[spot]]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest++ = RGB256k.RGB[r][g][b]; xfrac += xstep; @@ -2577,9 +2577,9 @@ namespace swrenderer { uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[texdata], texdata) : colormap[texdata]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; } dest++; @@ -2603,9 +2603,9 @@ namespace swrenderer { uint32_t fg = num_dynlights != 0 ? AddLightsSpan(dynlights, num_dynlights, viewpos_x, colormap[texdata], texdata) : colormap[texdata]; uint32_t bg = *dest; - int r = MAX((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); - int g = MAX((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); - int b = MAX((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); + int r = max((palette[fg].r * _srcalpha + palette[bg].r * _destalpha)>>18, 0); + int g = max((palette[fg].g * _srcalpha + palette[bg].g * _destalpha)>>18, 0); + int b = max((palette[fg].b * _srcalpha + palette[bg].b * _destalpha)>>18, 0); *dest = RGB256k.RGB[r][g][b]; } dest++; @@ -2859,7 +2859,7 @@ namespace swrenderer if (count <= 0) return; - int particle_texture_index = MIN(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); + int particle_texture_index = min(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); const uint32_t *source = &particle_texture[particle_texture_index][(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; uint32_t particle_alpha = _alpha; @@ -3060,30 +3060,6 @@ namespace swrenderer wpos += wstepX; curlight += lightstep; } - - if (r_modelscene) - { - for (int x = x1; x < x2; x++) - { - int y1 = uwal[x]; - int y2 = dwal[x]; - if (y2 > y1) - { - int count = y2 - y1; - - float w1 = 1.0f / wallargs.WallC.sz1; - float w2 = 1.0f / wallargs.WallC.sz2; - float t = (x - wallargs.WallC.sx1 + 0.5f) / (wallargs.WallC.sx2 - wallargs.WallC.sx1); - float wcol = w1 * (1.0f - t) + w2 * t; - float zcol = 1.0f / wcol; - float zbufferdepth = 1.0f / (zcol / wallargs.FocalTangent); - - wallcolargs.SetDest(x, y1); - wallcolargs.SetCount(count); - DrawDepthColumn(wallcolargs, zbufferdepth); - } - } - } } template @@ -3122,7 +3098,7 @@ namespace swrenderer uint32_t next_uv_wrap = available / texelStepY; if (available % texelStepY != 0) next_uv_wrap++; - uint32_t count = MIN(left, next_uv_wrap); + uint32_t count = min(left, next_uv_wrap); drawerargs.SetDest(x, y); drawerargs.SetCount(count); diff --git a/src/rendering/swrenderer/drawers/r_draw_rgba.cpp b/src/rendering/swrenderer/drawers/r_draw_rgba.cpp index b6360981c..7878e3e5a 100644 --- a/src/rendering/swrenderer/drawers/r_draw_rgba.cpp +++ b/src/rendering/swrenderer/drawers/r_draw_rgba.cpp @@ -34,7 +34,7 @@ */ #include -#include "templates.h" + #include "doomdef.h" #include "filesystem.h" @@ -257,8 +257,8 @@ namespace swrenderer int _fuzzviewheight = fuzzviewheight; int x = _x; - int yl = MAX(_yl, 1); - int yh = MIN(_yh, _fuzzviewheight); + int yl = max(_yl, 1); + int yh = min(_yh, _fuzzviewheight); int count = yh - yl + 1; if (count <= 0) return; @@ -304,8 +304,8 @@ namespace swrenderer int _fuzzpos = fuzzpos; int _fuzzviewheight = fuzzviewheight; - int yl = MAX(_yl, 1); - int yh = MIN(_yh, _fuzzviewheight); + int yl = max(_yl, 1); + int yh = min(_yh, _fuzzviewheight); int count = yh - yl + 1; @@ -328,7 +328,7 @@ namespace swrenderer if (available % fuzzstep != 0) next_wrap++; - int cnt = MIN(count, next_wrap); + int cnt = min(count, next_wrap); count -= cnt; do { @@ -383,7 +383,7 @@ namespace swrenderer if (available % fuzzstep != 0) next_wrap++; - int cnt = MIN(count, next_wrap); + int cnt = min(count, next_wrap); count -= cnt; do { @@ -810,7 +810,7 @@ namespace swrenderer if (count <= 0) return; - int particle_texture_index = MIN(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); + int particle_texture_index = min(gl_particles_style, NUM_PARTICLE_TEXTURES - 1); const uint32_t *source = &particle_texture[particle_texture_index][(_fracposx >> FRACBITS) * PARTICLE_TEXTURE_SIZE]; uint32_t particle_alpha = _alpha; @@ -956,30 +956,6 @@ namespace swrenderer wpos += wstepX; curlight += lightstep; } - - if (r_modelscene) - { - for (int x = x1; x < x2; x++) - { - int y1 = uwal[x]; - int y2 = dwal[x]; - if (y2 > y1) - { - int count = y2 - y1; - - float w1 = 1.0f / wallargs.WallC.sz1; - float w2 = 1.0f / wallargs.WallC.sz2; - float t = (x - wallargs.WallC.sx1 + 0.5f) / (wallargs.WallC.sx2 - wallargs.WallC.sx1); - float wcol = w1 * (1.0f - t) + w2 * t; - float zcol = 1.0f / wcol; - float zbufferdepth = 1.0f / (zcol / wallargs.FocalTangent); - - wallcolargs.SetDest(x, y1); - wallcolargs.SetCount(count); - DrawDepthColumn(wallcolargs, zbufferdepth); - } - } - } } template @@ -991,9 +967,9 @@ namespace swrenderer double xmagnitude = fabs(static_cast(texelStepX) * (1.0 / 0x1'0000'0000LL)); double ymagnitude = fabs(static_cast(texelStepY) * (1.0 / 0x1'0000'0000LL)); - double magnitude = MAX(ymagnitude, xmagnitude); + double magnitude = max(ymagnitude, xmagnitude); double min_lod = -1000.0; - double lod = MAX(log2(magnitude) + r_lod_bias, min_lod); + double lod = max(log2(magnitude) + r_lod_bias, min_lod); bool magnifying = lod < 0.0f; int mipmap_offset = 0; @@ -1006,8 +982,8 @@ namespace swrenderer { mipmap_offset += mip_width * mip_height; level--; - mip_width = MAX(mip_width >> 1, 1); - mip_height = MAX(mip_height >> 1, 1); + mip_width = max(mip_width >> 1, 1); + mip_height = max(mip_height >> 1, 1); } } diff --git a/src/rendering/swrenderer/drawers/r_draw_sky32.h b/src/rendering/swrenderer/drawers/r_draw_sky32.h index df208afab..ea9dff4f7 100644 --- a/src/rendering/swrenderer/drawers/r_draw_sky32.h +++ b/src/rendering/swrenderer/drawers/r_draw_sky32.h @@ -91,7 +91,7 @@ namespace swrenderer uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t fg = source0[sample_index]; - uint32_t alpha = MAX(MIN(frac >> (16 - start_fade), 256), 0); + uint32_t alpha = max(min(frac >> (16 - start_fade), 256), 0); uint32_t inv_alpha = 256 - alpha; BgraColor c = fg; @@ -122,7 +122,7 @@ namespace swrenderer uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t fg = source0[sample_index]; - uint32_t alpha = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + uint32_t alpha = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0); uint32_t inv_alpha = 256 - alpha; BgraColor c = fg; @@ -187,7 +187,7 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } @@ -220,11 +220,11 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } - uint32_t alpha = MAX(MIN(frac >> (16 - start_fade), 256), 0); + uint32_t alpha = max(min(frac >> (16 - start_fade), 256), 0); uint32_t inv_alpha = 256 - alpha; BgraColor c = fg; @@ -243,7 +243,7 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } *dest = fg; @@ -260,11 +260,11 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } - uint32_t alpha = MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0); + uint32_t alpha = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0); uint32_t inv_alpha = 256 - alpha; BgraColor c = fg; diff --git a/src/rendering/swrenderer/drawers/r_draw_sky32_sse2.h b/src/rendering/swrenderer/drawers/r_draw_sky32_sse2.h index 998833416..bc2411b83 100644 --- a/src/rendering/swrenderer/drawers/r_draw_sky32_sse2.h +++ b/src/rendering/swrenderer/drawers/r_draw_sky32_sse2.h @@ -91,7 +91,7 @@ namespace swrenderer uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t fg = source0[sample_index]; - __m128i alpha = _mm_set1_epi16(MAX(MIN(frac >> (16 - start_fade), 256), 0)); + __m128i alpha = _mm_set1_epi16(max(min(frac >> (16 - start_fade), 256), 0)); __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); __m128i c = _mm_unpacklo_epi8(_mm_cvtsi32_si128(fg), _mm_setzero_si128()); @@ -120,7 +120,7 @@ namespace swrenderer uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS; uint32_t fg = source0[sample_index]; - __m128i alpha = _mm_set1_epi16(MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0)); + __m128i alpha = _mm_set1_epi16(max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0)); __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); __m128i c = _mm_unpacklo_epi8(_mm_cvtsi32_si128(fg), _mm_setzero_si128()); @@ -171,7 +171,7 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } @@ -216,11 +216,11 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } - __m128i alpha = _mm_set1_epi16(MAX(MIN(frac >> (16 - start_fade), 256), 0)); + __m128i alpha = _mm_set1_epi16(max(min(frac >> (16 - start_fade), 256), 0)); __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); __m128i c = _mm_unpacklo_epi8(_mm_cvtsi32_si128(fg), _mm_setzero_si128()); @@ -239,7 +239,7 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } *dest = fg; @@ -256,11 +256,11 @@ namespace swrenderer uint32_t fg = source0[sample_index]; if (fg == 0) { - uint32_t sample_index2 = MIN(sample_index, maxtextureheight1); + uint32_t sample_index2 = min(sample_index, maxtextureheight1); fg = source1[sample_index2]; } - __m128i alpha = _mm_set1_epi16(MAX(MIN(((2 << 24) - frac) >> (16 - start_fade), 256), 0)); + __m128i alpha = _mm_set1_epi16(max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0)); __m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha); __m128i c = _mm_unpacklo_epi8(_mm_cvtsi32_si128(fg), _mm_setzero_si128()); diff --git a/src/rendering/swrenderer/drawers/r_draw_span32.h b/src/rendering/swrenderer/drawers/r_draw_span32.h index 9534c496b..1c1e3e55d 100644 --- a/src/rendering/swrenderer/drawers/r_draw_span32.h +++ b/src/rendering/swrenderer/drawers/r_draw_span32.h @@ -94,8 +94,8 @@ namespace swrenderer break; texdata.source += texdata.width * texdata.height; - texdata.width = MAX(texdata.width / 2, 1); - texdata.height = MAX(texdata.height / 2, 1); + texdata.width = max(texdata.width / 2, 1); + texdata.height = max(texdata.height / 2, 1); level--; } } @@ -324,13 +324,13 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + // distance_attenuation = 1 - min(dist * (1/radius), 1) float Lyz2 = light_y; // L.y*L.y + L.z*L.z float Lx = light_x - viewpos_x; float dist2 = Lyz2 + Lx * Lx; float rcp_dist = 1.f/sqrt(dist2); float dist = dist2 * rcp_dist; - float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f); + float distance_attenuation = 256.0f - min(dist * light_radius, 256.0f); // The simple light type float simple_attenuation = distance_attenuation; @@ -348,13 +348,13 @@ namespace swrenderer lit.b += (light_color.b * attenuation) >> 8; } - lit.r = MIN(lit.r, 256); - lit.g = MIN(lit.g, 256); - lit.b = MIN(lit.b, 256); + lit.r = min(lit.r, 256); + lit.g = min(lit.g, 256); + lit.b = min(lit.b, 256); - fgcolor.r = MIN(fgcolor.r + ((material.r * lit.r) >> 8), 255); - fgcolor.g = MIN(fgcolor.g + ((material.g * lit.g) >> 8), 255); - fgcolor.b = MIN(fgcolor.b + ((material.b * lit.b) >> 8), 255); + fgcolor.r = min(fgcolor.r + ((material.r * lit.r) >> 8), 255); + fgcolor.g = min(fgcolor.g + ((material.g * lit.g) >> 8), 255); + fgcolor.b = min(fgcolor.b + ((material.b * lit.b) >> 8), 255); return fgcolor; } @@ -381,9 +381,9 @@ namespace swrenderer bgcolor.b = bgcolor.b * destalpha; BgraColor outcolor; - outcolor.r = MIN((fgcolor.r + bgcolor.r) >> 8, 255); - outcolor.g = MIN((fgcolor.g + bgcolor.g) >> 8, 255); - outcolor.b = MIN((fgcolor.b + bgcolor.b) >> 8, 255); + outcolor.r = min((fgcolor.r + bgcolor.r) >> 8, 255); + outcolor.g = min((fgcolor.g + bgcolor.g) >> 8, 255); + outcolor.b = min((fgcolor.b + bgcolor.b) >> 8, 255); return outcolor; } else @@ -405,21 +405,21 @@ namespace swrenderer BgraColor outcolor; if (BlendT::Mode == (int)SpanBlendModes::AddClamp) { - outcolor.r = MIN((fgcolor.r + bgcolor.r) >> 8, 255); - outcolor.g = MIN((fgcolor.g + bgcolor.g) >> 8, 255); - outcolor.b = MIN((fgcolor.b + bgcolor.b) >> 8, 255); + outcolor.r = min((fgcolor.r + bgcolor.r) >> 8, 255); + outcolor.g = min((fgcolor.g + bgcolor.g) >> 8, 255); + outcolor.b = min((fgcolor.b + bgcolor.b) >> 8, 255); } else if (BlendT::Mode == (int)SpanBlendModes::SubClamp) { - outcolor.r = MAX(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); } else if (BlendT::Mode == (int)SpanBlendModes::RevSubClamp) { - outcolor.r = MAX(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); } outcolor.a = 255; return outcolor; diff --git a/src/rendering/swrenderer/drawers/r_draw_span32_sse2.h b/src/rendering/swrenderer/drawers/r_draw_span32_sse2.h index 527545a9d..230ba8c13 100644 --- a/src/rendering/swrenderer/drawers/r_draw_span32_sse2.h +++ b/src/rendering/swrenderer/drawers/r_draw_span32_sse2.h @@ -94,8 +94,8 @@ namespace swrenderer break; texdata.source += texdata.width * texdata.height; - texdata.width = MAX(texdata.width / 2, 1); - texdata.height = MAX(texdata.height / 2, 1); + texdata.width = max(texdata.width / 2, 1); + texdata.height = max(texdata.height / 2, 1); level--; } } @@ -366,7 +366,7 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + // distance_attenuation = 1 - min(dist * (1/radius), 1) __m128 Lyz2 = light_y; // L.y*L.y + L.z*L.z __m128 Lx = _mm_sub_ps(light_x, viewpos_x); __m128 dist2 = _mm_add_ps(Lyz2, _mm_mul_ps(Lx, Lx)); diff --git a/src/rendering/swrenderer/drawers/r_draw_sprite32.h b/src/rendering/swrenderer/drawers/r_draw_sprite32.h index 7fa300f82..6ae563dc6 100644 --- a/src/rendering/swrenderer/drawers/r_draw_sprite32.h +++ b/src/rendering/swrenderer/drawers/r_draw_sprite32.h @@ -143,9 +143,9 @@ namespace swrenderer shade_light.g = shade_constants.light_green; shade_light.b = shade_constants.light_blue; desaturate = shade_constants.desaturate; - lightcontrib.r = MIN(light + dynlight.r, 256) - light; - lightcontrib.g = MIN(light + dynlight.g, 256) - light; - lightcontrib.b = MIN(light + dynlight.b, 256) - light; + lightcontrib.r = min(light + dynlight.r, 256) - light; + lightcontrib.g = min(light + dynlight.g, 256) - light; + lightcontrib.b = min(light + dynlight.b, 256) - light; mlight.r = light; mlight.g = light; mlight.b = light; @@ -161,9 +161,9 @@ namespace swrenderer shade_light.b = 0; desaturate = 0; lightcontrib = 0; - mlight.r = MIN(light + dynlight.r, 256); - mlight.g = MIN(light + dynlight.g, 256); - mlight.b = MIN(light + dynlight.b, 256); + mlight.r = min(light + dynlight.r, 256); + mlight.g = min(light + dynlight.g, 256); + mlight.b = min(light + dynlight.b, 256); } int count = args.Count(); @@ -300,9 +300,9 @@ namespace swrenderer fgcolor.g = (((shade_fade.g + ((fgcolor.g * inv_desaturate + intensity) >> 8) * mlight.g) >> 8) * shade_light.g) >> 8; fgcolor.b = (((shade_fade.b + ((fgcolor.b * inv_desaturate + intensity) >> 8) * mlight.b) >> 8) * shade_light.b) >> 8; - fgcolor.r = MIN(fgcolor.r + lit_dynlight.r, 255); - fgcolor.g = MIN(fgcolor.g + lit_dynlight.g, 255); - fgcolor.b = MIN(fgcolor.b + lit_dynlight.b, 255); + fgcolor.r = min(fgcolor.r + lit_dynlight.r, 255); + fgcolor.g = min(fgcolor.g + lit_dynlight.g, 255); + fgcolor.b = min(fgcolor.b + lit_dynlight.b, 255); return fgcolor; } } @@ -332,9 +332,9 @@ namespace swrenderer { uint32_t alpha = ifgshade; BgraColor outcolor; - outcolor.r = MIN(((fgcolor.r * alpha) >> 8) + bgcolor.r, 255); - outcolor.g = MIN(((fgcolor.g * alpha) >> 8) + bgcolor.g, 255); - outcolor.b = MIN(((fgcolor.b * alpha) >> 8) + bgcolor.b, 255); + outcolor.r = min(((fgcolor.r * alpha) >> 8) + bgcolor.r, 255); + outcolor.g = min(((fgcolor.g * alpha) >> 8) + bgcolor.g, 255); + outcolor.b = min(((fgcolor.b * alpha) >> 8) + bgcolor.b, 255); outcolor.a = 255; return outcolor; } @@ -357,21 +357,21 @@ namespace swrenderer BgraColor outcolor; if (BlendT::Mode == (int)SpriteBlendModes::AddClamp) { - outcolor.r = MIN((fgcolor.r + bgcolor.r) >> 8, 255); - outcolor.g = MIN((fgcolor.g + bgcolor.g) >> 8, 255); - outcolor.b = MIN((fgcolor.b + bgcolor.b) >> 8, 255); + outcolor.r = min((fgcolor.r + bgcolor.r) >> 8, 255); + outcolor.g = min((fgcolor.g + bgcolor.g) >> 8, 255); + outcolor.b = min((fgcolor.b + bgcolor.b) >> 8, 255); } else if (BlendT::Mode == (int)SpriteBlendModes::SubClamp) { - outcolor.r = MAX(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); } else if (BlendT::Mode == (int)SpriteBlendModes::RevSubClamp) { - outcolor.r = MAX(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); } outcolor.a = 255; return outcolor; diff --git a/src/rendering/swrenderer/drawers/r_draw_wall32.h b/src/rendering/swrenderer/drawers/r_draw_wall32.h index 65f7025b2..92056a9b7 100644 --- a/src/rendering/swrenderer/drawers/r_draw_wall32.h +++ b/src/rendering/swrenderer/drawers/r_draw_wall32.h @@ -236,13 +236,13 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + // distance_attenuation = 1 - min(dist * (1/radius), 1) float Lxy2 = light_x; // L.x*L.x + L.y*L.y float Lz = light_z - viewpos_z; float dist2 = Lxy2 + Lz * Lz; float rcp_dist = 1.f/sqrt(dist2); float dist = dist2 * rcp_dist; - float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f); + float distance_attenuation = 256.0f - min(dist * light_radius, 256.0f); // The simple light type float simple_attenuation = distance_attenuation; @@ -260,13 +260,13 @@ namespace swrenderer lit.b += (light_color.b * attenuation) >> 8; } - lit.r = MIN(lit.r, 256); - lit.g = MIN(lit.g, 256); - lit.b = MIN(lit.b, 256); + lit.r = min(lit.r, 256); + lit.g = min(lit.g, 256); + lit.b = min(lit.b, 256); - fgcolor.r = MIN(fgcolor.r + ((material.r * lit.r) >> 8), 255); - fgcolor.g = MIN(fgcolor.g + ((material.g * lit.g) >> 8), 255); - fgcolor.b = MIN(fgcolor.b + ((material.b * lit.b) >> 8), 255); + fgcolor.r = min(fgcolor.r + ((material.r * lit.r) >> 8), 255); + fgcolor.g = min(fgcolor.g + ((material.g * lit.g) >> 8), 255); + fgcolor.b = min(fgcolor.b + ((material.b * lit.b) >> 8), 255); return fgcolor; } @@ -302,21 +302,21 @@ namespace swrenderer BgraColor outcolor; if (BlendT::Mode == (int)WallBlendModes::AddClamp) { - outcolor.r = MIN((fgcolor.r + bgcolor.r) >> 8, 255); - outcolor.g = MIN((fgcolor.g + bgcolor.g) >> 8, 255); - outcolor.b = MIN((fgcolor.b + bgcolor.b) >> 8, 255); + outcolor.r = min((fgcolor.r + bgcolor.r) >> 8, 255); + outcolor.g = min((fgcolor.g + bgcolor.g) >> 8, 255); + outcolor.b = min((fgcolor.b + bgcolor.b) >> 8, 255); } else if (BlendT::Mode == (int)WallBlendModes::SubClamp) { - outcolor.r = MAX(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(fgcolor.r - bgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(fgcolor.g - bgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(fgcolor.b - bgcolor.b) >> 8, 0); } else if (BlendT::Mode == (int)WallBlendModes::RevSubClamp) { - outcolor.r = MAX(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); - outcolor.g = MAX(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); - outcolor.b = MAX(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); + outcolor.r = max(int32_t(bgcolor.r - fgcolor.r) >> 8, 0); + outcolor.g = max(int32_t(bgcolor.g - fgcolor.g) >> 8, 0); + outcolor.b = max(int32_t(bgcolor.b - fgcolor.b) >> 8, 0); } outcolor.a = 255; return outcolor; diff --git a/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h b/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h index 4ea8d4d75..1860ba667 100644 --- a/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h +++ b/src/rendering/swrenderer/drawers/r_draw_wall32_sse2.h @@ -280,7 +280,7 @@ namespace swrenderer // L = light-pos // dist = sqrt(dot(L, L)) - // distance_attenuation = 1 - MIN(dist * (1/radius), 1) + // distance_attenuation = 1 - min(dist * (1/radius), 1) __m128 Lxy2 = light_x; // L.x*L.x + L.y*L.y __m128 Lz = _mm_sub_ps(light_z, viewpos_z); __m128 dist2 = _mm_add_ps(Lxy2, _mm_mul_ps(Lz, Lz)); diff --git a/src/rendering/swrenderer/line/r_farclip_line.cpp b/src/rendering/swrenderer/line/r_farclip_line.cpp index e0f027578..8b2cd07f2 100644 --- a/src/rendering/swrenderer/line/r_farclip_line.cpp +++ b/src/rendering/swrenderer/line/r_farclip_line.cpp @@ -20,7 +20,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "doomstat.h" @@ -155,7 +155,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { short top = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeCeiling) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; - short bottom = MIN(walltop.ScreenY[x], floorclip[x]); + short bottom = min(walltop.ScreenY[x], floorclip[x]); if (top < bottom) { mCeilingPlane->top[x] = top; @@ -177,7 +177,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { - short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]); + short top = max(wallbottom.ScreenY[x], ceilingclip[x]); short bottom = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeFloor) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; if (top < bottom) { diff --git a/src/rendering/swrenderer/line/r_fogboundary.cpp b/src/rendering/swrenderer/line/r_fogboundary.cpp index 1a6e40519..ca8438bbb 100644 --- a/src/rendering/swrenderer/line/r_fogboundary.cpp +++ b/src/rendering/swrenderer/line/r_fogboundary.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -110,13 +110,13 @@ namespace swrenderer { if (fake_dc_colormap != basecolormapdata) { - stop = MIN(t1, b2); + stop = min(t1, b2); while (t2 < stop) { int y = t2++; drawerargs.DrawFogBoundaryLine(thread, y, xr, spanend[y]); } - stop = MAX(b1, t2); + stop = max(b1, t2); while (b2 > stop) { int y = --b2; @@ -125,16 +125,16 @@ namespace swrenderer } else { - t2 = MAX(t2, MIN(t1, b2)); - b2 = MIN(b2, MAX(b1, t2)); + t2 = max(t2, min(t1, b2)); + b2 = min(b2, max(b1, t2)); } - stop = MIN(t2, b1); + stop = min(t2, b1); while (t1 < stop) { spanend[t1++] = x; } - stop = MAX(b2, t2); + stop = max(b2, t2); while (b1 > stop) { spanend[--b1] = x; diff --git a/src/rendering/swrenderer/line/r_line.cpp b/src/rendering/swrenderer/line/r_line.cpp index e2e08b268..1a6717450 100644 --- a/src/rendering/swrenderer/line/r_line.cpp +++ b/src/rendering/swrenderer/line/r_line.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "engineerrors.h" #include "doomdef.h" #include "doomstat.h" @@ -752,7 +752,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { short top = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeCeiling) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; - short bottom = MIN(walltop.ScreenY[x], floorclip[x]); + short bottom = min(walltop.ScreenY[x], floorclip[x]); if (top < bottom) { mCeilingPlane->top[x] = top; @@ -774,7 +774,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { - short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]); + short top = max(wallbottom.ScreenY[x], ceilingclip[x]); short bottom = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeFloor) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; if (top < bottom) { @@ -804,7 +804,7 @@ namespace swrenderer { for (int x = x1; x < x2; ++x) { - walllower.ScreenY[x] = MIN(MAX(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); + walllower.ScreenY[x] = min(max(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); } memcpy(clip3d->fakeFloor->floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -816,7 +816,7 @@ namespace swrenderer { for (int x = x1; x < x2; ++x) { - wallupper.ScreenY[x] = MAX(MIN(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); + wallupper.ScreenY[x] = max(min(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); } memcpy(clip3d->fakeFloor->ceilingclip + x1, wallupper.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -839,7 +839,7 @@ namespace swrenderer { // top wall for (int x = x1; x < x2; ++x) { - wallupper.ScreenY[x] = MAX(MIN(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); + wallupper.ScreenY[x] = max(min(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); } memcpy(ceilingclip + x1, wallupper.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -852,7 +852,7 @@ namespace swrenderer { // bottom wall for (int x = x1; x < x2; ++x) { - walllower.ScreenY[x] = MIN(MAX(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); + walllower.ScreenY[x] = min(max(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); } memcpy(floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -873,7 +873,7 @@ namespace swrenderer texcoords.ProjectTop(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC, mTopTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, false, false, OPAQUE); + renderWallpart.Render(mFrontSector, mLineSegment, side_t::top, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, false, false, OPAQUE); } void SWRenderLine::RenderMiddleTexture(int x1, int x2) @@ -885,7 +885,7 @@ namespace swrenderer texcoords.ProjectMid(Thread->Viewport.get(), mFrontSector, mLineSegment, WallC, mMiddleTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); + renderWallpart.Render(mFrontSector, mLineSegment, side_t::mid, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); } void SWRenderLine::RenderBottomTexture(int x1, int x2) @@ -898,6 +898,6 @@ namespace swrenderer texcoords.ProjectBottom(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC, mBottomTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); + renderWallpart.Render(mFrontSector, mLineSegment, side_t::bottom, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); } } diff --git a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp index b4c5fa544..ba89086ed 100644 --- a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp @@ -21,7 +21,7 @@ // #include -#include "templates.h" + #include "doomdef.h" #include "m_bbox.h" @@ -122,20 +122,20 @@ namespace swrenderer top -= Thread->Viewport->viewpoint.Pos.Z; bot -= Thread->Viewport->viewpoint.Pos.Z; - ceilZ = MIN(ceilZ, top); - floorZ = MAX(floorZ, bot); + ceilZ = min(ceilZ, top); + floorZ = max(floorZ, bot); } // Clip wall by the current 3D floor render range. if (m3DFloor.clipTop) { double clipZ = m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z; - ceilZ = MIN(ceilZ, clipZ); + ceilZ = min(ceilZ, clipZ); } if (m3DFloor.clipBottom) { double clipZ = m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z; - floorZ = MAX(floorZ, clipZ); + floorZ = max(floorZ, clipZ); } wallupper.Project(Thread->Viewport.get(), ceilZ, &ds->WallC); @@ -191,11 +191,11 @@ namespace swrenderer sector_t tempsec; const sector_t* lightsector = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); - fixed_t alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.)); + fixed_t alpha = FLOAT2FIXED((float)min(curline->linedef->alpha, 1.)); bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; RenderWallPart renderWallpart(Thread); - renderWallpart.Render(lightsector, curline, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, true, additive, alpha); + renderWallpart.Render(lightsector, curline, side_t::mid, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, true, additive, alpha); } void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic) @@ -216,7 +216,7 @@ namespace swrenderer walltexcoords.Project3DFloor(Thread->Viewport.get(), rover, curline, ds->WallC, rw_pic); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(lightsector, curline, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha); + renderWallpart.Render(lightsector, curline, side_t::top, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha); RenderDecal::RenderDecals(Thread, ds, curline, lightsector, wallupper.ScreenY, walllower.ScreenY, true); } @@ -580,7 +580,7 @@ namespace swrenderer const sector_t* lightsector = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); ProjectedWallLight walllight; - walllight.SetColormap(lightsector, curline); + walllight.SetColormap(lightsector, curline, side_t::mid); walllight.SetLightLeft(Thread, ds->WallC); RenderFogBoundary renderfog; @@ -614,16 +614,16 @@ namespace swrenderer double frontfz1 = ds->curline->frontsector->floorplane.ZatPoint(ds->curline->v1); double frontcz2 = ds->curline->frontsector->ceilingplane.ZatPoint(ds->curline->v2); double frontfz2 = ds->curline->frontsector->floorplane.ZatPoint(ds->curline->v2); - top = MAX(frontcz1, frontcz2); - bot = MIN(frontfz1, frontfz2); + top = max(frontcz1, frontcz2); + bot = min(frontfz1, frontfz2); if (m3DFloor.clipTop) { - top = MIN(top, m3DFloor.sclipTop); + top = min(top, m3DFloor.sclipTop); } if (m3DFloor.clipBottom) { - bot = MAX(bot, m3DFloor.sclipBottom); + bot = max(bot, m3DFloor.sclipBottom); } } @@ -632,9 +632,9 @@ namespace swrenderer double texheight = tex->GetScaledHeight() / fabs(curline->sidedef->GetTextureYScale(side_t::mid)); double texturemid; if (curline->linedef->flags & ML_DONTPEGBOTTOM) - texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; + texturemid = max(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; else - texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + texturemid = min(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); if (tex->useWorldPanning(curline->GetLevel())) rowoffset /= fabs(tex->GetScale().Y * curline->sidedef->GetTextureYScale(side_t::mid)); diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index 1d4a4c64c..0e2338d1e 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -61,7 +61,7 @@ namespace swrenderer Thread = thread; } - void RenderWallPart::Render(const sector_t* lightsector, seg_t* curline, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, const ProjectedWallTexcoords& texcoords, bool mask, bool additive, fixed_t alpha) + void RenderWallPart::Render(const sector_t* lightsector, seg_t* curline, int tier, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, const ProjectedWallTexcoords& texcoords, bool mask, bool additive, fixed_t alpha) { if (pic == nullptr) return; @@ -70,6 +70,7 @@ namespace swrenderer this->x2 = x2; this->lightsector = lightsector; this->curline = curline; + this->tier = tier; this->WallC = WallC; this->pic = pic; this->mask = mask; @@ -78,7 +79,7 @@ namespace swrenderer light_list = GetLightList(); - mLight.SetColormap(lightsector, curline); + mLight.SetColormap(lightsector, curline, tier); mLight.SetLightLeft(Thread, WallC); CameraLight* cameraLight = CameraLight::Instance(); @@ -114,7 +115,7 @@ namespace swrenderer down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; } - mLight.SetColormap(lightsector, curline, &lightsector->e->XFloor.lightlist[i]); + mLight.SetColormap(lightsector, curline, tier, &lightsector->e->XFloor.lightlist[i]); } ProcessNormalWall(up, dwal, texcoords); diff --git a/src/rendering/swrenderer/line/r_walldraw.h b/src/rendering/swrenderer/line/r_walldraw.h index 3db272807..4088e792e 100644 --- a/src/rendering/swrenderer/line/r_walldraw.h +++ b/src/rendering/swrenderer/line/r_walldraw.h @@ -47,6 +47,7 @@ namespace swrenderer void Render( const sector_t *lightsector, seg_t *curline, + int tier, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, @@ -70,6 +71,7 @@ namespace swrenderer FSoftwareTexture *pic = nullptr; const sector_t *lightsector = nullptr; seg_t *curline = nullptr; + int tier; FWallCoords WallC; ProjectedWallLight mLight; diff --git a/src/rendering/swrenderer/line/r_wallsetup.cpp b/src/rendering/swrenderer/line/r_wallsetup.cpp index 2f864581e..2ecf3cab9 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.cpp +++ b/src/rendering/swrenderer/line/r_wallsetup.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "doomstat.h" @@ -305,7 +305,7 @@ namespace swrenderer { for (int i = x1; i < x2; i++) { - ScreenY[i] = std::min(ScreenY[i], clip.sprbottomclip[i]); + ScreenY[i] = min(ScreenY[i], clip.sprbottomclip[i]); } } @@ -441,8 +441,8 @@ namespace swrenderer float yscale = GetYScale(sidedef, pic, side_t::mid); double cameraZ = viewport->viewpoint.Pos.Z; - double texZFloor = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)); - double texZCeiling = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + double texZFloor = max(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)); + double texZCeiling = min(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); double texturemid; if (yscale >= 0) @@ -687,7 +687,7 @@ namespace swrenderer } } - void ProjectedWallLight::SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit) + void ProjectedWallLight::SetColormap(const sector_t *frontsector, seg_t *lineseg, int tier, lightlist_t *lit) { if (!lit) { @@ -695,7 +695,7 @@ namespace swrenderer foggy = frontsector->Level->fadeto || frontsector->Colormap.FadeColor || (frontsector->Level->flags & LEVEL_HASFADETABLE); if (!(lineseg->sidedef->Flags & WALLF_POLYOBJ)) - lightlevel = lineseg->sidedef->GetLightLevel(foggy, frontsector->lightlevel); + lightlevel = lineseg->sidedef->GetLightLevel(foggy, frontsector->lightlevel, tier); else lightlevel = frontsector->GetLightLevel(); } @@ -703,7 +703,7 @@ namespace swrenderer { basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); foggy = frontsector->Level->fadeto || basecolormap->Fade || (frontsector->Level->flags & LEVEL_HASFADETABLE); - lightlevel = lineseg->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, lit->lightsource != nullptr); + lightlevel = lineseg->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, tier, lit->lightsource != nullptr); } } } diff --git a/src/rendering/swrenderer/line/r_wallsetup.h b/src/rendering/swrenderer/line/r_wallsetup.h index 4eadd311a..07b07f0f5 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.h +++ b/src/rendering/swrenderer/line/r_wallsetup.h @@ -119,7 +119,7 @@ namespace swrenderer float GetLightStep() const { return lightstep; } bool IsSpriteLight() const { return spritelight; } - void SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit = nullptr); + void SetColormap(const sector_t *frontsector, seg_t *lineseg, int tier, lightlist_t *lit = nullptr); void SetLightLeft(RenderThread *thread, const FWallCoords &wallc); void SetSpriteLight() { lightleft = 0.0f; lightstep = 0.0f; spritelight = true; } diff --git a/src/rendering/swrenderer/plane/r_flatplane.cpp b/src/rendering/swrenderer/plane/r_flatplane.cpp index 9075fe910..639e28d51 100644 --- a/src/rendering/swrenderer/plane/r_flatplane.cpp +++ b/src/rendering/swrenderer/plane/r_flatplane.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "engineerrors.h" #include "filesystem.h" #include "doomdef.h" @@ -92,7 +92,7 @@ namespace swrenderer pviewy = _yscale * pviewy; // left to right mapping - planeang += (Thread->Viewport->viewpoint.Angles.Yaw - 90).Radians(); + planeang += (Thread->Viewport->viewpoint.Angles.Yaw - DAngle::fromDeg(90)).Radians(); auto viewport = Thread->Viewport.get(); @@ -178,9 +178,9 @@ namespace swrenderer double distance2 = viewport->PlaneDepth(y + 1, planeheight); double xmagnitude = fabs(ystepscale * (distance2 - distance) * viewport->FocalLengthX); double ymagnitude = fabs(xstepscale * (distance2 - distance) * viewport->FocalLengthX); - double magnitude = MAX(ymagnitude, xmagnitude); + double magnitude = max(ymagnitude, xmagnitude); double min_lod = -1000.0; - drawerargs.SetTextureLOD(MAX(log2(magnitude) + r_lod_bias, min_lod)); + drawerargs.SetTextureLOD(max(log2(magnitude) + r_lod_bias, min_lod)); } if (plane_shade) @@ -270,8 +270,6 @@ namespace swrenderer drawerargs.SetDestX2(x2); drawerargs.DrawSpan(Thread); - if (r_modelscene) - drawerargs.DrawDepthSpan(Thread, zbufferdepth, zbufferdepth); } ///////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/swrenderer/plane/r_planerenderer.cpp b/src/rendering/swrenderer/plane/r_planerenderer.cpp index f251d5c71..9875fe0fe 100644 --- a/src/rendering/swrenderer/plane/r_planerenderer.cpp +++ b/src/rendering/swrenderer/plane/r_planerenderer.cpp @@ -23,7 +23,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -65,14 +65,14 @@ namespace swrenderer int stop; // Draw any spans that have just closed - stop = MIN(t1, b2); + stop = min(t1, b2); while (t2 < stop) { int y = t2++; int x2 = spanend[y]; RenderLine(y, xr, x2); } - stop = MAX(b1, t2); + stop = max(b1, t2); while (b2 > stop) { int y = --b2; @@ -81,12 +81,12 @@ namespace swrenderer } // Mark any spans that have just opened - stop = MIN(t2, b1); + stop = min(t2, b1); while (t1 < stop) { spanend[t1++] = x; } - stop = MAX(b2, t2); + stop = max(b2, t2); while (b1 > stop) { spanend[--b1] = x; diff --git a/src/rendering/swrenderer/plane/r_skyplane.cpp b/src/rendering/swrenderer/plane/r_skyplane.cpp index cc59301ad..35a04cf4c 100644 --- a/src/rendering/swrenderer/plane/r_skyplane.cpp +++ b/src/rendering/swrenderer/plane/r_skyplane.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -94,8 +94,8 @@ namespace swrenderer skyiscale = float(r_Yaspect / freelookviewheight); skyscale = freelookviewheight / r_Yaspect; - skyiscale *= float(thread->Viewport->viewpoint.FieldOfView.Degrees / 90.); - skyscale *= float(90. / thread->Viewport->viewpoint.FieldOfView.Degrees); + skyiscale *= float(thread->Viewport->viewpoint.FieldOfView.Degrees() / 90.); + skyscale *= float(90. / thread->Viewport->viewpoint.FieldOfView.Degrees()); } if (Level->skystretch) @@ -109,8 +109,8 @@ namespace swrenderer // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of // the texture as the cylinder's circumfrence. - sky1cyl = MAX(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); - sky2cyl = MAX(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); + sky1cyl = max(sskytex1->GetWidth(), fixed_t(sskytex1->GetScale().X * 1024)); + sky2cyl = max(sskytex2->GetWidth(), fixed_t(sskytex2->GetScale().Y * 1024)); } void RenderSkyPlane::Render(VisiblePlane *pl) @@ -199,7 +199,7 @@ namespace swrenderer skyflip = l->args[2] ? 0u : ~0u; int frontxscale = int(frontskytex->GetScale().X * 1024); - frontcyl = MAX(frontskytex->GetWidth(), frontxscale); + frontcyl = max(frontskytex->GetWidth(), frontxscale); if (Level->skystretch) { skymid = skymid * frontskytex->GetScaledHeight() / (SKYSTRETCH_HEIGHT + skyoffset); @@ -267,8 +267,6 @@ namespace swrenderer else drawerargs.DrawDoubleSkyColumn(Thread); - if (r_modelscene) - drawerargs.DrawDepthSkyColumn(Thread, 1.0f / 65536.0f); } void RenderSkyPlane::DrawSkyColumn(int start_x, int y1, int y2) diff --git a/src/rendering/swrenderer/plane/r_slopeplane.cpp b/src/rendering/swrenderer/plane/r_slopeplane.cpp index 6bc8e946c..7a00e70ad 100644 --- a/src/rendering/swrenderer/plane/r_slopeplane.cpp +++ b/src/rendering/swrenderer/plane/r_slopeplane.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -205,22 +205,5 @@ namespace swrenderer void RenderSlopePlane::RenderLine(int y, int x1, int x2) { drawerargs.DrawTiltedSpan(Thread, y, x1, x2, plane_sz, plane_su, plane_sv, plane_shade, lightlevel, foggy, planelightfloat, pviewx, pviewy, basecolormap); - - if (r_modelscene) - { - double viewZ = 1.0; - double viewX1 = Thread->Viewport->ScreenToViewX(x1, viewZ); - double viewX2 = Thread->Viewport->ScreenToViewX(x2 + 1, viewZ); - double viewY = Thread->Viewport->ScreenToViewY(y, viewZ); - - // Find depth values for the span - float zbufferdepth1 = (float)(-planeD / (planeNormal | DVector3(viewX1, viewZ, viewY))); - float zbufferdepth2 = (float)(-planeD / (planeNormal | DVector3(viewX2, viewZ, viewY))); - - drawerargs.SetDestX1(x1); - drawerargs.SetDestX2(x2); - drawerargs.SetDestY(Thread->Viewport.get(), y); - drawerargs.DrawDepthSpan(Thread, 1.0f / zbufferdepth1, 1.0f / zbufferdepth2); - } } } diff --git a/src/rendering/swrenderer/plane/r_visibleplane.cpp b/src/rendering/swrenderer/plane/r_visibleplane.cpp index 75c562194..c8517cac4 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplane.cpp @@ -23,7 +23,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" diff --git a/src/rendering/swrenderer/plane/r_visibleplane.h b/src/rendering/swrenderer/plane/r_visibleplane.h index 101be05bc..fcb5c6786 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.h +++ b/src/rendering/swrenderer/plane/r_visibleplane.h @@ -70,7 +70,7 @@ namespace swrenderer int extralight = 0; double visibility = 0.0; DVector3 viewpos = { 0.0, 0.0, 0.0 }; - DAngle viewangle = { 0.0 }; + DAngle viewangle = nullAngle; fixed_t Alpha = 0; bool Additive = false; diff --git a/src/rendering/swrenderer/plane/r_visibleplanelist.cpp b/src/rendering/swrenderer/plane/r_visibleplanelist.cpp index a265be5d2..bddc4f232 100644 --- a/src/rendering/swrenderer/plane/r_visibleplanelist.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplanelist.cpp @@ -23,7 +23,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -121,7 +121,7 @@ namespace swrenderer xform = &nulltransform; nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0; nulltransform.xScale = nulltransform.yScale = 1; - nulltransform.Angle = nulltransform.baseAngle = 0.0; + nulltransform.Angle = nulltransform.baseAngle = nullAngle; additive = false; // [RH] Map floor skies and ceiling skies to separate visplanes. This isn't // always necessary, but it is needed if a floor and ceiling sky are in the diff --git a/src/rendering/swrenderer/r_all.cpp b/src/rendering/swrenderer/r_all.cpp index 91142a1df..66179cb46 100644 --- a/src/rendering/swrenderer/r_all.cpp +++ b/src/rendering/swrenderer/r_all.cpp @@ -34,7 +34,6 @@ #include "things/r_visiblespritelist.cpp" #include "things/r_voxel.cpp" #include "things/r_wallsprite.cpp" -#include "things/r_model.cpp" #include "viewport/r_drawerargs.cpp" #include "viewport/r_skydrawer.cpp" #include "viewport/r_spandrawer.cpp" diff --git a/src/rendering/swrenderer/r_renderthread.cpp b/src/rendering/swrenderer/r_renderthread.cpp index 4c3e4d2c6..19f016ef9 100644 --- a/src/rendering/swrenderer/r_renderthread.cpp +++ b/src/rendering/swrenderer/r_renderthread.cpp @@ -21,7 +21,7 @@ */ #include -#include "templates.h" + #include "doomdef.h" #include "m_bbox.h" @@ -53,7 +53,6 @@ #include "swrenderer/drawers/r_draw_pal.h" #include "swrenderer/viewport/r_viewport.h" #include "r_memory.h" -#include "common/rendering/polyrenderer/drawers/poly_thread.h" std::pair& R_GetSkyCapColor(FGameTexture* tex); @@ -75,7 +74,6 @@ namespace swrenderer PlaneList.reset(new VisiblePlaneList(this)); DrawSegments.reset(new DrawSegmentList(this)); ClipSegments.reset(new RenderClipSegment()); - Poly.reset(new PolyTriangleThreadData(0, 1, 0, 1, 0, screen->GetHeight())); tc_drawers.reset(new SWTruecolorDrawers(this)); pal_drawers.reset(new SWPalDrawers(this)); } diff --git a/src/rendering/swrenderer/r_renderthread.h b/src/rendering/swrenderer/r_renderthread.h index ba862c775..344b8ee53 100644 --- a/src/rendering/swrenderer/r_renderthread.h +++ b/src/rendering/swrenderer/r_renderthread.h @@ -26,11 +26,9 @@ #include class RenderMemory; -class PolyTriangleThreadData; struct FDynamicLight; EXTERN_CVAR(Bool, r_models); -extern bool r_modelscene; namespace swrenderer { @@ -75,7 +73,6 @@ namespace swrenderer std::unique_ptr ClipSegments; std::unique_ptr Viewport; std::unique_ptr Light; - std::unique_ptr Poly; TArray AddedLightsArray; diff --git a/src/rendering/swrenderer/r_swcolormaps.cpp b/src/rendering/swrenderer/r_swcolormaps.cpp index f488e4e82..a2ca4666d 100644 --- a/src/rendering/swrenderer/r_swcolormaps.cpp +++ b/src/rendering/swrenderer/r_swcolormaps.cpp @@ -45,14 +45,13 @@ #include "c_dispatch.h" #include "sc_man.h" #include "v_text.h" -#include "st_start.h" #include "doomstat.h" #include "v_palette.h" #include "colormatcher.h" #include "r_data/colormaps.h" #include "r_swcolormaps.h" #include "v_video.h" -#include "templates.h" + #include "r_utility.h" #include "swrenderer/r_renderer.h" #include @@ -354,7 +353,7 @@ void SetDefaultColormap (const char *name) // [RH] If using BUILD's palette, generate the colormap if (lump == -1 || fileSystem.CheckNumForFullName("palette.dat") >= 0 || fileSystem.CheckNumForFullName("blood.pal") >= 0) { - Printf ("Make colormap\n"); + DPrintf (DMSG_NOTIFY, "Make colormap\n"); FDynamicColormap foo; foo.Color = 0xFFFFFF; diff --git a/src/rendering/swrenderer/r_swrenderer.cpp b/src/rendering/swrenderer/r_swrenderer.cpp index 66ebb7484..4c2414db5 100644 --- a/src/rendering/swrenderer/r_swrenderer.cpp +++ b/src/rendering/swrenderer/r_swrenderer.cpp @@ -250,7 +250,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *camtex, AActor *viewp CameraLight savedCameraLight = *CameraLight::Instance(); DAngle savedfov = cameraViewpoint.FieldOfView; - R_SetFOV (cameraViewpoint, fov); + R_SetFOV (cameraViewpoint, DAngle::fromDeg(fov)); mScene.RenderViewToCanvas(viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), camtex->bFirstUpdate); diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index f6c58a807..491370dfc 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -39,12 +39,6 @@ #include "d_main.h" #include "v_draw.h" -// [RH] Base blending values (for e.g. underwater) -int BaseBlendR, BaseBlendG, BaseBlendB; -float BaseBlendA; - - - class FSWPaletteTexture : public FImageSource { public: diff --git a/src/rendering/swrenderer/scene/r_3dfloors.cpp b/src/rendering/swrenderer/scene/r_3dfloors.cpp index 8196462f4..c8e9a4521 100644 --- a/src/rendering/swrenderer/scene/r_3dfloors.cpp +++ b/src/rendering/swrenderer/scene/r_3dfloors.cpp @@ -32,7 +32,7 @@ ** */ -#include "templates.h" + #include "doomdef.h" #include "p_local.h" #include "c_dispatch.h" @@ -43,7 +43,7 @@ #include "swrenderer/r_renderthread.h" #include "r_memory.h" -CVAR(Int, r_3dfloors, true, 0); +CVAR(Int, r_3dfloors, 1, 0); namespace swrenderer { diff --git a/src/rendering/swrenderer/scene/r_light.cpp b/src/rendering/swrenderer/scene/r_light.cpp index 5b8a689b2..2e6046ffb 100644 --- a/src/rendering/swrenderer/scene/r_light.cpp +++ b/src/rendering/swrenderer/scene/r_light.cpp @@ -23,7 +23,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -149,7 +149,7 @@ namespace swrenderer bool nolightfade = !foggy && ((viewport->Level()->flags3 & LEVEL3_NOLIGHTFADE)); if (nolightfade) { - return (MAX(255 - lightlevel, 0) * NUMCOLORMAPS) << (FRACBITS - 8); + return (max(255 - lightlevel, 0) * NUMCOLORMAPS) << (FRACBITS - 8); } else { diff --git a/src/rendering/swrenderer/scene/r_light.h b/src/rendering/swrenderer/scene/r_light.h index d14c73b55..8f1d6adcc 100644 --- a/src/rendering/swrenderer/scene/r_light.h +++ b/src/rendering/swrenderer/scene/r_light.h @@ -43,12 +43,12 @@ // Convert a shade and visibility to a clamped colormap index. // Result is not fixed point. // Change R_CalcTiltedLighting() when this changes. -#define GETPALOOKUP(vis,shade) (clamp (((shade)-FLOAT2FIXED(MIN(MAXLIGHTVIS,double(vis))))>>FRACBITS, 0, NUMCOLORMAPS-1)) +#define GETPALOOKUP(vis,shade) (clamp (((shade)-FLOAT2FIXED(min(MAXLIGHTVIS,double(vis))))>>FRACBITS, 0, NUMCOLORMAPS-1)) // Calculate the light multiplier for dc_light/ds_light // This is used instead of GETPALOOKUP when ds_colormap/dc_colormap is set to the base colormap // Returns a value between 0 and 1 in fixed point -#define LIGHTSCALE(vis,shade) FLOAT2FIXED(clamp((FIXED2DBL(shade) - (MIN(MAXLIGHTVIS,double(vis)))) / NUMCOLORMAPS, 0.0, (NUMCOLORMAPS-1)/(double)NUMCOLORMAPS)) +#define LIGHTSCALE(vis,shade) FLOAT2FIXED(clamp((FIXED2DBL(shade) - (min(MAXLIGHTVIS,double(vis)))) / NUMCOLORMAPS, 0.0, (NUMCOLORMAPS-1)/(double)NUMCOLORMAPS)) struct FSWColormap; @@ -82,7 +82,7 @@ namespace swrenderer // The vis value to pass into the GETPALOOKUP or LIGHTSCALE macros double WallVis(double screenZ, bool foggy) const { return WallGlobVis(foggy) / screenZ; } - double SpriteVis(double screenZ, bool foggy) const { return SpriteGlobVis(foggy) / MAX(screenZ, MINZ); } + double SpriteVis(double screenZ, bool foggy) const { return SpriteGlobVis(foggy) / max(screenZ, MINZ); } double FlatPlaneVis(int screenY, double planeheight, bool foggy, RenderViewport *viewport) const { return FlatPlaneGlobVis(foggy) / planeheight * fabs(viewport->CenterY - screenY); } double SlopePlaneGlobVis(bool foggy) const { return (NoLightFade && !foggy) ? 0.0f : TiltVisibility; } diff --git a/src/rendering/swrenderer/scene/r_opaque_pass.cpp b/src/rendering/swrenderer/scene/r_opaque_pass.cpp index 9bb69562c..bcd864d05 100644 --- a/src/rendering/swrenderer/scene/r_opaque_pass.cpp +++ b/src/rendering/swrenderer/scene/r_opaque_pass.cpp @@ -28,7 +28,7 @@ #include -#include "templates.h" + #include "doomdef.h" @@ -46,7 +46,6 @@ #include "swrenderer/things/r_wallsprite.h" #include "swrenderer/things/r_voxel.h" #include "swrenderer/things/r_particle.h" -#include "swrenderer/things/r_model.h" #include "swrenderer/segments/r_clipsegment.h" #include "swrenderer/line/r_wallsetup.h" #include "swrenderer/line/r_farclip_line.h" @@ -87,7 +86,7 @@ namespace double line_distance_cull = 1e16; } -CUSTOM_CVAR(Float, r_sprite_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, r_sprite_distance_cull, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (r_sprite_distance_cull > 0.0) { @@ -99,7 +98,7 @@ CUSTOM_CVAR(Float, r_sprite_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } -CUSTOM_CVAR(Float, r_line_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, r_line_distance_cull, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (r_line_distance_cull > 0.0) { @@ -111,7 +110,7 @@ CUSTOM_CVAR(Float, r_line_distance_cull, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) } } -CUSTOM_CVAR(Float, r_model_distance_cull, 1024, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) // Experimental for the moment until a good default is chosen +CUSTOM_CVAR(Float, r_model_distance_cull, 1024.f, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) // Experimental for the moment until a good default is chosen { if (r_model_distance_cull > 0.0) { @@ -606,12 +605,6 @@ namespace swrenderer } Add3DFloorPlanes(sub, frontsector, basecolormap, foggy, adjusted_ceilinglightlevel, adjusted_floorlightlevel); - - // killough 9/18/98: Fix underwater slowdown, by passing real sector - // instead of fake one. Improve sprite lighting by basing sprite - // lightlevels on floor & ceiling lightlevels in the surrounding area. - // [RH] Handle sprite lighting like Duke 3D: If the ceiling is a sky, sprites are lit by - // it, otherwise they are lit by the floor. auto nc = !!(frontsector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); AddSprites(sub->sector, frontsector->GetTexture(sector_t::ceiling) == skyflatnum ? ceilinglightlevel : floorlightlevel, FakeSide, foggy, GetSpriteColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::sprites], nc)); @@ -700,7 +693,7 @@ namespace swrenderer if (!(clip3d->fakeFloor->fakeFloor->flags & FF_RENDERPLANES)) continue; if (clip3d->fakeFloor->fakeFloor->alpha == 0) continue; if (clip3d->fakeFloor->fakeFloor->flags & FF_THISINSIDE && clip3d->fakeFloor->fakeFloor->flags & FF_INVERTSECTOR) continue; - fixed_t fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); + fixed_t fakeAlpha = min(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (clip3d->fakeFloor->validcount != validcount) { clip3d->fakeFloor->validcount = validcount; @@ -764,7 +757,7 @@ namespace swrenderer if (!(clip3d->fakeFloor->fakeFloor->flags & FF_RENDERPLANES)) continue; if (clip3d->fakeFloor->fakeFloor->alpha == 0) continue; if (!(clip3d->fakeFloor->fakeFloor->flags & FF_THISINSIDE) && (clip3d->fakeFloor->fakeFloor->flags & (FF_SWIMMABLE | FF_INVERTSECTOR)) == (FF_SWIMMABLE | FF_INVERTSECTOR)) continue; - fixed_t fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); + fixed_t fakeAlpha = min(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (clip3d->fakeFloor->validcount != validcount) { @@ -939,13 +932,7 @@ namespace swrenderer ThingSprite sprite; int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); - FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); - if (r_modelscene && modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull) - { - DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); - RenderModel::Project(Thread, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); - } - else if (GetThingSprite(thing, sprite)) + if (GetThingSprite(thing, sprite)) { FDynamicColormap *thingColormap = basecolormap; int thinglightlevel = lightlevel; @@ -955,7 +942,16 @@ namespace swrenderer auto nc = !!(thing->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); thingColormap = GetSpriteColorTable(thing->Sector->Colormap, thing->Sector->SpecialColors[sector_t::sprites], nc); } + if (thing->LightLevel > -1) + { + thinglightlevel = thing->LightLevel; + if (thing->flags8 & MF8_ADDLIGHTLEVEL) + { + thinglightlevel += thing->Sector->GetTexture(sector_t::ceiling) == skyflatnum ? thing->Sector->GetCeilingLight() : thing->Sector->GetFloorLight(); + thinglightlevel = clamp(thinglightlevel, 0, 255); + } + } if ((sprite.renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) { RenderWallSprite::Project(Thread, thing, sprite.pos, sprite.tex, sprite.spriteScale, sprite.renderflags, thinglightlevel, foggy, thingColormap); @@ -997,6 +993,7 @@ namespace swrenderer // Don't waste time projecting sprites that are definitely not visible. if (thing == nullptr || (thing->renderflags & RF_INVISIBLE) || + (thing->renderflags & RF_MAYBEINVISIBLE) || !thing->RenderStyle.IsVisible(thing->Alpha) || !thing->IsVisibleToPlayer() || !thing->IsInsideVisibleAngles()) @@ -1004,6 +1001,16 @@ namespace swrenderer return false; } + if ((thing->flags8 & MF8_MASTERNOSEE) && thing->master != nullptr) + { + // Make MASTERNOSEE actors invisible if their master + // is invisible due to viewpoint shenanigans. + if (thing->master->renderflags & RF_MAYBEINVISIBLE) + { + return false; + } + } + // check renderrequired vs ~r_rendercaps, if anything matches we don't support that feature, // check renderhidden vs r_rendercaps, if anything matches we do support that feature and should hide it. if ((!r_debug_disable_vis_filter && !!(thing->RenderRequired & ~r_renderercaps)) || @@ -1016,6 +1023,17 @@ namespace swrenderer if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && !!P_PointOnLineSidePrecise(thing->Pos(), renderportal->CurrentPortal->dst)) return false; + // [Nash] filter visibility in mirrors + bool isInMirror = renderportal != nullptr && renderportal->IsInMirrorRecursively; + if (thing->renderflags2 & RF2_INVISIBLEINMIRRORS && isInMirror) + { + return false; + } + else if (thing->renderflags2 & RF2_ONLYVISIBLEINMIRRORS && !isInMirror) + { + return false; + } + double distanceSquared = (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared(); if (distanceSquared > sprite_distance_cull) return false; @@ -1027,11 +1045,12 @@ 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.spritenum = thing->sprite; sprite.tex = nullptr; sprite.voxel = nullptr; - sprite.spriteScale = thing->Scale; + sprite.spriteScale = DVector2(thing->Scale.X, thing->Scale.Y); sprite.renderflags = thing->renderflags; if (thing->player != nullptr) @@ -1055,16 +1074,16 @@ namespace swrenderer if (sprframe->Texture[0] == sprframe->Texture[1]) { if (thing->flags7 & MF7_SPRITEANGLE) - rot = (thing->SpriteAngle + 45.0 / 2 * 9).BAMs() >> 28; + rot = (thing->SpriteAngle + DAngle::fromDeg(45.0 / 2 * 9)).BAMs() >> 28; else - rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + 45.0 / 2 * 9).BAMs() >> 28; + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + DAngle::fromDeg(45.0 / 2 * 9)).BAMs() >> 28; } else { if (thing->flags7 & MF7_SPRITEANGLE) - rot = (thing->SpriteAngle + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (thing->SpriteAngle + DAngle::fromDeg(45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; else - rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + DAngle::fromDeg(45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; } sprite.picnum = sprframe->Texture[rot]; if (sprframe->Flip & (1 << rot)) diff --git a/src/rendering/swrenderer/scene/r_portal.cpp b/src/rendering/swrenderer/scene/r_portal.cpp index f0c914671..6135c3f61 100644 --- a/src/rendering/swrenderer/scene/r_portal.cpp +++ b/src/rendering/swrenderer/scene/r_portal.cpp @@ -24,7 +24,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "d_net.h" #include "doomstat.h" @@ -46,7 +46,6 @@ #include "v_palette.h" #include "po_man.h" #include "p_effect.h" -#include "st_start.h" #include "v_font.h" #include "r_data/colormaps.h" #include "p_maputl.h" @@ -330,9 +329,9 @@ namespace swrenderer DAngle startang = viewpoint.Angles.Yaw; DVector3 startpos = viewpoint.Pos; DVector3 savedpath[2] = { viewpoint.Path[0], viewpoint.Path[1] }; - ActorRenderFlags savedvisibility = viewpoint.camera ? viewpoint.camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0); + ActorRenderFlags savedvisibility = viewpoint.camera ? viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0); - viewpoint.camera->renderflags &= ~RF_INVISIBLE; + viewpoint.camera->renderflags &= ~RF_MAYBEINVISIBLE; CurrentPortalUniq++; @@ -340,6 +339,8 @@ namespace swrenderer if (pds->mirror) { + IsInMirrorRecursively = true; + //vertex_t *v1 = ds->curline->v1; vertex_t *v1 = pds->src->v1; @@ -389,7 +390,7 @@ namespace swrenderer if (dist1 + dist2 < distp + 1) { - viewpoint.camera->renderflags |= RF_INVISIBLE; + viewpoint.camera->renderflags |= RF_MAYBEINVISIBLE; } } } @@ -436,7 +437,7 @@ namespace swrenderer Thread->OpaquePass->RenderScene(Thread->Viewport->Level()); Thread->Clip3D->ResetClip(); // reset clips (floor/ceiling) - if (!savedvisibility && viewpoint.camera) viewpoint.camera->renderflags &= ~RF_INVISIBLE; + if (!savedvisibility && viewpoint.camera) viewpoint.camera->renderflags &= ~RF_MAYBEINVISIBLE; Thread->PlaneList->Render(); RenderPlanePortals(); @@ -466,6 +467,7 @@ namespace swrenderer CurrentPortal = prevpds; MirrorFlags = prevmf; + IsInMirrorRecursively = false; viewpoint.Angles.Yaw = startang; viewpoint.Pos = startpos; viewpoint.Path[0] = savedpath[0]; diff --git a/src/rendering/swrenderer/scene/r_portal.h b/src/rendering/swrenderer/scene/r_portal.h index 34a49a4ff..cf1f075d5 100644 --- a/src/rendering/swrenderer/scene/r_portal.h +++ b/src/rendering/swrenderer/scene/r_portal.h @@ -48,6 +48,10 @@ namespace swrenderer int WindowRight = 0; uint16_t MirrorFlags = 0; + // [Nash] this is set when first entering a mirror portal, and is unset when leaving the final mirror portal recursion + // Used for the RF2_INVISIBLEINMIRRORS and RF2_ONLYVISIBLEINMIRRORS features + bool IsInMirrorRecursively = false; + PortalDrawseg* CurrentPortal = nullptr; int CurrentPortalUniq = 0; bool CurrentPortalInSkybox = false; diff --git a/src/rendering/swrenderer/scene/r_scene.cpp b/src/rendering/swrenderer/scene/r_scene.cpp index 2558a2f2a..56aa72560 100644 --- a/src/rendering/swrenderer/scene/r_scene.cpp +++ b/src/rendering/swrenderer/scene/r_scene.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "v_draw.h" #include "filesystem.h" #include "doomdef.h" @@ -59,18 +59,12 @@ #include "swrenderer/things/r_playersprite.h" #include -#ifdef WIN32 -void PeekThreadedErrorPane(); -#endif - EXTERN_CVAR(Int, r_clearbuffer) EXTERN_CVAR(Int, r_debug_draw) CVAR(Int, r_scene_multithreaded, 1, 0); CVAR(Bool, r_models, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -bool r_modelscene = false; - namespace swrenderer { cycle_t WallCycles, PlaneCycles, MaskedCycles; @@ -104,18 +98,6 @@ namespace swrenderer ActiveRatio(width, height, &trueratio); viewport->SetViewport(player->camera->Level, MainThread(), width, height, trueratio); - /*r_modelscene = r_models && Models.Size() > 0; - if (r_modelscene) - { - if (!DepthStencil || DepthStencil->Width() != viewport->RenderTarget->GetWidth() || DepthStencil->Height() != viewport->RenderTarget->GetHeight()) - { - DepthStencil.reset(); - DepthStencil.reset(new PolyDepthStencil(viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight())); - } - PolyTriangleDrawer::SetViewport(MainThread()->DrawQueue, 0, 0, viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight(), viewport->RenderTarget, DepthStencil.get()); - PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); - }*/ - if (r_clearbuffer != 0 || r_debug_draw != 0) { if (!viewport->RenderTarget->IsBgra()) @@ -162,24 +144,19 @@ namespace swrenderer R_UpdateFuzzPosFrameStart(); - if (r_modelscene) - MainThread()->Viewport->SetupPolyViewport(MainThread()); - FRenderViewpoint origviewpoint = MainThread()->Viewport->viewpoint; ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags; // Never draw the player unless in chasecam mode if (!MainThread()->Viewport->viewpoint.showviewer) { - MainThread()->Viewport->viewpoint.camera->renderflags |= RF_INVISIBLE; + MainThread()->Viewport->viewpoint.camera->renderflags |= RF_MAYBEINVISIBLE; } RenderThreadSlices(); // Mirrors fail to restore the original viewpoint -- we need it for the HUD weapon to draw correctly. MainThread()->Viewport->viewpoint = origviewpoint; - if (r_modelscene) - MainThread()->Viewport->SetupPolyViewport(MainThread()); if (renderPlayerSprites) RenderPSprites(); @@ -239,12 +216,7 @@ namespace swrenderer finished_threads++; if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); })) { -#ifdef WIN32 - PeekThreadedErrorPane(); -#endif - // Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing - int *threadCrashed = nullptr; - *threadCrashed = 0xdeadbeef; + I_FatalError("Render threads did not finish within 5 seconds!"); } finished_threads = 0; } @@ -268,12 +240,6 @@ namespace swrenderer thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible thread->Portal->SetMainPortal(); - /*if (r_modelscene && thread->MainThread) - PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); - - PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget, DepthStencil.get()); - PolyTriangleDrawer::SetScissor(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight);*/ - // Cull things outside the range seen by this thread VisibleSegmentRenderer visitor; if (thread->X1 > 0) @@ -397,14 +363,6 @@ namespace swrenderer viewwindowy = y; viewactive = true; viewport->SetViewport(actor->Level, MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); - if (r_modelscene) - { - if (!DepthStencil || DepthStencil->Width() != viewport->RenderTarget->GetWidth() || DepthStencil->Height() != viewport->RenderTarget->GetHeight()) - { - DepthStencil.reset(); - DepthStencil.reset(new PolyDepthStencil(viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight())); - } - } // Render: RenderActorView(actor, false, dontmaplines); @@ -430,7 +388,7 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////// - ADD_STAT(fps) + ADD_STAT(swfps) { FString out; out.Format("frame=%04.1f ms walls=%04.1f ms planes=%04.1f ms masked=%04.1f ms", @@ -441,7 +399,7 @@ namespace swrenderer static double f_acc, w_acc, p_acc, m_acc; static int acc_c; - ADD_STAT(fps_accumulated) + ADD_STAT(swfps_accumulated) { f_acc += FrameCycles.TimeMS(); w_acc += WallCycles.TimeMS(); diff --git a/src/rendering/swrenderer/scene/r_scene.h b/src/rendering/swrenderer/scene/r_scene.h index c5fa8e959..035d12133 100644 --- a/src/rendering/swrenderer/scene/r_scene.h +++ b/src/rendering/swrenderer/scene/r_scene.h @@ -32,8 +32,6 @@ extern cycle_t FrameCycles; -class PolyDepthStencil; - namespace swrenderer { extern cycle_t WallCycles, PlaneCycles, MaskedCycles, DrawerWaitCycles; @@ -69,7 +67,6 @@ namespace swrenderer bool dontmaplines = false; int clearcolor = 0; - std::unique_ptr DepthStencil; std::vector> Threads; std::mutex start_mutex; std::condition_variable start_condition; diff --git a/src/rendering/swrenderer/scene/r_translucent_pass.cpp b/src/rendering/swrenderer/scene/r_translucent_pass.cpp index 9d83549d0..101f53ef7 100644 --- a/src/rendering/swrenderer/scene/r_translucent_pass.cpp +++ b/src/rendering/swrenderer/scene/r_translucent_pass.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" diff --git a/src/rendering/swrenderer/segments/r_clipsegment.cpp b/src/rendering/swrenderer/segments/r_clipsegment.cpp index 3afb4bab3..b08cab770 100644 --- a/src/rendering/swrenderer/segments/r_clipsegment.cpp +++ b/src/rendering/swrenderer/segments/r_clipsegment.cpp @@ -20,7 +20,7 @@ //----------------------------------------------------------------------------- #include -#include "templates.h" + #include "doomdef.h" #include "m_bbox.h" diff --git a/src/rendering/swrenderer/segments/r_drawsegment.cpp b/src/rendering/swrenderer/segments/r_drawsegment.cpp index fd7517d72..6905ebf44 100644 --- a/src/rendering/swrenderer/segments/r_drawsegment.cpp +++ b/src/rendering/swrenderer/segments/r_drawsegment.cpp @@ -20,7 +20,7 @@ //----------------------------------------------------------------------------- #include -#include "templates.h" + #include "doomdef.h" #include "m_bbox.h" @@ -104,21 +104,21 @@ namespace swrenderer DrawSegmentGroup group; group.BeginIndex = index; - group.EndIndex = MIN(index + groupSize, SegmentsCount()); + group.EndIndex = min(index + groupSize, SegmentsCount()); group.x1 = ds->x1; group.x2 = ds->x2; - group.neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2); - group.fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2); + group.neardepth = min(ds->WallC.sz1, ds->WallC.sz2); + group.fardepth = max(ds->WallC.sz1, ds->WallC.sz2); for (unsigned int groupIndex = group.BeginIndex + 1; groupIndex < group.EndIndex; groupIndex++) { ds = Segment(groupIndex); - group.x1 = MIN(group.x1, ds->x1); - group.x2 = MAX(group.x2, ds->x2); - group.neardepth = MIN(group.neardepth, ds->WallC.sz1); - group.neardepth = MIN(group.neardepth, ds->WallC.sz2); - group.fardepth = MAX(ds->WallC.sz1, group.fardepth); - group.fardepth = MAX(ds->WallC.sz2, group.fardepth); + group.x1 = min(group.x1, ds->x1); + group.x2 = max(group.x2, ds->x2); + group.neardepth = min(group.neardepth, ds->WallC.sz1); + group.neardepth = min(group.neardepth, ds->WallC.sz2); + group.fardepth = max(ds->WallC.sz1, group.fardepth); + group.fardepth = max(ds->WallC.sz2, group.fardepth); } for (int x = group.x1; x < group.x2; x++) diff --git a/src/rendering/swrenderer/segments/r_portalsegment.cpp b/src/rendering/swrenderer/segments/r_portalsegment.cpp index 6f69c7869..dbdd7892d 100644 --- a/src/rendering/swrenderer/segments/r_portalsegment.cpp +++ b/src/rendering/swrenderer/segments/r_portalsegment.cpp @@ -20,7 +20,7 @@ //----------------------------------------------------------------------------- #include -#include "templates.h" + #include "doomdef.h" #include "m_bbox.h" diff --git a/src/rendering/swrenderer/textures/r_swtexture.cpp b/src/rendering/swrenderer/textures/r_swtexture.cpp index 662c12d57..1336abfd2 100644 --- a/src/rendering/swrenderer/textures/r_swtexture.cpp +++ b/src/rendering/swrenderer/textures/r_swtexture.cpp @@ -364,8 +364,8 @@ void FSoftwareTexture::CreatePixelsBgraWithMipmaps() int buffersize = 0; for (int i = 0; i < levels; i++) { - int w = MAX(GetPhysicalWidth() >> i, 1); - int h = MAX(GetPhysicalHeight() >> i, 1); + int w = max(GetPhysicalWidth() >> i, 1); + int h = max(GetPhysicalHeight() >> i, 1); buffersize += w * h; } PixelsBgra.Resize(buffersize); @@ -379,7 +379,7 @@ int FSoftwareTexture::MipmapLevels() int heightbits = 0; while ((GetPhysicalHeight() >> heightbits) != 0) heightbits++; - return MAX(widthbits, heightbits); + return max(widthbits, heightbits); } //========================================================================== @@ -430,20 +430,20 @@ void FSoftwareTexture::GenerateBgraMipmaps() Color4f *dest = src + GetPhysicalWidth() * GetPhysicalHeight(); for (int i = 1; i < levels; i++) { - int srcw = MAX(GetPhysicalWidth() >> (i - 1), 1); - int srch = MAX(GetPhysicalHeight() >> (i - 1), 1); - int w = MAX(GetPhysicalWidth() >> i, 1); - int h = MAX(GetPhysicalHeight() >> i, 1); + int srcw = max(GetPhysicalWidth() >> (i - 1), 1); + int srch = max(GetPhysicalHeight() >> (i - 1), 1); + int w = max(GetPhysicalWidth() >> i, 1); + int h = max(GetPhysicalHeight() >> i, 1); // Downscale for (int x = 0; x < w; x++) { int sx0 = x * 2; - int sx1 = MIN((x + 1) * 2, srcw - 1); + int sx1 = min((x + 1) * 2, srcw - 1); for (int y = 0; y < h; y++) { int sy0 = y * 2; - int sy1 = MIN((y + 1) * 2, srch - 1); + int sy1 = min((y + 1) * 2, srch - 1); Color4f src00 = src[sy0 + sx0 * srch]; Color4f src01 = src[sy1 + sx0 * srch]; @@ -493,14 +493,14 @@ void FSoftwareTexture::GenerateBgraMipmaps() uint32_t *dest = PixelsBgra.Data() + GetPhysicalWidth() * GetPhysicalHeight(); for (int i = 1; i < levels; i++) { - int w = MAX(GetPhysicalWidth() >> i, 1); - int h = MAX(GetPhysicalHeight() >> i, 1); + int w = max(GetPhysicalWidth() >> i, 1); + int h = max(GetPhysicalHeight() >> i, 1); for (int j = 0; j < w * h; j++) { - uint32_t a = (uint32_t)clamp(powf(MAX(src[j].a, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); - uint32_t r = (uint32_t)clamp(powf(MAX(src[j].r, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); - uint32_t g = (uint32_t)clamp(powf(MAX(src[j].g, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); - uint32_t b = (uint32_t)clamp(powf(MAX(src[j].b, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); + uint32_t a = (uint32_t)clamp(powf(max(src[j].a, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); + uint32_t r = (uint32_t)clamp(powf(max(src[j].r, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); + uint32_t g = (uint32_t)clamp(powf(max(src[j].g, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); + uint32_t b = (uint32_t)clamp(powf(max(src[j].b, 0.0f), 1.0f / 2.2f) * 255.0f + 0.5f, 0.0f, 255.0f); dest[j] = (a << 24) | (r << 16) | (g << 8) | b; } src += w * h; diff --git a/src/rendering/swrenderer/textures/warpbuffer.h b/src/rendering/swrenderer/textures/warpbuffer.h index 114b8af00..778706850 100644 --- a/src/rendering/swrenderer/textures/warpbuffer.h +++ b/src/rendering/swrenderer/textures/warpbuffer.h @@ -43,7 +43,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)); + TYPE *buffer = (TYPE *)alloca(sizeof(TYPE) * max(width, height)); // [mxd] Rewrote to fix animation for NPo2 textures unsigned timebase = unsigned(time * Speed * 32 / 28); for (y = height - 1; y >= 0; y--) diff --git a/src/rendering/swrenderer/textures/warptexture.cpp b/src/rendering/swrenderer/textures/warptexture.cpp index ce3cb2f52..10e51ddb0 100644 --- a/src/rendering/swrenderer/textures/warptexture.cpp +++ b/src/rendering/swrenderer/textures/warptexture.cpp @@ -126,20 +126,20 @@ void FWarpTexture::GenerateBgraMipmapsFast() int levels = MipmapLevels(); for (int i = 1; i < levels; i++) { - int srcw = MAX(GetPhysicalWidth() >> (i - 1), 1); - int srch = MAX(GetPhysicalHeight() >> (i - 1), 1); - int w = MAX(GetPhysicalWidth() >> i, 1); - int h = MAX(GetPhysicalHeight() >> i, 1); + int srcw = max(GetPhysicalWidth() >> (i - 1), 1); + int srch = max(GetPhysicalHeight() >> (i - 1), 1); + int w = max(GetPhysicalWidth() >> i, 1); + int h = max(GetPhysicalHeight() >> i, 1); for (int x = 0; x < w; x++) { int sx0 = x * 2; - int sx1 = MIN((x + 1) * 2, srcw - 1); + int sx1 = min((x + 1) * 2, srcw - 1); for (int y = 0; y < h; y++) { int sy0 = y * 2; - int sy1 = MIN((y + 1) * 2, srch - 1); + int sy1 = min((y + 1) * 2, srch - 1); uint32_t src00 = src[sy0 + sx0 * srch]; uint32_t src01 = src[sy1 + sx0 * srch]; diff --git a/src/rendering/swrenderer/things/r_decal.cpp b/src/rendering/swrenderer/things/r_decal.cpp index ffe06c0a1..533b8876c 100644 --- a/src/rendering/swrenderer/things/r_decal.cpp +++ b/src/rendering/swrenderer/things/r_decal.cpp @@ -21,7 +21,7 @@ #include #include -#include "templates.h" + #include "doomdef.h" #include "doomstat.h" @@ -157,6 +157,8 @@ namespace swrenderer if (x1 >= clipper->x2 || x2 <= clipper->x1) return; + int tier = side_t::mid; + if (drawsegPass) { uint32_t clipMode = decal->RenderFlags & RF_CLIPMASK; @@ -203,6 +205,7 @@ namespace swrenderer break; case RF_CLIPUPPER: + tier = side_t::top; mceilingclip = walltop; mfloorclip = thread->OpaquePass->ceilingclip; break; @@ -211,6 +214,7 @@ namespace swrenderer return; case RF_CLIPLOWER: + tier = side_t::bottom; mceilingclip = thread->OpaquePass->floorclip; mfloorclip = wallbottom; break; @@ -219,7 +223,7 @@ namespace swrenderer // Prepare lighting ProjectedWallLight light; - light.SetColormap(lightsector, curline); + light.SetColormap(lightsector, curline, tier); light.SetLightLeft(thread, WallC); usecolormap = light.GetBaseColormap(); diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp deleted file mode 100644 index 548dc7bab..000000000 --- a/src/rendering/swrenderer/things/r_model.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 -#include "templates.h" -#include "doomdef.h" -#include "sbar.h" -#include "r_data/r_translate.h" -#include "r_model.h" -#include "r_data/r_vanillatrans.h" -#include "actorinlines.h" -#include "i_time.h" -#include "texturemanager.h" -#include "r_memory.h" -#include "swrenderer/r_swcolormaps.h" -#include "swrenderer/viewport/r_viewport.h" -#include "swrenderer/scene/r_light.h" - -namespace swrenderer -{ - void RenderModel::Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) - { - // transform the origin point - double tr_x = x - thread->Viewport->viewpoint.Pos.X; - double tr_y = y - thread->Viewport->viewpoint.Pos.Y; - double tz = tr_x * thread->Viewport->viewpoint.TanCos + tr_y * thread->Viewport->viewpoint.TanSin; - - // thing is behind view plane? - if (tz < MINZ) - return; - - double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos; - - // Flip for mirrors - if (thread->Portal->MirrorFlags & RF_XFLIP) - { - tx = viewwidth - tx - 1; - } - - // too far off the side? - if (fabs(tx / 64) > fabs(tz)) - return; - - RenderModel *vis = thread->FrameMemory->NewObject(x, y, z, smf, actor, float(1 / tz)); - vis->CurrentPortalUniq = thread->Portal->CurrentPortalUniq; - vis->WorldToClip = thread->Viewport->WorldToClip; - vis->MirrorWorldToClip = !!(thread->Portal->MirrorFlags & RF_XFLIP); - thread->SpriteList->Push(vis); - } - - RenderModel::RenderModel(float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, float idepth) : x(x), y(y), z(z), smf(smf), actor(actor) - { - gpos = { x, y, z }; - this->idepth = idepth; - } - - void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) - { -#if 0 - SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip); - - renderer.sector = actor->Sector; - renderer.RenderStyle = actor->RenderStyle; - renderer.RenderAlpha = (float)actor->Alpha; - if (!renderer.RenderStyle.IsVisible(renderer.RenderAlpha)) - return; - - bool foggy = false; - int actualextralight = foggy ? 0 : thread->Viewport->viewpoint.extralight << 4; - bool fullbrightSprite = ((actor->renderflags & RF_FULLBRIGHT) || (actor->flags5 & MF5_BRIGHT)); - renderer.lightlevel = fullbrightSprite ? 255 : actor->Sector->lightlevel + actualextralight; - renderer.visibility = thread->Light->SpriteGlobVis(foggy); - - renderer.fillcolor = actor->fillcolor; - renderer.Translation = actor->Translation; - - renderer.AddLights(actor); - RenderModel(&renderer, x, y, z, smf, actor, r_viewpoint.TicFrac); - PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); -#endif - } - - ///////////////////////////////////////////////////////////////////////////// - - static bool isBright(DPSprite *psp) - { - if (psp != nullptr && psp->GetState() != nullptr) - { - bool disablefullbright = false; - FTextureID lump = sprites[psp->GetSprite()].GetSpriteFrame(psp->GetFrame(), 0, 0., nullptr); - if (lump.isValid()) - { - auto tex = TexMan.GetGameTexture(lump, true); - if (tex) disablefullbright = tex->isFullbrightDisabled(); - } - return psp->GetState()->GetFullbright() && !disablefullbright; - } - return false; - } - - void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy) - { -#if 0 - SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false); - - AActor *playermo = players[consoleplayer].camera; - auto rs = psp->GetRenderStyle(playermo->RenderStyle, playermo->Alpha); - renderer.sector = playermo->Sector; - renderer.RenderStyle = rs.first; - renderer.RenderAlpha = rs.second; - if (psp->Flags & PSPF_FORCEALPHA) renderer.RenderAlpha = 0.0f; - if (!renderer.RenderStyle.IsVisible(renderer.RenderAlpha)) - return; - - bool foggy = false; - int actualextralight = foggy ? 0 : thread->Viewport->viewpoint.extralight << 4; - bool fullbrightSprite = isBright(psp); - renderer.lightlevel = fullbrightSprite ? 255 : playermo->Sector->lightlevel + actualextralight; - renderer.visibility = thread->Light->SpriteGlobVis(foggy); - - PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; - ThingColor.a = 255; - - renderer.fillcolor = fullbrightSprite ? ThingColor : ThingColor.Modulate(playermo->Sector->SpecialColors[sector_t::sprites]); - uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0; - if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = playermo->Translation; - renderer.Translation = trans; - - RenderHUDModel(&renderer, psp, ofsx, ofsy); - PolyTriangleDrawer::SetModelVertexShader(thread->DrawQueue, -1, -1, 0.0f); -#endif - } - - ///////////////////////////////////////////////////////////////////////////// - -#if 0 - SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) - : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) - { - static PolySWInputAssembly input; - PolyTriangleDrawer::SetInputAssembly(thread->DrawQueue, &input); - } - - void SWModelRenderer::AddLights(AActor *actor) - { - if (r_dynlights && actor) - { - auto &addedLights = Thread->AddedLightsArray; - - addedLights.Clear(); - - float x = (float)actor->X(); - float y = (float)actor->Y(); - float z = (float)actor->Center(); - float actorradius = (float)actor->RenderRadius(); - float radiusSquared = actorradius * actorradius; - - BSPWalkCircle(actor->Level, x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor - { - FLightNode * node = subsector->section->lighthead; - while (node) // check all lights touching a subsector - { - FDynamicLight *light = node->lightsource; - if (light->ShouldLightActor(actor)) - { - int group = subsector->sector->PortalGroup; - DVector3 pos = light->PosRelative(group); - float radius = (float)(light->GetRadius() + actorradius); - double dx = pos.X - x; - double dy = pos.Y - y; - double dz = pos.Z - z; - double distSquared = dx * dx + dy * dy + dz * dz; - if (distSquared < radius * radius) // Light and actor touches - { - if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector - { - addedLights.Push(light); - } - } - } - node = node->nextLight; - } - }); - - NumLights = addedLights.Size(); - Lights = Thread->FrameMemory->AllocMemory(NumLights); - for (int i = 0; i < NumLights; i++) - { - FDynamicLight *lightsource = addedLights[i]; - - bool is_point_light = lightsource->IsAttenuated(); - - uint32_t red = lightsource->GetRed(); - uint32_t green = lightsource->GetGreen(); - uint32_t blue = lightsource->GetBlue(); - - PolyLight &light = Lights[i]; - light.x = (float)lightsource->X(); - light.y = (float)lightsource->Y(); - light.z = (float)lightsource->Z(); - light.radius = 256.0f / lightsource->GetRadius(); - light.color = (red << 16) | (green << 8) | blue; - if (is_point_light) - light.radius = -light.radius; - } - } - } - - void SWModelRenderer::BeginDrawModel(FRenderStyale style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) - { - const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); - - ClipTop = {}; - ClipBottom = {}; - if (Clip3DFloor.clipTop || Clip3DFloor.clipBottom) - { - // Convert 3d floor clipping planes from world to object space - - VSMatrix inverseMat; - const_cast(objectToWorldMatrix).inverseMatrix(inverseMat); - Mat4f worldToObject; - inverseMat.copy(worldToObject.Matrix); - - // Note: Y and Z is swapped here - - Vec4f one = worldToObject * Vec4f(0.0f, 1.0f, 0.0f, 1.0f); - Vec4f zero = worldToObject * Vec4f(0.0f, 0.0f, 0.0f, 1.0f); - Vec4f up = { one.X - zero.X, one.Y - zero.Y, one.Z - zero.Z }; - - if (Clip3DFloor.clipTop) - { - Vec4f p = worldToObject * Vec4f(0.0f, Clip3DFloor.sclipTop, 0.0f, 1.0f); - float d = up.X * p.X + up.Y * p.Y + up.Z * p.Z; - ClipTop = { -up.X, -up.Y, -up.Z, d }; - } - - if (Clip3DFloor.clipBottom) - { - Vec4f p = worldToObject * Vec4f(0.0f, Clip3DFloor.sclipBottom, 0.0f, 1.0f); - float d = up.X * p.X + up.Y * p.Y + up.Z * p.Z; - ClipBottom = { up.X, up.Y, up.Z, -d }; - } - } - - SetTransform(); - - if (style == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES)) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip)); - } - - void SWModelRenderer::EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) - { - if (style == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES)) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true); - } - - IModelVertexBuffer *SWModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe) - { - return new SWModelVertexBuffer(needindex, singleframe); - } - - VSMatrix SWModelRenderer::GetViewToWorldMatrix() - { - // Calculate the WorldToView matrix as it would have looked like without yshearing: - const auto &Viewpoint = Thread->Viewport->viewpoint; - auto Level = Thread->Viewport->Level(); - const auto &Viewwindow = Thread->Viewport->viewwindow; - double radPitch = Viewpoint.Angles.Pitch.Normalized180().Radians(); - double angx = cos(radPitch); - double angy = sin(radPitch) * Level->info->pixelstretch; - double alen = sqrt(angx*angx + angy*angy); - float adjustedPitch = (float)asin(angy / alen); - float adjustedViewAngle = (float)(Viewpoint.Angles.Yaw - 90).Radians(); - float ratio = Viewwindow.WidescreenRatio; - float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio; - float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees); - Mat4f altWorldToView = - Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) * - Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) * - Mat4f::Scale(1.0f, Level->info->pixelstretch, 1.0f) * - Mat4f::SwapYZ() * - Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z); - - Mat4f swapYZ = Mat4f::Null(); - swapYZ.Matrix[0 + 0 * 4] = 1.0f; - swapYZ.Matrix[1 + 2 * 4] = 1.0f; - swapYZ.Matrix[2 + 1 * 4] = 1.0f; - swapYZ.Matrix[3 + 3 * 4] = 1.0f; - - VSMatrix worldToView; - worldToView.loadMatrix((altWorldToView * swapYZ).Matrix); - - VSMatrix objectToWorld; - worldToView.inverseMatrix(objectToWorld); - return objectToWorld; - } - - void SWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored) - { - const_cast(objectToWorldMatrix).copy(ObjectToWorld.Matrix); - ClipTop = {}; - ClipBottom = {}; - SetTransform(); - PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, true); - - if (style == LegacyRenderStyles[STYLE_Normal]) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip)); - } - - void SWModelRenderer::EndDrawHUDModel(FRenderStyle style) - { - PolyTriangleDrawer::SetWeaponScene(Thread->DrawQueue, false); - - if (style == LegacyRenderStyles[STYLE_Normal]) - PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true); - } - - void SWModelRenderer::SetInterpolation(double interpolation) - { - InterpolationFactor = (float)interpolation; - } - - void SWModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int translation) - { - SkinTexture = skin; - } - - void SWModelRenderer::SetTransform() - { - Mat4f swapYZ = Mat4f::Null(); - swapYZ.Matrix[0 + 0 * 4] = 1.0f; - swapYZ.Matrix[1 + 2 * 4] = 1.0f; - swapYZ.Matrix[2 + 1 * 4] = 1.0f; - swapYZ.Matrix[3 + 3 * 4] = 1.0f; - ObjectToWorld = swapYZ * ObjectToWorld; - - PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject((*WorldToClip) * ObjectToWorld), Thread->FrameMemory->NewObject(ObjectToWorld)); - } - - void SWModelRenderer::DrawArrays(int start, int count) - { - PolyDrawArgs args; - auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); - args.SetLights(Lights, NumLights); - args.SetNormal(FVector3(0.0f, 0.0f, 0.0f)); - args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture->GetSoftwareTexture(), fullbrightSprite); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - args.SetClipPlane(0, PolyClipPlane()); - args.SetClipPlane(1, ClipTop); - args.SetClipPlane(2, ClipBottom); - - PolyTriangleDrawer::PushDrawArgs(Thread->DrawQueue, args); - PolyTriangleDrawer::Draw(Thread->DrawQueue, start, count); - } - - void SWModelRenderer::DrawElements(int numIndices, size_t offset) - { - PolyDrawArgs args; - auto nc = !!(sector->Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); - args.SetLight(GetSpriteColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], nc), lightlevel, visibility, fullbrightSprite); - args.SetLights(Lights, NumLights); - args.SetNormal(FVector3(0.0f, 0.0f, 0.0f)); - args.SetStyle(RenderStyle, RenderAlpha, fillcolor, Translation, SkinTexture->GetSoftwareTexture(), fullbrightSprite); - args.SetDepthTest(true); - args.SetWriteDepth(true); - args.SetWriteStencil(false); - args.SetClipPlane(0, PolyClipPlane()); - args.SetClipPlane(1, ClipTop); - args.SetClipPlane(2, ClipBottom); - - PolyTriangleDrawer::PushDrawArgs(Thread->DrawQueue, args); - PolyTriangleDrawer::DrawIndexed(Thread->DrawQueue, static_cast(offset / sizeof(unsigned int)), numIndices); - } - - ///////////////////////////////////////////////////////////////////////////// - - SWModelVertexBuffer::SWModelVertexBuffer(bool needindex, bool singleframe) - { - } - - SWModelVertexBuffer::~SWModelVertexBuffer() - { - } - - FModelVertex *SWModelVertexBuffer::LockVertexBuffer(unsigned int size) - { - mVertexBuffer.Resize(size); - return &mVertexBuffer[0]; - } - - void SWModelVertexBuffer::UnlockVertexBuffer() - { - } - - unsigned int *SWModelVertexBuffer::LockIndexBuffer(unsigned int size) - { - mIndexBuffer.Resize(size); - return &mIndexBuffer[0]; - } - - void SWModelVertexBuffer::UnlockIndexBuffer() - { - } - - void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) - { - SWModelRenderer *swrenderer = (SWModelRenderer *)renderer; - - if (mVertexBuffer.Size() > 0) - PolyTriangleDrawer::SetVertexBuffer(swrenderer->Thread->DrawQueue, &mVertexBuffer[0]); - if (mIndexBuffer.Size() > 0) - PolyTriangleDrawer::SetIndexBuffer(swrenderer->Thread->DrawQueue, &mIndexBuffer[0]); - - PolyTriangleDrawer::SetModelVertexShader(swrenderer->Thread->DrawQueue, frame1, frame2, swrenderer->InterpolationFactor); - } -#endif -} diff --git a/src/rendering/swrenderer/things/r_model.h b/src/rendering/swrenderer/things/r_model.h deleted file mode 100644 index 4c0c5a342..000000000 --- a/src/rendering/swrenderer/things/r_model.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -** Polygon Doom software renderer -** Copyright (c) 2016 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 "polyrenderer/drawers/poly_triangle.h" -#include "matrix.h" -#include "models.h" -#include "swrenderer/r_renderthread.h" -#include "swrenderer/things/r_visiblesprite.h" - -struct PolyLight; - -namespace swrenderer -{ - void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy); - - class RenderModel : public VisibleSprite - { - public: - RenderModel(float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, float idepth); - - static void Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); - - protected: - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; - bool IsModel() const override { return true; } - - private: - float x, y, z; - FSpriteModelFrame *smf; - AActor *actor; - VSMatrix WorldToClip; - bool MirrorWorldToClip; - }; - -#if 0 - class SWModelRenderer : public FModelRenderer - { - public: - SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip); - - void AddLights(AActor *actor); - - ModelRendererType GetType() const override { return SWModelRendererType; } - - void BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override; - void EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) 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 SetInterpolation(double interpolation) override; - void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override; - void DrawArrays(int start, int count) override; - void DrawElements(int numIndices, size_t offset) override; - - void SetTransform(); - - RenderThread *Thread = nullptr; - Fake3DTranslucent Clip3DFloor; - - FRenderStyle RenderStyle; - float RenderAlpha; - sector_t *sector; - bool fullbrightSprite; - int lightlevel; - double visibility; - uint32_t fillcolor; - uint32_t Translation; - - Mat4f ObjectToWorld; - PolyClipPlane ClipTop, ClipBottom; - FTexture *SkinTexture = nullptr; - float InterpolationFactor = 0.0; - Mat4f *WorldToClip = nullptr; - bool MirrorWorldToClip = false; - PolyLight *Lights = nullptr; - int NumLights = 0; - }; - - class SWModelVertexBuffer : public IModelVertexBuffer - { - public: - SWModelVertexBuffer(bool needindex, bool singleframe); - ~SWModelVertexBuffer(); - - FModelVertex *LockVertexBuffer(unsigned int size) override; - void UnlockVertexBuffer() override; - - unsigned int *LockIndexBuffer(unsigned int size) override; - void UnlockIndexBuffer() override; - - void SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) override; - - private: - TArray mVertexBuffer; - TArray mIndexBuffer; - }; -#endif -} diff --git a/src/rendering/swrenderer/things/r_particle.cpp b/src/rendering/swrenderer/things/r_particle.cpp index 6e9f2b00e..23a859c0e 100644 --- a/src/rendering/swrenderer/things/r_particle.cpp +++ b/src/rendering/swrenderer/things/r_particle.cpp @@ -23,9 +23,10 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" +#include "i_interface.h" #include "filesystem.h" #include "c_console.h" @@ -120,8 +121,8 @@ namespace swrenderer // calculate edges of the shape double psize = particle->size / 8.0; - x1 = MAX(renderportal->WindowLeft, thread->Viewport->viewwindow.centerx + xs_RoundToInt((tx - psize) * xscale)); - x2 = MIN(renderportal->WindowRight, thread->Viewport->viewwindow.centerx + xs_RoundToInt((tx + psize) * xscale)); + x1 = max(renderportal->WindowLeft, thread->Viewport->viewwindow.centerx + xs_RoundToInt((tx - psize) * xscale)); + x2 = min(renderportal->WindowRight, thread->Viewport->viewwindow.centerx + xs_RoundToInt((tx + psize) * xscale)); if (x1 >= x2) return; @@ -285,7 +286,7 @@ namespace swrenderer if (ds->drawsegclip.CurrentPortalUniq == CurrentPortalUniq) { RenderDrawSegment renderer(thread); - renderer.Render(ds, MAX(ds->x1, x1), MIN(ds->x2, x2), clip3DFloor); + renderer.Render(ds, max(ds->x1, x1), min(ds->x2, x2), clip3DFloor); } } } diff --git a/src/rendering/swrenderer/things/r_playersprite.cpp b/src/rendering/swrenderer/things/r_playersprite.cpp index f1fc735ab..87ae07496 100644 --- a/src/rendering/swrenderer/things/r_playersprite.cpp +++ b/src/rendering/swrenderer/things/r_playersprite.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" @@ -97,8 +97,6 @@ namespace swrenderer (r_deathcamera && Thread->Viewport->viewpoint.camera->health <= 0)) return; - renderHUDModel = r_modelscene && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); - FDynamicColormap *basecolormap; CameraLight *cameraLight = CameraLight::Instance(); auto nc = !!(Thread->Viewport->Level()->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING); @@ -256,16 +254,11 @@ namespace swrenderer sy += wy; } - if (renderHUDModel) - { - RenderHUDModel(Thread, pspr, (float)sx, (float)sy); - return; - } - auto viewport = Thread->Viewport.get(); double pspritexscale = viewport->viewwindow.centerxwide / 160.0; - double pspriteyscale = pspritexscale * viewport->BaseYaspectMul * ((double)SCREENHEIGHT / SCREENWIDTH) * r_viewwindow.WidescreenRatio; + double pspriteyscale = pspritexscale * pspr->baseScale.Y * ((double)SCREENHEIGHT / SCREENWIDTH) * r_viewwindow.WidescreenRatio; + pspritexscale *= pspr->baseScale.X; // [XA] don't accidentally apply this to the Y calculation above; math be weird double pspritexiscale = 1 / pspritexscale; int tleft = tex->GetDisplayLeftOffset(0); @@ -292,7 +285,8 @@ namespace swrenderer vis.renderflags = owner->renderflags; FSoftwareTexture* stex = GetSoftwareTexture(tex); - vis.texturemid = (BASEYCENTER - sy) * stex->GetScale().Y + stex->GetTopOffset(0); + double textureadj = (120.0f / pspr->baseScale.Y) - BASEYCENTER; // [XA] scale relative to weapon baseline + vis.texturemid = (BASEYCENTER - sy - textureadj) * stex->GetScale().Y + stex->GetTopOffset(0); // Force it to use software rendering when drawing to a canvas texture. bool renderToCanvas = viewport->RenderingToCanvas; diff --git a/src/rendering/swrenderer/things/r_playersprite.h b/src/rendering/swrenderer/things/r_playersprite.h index 494e693f2..b32f0bf8e 100644 --- a/src/rendering/swrenderer/things/r_playersprite.h +++ b/src/rendering/swrenderer/things/r_playersprite.h @@ -92,11 +92,10 @@ namespace swrenderer private: void RenderSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, int lightlevel, FDynamicColormap *basecolormap, bool foggy); - enum { BASEXCENTER = 160 }; - enum { BASEYCENTER = 100 }; + static constexpr int BASEXCENTER = 160; + static constexpr int BASEYCENTER = 100; TArray AcceleratedSprites; sector_t tempsec; - bool renderHUDModel = false; }; } diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 3602afa11..39c2e82e3 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" diff --git a/src/rendering/swrenderer/things/r_visiblesprite.cpp b/src/rendering/swrenderer/things/r_visiblesprite.cpp index 16e3435c5..1878008cd 100644 --- a/src/rendering/swrenderer/things/r_visiblesprite.cpp +++ b/src/rendering/swrenderer/things/r_visiblesprite.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" @@ -61,8 +61,8 @@ namespace swrenderer DrawSegment *ds = segmentlist->TranslucentSegment(index); if (ds->drawsegclip.SubsectorDepth >= SubsectorDepth && ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq) { - int r1 = MAX(ds->x1, 0); - int r2 = MIN(ds->x2, viewwidth - 1); + int r1 = max(ds->x1, 0); + int r2 = min(ds->x2, viewwidth - 1); RenderDrawSegment renderer(thread); renderer.Render(ds, r1, r2, clip3DFloor); @@ -200,17 +200,17 @@ namespace swrenderer { // seen below floor: clip top if (!spr->IsVoxel() && h > topclip) { - topclip = short(MIN(h, viewheight)); + topclip = short(min(h, viewheight)); } - hzt = MIN(hzt, hz); + hzt = min(hzt, hz); } else { // seen in the middle: clip bottom if (!spr->IsVoxel() && h < botclip) { - botclip = MAX(0, h); + botclip = max(0, h); } - hzb = MAX(hzb, hz); + hzb = max(hzb, hz); } } if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECMF_FAKEFLOORONLY)) @@ -222,17 +222,17 @@ namespace swrenderer { // seen above ceiling: clip bottom if (!spr->IsVoxel() && h < botclip) { - botclip = MAX(0, h); + botclip = max(0, h); } - hzb = MAX(hzb, hz); + hzb = max(hzb, hz); } else { // seen in the middle: clip top if (!spr->IsVoxel() && h > topclip) { - topclip = MIN(h, viewheight); + topclip = min(h, viewheight); } - hzt = MIN(hzt, hz); + hzt = min(hzt, hz); } } } @@ -242,7 +242,7 @@ namespace swrenderer int clip = xs_RoundToInt(viewport->CenterY - (spr->texturemid - spr->pic->GetHeight() + spr->floorclip) * spr->yscale); if (clip < botclip) { - botclip = MAX(0, clip); + botclip = max(0, clip); } } @@ -262,10 +262,10 @@ namespace swrenderer int h = xs_RoundToInt(viewport->CenterY - (hz - viewport->viewpoint.Pos.Z) * scale); if (h < botclip) { - botclip = MAX(0, h); + botclip = max(0, h); } } - hzb = MAX(hzb, clip3DFloor.sclipBottom); + hzb = max(hzb, clip3DFloor.sclipBottom); } if (clip3DFloor.clipTop) { @@ -283,12 +283,15 @@ namespace swrenderer int h = xs_RoundToInt(viewport->CenterY - (hz - viewport->viewpoint.Pos.Z) * scale); if (h > topclip) { - topclip = short(MIN(h, viewheight)); + topclip = short(min(h, viewheight)); } } - hzt = MIN(hzt, clip3DFloor.sclipTop); + hzt = min(hzt, clip3DFloor.sclipTop); } + // Make sure bottom clipping stays within the view size + botclip = min(botclip, viewheight); + if (topclip >= botclip) { spr->Light.BaseColormap = colormap; @@ -313,24 +316,6 @@ namespace swrenderer DrawSegmentList *segmentlist = thread->DrawSegments.get(); RenderPortal *renderportal = thread->Portal.get(); - // Render draw segments behind sprite - if (r_modelscene) - { - int subsectordepth = spr->SubsectorDepth; - for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++) - { - DrawSegment *ds = segmentlist->TranslucentSegment(index); - if (ds->drawsegclip.SubsectorDepth >= subsectordepth && ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq) - { - int r1 = MAX(ds->x1, 0); - int r2 = MIN(ds->x2, viewwidth - 1); - - RenderDrawSegment renderer(thread); - renderer.Render(ds, r1, r2, clip3DFloor); - } - } - } - else { for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++) { @@ -341,8 +326,8 @@ namespace swrenderer continue; } - float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2); - float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2); + float neardepth = min(ds->WallC.sz1, ds->WallC.sz2); + float fardepth = max(ds->WallC.sz1, ds->WallC.sz2); // Check if sprite is in front of draw seg: if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) && @@ -351,8 +336,8 @@ namespace swrenderer { if (ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq) { - int r1 = MAX(ds->x1, x1); - int r2 = MIN(ds->x2, x2); + int r1 = max(ds->x1, x1); + int r2 = min(ds->x2, x2); RenderDrawSegment renderer(thread); renderer.Render(ds, r1, r2, clip3DFloor); @@ -370,8 +355,8 @@ namespace swrenderer if (group.fardepth < spr->depth) { - int r1 = MAX(group.x1, x1); - int r2 = MIN(group.x2, x2); + int r1 = max(group.x1, x1); + int r2 = min(group.x2, x2); // Clip bottom short *clip1 = clipbot + r1; @@ -410,11 +395,11 @@ namespace swrenderer continue; } - int r1 = MAX(ds->x1, x1); - int r2 = MIN(ds->x2, x2); + int r1 = max(ds->x1, x1); + int r2 = min(ds->x2, x2); - float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2); - float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2); + float neardepth = min(ds->WallC.sz1, ds->WallC.sz2); + float fardepth = max(ds->WallC.sz1, ds->WallC.sz2); // Check if sprite is in front of draw seg: if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) && diff --git a/src/rendering/swrenderer/things/r_visiblespritelist.cpp b/src/rendering/swrenderer/things/r_visiblespritelist.cpp index 99c3748ce..fb25bb5ea 100644 --- a/src/rendering/swrenderer/things/r_visiblespritelist.cpp +++ b/src/rendering/swrenderer/things/r_visiblespritelist.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" @@ -83,23 +83,6 @@ namespace swrenderer SortedSprites[i] = Sprites[first + count - i - 1]; } - if (r_modelscene) - { - for (unsigned int i = 0; i < count; i++) - { - FVector2 worldPos = SortedSprites[i]->WorldPos().XY(); - SortedSprites[i]->SubsectorDepth = FindSubsectorDepth(thread, { worldPos.X, worldPos.Y }); - } - - std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool - { - if (a->SubsectorDepth != b->SubsectorDepth) - return a->SubsectorDepth < b->SubsectorDepth; - else - return a->SortDist() > b->SortDist(); - }); - } - else { std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool { diff --git a/src/rendering/swrenderer/things/r_voxel.cpp b/src/rendering/swrenderer/things/r_voxel.cpp index dc8ef9de1..455ad48ab 100644 --- a/src/rendering/swrenderer/things/r_voxel.cpp +++ b/src/rendering/swrenderer/things/r_voxel.cpp @@ -32,7 +32,7 @@ // the GNU General Public License v3.0. #include -#include "templates.h" + #include "doomdef.h" #include "sbar.h" #include "r_data/r_translate.h" @@ -135,12 +135,12 @@ namespace swrenderer int voxelspin = (thing->flags & MF_DROPPED) ? voxel->DroppedSpin : voxel->PlacedSpin; if (voxelspin != 0) { - DAngle ang = double(screen->FrameTime) * voxelspin / 1000; + DAngle ang = DAngle::fromDeg((screen->FrameTime) * voxelspin / 1000.); vis->Angle -= ang; } vis->pa.vpos = { (float)thread->Viewport->viewpoint.Pos.X, (float)thread->Viewport->viewpoint.Pos.Y, (float)thread->Viewport->viewpoint.Pos.Z }; - vis->pa.vang = FAngle((float)thread->Viewport->viewpoint.Angles.Yaw.Degrees); + vis->pa.vang = FAngle::fromDeg(((float)thread->Viewport->viewpoint.Angles.Yaw.Degrees())); // killough 3/27/98: save sector for special clipping later vis->heightsec = heightsec; @@ -324,7 +324,7 @@ namespace swrenderer // Select mip level i = abs(DMulScale(dasprx - globalposx, cosang, daspry - globalposy, sinang, 6)); - i = DivScale(i, MIN(daxscale, dayscale), 6); + i = DivScale(i, min(daxscale, dayscale), 6); j = xs_Fix<13>::ToFix(viewport->FocalLengthX); for (k = 0; i >= j && k < voxobj->NumMips; ++k) { @@ -372,7 +372,7 @@ namespace swrenderer gyinc = DMulScale(sprcosang, cosang, sprsinang, sinang, 10); if ((abs(globalposz - dasprz) >> 10) >= abs(dazscale)) return; - x = 0; y = 0; j = MAX(mip->SizeX, mip->SizeY); + 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); for (i = 0; i <= j; i++) @@ -487,8 +487,8 @@ namespace swrenderer if (flags & DVF_FIND_X1X2) { - coverageX1 = MIN(coverageX1, lx); - coverageX2 = MAX(coverageX2, rx); + coverageX1 = min(coverageX1, lx); + coverageX2 = max(coverageX2, rx); continue; } @@ -550,9 +550,9 @@ namespace swrenderer else yinc = (((1 << 24) - 1) / (z2 - z1)) * zleng >> 8; } // [RH] Clip each column separately, not just by the first one. - for (int stripwidth = MIN(countof(z1a), rx - lx), lxt = lx; + for (int stripwidth = min(countof(z1a), rx - lx), lxt = lx; lxt < rx; - (lxt += countof(z1a)), stripwidth = MIN(countof(z1a), rx - lxt)) + (lxt += countof(z1a)), stripwidth = min(countof(z1a), rx - lxt)) { // Calculate top and bottom pixels locations for (int xxx = 0; xxx < stripwidth; ++xxx) @@ -560,7 +560,7 @@ namespace swrenderer if (zleng == 1) { yplc[xxx] = 0; - z1a[xxx] = MAX(z1, daumost[lxt + xxx]); + z1a[xxx] = max(z1, daumost[lxt + xxx]); } else { @@ -575,7 +575,7 @@ namespace swrenderer z1a[xxx] = z1; } } - z2a[xxx] = MIN(z2, dadmost[lxt + xxx]); + z2a[xxx] = min(z2, dadmost[lxt + xxx]); } const uint8_t *columnColors = col; @@ -991,8 +991,8 @@ namespace swrenderer int ztop = slab->ztop; int zbottom = ztop + slab->zleng; - //ztop = MAX(ztop, minZ); - //zbottom = MIN(zbottom, maxZ); + //ztop = max(ztop, minZ); + //zbottom = min(zbottom, maxZ); for (int z = ztop; z < zbottom; z++) { @@ -1023,10 +1023,10 @@ namespace swrenderer DVector3 screenPos = viewport->PointViewToScreen(viewPos); DVector2 screenExtent = viewport->ScaleViewToScreen({ extentX, extentY }, viewPos.Z, pixelstretch); - int x1 = MAX((int)(screenPos.X - screenExtent.X), 0); - int x2 = MIN((int)(screenPos.X + screenExtent.X + 0.5f), viewwidth - 1); - int y1 = MAX((int)(screenPos.Y - screenExtent.Y), 0); - int y2 = MIN((int)(screenPos.Y + screenExtent.Y + 0.5f), viewheight - 1); + int x1 = max((int)(screenPos.X - screenExtent.X), 0); + int x2 = min((int)(screenPos.X + screenExtent.X + 0.5f), viewwidth - 1); + int y1 = max((int)(screenPos.Y - screenExtent.Y), 0); + int y2 = min((int)(screenPos.Y + screenExtent.Y + 0.5f), viewheight - 1); int pixelsize = viewport->RenderTarget->IsBgra() ? 4 : 1; @@ -1034,8 +1034,8 @@ namespace swrenderer { for (int x = x1; x < x2; x++) { - int columnY1 = MAX(y1, (int)cliptop[x]); - int columnY2 = MIN(y2, (int)clipbottom[x]); + int columnY1 = max(y1, (int)cliptop[x]); + int columnY2 = min(y2, (int)clipbottom[x]); if (columnY1 < columnY2) { drawerargs.SetDest(x, columnY1); diff --git a/src/rendering/swrenderer/things/r_voxel.h b/src/rendering/swrenderer/things/r_voxel.h index d9164899b..94405ef97 100644 --- a/src/rendering/swrenderer/things/r_voxel.h +++ b/src/rendering/swrenderer/things/r_voxel.h @@ -70,7 +70,7 @@ namespace swrenderer struct posang { FVector3 vpos = { 0.0f, 0.0f, 0.0f }; // view origin - FAngle vang = { 0.0f }; // view angle + FAngle vang = nullFAngle; // view angle }; struct VoxelBlockEntry @@ -80,7 +80,7 @@ namespace swrenderer }; posang pa; - DAngle Angle = { 0.0 }; + DAngle Angle = nullAngle; fixed_t xscale = 0; FVoxel *voxel = nullptr; bool bInMirror = false; diff --git a/src/rendering/swrenderer/things/r_wallsprite.cpp b/src/rendering/swrenderer/things/r_wallsprite.cpp index bc14fc148..b4dcc9bf2 100644 --- a/src/rendering/swrenderer/things/r_wallsprite.cpp +++ b/src/rendering/swrenderer/things/r_wallsprite.cpp @@ -23,7 +23,7 @@ #include #include #include "p_lnspec.h" -#include "templates.h" + #include "doomdef.h" #include "m_swap.h" @@ -75,7 +75,7 @@ namespace swrenderer double x1, x2; DVector2 left, right; double gzb, gzt, tz; - DAngle ang = thing->Angles.Yaw + 90; + DAngle ang = thing->Angles.Yaw + DAngle::fromDeg(90); double angcos = ang.Cos(); double angsin = ang.Sin(); @@ -159,8 +159,8 @@ namespace swrenderer { auto spr = this; - int x1 = MAX(spr->x1, spr->wallc.sx1); - int x2 = MIN(spr->x2, spr->wallc.sx2); + int x1 = max(spr->x1, spr->wallc.sx1); + int x2 = min(spr->x2, spr->wallc.sx2); if (x1 >= x2) return; diff --git a/src/rendering/swrenderer/viewport/r_drawerargs.cpp b/src/rendering/swrenderer/viewport/r_drawerargs.cpp index cf12dc41f..9591b4498 100644 --- a/src/rendering/swrenderer/viewport/r_drawerargs.cpp +++ b/src/rendering/swrenderer/viewport/r_drawerargs.cpp @@ -81,7 +81,7 @@ namespace swrenderer shadeConstants.fade_green = mBaseColormap->Fade.g; shadeConstants.fade_blue = mBaseColormap->Fade.b; shadeConstants.fade_alpha = mBaseColormap->Fade.a; - shadeConstants.desaturate = MIN(abs(mBaseColormap->Desaturate), 255) * 255 / 256; + shadeConstants.desaturate = min(abs(mBaseColormap->Desaturate), 255) * 255 / 256; shadeConstants.simple_shade = (mBaseColormap->Color.d == 0x00ffffff && mBaseColormap->Fade.d == 0x00000000 && mBaseColormap->Desaturate == 0); } else diff --git a/src/rendering/swrenderer/viewport/r_drawerargs.h b/src/rendering/swrenderer/viewport/r_drawerargs.h index 0cd5d3d20..339e00e55 100644 --- a/src/rendering/swrenderer/viewport/r_drawerargs.h +++ b/src/rendering/swrenderer/viewport/r_drawerargs.h @@ -1,7 +1,7 @@ #pragma once -#include "templates.h" + #include "doomtype.h" #include "doomdef.h" #include "r_defs.h" diff --git a/src/rendering/swrenderer/viewport/r_skydrawer.cpp b/src/rendering/swrenderer/viewport/r_skydrawer.cpp index 008903498..87088fead 100644 --- a/src/rendering/swrenderer/viewport/r_skydrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_skydrawer.cpp @@ -25,11 +25,6 @@ namespace swrenderer { - void SkyDrawerArgs::DrawDepthSkyColumn(RenderThread *thread, float idepth) - { - thread->Drawers(dc_viewport)->DrawDepthSkyColumn(*this, idepth); - } - void SkyDrawerArgs::DrawSingleSkyColumn(RenderThread *thread) { thread->Drawers(dc_viewport)->DrawSingleSkyColumn(*this); diff --git a/src/rendering/swrenderer/viewport/r_spandrawer.cpp b/src/rendering/swrenderer/viewport/r_spandrawer.cpp index c101ac80c..59b298cd3 100644 --- a/src/rendering/swrenderer/viewport/r_spandrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_spandrawer.cpp @@ -121,11 +121,6 @@ namespace swrenderer } } - void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2) - { - thread->Drawers(ds_viewport)->DrawDepthSpan(*this, idepth1, idepth2); - } - void SpanDrawerArgs::DrawSpan(RenderThread *thread) { (thread->Drawers(ds_viewport)->*spanfunc)(*this); diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp index 316f6af91..8217eeaf5 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp @@ -70,8 +70,8 @@ namespace swrenderer iscale = -iscale; float vstepY = iscale / WallC.sz1 / (viewport->InvZtoScale / WallC.sz1); - int x1 = MAX(WallC.sx1, clipx1); - int x2 = MIN(WallC.sx2, clipx2); + int x1 = max(WallC.sx1, clipx1); + int x2 = min(WallC.sx2, clipx2); if (x1 >= x2) return; @@ -127,10 +127,10 @@ namespace swrenderer void SpriteDrawerArgs::DrawMasked2D(RenderThread* thread, double x0, double x1, double y0, double y1, FSoftwareTexture* tex, FRenderStyle style) { - int sx0 = MAX((int)x0, 0); - int sx1 = MIN((int)x1, viewwidth); - int sy0 = MAX((int)y0, 0); - int sy1 = MIN((int)y1, viewheight); + int sx0 = max((int)x0, 0); + int sx1 = min((int)x1, viewwidth); + int sy0 = max((int)y0, 0); + int sy1 = min((int)y1, viewheight); if (sx0 >= sx1 || sy0 >= sy1) return; @@ -169,9 +169,9 @@ namespace swrenderer { double xmagnitude = fabs(static_cast(texelStepX)* (1.0 / 0x1'0000'0000LL)); double ymagnitude = fabs(static_cast(texelStepY)* (1.0 / 0x1'0000'0000LL)); - double magnitude = MAX(ymagnitude, xmagnitude); + double magnitude = max(ymagnitude, xmagnitude); double min_lod = -1000.0; - double lod = MAX(log2(magnitude) + r_lod_bias, min_lod); + double lod = max(log2(magnitude) + r_lod_bias, min_lod); bool magnifying = lod < 0.0f; int mipmap_offset = 0; @@ -184,8 +184,8 @@ namespace swrenderer { mipmap_offset += mip_width * mip_height; level--; - mip_width = MAX(mip_width >> 1, 1); - mip_height = MAX(mip_height >> 1, 1); + mip_width = max(mip_width >> 1, 1); + mip_height = max(mip_height >> 1, 1); } } @@ -195,7 +195,7 @@ namespace swrenderer bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter); if (filter_nearest) { - xoffset = MAX(MIN(xoffset, (mip_width << FRACBITS) - 1), 0); + xoffset = max(min(xoffset, (mip_width << FRACBITS) - 1), 0); int tx = xoffset >> FRACBITS; dc_source = (uint8_t*)(pixels + tx * mip_height); @@ -205,10 +205,10 @@ namespace swrenderer } else { - xoffset = MAX(MIN(xoffset - (FRACUNIT / 2), (mip_width << FRACBITS) - 1), 0); + xoffset = max(min(xoffset - (FRACUNIT / 2), (mip_width << FRACBITS) - 1), 0); int tx0 = xoffset >> FRACBITS; - int tx1 = MIN(tx0 + 1, mip_width - 1); + int tx1 = min(tx0 + 1, mip_width - 1); dc_source = (uint8_t*)(pixels + tx0 * mip_height); dc_source2 = (uint8_t*)(pixels + tx1 * mip_height); dc_textureheight = mip_height; @@ -233,8 +233,8 @@ namespace swrenderer if (flipY) std::swap(dc_yl, dc_yh); - dc_yl = std::max(dc_yl, cliptop); - dc_yh = std::min(dc_yh, clipbottom); + dc_yl = max(dc_yl, cliptop); + dc_yh = min(dc_yh, clipbottom); if (dc_yl <= dc_yh) { @@ -271,8 +271,8 @@ namespace swrenderer if (flipY) std::swap(dc_yl, dc_yh); - dc_yl = std::max(dc_yl, cliptop); - dc_yh = std::min(dc_yh, clipbottom); + dc_yl = max(dc_yl, cliptop); + dc_yh = min(dc_yh, clipbottom); if (dc_yl < dc_yh) { @@ -282,12 +282,12 @@ namespace swrenderer dc_yl--; fixed_t maxfrac = ((top + length) << FRACBITS) - 1; - dc_texturefrac = MAX(dc_texturefrac, 0); - dc_texturefrac = MIN(dc_texturefrac, maxfrac); + dc_texturefrac = max(dc_texturefrac, 0); + dc_texturefrac = min(dc_texturefrac, maxfrac); if (dc_iscale > 0) - dc_count = MIN(dc_count, (maxfrac - dc_texturefrac + dc_iscale - 1) / dc_iscale); + dc_count = min(dc_count, (maxfrac - dc_texturefrac + dc_iscale - 1) / dc_iscale); else if (dc_iscale < 0) - dc_count = MIN(dc_count, (dc_texturefrac - dc_iscale) / (-dc_iscale)); + dc_count = min(dc_count, (dc_texturefrac - dc_iscale) / (-dc_iscale)); (thread->Drawers(dc_viewport)->*colfunc)(*this); } diff --git a/src/rendering/swrenderer/viewport/r_viewport.cpp b/src/rendering/swrenderer/viewport/r_viewport.cpp index 3fdbe558e..aa455cf06 100644 --- a/src/rendering/swrenderer/viewport/r_viewport.cpp +++ b/src/rendering/swrenderer/viewport/r_viewport.cpp @@ -22,7 +22,7 @@ #include #include -#include "templates.h" + #include "filesystem.h" #include "doomdef.h" @@ -134,7 +134,7 @@ namespace swrenderer mysnprintf(temp, countof(temp), "%d x %d", viewwidth, viewheight); value.String = temp; - r_viewsize.ForceSet(value, CVAR_String); + r_viewsize->ForceSet(value, CVAR_String); } fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to diff --git a/src/rendering/swrenderer/viewport/r_viewport.h b/src/rendering/swrenderer/viewport/r_viewport.h index 54d3090f6..a43da8f25 100644 --- a/src/rendering/swrenderer/viewport/r_viewport.h +++ b/src/rendering/swrenderer/viewport/r_viewport.h @@ -11,8 +11,6 @@ #define MINZ double((2048*4) / double(1 << 20)) -class PolyDepthStencil; - namespace swrenderer { class RenderThread; diff --git a/src/scripting/backend/codegen_doom.cpp b/src/scripting/backend/codegen_doom.cpp index 30385519c..1d008446c 100644 --- a/src/scripting/backend/codegen_doom.cpp +++ b/src/scripting/backend/codegen_doom.cpp @@ -44,7 +44,7 @@ #include "texturemanager.h" #include "m_random.h" #include "v_font.h" -#include "templates.h" + #include "actor.h" #include "p_lnspec.h" #include "g_levellocals.h" diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 15722cd6f..82d40d34d 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -405,7 +405,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (sc.Compare ("Scale")) { sc.MustGetFloat (); - defaults->Scale.X = defaults->Scale.Y = sc.Float; + defaults->Scale.X = defaults->Scale.Y = float(sc.Float); } else if (sc.Compare ("RenderStyle")) { @@ -504,17 +504,17 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, sc.Compare ("DeathSound")) { sc.MustGetString (); - defaults->DeathSound = sc.String; + defaults->DeathSound = S_FindSound(sc.String); } else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathSound")) { sc.MustGetString (); - defaults->ActiveSound = sc.String; + defaults->ActiveSound = S_FindSound(sc.String); } else if (def == DEF_Projectile && sc.Compare ("SpawnSound")) { sc.MustGetString (); - defaults->SeeSound = sc.String; + defaults->SeeSound = S_FindSound(sc.String); } else if (def == DEF_Projectile && sc.Compare ("DoomBounce")) { @@ -531,7 +531,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Pickup && sc.Compare ("PickupSound")) { sc.MustGetString (); - defaults->IntVar(NAME_PickupSound) = FSoundID(sc.String); + defaults->IntVar(NAME_PickupSound) = S_FindSound(sc.String).index(); } else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) { diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 40e106baa..2658ebe18 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -83,7 +83,7 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, PNamespace *spc) if (spc) { PClassType *vmtype = nullptr == cls ? nullptr : cls->VMType; - FCompileContext ctx(spc, vmtype, true); + FCompileContext ctx(spc, vmtype, true, MakeVersion(0,0)); data = data->Resolve(ctx); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 96c654e3b..8d49f7604 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -144,7 +144,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type) if (type == TypeSound) { sc.MustGetString(); - x = new FxConstant(FSoundID(sc.String), sc); + x = new FxConstant(S_FindSound(sc.String), sc); } else if (type == TypeBool || type == TypeSInt32 || type == TypeFloat64) { @@ -879,7 +879,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul else if (f->Type == TypeSound) { sc.MustGetString(); - *(FSoundID*)addr = sc.String; + *(FSoundID*)addr = S_FindSound(sc.String); } else if (f->Type == TypeColor) { diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 1c060b61c..d170096fb 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -318,6 +318,12 @@ static void CheckLabel(PClassActor *obj, FStateLabel *slb, int useflag, FName st auto state = slb->State; if (state != nullptr) { + if (uintptr_t(state) <= 0xffff) + { + // can't do much here aside from printing a message and aborting. + I_Error("Bad state label %s in actor %s", slb->Label.GetChars(), obj->TypeName.GetChars()); + } + if (!(state->UseFlags & useflag)) { GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "%s references state %s as %s state, but this state is not flagged for use as %s.\n", diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 9b20e2d51..2861456d8 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -338,6 +338,12 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF8, MAP07BOSS2, AActor, flags8), DEFINE_FLAG(MF8, AVOIDHAZARDS, AActor, flags8), DEFINE_FLAG(MF8, STAYONLIFT, AActor, flags8), + DEFINE_FLAG(MF8, DONTFOLLOWPLAYERS, AActor, flags8), + DEFINE_FLAG(MF8, SEEFRIENDLYMONSTERS, AActor, flags8), + DEFINE_FLAG(MF8, CROSSLINECHECK, AActor, flags8), + DEFINE_FLAG(MF8, MASTERNOSEE, AActor, flags8), + DEFINE_FLAG(MF8, ADDLIGHTLEVEL, AActor, flags8), + DEFINE_FLAG(MF8, ONLYSLAMSOLID, AActor, flags8), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), @@ -363,6 +369,8 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, ZDOOMTRANS, AActor, renderflags), DEFINE_FLAG(RF, CASTSPRITESHADOW, AActor, renderflags), DEFINE_FLAG(RF, NOSPRITESHADOW, AActor, renderflags), + DEFINE_FLAG(RF2, INVISIBLEINMIRRORS, AActor, renderflags2), + DEFINE_FLAG(RF2, ONLYVISIBLEINMIRRORS, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), @@ -700,6 +708,10 @@ void InitThingdef() sectorportalstruct->Size = sizeof(FSectorPortal); sectorportalstruct->Align = alignof(FSectorPortal); + auto lineportalstruct = NewStruct("LinePortal", nullptr, true); + lineportalstruct->Size = sizeof(FLinePortal); + lineportalstruct->Align = alignof(FLinePortal); + auto playerclassstruct = NewStruct("PlayerClass", nullptr, true); playerclassstruct->Size = sizeof(FPlayerClass); playerclassstruct->Align = alignof(FPlayerClass); @@ -712,6 +724,10 @@ void InitThingdef() teamstruct->Size = sizeof(FTeam); teamstruct->Align = alignof(FTeam); + auto terraindefstruct = NewStruct("TerrainDef", nullptr, true); + terraindefstruct->Size = sizeof(FTerrainDef); + terraindefstruct->Align = alignof(FTerrainDef); + PStruct *pstruct = NewStruct("PlayerInfo", nullptr, true); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); @@ -727,21 +743,6 @@ void InitThingdef() } ); - auto fontstruct = NewStruct("FFont", nullptr, true); - fontstruct->Size = sizeof(FFont); - fontstruct->Align = alignof(FFont); - NewPointer(fontstruct, false)->InstallHandlers( - [](FSerializer &ar, const char *key, const void *addr) - { - ar(key, *(FFont **)addr); - }, - [](FSerializer &ar, const char *key, void *addr) - { - Serialize(ar, key, *(FFont **)addr, nullptr); - return true; - } - ); - auto wbplayerstruct = NewStruct("WBPlayerStruct", nullptr, true); wbplayerstruct->Size = sizeof(wbplayerstruct_t); wbplayerstruct->Align = alignof(wbplayerstruct_t); @@ -789,6 +790,10 @@ void InitThingdef() auto fltd = NewStruct("FLineTraceData", nullptr); fltd->Size = sizeof(FLineTraceData); fltd->Align = alignof(FLineTraceData); + + auto fspp = NewStruct("FSpawnParticleParams", nullptr); + fspp->Size = sizeof(FSpawnParticleParams); + fspp->Align = alignof(FSpawnParticleParams); } void SynthesizeFlagFields() @@ -813,7 +818,7 @@ void SynthesizeFlagFields() DEFINE_ACTION_FUNCTION(DObject, BAM) { PARAM_PROLOGUE; - PARAM_FLOAT(ang); - ACTION_RETURN_INT(DAngle(ang).BAMs()); + PARAM_ANGLE(ang); + ACTION_RETURN_INT(ang.BAMs()); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 48db073d0..1202d2489 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -528,7 +528,9 @@ DEFINE_PROPERTY(skip_super, 0, Actor) return; } - *defaults = *GetDefault(); + // major hack job alert. This is only supposed to copy the parts that actually are defined by AActor itself. + memcpy(&defaults->snext, &GetDefault()->snext, (uint8_t*)&defaults[1] - (uint8_t*)&defaults->snext); + ResetBaggage (&bag, RUNTIME_CLASS(AActor)); static_cast(bag.Info)->ActorInfo()->SkipSuperSet = true; // ZScript processes the states later so this property must be flagged for later handling. } @@ -618,7 +620,7 @@ DEFINE_PROPERTY(damage, X, Actor) DEFINE_PROPERTY(scale, F, Actor) { PROP_DOUBLE_PARM(id, 0); - defaults->Scale.X = defaults->Scale.Y = id; + defaults->Scale.X = defaults->Scale.Y = float(id); } //========================================================================== @@ -959,7 +961,7 @@ DEFINE_PROPERTY(gravity, F, Actor) DEFINE_PROPERTY(spriteangle, F, Actor) { PROP_DOUBLE_PARM(i, 0); - defaults->SpriteAngle = i; + defaults->SpriteAngle = DAngle::fromDeg(i); } //========================================================================== diff --git a/src/scripting/vmiterators.cpp b/src/scripting/vmiterators.cpp index e5f0d78e8..32d1ca1f8 100644 --- a/src/scripting/vmiterators.cpp +++ b/src/scripting/vmiterators.cpp @@ -123,7 +123,7 @@ IMPLEMENT_CLASS(DBlockLinesIterator, true, false); static DBlockLinesIterator *CreateBLI(AActor *origin, double radius) { - return Create(origin, radius); + return Create(PARAM_NULLCHECK(origin, origin), radius); } DEFINE_ACTION_FUNCTION_NATIVE(DBlockLinesIterator, Create, CreateBLI) @@ -198,7 +198,7 @@ IMPLEMENT_CLASS(DBlockThingsIterator, true, false); static DBlockThingsIterator *CreateBTI(AActor *origin, double radius, bool ignore) { - return Create(origin, radius, ignore); + return Create(PARAM_NULLCHECK(origin, origin), radius, ignore); } diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index b37114191..d672a5192 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -78,6 +78,30 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraToTexture, SetCameraToTexture) return 0; } +static void SetCameraTextureAspectRatio(const FString &texturename, double aspectScale, bool useTextureRatio) +{ + FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); + if (textureid.isValid()) + { + // Only proceed if the texture actually has a canvas. + auto tex = TexMan.GetGameTexture(textureid); + if (tex && tex->isHardwareCanvas()) + { + static_cast(tex->GetTexture())->SetAspectRatio(aspectScale, useTextureRatio); + } + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraTextureAspectRatio, SetCameraTextureAspectRatio) +{ + PARAM_PROLOGUE; + PARAM_STRING(texturename); + PARAM_FLOAT(aspect); + PARAM_BOOL(useTextureRatio); + SetCameraTextureAspectRatio(texturename, aspect, useTextureRatio); + return 0; +} + //===================================================================================== // // sector_t exports @@ -446,6 +470,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, GetTerrain, GetTerrain) ACTION_RETURN_INT(GetTerrain(self, pos)); } +DEFINE_ACTION_FUNCTION_NATIVE(_Sector, GetFloorTerrain, GetFloorTerrain_S) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_INT(pos); + ACTION_RETURN_POINTER(GetFloorTerrain_S(self, pos)); +} DEFINE_ACTION_FUNCTION_NATIVE(_Sector, CheckPortalPlane, CheckPortalPlane) { @@ -532,7 +562,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(pos); PARAM_FLOAT(o); - self->SetXOffset(pos, o); + self->SetYOffset(pos, o); return 0; } @@ -617,7 +647,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) static void SetAngle(sector_t *self, int pos, double o) { - self->SetAngle(pos, o); + self->SetAngle(pos, DAngle::fromDeg(o)); } DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetAngle, SetAngle) @@ -631,7 +661,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) static double GetAngle(sector_t *self, int pos, bool addbase) { - return self->GetAngle(pos, addbase).Degrees; + return self->GetAngle(pos, addbase).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(_Sector, GetAngle, GetAngle) @@ -639,12 +669,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(pos); PARAM_BOOL(addbase); - ACTION_RETURN_FLOAT(self->GetAngle(pos, addbase).Degrees); + ACTION_RETURN_FLOAT(self->GetAngle(pos, addbase).Degrees()); } static void SetBase(sector_t *self, int pos, double o, double a) { - self->SetBase(pos, o, a); + self->SetBase(pos, o, DAngle::fromDeg(a)); } DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetBase, SetBase) @@ -1169,12 +1199,36 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) return self->getPortalAlignment(); } + DEFINE_ACTION_FUNCTION(_Line, getPortalFlags) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + ACTION_RETURN_INT(self->getPortalFlags()); + } + DEFINE_ACTION_FUNCTION_NATIVE(_Line, getPortalAlignment, getPortalAlignment) { PARAM_SELF_STRUCT_PROLOGUE(line_t); ACTION_RETURN_INT(self->getPortalAlignment()); } + DEFINE_ACTION_FUNCTION(_Line, getPortalType) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + ACTION_RETURN_INT(self->getPortalType()); + } + + DEFINE_ACTION_FUNCTION(_Line, getPortalDisplacement) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + ACTION_RETURN_VEC2(self->getPortalDisplacement()); + } + + DEFINE_ACTION_FUNCTION(_Line, getPortalAngleDiff) + { + PARAM_SELF_STRUCT_PROLOGUE(line_t); + ACTION_RETURN_FLOAT(self->getPortalAngleDiff().Degrees()); + } + static int LineIndex(line_t *self) { return self->Index(); @@ -1615,7 +1669,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); PARAM_NAME(seq); PARAM_INT(state); - F_StartIntermission(seq, (uint8_t)state); + G_StartSlideshow(self, seq); return 0; } @@ -1786,7 +1840,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FWeaponSlots, LocateWeapon, LocateWeapon) if (numret >= 1) ret[0].SetInt(retv); if (numret >= 2) ret[1].SetInt(slot); if (numret >= 3) ret[2].SetInt(index); - return MIN(numret, 3); + return min(numret, 3); } static PClassActor *GetWeapon(FWeaponSlots *self, int slot, int index) @@ -2123,7 +2177,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, GetInventoryIcon, GetInventoryIcon FTextureID icon = FSetTextureID(GetInventoryIcon(item, flags, &applyscale)); if (numret >= 1) ret[0].SetInt(icon.GetIndex()); if (numret >= 2) ret[1].SetInt(applyscale); - return MIN(numret, 2); + return min(numret, 2); } //===================================================================================== @@ -2389,6 +2443,29 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec3Diff, Vec3Diff) ACTION_RETURN_VEC3(VecDiff(self, DVector3(x1, y1, z1), DVector3(x2, y2, z2))); } +DEFINE_ACTION_FUNCTION(FLevelLocals, GetDisplacement) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(pg1); + PARAM_INT(pg2); + + DVector2 ofs(0, 0); + if (pg1 != pg2) + { + unsigned i = pg1 + self->Displacements.size * pg2; + if (i < self->Displacements.data.Size()) + ofs = self->Displacements.data[i].pos; + } + + ACTION_RETURN_VEC2(ofs); +} + +DEFINE_ACTION_FUNCTION(FLevelLocals, GetPortalGroupCount) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + ACTION_RETURN_INT(self->Displacements.size); +} + void SphericalCoords(FLevelLocals *self, double vpX, double vpY, double vpZ, double tX, double tY, double tZ, double viewYaw, double viewPitch, int absolute, DVector3 *result) { @@ -2397,8 +2474,8 @@ void SphericalCoords(FLevelLocals *self, double vpX, double vpY, double vpZ, dou auto vecTo = absolute ? target - viewpoint : VecDiff(self, viewpoint, target); *result = (DVector3( - deltaangle(vecTo.Angle(), viewYaw).Degrees, - deltaangle(vecTo.Pitch(), viewPitch).Degrees, + deltaangle(vecTo.Angle(), DAngle::fromDeg(viewYaw)).Degrees(), + deltaangle(vecTo.Pitch(), DAngle::fromDeg(viewPitch)).Degrees(), vecTo.Length() )); @@ -2420,6 +2497,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SphericalCoords, SphericalCoords) ACTION_RETURN_VEC3(result); } +static void LookupString(FLevelLocals *level, uint32_t index, FString *res) +{ + *res = level->Behaviors.LookupString(index); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, LookupString, LookupString) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_UINT(index); + FString res; + LookupString(self, index, &res); + ACTION_RETURN_STRING(res); +} static int isFrozen(FLevelLocals *self) { @@ -2489,7 +2579,7 @@ DEFINE_ACTION_FUNCTION(_Screen, GetViewWindow) if (numret > 1) ret[1].SetInt(viewwindowy); if (numret > 2) ret[2].SetInt(viewwidth); if (numret > 3) ret[3].SetInt(viewheight); - return MIN(numret, 4); + return min(numret, 4); } DEFINE_ACTION_FUNCTION(_Console, MidPrint) @@ -2653,6 +2743,7 @@ DEFINE_FIELD(FLevelLocals, sectors) DEFINE_FIELD(FLevelLocals, lines) DEFINE_FIELD(FLevelLocals, sides) DEFINE_FIELD(FLevelLocals, vertexes) +DEFINE_FIELD(FLevelLocals, linePortals) DEFINE_FIELD(FLevelLocals, sectorPortals) DEFINE_FIELD(FLevelLocals, time) DEFINE_FIELD(FLevelLocals, maptime) @@ -2702,6 +2793,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags, noinventorybar, LEVEL_NOINVENTORYBAR) DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG) DEFINE_FIELD_BIT(FLevelLocals, flags, actownspecial, LEVEL_ACTOWNSPECIAL) DEFINE_FIELD_BIT(FLevelLocals, flags, sndseqtotalctrl, LEVEL_SNDSEQTOTALCTRL) +DEFINE_FIELD_BIT(FLevelLocals, flags, useplayerstartz, LEVEL_USEPLAYERSTARTZ) DEFINE_FIELD_BIT(FLevelLocals, flags2, allmap, LEVEL2_ALLMAP) DEFINE_FIELD_BIT(FLevelLocals, flags2, missilesactivateimpact, LEVEL2_MISSILESACTIVATEIMPACT) DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLINGDAMAGE) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 2f5c26e9d..244a05879 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -59,7 +59,7 @@ DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); void PrintPickupMessage(bool localview, const FString &str); -bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nullptr, FSoundID sound = 0); +bool P_CheckForResurrection(AActor* self, bool usevilestates, FState* state = nullptr, FSoundID sound = NO_SOUND); // FCheckPosition requires explicit construction and destruction when used in the VM @@ -173,7 +173,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundVolume, S_ChangeActorSoundVolume) DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) { PARAM_SELF_PROLOGUE(AActor); - PARAM_SOUND(soundid); + PARAM_INT(soundid); PARAM_INT(channel); PARAM_FLOAT(volume); PARAM_BOOL(looping); @@ -187,7 +187,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound) { PARAM_SELF_PROLOGUE(AActor); - PARAM_SOUND(soundid); + PARAM_INT(soundid); PARAM_INT(channel); PARAM_INT(flags); PARAM_FLOAT(volume); @@ -198,7 +198,35 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound) return 0; } -DEFINE_ACTION_FUNCTION_NATIVE(AActor, IsActorPlayingSound, S_IsActorPlayingSomething) + +void A_StartSoundIfNotSame(AActor *self, int soundid, int checksoundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime) +{ + if (!S_AreSoundsEquivalent (self, FSoundID::fromInt(soundid), FSoundID::fromInt(checksoundid))) + A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSoundIfNotSame, A_StartSoundIfNotSame) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(soundid); + PARAM_INT(checksoundid); + PARAM_INT(channel); + PARAM_INT(flags); + PARAM_FLOAT(volume); + PARAM_FLOAT(attenuation); + PARAM_FLOAT(pitch); + PARAM_FLOAT(startTime); + A_StartSoundIfNotSame(self, soundid, checksoundid, channel, flags, volume, attenuation, pitch, startTime); + return 0; +} + +// direct native scripting export. +static int S_IsActorPlayingSomethingID(AActor* actor, int channel, int sound_id) +{ + return S_IsActorPlayingSomething(actor, channel, FSoundID::fromInt(sound_id)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, IsActorPlayingSound, S_IsActorPlayingSomethingID) { PARAM_SELF_PROLOGUE(AActor); PARAM_INT(channel); @@ -217,7 +245,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckKeys, P_CheckKeys) static double deltaangleDbl(double a1, double a2) { - return deltaangle(DAngle(a1), DAngle(a2)).Degrees; + return deltaangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, deltaangle, deltaangleDbl) // should this be global? @@ -225,12 +253,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, deltaangle, deltaangleDbl) // should this PARAM_PROLOGUE; PARAM_FLOAT(a1); PARAM_FLOAT(a2); - ACTION_RETURN_FLOAT(deltaangle(DAngle(a1), DAngle(a2)).Degrees); + ACTION_RETURN_FLOAT(deltaangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees()); } static double absangleDbl(double a1, double a2) { - return absangle(DAngle(a1), DAngle(a2)).Degrees; + return absangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, absangle, absangleDbl) // should this be global? @@ -238,7 +266,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, absangle, absangleDbl) // should this be g PARAM_PROLOGUE; PARAM_FLOAT(a1); PARAM_FLOAT(a2); - ACTION_RETURN_FLOAT(absangle(DAngle(a1), DAngle(a2)).Degrees); + ACTION_RETURN_FLOAT(absangle(DAngle::fromDeg(a1), DAngle::fromDeg(a2)).Degrees()); } static double Distance2DSquared(AActor *self, AActor *other) @@ -331,7 +359,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetDamage, SetDamage) static double PitchFromVel(AActor* self) { - return self->Vel.Pitch().Degrees; + return self->Vel.Pitch().Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, PitchFromVel, PitchFromVel) @@ -357,7 +385,7 @@ static void VelFromAngle(AActor *self, double speed, double angle) } else { - self->VelFromAngle(speed, angle); + self->VelFromAngle(speed, DAngle::fromDeg(angle)); } } } @@ -373,7 +401,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, VelFromAngle, VelFromAngle) static void Vel3DFromAngle(AActor *self, double speed, double angle, double pitch) { - self->Vel3DFromAngle(angle, pitch, speed); + self->Vel3DFromAngle(DAngle::fromDeg(angle), DAngle::fromDeg(pitch), speed); } // This combines all 3 variations of the internal function @@ -402,7 +430,7 @@ static void Thrust(AActor *self, double speed, double angle) } else { - self->Thrust(angle, speed); + self->Thrust(DAngle::fromDeg(angle), speed); } } } @@ -418,7 +446,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, Thrust, Thrust) static double AngleTo(AActor *self, AActor *targ, bool absolute) { - return self->AngleTo(PARAM_NULLCHECK(targ, targ), absolute).Degrees; + return self->AngleTo(PARAM_NULLCHECK(targ, targ), absolute).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AngleTo, AngleTo) @@ -426,12 +454,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, AngleTo, AngleTo) PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT_NOT_NULL(targ, AActor); PARAM_BOOL(absolute); - ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); + ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees()); } static void AngleToVector(double angle, double length, DVector2 *result) { - *result = DAngle(angle).ToVector(length); + *result = DAngle::fromDeg(angle).ToVector(length); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AngleToVector, AngleToVector) @@ -458,14 +486,14 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, RotateVector, RotateVector) static double Normalize180(double angle) { - return DAngle(angle).Normalized180().Degrees; + return DAngle::fromDeg(angle).Normalized180().Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Normalize180, Normalize180) { PARAM_PROLOGUE; PARAM_ANGLE(angle); - ACTION_RETURN_FLOAT(angle.Normalized180().Degrees); + ACTION_RETURN_FLOAT(angle.Normalized180().Degrees()); } static double DistanceBySpeed(AActor *self, AActor *targ, double speed) @@ -498,7 +526,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetXYZ, SetXYZ) static void Vec2Angle(AActor *self, double length, double angle, bool absolute, DVector2 *result) { - *result = self->Vec2Angle(length, angle, absolute); + *result = self->Vec2Angle(length, DAngle::fromDeg(angle), absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2Angle, Vec2Angle) @@ -536,7 +564,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec2To, Vec2To) static void Vec3Angle(AActor *self, double length, double angle, double z, bool absolute, DVector3 *result) { - *result = self->Vec3Angle(length, angle, z, absolute); + *result = self->Vec3Angle(length, DAngle::fromDeg(angle), z, absolute); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, Vec3Angle, Vec3Angle) @@ -688,6 +716,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearInterpolation, ClearInterpolation) return 0; } +DEFINE_ACTION_FUNCTION(AActor, ClearFOVInterpolation) +{ + PARAM_SELF_PROLOGUE(AActor); + self->ClearFOVInterpolation(); + return 0; +} + static int ApplyDamageFactors(PClassActor *itemcls, int damagetype, int damage, int defdamage) { DmgFactors &df = itemcls->ActorInfo()->DamageFactors; @@ -1128,7 +1163,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckMove, CheckMove) static double AimLineAttack(AActor *self, double angle, double distance, FTranslatedLineTarget *pLineTarget, double vrange, int flags, AActor *target, AActor *friender) { - return P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees; + flags &= ~ALF_IGNORENOAUTOAIM; // just to be safe. This flag is not supposed to be accesible to scripting. + return P_AimLineAttack(self, DAngle::fromDeg(angle), distance, pLineTarget, DAngle::fromDeg(vrange), flags, target, friender).Degrees(); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, AimLineAttack, AimLineAttack) @@ -1141,13 +1177,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, AimLineAttack, AimLineAttack) PARAM_INT(flags); PARAM_OBJECT(target, AActor); PARAM_OBJECT(friender, AActor); - ACTION_RETURN_FLOAT(P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees); + ACTION_RETURN_FLOAT(P_AimLineAttack(self, angle, distance, pLineTarget, vrange, flags, target, friender).Degrees()); } static AActor *ZS_LineAttack(AActor *self, double angle, double distance, double pitch, int damage, int damageType, PClassActor *puffType, int flags, FTranslatedLineTarget *victim, double offsetz, double offsetforward, double offsetside, int *actualdamage) { if (puffType == nullptr) puffType = PClass::FindActor(NAME_BulletPuff); // P_LineAttack does not work without a puff to take info from. - return P_LineAttack(self, angle, distance, pitch, damage, ENamedName(damageType), puffType, flags, victim, actualdamage, offsetz, offsetforward, offsetside); + return P_LineAttack(self, DAngle::fromDeg(angle), distance, DAngle::fromDeg(pitch), damage, ENamedName(damageType), puffType, flags, victim, actualdamage, offsetz, offsetforward, offsetside); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineAttack, ZS_LineAttack) @@ -1174,7 +1210,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineAttack, ZS_LineAttack) static int LineTrace(AActor *self, double angle, double distance, double pitch, int flags, double offsetz, double offsetforward, double offsetside, FLineTraceData *data) { - return P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data); + return P_LineTrace(self,DAngle::fromDeg(angle),distance,DAngle::fromDeg(pitch),flags,offsetz,offsetforward,offsetside,data); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineTrace, LineTrace) @@ -1188,12 +1224,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, LineTrace, LineTrace) PARAM_FLOAT(offsetforward); PARAM_FLOAT(offsetside); PARAM_OUTPOINTER(data, FLineTraceData); - ACTION_RETURN_BOOL(P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data)); + ACTION_RETURN_BOOL(P_LineTrace(self,DAngle::fromDeg(angle),distance,DAngle::fromDeg(pitch),flags,offsetz,offsetforward,offsetside,data)); } static void TraceBleedAngle(AActor *self, int damage, double angle, double pitch) { - P_TraceBleed(damage, self, angle, pitch); + P_TraceBleed(damage, self, DAngle::fromDeg(angle), DAngle::fromDeg(pitch)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, TraceBleedAngle, TraceBleedAngle) @@ -1203,7 +1239,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, TraceBleedAngle, TraceBleedAngle) PARAM_FLOAT(angle); PARAM_FLOAT(pitch); - P_TraceBleed(damage, self, angle, pitch); + P_TraceBleed(damage, self, DAngle::fromDeg(angle), DAngle::fromDeg(pitch)); return 0; } @@ -1325,7 +1361,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetReplacee, ZS_GetReplacee) static void DrawSplash(AActor *self, int count, double angle, int kind) { - P_DrawSplash(self->Level, count, self->Pos(), angle, kind); + P_DrawSplash(self->Level, count, self->Pos(), DAngle::fromDeg(angle), kind); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, DrawSplash, DrawSplash) @@ -1334,7 +1370,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, DrawSplash, DrawSplash) PARAM_INT(count); PARAM_FLOAT(angle); PARAM_INT(kind); - P_DrawSplash(self->Level, count, self->Pos(), angle, kind); + P_DrawSplash(self->Level, count, self->Pos(), DAngle::fromDeg(angle), kind); return 0; } @@ -1592,7 +1628,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_ExtChase, A_ExtChase) int CheckForResurrection(AActor *self, FState* state, int sound) { - return P_CheckForResurrection(self, false, state, sound); + return P_CheckForResurrection(self, false, state, FSoundID::fromInt(sound)); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_CheckForResurrection, CheckForResurrection) @@ -1600,12 +1636,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_CheckForResurrection, CheckForResurrecti PARAM_SELF_PROLOGUE(AActor); PARAM_STATE(state); PARAM_INT(sound); - ACTION_RETURN_BOOL(P_CheckForResurrection(self, false, state, sound)); + ACTION_RETURN_BOOL(CheckForResurrection(self, state, sound)); } static void ZS_Face(AActor *self, AActor *faceto, double max_turn, double max_pitch, double ang_offset, double pitch_offset, int flags, double z_add) { - A_Face(self, faceto, max_turn, max_pitch, ang_offset, pitch_offset, flags, z_add); + A_Face(self, faceto, DAngle::fromDeg(max_turn), DAngle::fromDeg(max_pitch), DAngle::fromDeg(ang_offset), DAngle::fromDeg(pitch_offset), flags, z_add); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_Face, ZS_Face) @@ -1713,6 +1749,27 @@ DEFINE_ACTION_FUNCTION_NATIVE(AInventory, PrintPickupMessage, PrintPickupMessage // //===================================================================================== +DEFINE_ACTION_FUNCTION_NATIVE(AKey, IsLockDefined, P_IsLockDefined) +{ + PARAM_PROLOGUE; + PARAM_INT(locknum); + ACTION_RETURN_BOOL(P_IsLockDefined(locknum)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetMapColorForLock, P_GetMapColorForLock) +{ + PARAM_PROLOGUE; + PARAM_INT(locknum); + ACTION_RETURN_INT(P_GetMapColorForLock(locknum)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetMapColorForKey, P_GetMapColorForKey) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(key, AActor); + ACTION_RETURN_INT(P_GetMapColorForKey(key)); +} + DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyTypeCount, P_GetKeyTypeCount) { PARAM_PROLOGUE; @@ -1757,6 +1814,51 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckFor3DCeilingHit, CheckFor3DCeilingHit ACTION_RETURN_BOOL(P_CheckFor3DCeilingHit(self, z, trigger)); } +//===================================================================================== +// +// Bounce exports +// +//===================================================================================== +DEFINE_ACTION_FUNCTION(AActor, BounceActor) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(blocking, AActor); + PARAM_BOOL(onTop); + + ACTION_RETURN_BOOL(P_BounceActor(self, blocking, onTop)); +} + +DEFINE_ACTION_FUNCTION(AActor, BounceWall) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(l, line_t); + + auto cur = self->BlockingLine; + if (l) + self->BlockingLine = l; + + bool res = P_BounceWall(self); + self->BlockingLine = cur; + + ACTION_RETURN_BOOL(res); +} + +DEFINE_ACTION_FUNCTION(AActor, BouncePlane) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_POINTER(plane, secplane_t); + + ACTION_RETURN_BOOL(self->FloorBounceMissile(*plane)); +} + +DEFINE_ACTION_FUNCTION(AActor, PlayBounceSound) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_BOOL(onFloor); + + self->PlayBounceSound(onFloor); + return 0; +} static int isFrozen(AActor *self) @@ -1770,7 +1872,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFrozen, isFrozen) ACTION_RETURN_BOOL(isFrozen(self)); } - //=========================================================================== // // PlayerPawn functions @@ -1796,7 +1897,31 @@ DEFINE_ACTION_FUNCTION_NATIVE(APlayerPawn, GetPrintableDisplayName, GetPrintable ACTION_RETURN_STRING(type->GetDisplayName()); } +static void SetViewPos(AActor *self, double x, double y, double z, int flags) +{ + if (!self->ViewPos) + { + self->ViewPos = Create(); + } + DVector3 pos = { x,y,z }; + self->ViewPos->Set(pos, flags); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetViewPos, SetViewPos) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_INT(flags); + SetViewPos(self, x, y, z, flags); + return 0; +} + +IMPLEMENT_CLASS(DViewPosition, false, false); +DEFINE_FIELD_X(ViewPosition, DViewPosition, Offset) +DEFINE_FIELD_X(ViewPosition, DViewPosition, Flags) DEFINE_FIELD(DThinker, Level) DEFINE_FIELD(AActor, snext) @@ -1806,6 +1931,7 @@ DEFINE_FIELD_NAMED(AActor, __Pos.X, x) DEFINE_FIELD_NAMED(AActor, __Pos.Y, y) DEFINE_FIELD_NAMED(AActor, __Pos.Z, z) DEFINE_FIELD(AActor, SpriteOffset) +DEFINE_FIELD(AActor, WorldOffset) DEFINE_FIELD(AActor, Prev) DEFINE_FIELD(AActor, SpriteAngle) DEFINE_FIELD(AActor, SpriteRotation) @@ -1884,6 +2010,7 @@ DEFINE_FIELD(AActor, special) DEFINE_FIELD(AActor, tid) DEFINE_FIELD(AActor, TIDtoHate) DEFINE_FIELD(AActor, waterlevel) +DEFINE_FIELD(AActor, waterdepth) DEFINE_FIELD(AActor, Score) DEFINE_FIELD(AActor, accuracy) DEFINE_FIELD(AActor, stamina) @@ -1921,6 +2048,7 @@ DEFINE_FIELD(AActor, BlockingLine) DEFINE_FIELD(AActor, Blocking3DFloor) DEFINE_FIELD(AActor, BlockingCeiling) DEFINE_FIELD(AActor, BlockingFloor) +DEFINE_FIELD(AActor, freezetics) DEFINE_FIELD(AActor, PoisonDamage) DEFINE_FIELD(AActor, PoisonDamageType) DEFINE_FIELD(AActor, PoisonDuration) @@ -1975,9 +2103,11 @@ DEFINE_FIELD(AActor, friendlyseeblocks) DEFINE_FIELD(AActor, SpawnTime) DEFINE_FIELD(AActor, InventoryID) DEFINE_FIELD(AActor, ThruBits) +DEFINE_FIELD(AActor, ViewPos) 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_X(FCheckPosition, FCheckPosition, thing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos); @@ -2033,3 +2163,36 @@ DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LineSide); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LinePart); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, SectorPlane); DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitType); + +DEFINE_FIELD_NAMED_X(FSpawnParticleParams, FSpawnParticleParams, color, color1); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, texture); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, style); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, flags); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, lifetime); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, size); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, sizestep); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, pos); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, vel); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, accel); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, startalpha); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, fadestep); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, startroll); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, rollvel); +DEFINE_FIELD_X(FSpawnParticleParams, FSpawnParticleParams, rollacc); + +static void SpawnParticle(FLevelLocals *Level, FSpawnParticleParams *params) +{ + P_SpawnParticle(Level, params->pos, params->vel, params->accel, + params->color, params->startalpha, params->lifetime, + params->size, params->fadestep, params->sizestep, + params->flags, params->texture, ERenderStyle(params->style), + params->startroll, params->rollvel, params->rollacc); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnParticle, SpawnParticle) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_POINTER(p, FSpawnParticleParams); + SpawnParticle(self, p); + return 0; +} diff --git a/src/scripting/zscript/zcc_compile_doom.cpp b/src/scripting/zscript/zcc_compile_doom.cpp index cc19533a1..642fac09f 100644 --- a/src/scripting/zscript/zcc_compile_doom.cpp +++ b/src/scripting/zscript/zcc_compile_doom.cpp @@ -242,7 +242,7 @@ void ZCCDoomCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pr const char * p = prop->params; auto exp = property->Values; - FCompileContext ctx(OutNamespace, bag.Info->VMType, false); + FCompileContext ctx(OutNamespace, bag.Info->VMType, false, mVersion); while (true) { FPropParam conv; @@ -425,7 +425,7 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * } auto exp = property->Values; - FCompileContext ctx(OutNamespace, bag.Info->VMType, false); + FCompileContext ctx(OutNamespace, bag.Info->VMType, false, mVersion); for (auto f : prop->Variables) { void *addr; @@ -452,9 +452,105 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * } else if (!ex->isConstant()) { + if (ex->ExprType == EFX_VectorValue && ex->ValueType == f->Type) + { + auto v = static_cast(ex); + if (f->Type == TypeVector2) + { + if(!v->isConstVector(2)) + { + Error(exp, "%s: non-constant Vector2 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector2*)addr) = DVector2( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector2) + { + if(!v->isConstVector(2)) + { + Error(exp, "%s: non-constant FVector2 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector2*)addr) = FVector2( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else if (f->Type == TypeVector3) + { + if(!v->isConstVector(3)) + { + Error(exp, "%s: non-constant Vector3 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector3*)addr) = DVector3( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat(), + static_cast(v->xyzw[2])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector3) + { + if(!v->isConstVector(3)) + { + Error(exp, "%s: non-constant FVector3 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector3*)addr) = FVector3( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()), + float(static_cast(v->xyzw[2])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else if (f->Type == TypeVector4) + { + if(!v->isConstVector(4)) + { + Error(exp, "%s: non-constant Vector4 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector4*)addr) = DVector4( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat(), + static_cast(v->xyzw[2])->GetValue().GetFloat(), + static_cast(v->xyzw[3])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector4) + { + if(!v->isConstVector(4)) + { + Error(exp, "%s: non-constant FVector4 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector4*)addr) = FVector4( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()), + float(static_cast(v->xyzw[2])->GetValue().GetFloat()), + float(static_cast(v->xyzw[3])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else + { + Error(exp, "%s: invalid vector parameter", prop->SymbolName.GetChars()); + return; + } + } + else + { + if (exp->Type != TypeError) Error(exp, "%s: non-constant parameter", prop->SymbolName.GetChars()); + return; + } // If we get TypeError, there has already been a message from deeper down so do not print another one. - if (exp->Type != TypeError) Error(exp, "%s: non-constant parameter", prop->SymbolName.GetChars()); - return; } if (f->Type == TypeBool) @@ -467,7 +563,7 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * } else if (f->Type == TypeSound) { - *(FSoundID*)addr = GetStringConst(ex, ctx); + *(FSoundID*)addr = S_FindSound(GetStringConst(ex, ctx)); } else if (f->Type == TypeColor && ex->ValueType == TypeString) // colors can also be specified as ints. { @@ -511,6 +607,7 @@ void ZCCDoomCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * { Error(property, "unhandled property type %s", f->Type->DescriptiveName()); } +vector_ok: exp->ToErrorNode(); // invalidate after processing. exp = static_cast(exp->SiblingNext); } @@ -907,7 +1004,7 @@ void ZCCDoomCompiler::CompileStates() { state.sprite = GetSpriteIndex(sl->Sprite->GetChars()); } - FCompileContext ctx(OutNamespace, c->Type(), false); + FCompileContext ctx(OutNamespace, c->Type(), false, mVersion); if (CheckRandom(sl->Duration)) { auto func = static_cast(sl->Duration); diff --git a/src/serializer_doom.cpp b/src/serializer_doom.cpp index 4a011c28d..953bb9afc 100644 --- a/src/serializer_doom.cpp +++ b/src/serializer_doom.cpp @@ -117,7 +117,7 @@ FSerializer &SerializeArgs(FSerializer& arc, const char *key, int *args, int *de { if (val->IsArray()) { - unsigned int cnt = MIN(val->Size(), 5); + unsigned int cnt = min(val->Size(), 5); for (unsigned int i = 0; i < cnt; i++) { const rapidjson::Value &aval = (*val)[i]; diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index a982d9b67..928cdeba5 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -34,7 +34,7 @@ // HEADER FILES ------------------------------------------------------------ -#include "templates.h" + #include "actor.h" #include "c_dispatch.h" #include "filesystem.h" @@ -70,28 +70,38 @@ struct FPlayerClassLookup // a particular class and gender. class FPlayerSoundHashTable { + TMap map; public: - FPlayerSoundHashTable(); - FPlayerSoundHashTable(const FPlayerSoundHashTable &other); - ~FPlayerSoundHashTable(); - void AddSound (int player_sound_id, int sfx_id); - int LookupSound (int player_sound_id); - FPlayerSoundHashTable &operator= (const FPlayerSoundHashTable &other); - void MarkUsed(); + void AddSound(FSoundID player_sound_id, FSoundID sfx_id) + { + map.Insert(player_sound_id.index(), sfx_id); + } + FSoundID LookupSound(FSoundID player_sound_id) + { + auto v = map.CheckKey(player_sound_id.index()); + return v ? *v : NO_SOUND; + } + void MarkUsed() + { + decltype(map)::Iterator it(map); + decltype(map)::Pair* pair; + + while (it.NextPair(pair)) + { + soundEngine->MarkUsed(pair->Value); + } + } protected: struct Entry { - Entry *Next; - int PlayerSoundID; - int SfxID; + Entry* Next; + FSoundID PlayerSoundID; + FSoundID SfxID; }; enum { NUM_BUCKETS = 23 }; - Entry *Buckets[NUM_BUCKETS]; - - void Init (); - void Free (); + Entry* Buckets[NUM_BUCKETS]; }; struct FAmbientSound @@ -153,7 +163,7 @@ struct FSavedPlayerSoundInfo { FName pclass; int gender; - int refid; + FSoundID refid; int lumpnum; bool alias; }; @@ -170,18 +180,18 @@ extern bool IsFloat (const char *str); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int SortPlayerClasses (const void *a, const void *b); -static int S_DupPlayerSound (const char *pclass, int gender, int refid, int aliasref); -static void S_SavePlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool alias); +static FSoundID S_DupPlayerSound (const char *pclass, int gender, FSoundID refid, FSoundID aliasref); +static void S_SavePlayerSound (const char *pclass, int gender, FSoundID refid, int lumpnum, bool alias); static void S_RestorePlayerSounds(); static int S_AddPlayerClass (const char *name); static int S_AddPlayerGender (int classnum, int gender); static int S_FindPlayerClass (const char *name); -static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid); -static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, int &refid); +static FSoundID S_LookupPlayerSound (int classidx, int gender, FSoundID refid); +static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, FSoundID &refid); static void S_AddSNDINFO (int lumpnum); static void S_AddBloodSFX (int lumpnum); static void S_AddStrifeVoice (int lumpnum); -static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc=NULL); +static FSoundID S_AddSound (const char *logicalname, int lumpnum, FScanner *sc=NULL); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -248,7 +258,6 @@ static uint8_t CurrentPitchMask; static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArray &chain) { - auto &S_sfx = soundEngine->GetSounds(); sfxinfo_t *me = sfx; bool success = true; unsigned siz = chain.Size(); @@ -271,7 +280,7 @@ static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArrayResolveRandomSound(me); for (unsigned i = 0; i < list->Choices.Size(); ++i) { - auto rsfx = &S_sfx[list->Choices[i]]; + auto rsfx = soundEngine->GetWritableSfx(list->Choices[i]); if (rsfx == startsfx) { Printf(TEXTCOLOR_RED "recursive sound $random found for %s:\n", startsfx->name.GetChars()); @@ -289,7 +298,7 @@ static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArraylink != sfxinfo_t::NO_LINK) { - me = &S_sfx[me->link]; + me = soundEngine->GetWritableSfx(me->link); if (me == startsfx) { Printf(TEXTCOLOR_RED "recursive sound $alias found for %s:\n", startsfx->name.GetChars()); @@ -314,22 +323,21 @@ void S_CheckIntegrity() TArray chain; TArray broken; - auto &S_sfx = soundEngine->GetSounds(); - broken.Resize(S_sfx.Size()); - memset(&broken[0], 0, sizeof(bool)*S_sfx.Size()); - for (unsigned i = 0; i < S_sfx.Size(); i++) + broken.Resize(soundEngine->GetNumSounds()); + memset(&broken[0], 0, sizeof(bool) * soundEngine->GetNumSounds()); + for (unsigned i = 0; i < soundEngine->GetNumSounds(); i++) { - auto &sfx = S_sfx[i]; + auto &sfx = *soundEngine->GetWritableSfx(FSoundID::fromInt(i)); broken[i] = !S_CheckSound(&sfx, &sfx, chain); } - for (unsigned i = 0; i < S_sfx.Size(); i++) + for (unsigned i = 0; i < soundEngine->GetNumSounds(); i++) { if (broken[i]) { - auto &sfx = S_sfx[i]; + auto& sfx = *soundEngine->GetWritableSfx(FSoundID::fromInt(i)); Printf(TEXTCOLOR_RED "Sound %s has been disabled\n", sfx.name.GetChars()); sfx.bRandomHeader = false; - sfx.link = 0; // link to the empty sound. + sfx.link = NO_SOUND; // link to the empty sound. } } } @@ -345,20 +353,15 @@ void S_CheckIntegrity() unsigned int S_GetMSLength(FSoundID sound) { - auto &S_sfx = soundEngine->GetSounds(); - if ((unsigned int)sound >= S_sfx.Size()) - { - return 0; - } - - sfxinfo_t *sfx = &S_sfx[sound]; + sfxinfo_t* sfx = soundEngine->GetWritableSfx(sound); + if (!sfx) return 0; // Resolve player sounds, random sounds, and aliases if (sfx->link != sfxinfo_t::NO_LINK) { if (sfx->UserData[0] & SND_PlayerReserve) { - sfx = &S_sfx[S_FindSkinnedSound (NULL, sound)]; + sfx = soundEngine->GetWritableSfx(S_FindSkinnedSound(NULL, sound)); } else if (sfx->bRandomHeader) { @@ -379,7 +382,7 @@ unsigned int S_GetMSLength(FSoundID sound) } else { - sfx = &S_sfx[sfx->link]; + sfx = soundEngine->GetWritableSfx(sfx->link); } } @@ -403,22 +406,19 @@ DEFINE_ACTION_FUNCTION(DObject,S_GetLength) // lump. Otherwise, adds the new mapping by using S_AddSoundLump(). //========================================================================== -int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc) +FSoundID S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc) { int lump = fileSystem.CheckNumForFullName (lumpname, true, ns_sounds); return S_AddSound (logicalname, lump); } -static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) +static FSoundID S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) { - auto &S_sfx = soundEngine->GetSounds(); - int sfxid; + FSoundID sfxid = soundEngine->FindSoundNoHash (logicalname); - sfxid = soundEngine->FindSoundNoHash (logicalname); - - if (sfxid > 0) + if (sfxid.isvalid()) { // If the sound has already been defined, change the old definition - sfxinfo_t *sfx = &S_sfx[sfxid]; + auto sfx = soundEngine->GetWritableSfx(sfxid); if (sfx->UserData[0] & SND_PlayerReserve) { @@ -434,13 +434,13 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) // Redefining a player compatibility sound will redefine the target instead. if (sfx->UserData[0] & SND_PlayerCompat) { - sfx = &S_sfx[sfx->link]; + sfx = soundEngine->GetWritableSfx(sfx->link); } if (sfx->bRandomHeader) { FRandomSoundList* rnd = soundEngine->ResolveRandomSound(sfx); rnd->Choices.Reset(); - rnd->Owner = 0; + rnd->Owner = NO_SOUND; } sfx->lumpnum = lumpnum; sfx->bRandomHeader = false; @@ -468,8 +468,7 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) // Adds the given sound lump to the player sound lists. //========================================================================== -int S_AddPlayerSound (const char *pclass, int gender, int refid, - const char *lumpname) +FSoundID S_AddPlayerSound (const char *pclass, int gender, FSoundID refid, const char *lumpname) { int lump=-1; @@ -481,23 +480,25 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid, return S_AddPlayerSound (pclass, gender, refid, lump); } -int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool fromskin) +FSoundID S_AddPlayerSound (const char *pclass, int gender, FSoundID refid, int lumpnum, bool fromskin) { - auto &S_sfx = soundEngine->GetSounds(); FString fakename; - int id; + FSoundID id; + + auto sfx = soundEngine->GetSfx(refid); + if (refid == NO_SOUND || !sfx) return NO_SOUND; fakename = pclass; fakename += '"'; fakename += '0' + gender; fakename += '"'; - fakename += S_sfx[refid].name; + fakename += sfx->name.GetChars(); id = soundEngine->AddSoundLump (fakename, lumpnum, CurrentPitchMask); int classnum = S_AddPlayerClass (pclass); int soundlist = S_AddPlayerGender (classnum, gender); - PlayerSounds[soundlist].AddSound (S_sfx[refid].link, id); + PlayerSounds[soundlist].AddSound (sfx->link, id); if (fromskin) S_SavePlayerSound(pclass, gender, refid, lumpnum, false); @@ -511,16 +512,16 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bo // Adds the player sound as an alias to an existing sound. //========================================================================== -int S_AddPlayerSoundExisting (const char *pclass, int gender, int refid, - int aliasto, bool fromskin) +FSoundID S_AddPlayerSoundExisting (const char *pclass, int gender, FSoundID refid, FSoundID aliasto, bool fromskin) { int classnum = S_AddPlayerClass (pclass); int soundlist = S_AddPlayerGender (classnum, gender); + auto sfx = soundEngine->GetSfx(refid); + if (refid == NO_SOUND || !sfx) return NO_SOUND; - auto &S_sfx = soundEngine->GetSounds(); - PlayerSounds[soundlist].AddSound (S_sfx[refid].link, aliasto); + PlayerSounds[soundlist].AddSound (sfx->link, aliasto); - if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto, true); + if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto.index(), true); return aliasto; } @@ -532,173 +533,12 @@ int S_AddPlayerSoundExisting (const char *pclass, int gender, int refid, // Adds a player sound that uses the same sound as an existing player sound. //========================================================================== -int S_DupPlayerSound (const char *pclass, int gender, int refid, int aliasref) +FSoundID S_DupPlayerSound (const char *pclass, int gender, FSoundID refid, FSoundID aliasref) { - int aliasto = S_LookupPlayerSound (pclass, gender, aliasref); + auto aliasto = S_LookupPlayerSound (pclass, gender, aliasref); return S_AddPlayerSoundExisting (pclass, gender, refid, aliasto); } -//========================================================================== -// -// FPlayerSoundHashTable constructor -// -//========================================================================== - -FPlayerSoundHashTable::FPlayerSoundHashTable () -{ - Init(); -} - -//========================================================================== -// -// FPlayerSoundHashTable copy constructor -// -//========================================================================== - -FPlayerSoundHashTable::FPlayerSoundHashTable (const FPlayerSoundHashTable &other) -{ - Init(); - *this = other; -} - -//========================================================================== -// -// FPlayerSoundHashTable destructor -// -//========================================================================== - -FPlayerSoundHashTable::~FPlayerSoundHashTable () -{ - Free (); -} - -//========================================================================== -// -// FPlayerSoundHashTable :: Init -// -//========================================================================== - -void FPlayerSoundHashTable::Init () -{ - for (int i = 0; i < NUM_BUCKETS; ++i) - { - Buckets[i] = NULL; - } -} - -//========================================================================== -// -// FPlayerSoundHashTable :: Free -// -//========================================================================== - -void FPlayerSoundHashTable::Free () -{ - for (int i = 0; i < NUM_BUCKETS; ++i) - { - Entry *entry, *next; - - for (entry = Buckets[i]; entry != NULL; ) - { - next = entry->Next; - delete entry; - entry = next; - } - Buckets[i] = NULL; - } -} - -//========================================================================== -// -// FPlayerSoundHashTable :: operator= -// -//========================================================================== - -FPlayerSoundHashTable &FPlayerSoundHashTable::operator= (const FPlayerSoundHashTable &other) -{ - Free (); - for (int i = 0; i < NUM_BUCKETS; ++i) - { - Entry *entry; - - for (entry = other.Buckets[i]; entry != NULL; entry = entry->Next) - { - AddSound (entry->PlayerSoundID, entry->SfxID); - } - } - return *this; -} - -//========================================================================== -// -// FPlayerSoundHashTable :: AddSound -// -//========================================================================== - -void FPlayerSoundHashTable::AddSound (int player_sound_id, int sfx_id) -{ - Entry *entry; - unsigned bucket_num = (unsigned)player_sound_id % NUM_BUCKETS; - - // See if the entry exists already. - for (entry = Buckets[bucket_num]; - entry != NULL && entry->PlayerSoundID != player_sound_id; - entry = entry->Next) - { } - - if (entry != NULL) - { // If the player sound is already present, redefine it. - entry->SfxID = sfx_id; - } - else - { // Otherwise, add it to the start of its bucket. - entry = new Entry; - entry->Next = Buckets[bucket_num]; - entry->PlayerSoundID = player_sound_id; - entry->SfxID = sfx_id; - Buckets[bucket_num] = entry; - } -} - -//========================================================================== -// -// FPlayerSoundHashTable :: LookupSound -// -//========================================================================== - -int FPlayerSoundHashTable::LookupSound (int player_sound_id) -{ - Entry *entry; - unsigned bucket_num = (unsigned)player_sound_id % NUM_BUCKETS; - - // See if the entry exists already. - for (entry = Buckets[bucket_num]; - entry != NULL && entry->PlayerSoundID != player_sound_id; - entry = entry->Next) - { } - - return entry != NULL ? entry->SfxID : 0; -} - -//========================================================================== -// -// FPlayerSoundHashTable :: Mark -// -// Marks all sounds defined for this class/gender as used. -// -//========================================================================== - -void FPlayerSoundHashTable::MarkUsed() -{ - for (size_t i = 0; i < NUM_BUCKETS; ++i) - { - for (Entry *probe = Buckets[i]; probe != NULL; probe = probe->Next) - { - soundEngine->MarkUsed(probe->SfxID); - } - } -} - //========================================================================== // // S_ClearSoundData @@ -737,7 +577,6 @@ void S_ClearSoundData() void S_ParseSndInfo (bool redefine) { - auto &S_sfx = soundEngine->GetSounds(); int lump; if (!redefine) SavedPlayerSounds.Clear(); // clear skin sounds only for initial parsing. @@ -794,9 +633,9 @@ void S_AddLocalSndInfo(int lump) static void S_AddSNDINFO (int lump) { - auto &S_sfx = soundEngine->GetSounds(); bool skipToEndIf; - TArray list; + TArray list; + int wantassigns = -1; FScanner sc(lump); skipToEndIf = false; @@ -829,7 +668,7 @@ static void S_AddSNDINFO (int lump) ambient->periodmax = 0; ambient->volume = 0; ambient->attenuation = 0; - ambient->sound = 0; + ambient->sound = NO_SOUND; sc.MustGetString (); ambient->sound = FSoundID(soundEngine->FindSoundTentative(sc.String)); @@ -933,13 +772,14 @@ static void S_AddSNDINFO (int lump) case SI_PlayerSound: { // $playersound FString pclass; - int gender, refid, sfxnum; + int gender; + FSoundID refid, sfxnum; S_ParsePlayerSoundCommon (sc, pclass, gender, refid); sfxnum = S_AddPlayerSound (pclass, gender, refid, sc.String); if (0 == stricmp(sc.String, "dsempty")) { - S_sfx[sfxnum].UserData[0] |= SND_PlayerSilent; + soundEngine->GetWritableSfx(sfxnum)->UserData[0] |= SND_PlayerSilent; } } break; @@ -947,13 +787,15 @@ static void S_AddSNDINFO (int lump) case SI_PlayerSoundDup: { // $playersounddup FString pclass; - int gender, refid, targid; + int gender; + FSoundID refid, targid; S_ParsePlayerSoundCommon (sc, pclass, gender, refid); targid = soundEngine->FindSoundNoHash (sc.String); - if (!(S_sfx[targid].UserData[0] & SND_PlayerReserve)) + auto sfx = soundEngine->GetWritableSfx(targid); + if (!sfx || !(sfx->UserData[0] & SND_PlayerReserve)) { - sc.ScriptError ("%s is not a player sound", sc.String); + sc.ScriptError("%s is not a player sound", sc.String); } S_DupPlayerSound (pclass, gender, refid, targid); } @@ -962,22 +804,24 @@ static void S_AddSNDINFO (int lump) case SI_PlayerCompat: { // $playercompat FString pclass; - int gender, refid; - int sfxfrom, aliasto; + int gender; + FSoundID refid; + FSoundID sfxfrom, aliasto; S_ParsePlayerSoundCommon (sc, pclass, gender, refid); sfxfrom = S_AddSound (sc.String, -1, &sc); aliasto = S_LookupPlayerSound (pclass, gender, refid); - S_sfx[sfxfrom].link = aliasto; - S_sfx[sfxfrom].UserData[0] |= SND_PlayerCompat; + auto sfx = soundEngine->GetWritableSfx(sfxfrom); + sfx->link = aliasto; + sfx->UserData[0] |= SND_PlayerCompat; } break; case SI_PlayerAlias: { // $playeralias FString pclass; - int gender, refid; - int soundnum; + int gender; + FSoundID refid, soundnum; S_ParsePlayerSoundCommon (sc, pclass, gender, refid); soundnum = soundEngine->FindSoundTentative (sc.String); @@ -987,71 +831,76 @@ static void S_AddSNDINFO (int lump) case SI_Alias: { // $alias - int sfxfrom; + FSoundID sfxfrom; sc.MustGetString (); sfxfrom = S_AddSound (sc.String, -1, &sc); sc.MustGetString (); - if (S_sfx[sfxfrom].UserData[0] & SND_PlayerCompat) + auto sfx = soundEngine->GetWritableSfx(sfxfrom); + if (sfx->UserData[0] & SND_PlayerCompat) { - sfxfrom = S_sfx[sfxfrom].link; + sfxfrom = sfx->link; } - S_sfx[sfxfrom].link = soundEngine->FindSoundTentative (sc.String); - S_sfx[sfxfrom].NearLimit = -1; // Aliases must use the original sound's limit. + sfx->link = soundEngine->FindSoundTentative (sc.String); + sfx->NearLimit = -1; // Aliases must use the original sound's limit. } break; case SI_Limit: { // $limit [] - int sfx; + FSoundID sfxfrom; sc.MustGetString (); - sfx = soundEngine->FindSoundTentative (sc.String); + sfxfrom = soundEngine->FindSoundTentative (sc.String); sc.MustGetNumber (); - S_sfx[sfx].NearLimit = MIN(MAX(sc.Number, 0), 255); + auto sfx = soundEngine->GetWritableSfx(sfxfrom); + sfx->NearLimit = min(max(sc.Number, 0), 255); if (sc.CheckFloat()) { - S_sfx[sfx].LimitRange = float(sc.Float * sc.Float); + sfx->LimitRange = float(sc.Float * sc.Float); } } break; case SI_Singular: { // $singular - int sfx; + FSoundID sfx; sc.MustGetString (); sfx = soundEngine->FindSoundTentative (sc.String); - S_sfx[sfx].bSingular = true; + auto sfxp = soundEngine->GetWritableSfx(sfx); + sfxp->bSingular = true; } break; case SI_PitchShift: { // $pitchshift - int sfx; + FSoundID sfx; sc.MustGetString (); sfx = soundEngine->FindSoundTentative (sc.String); sc.MustGetNumber (); - S_sfx[sfx].PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1; + auto sfxp = soundEngine->GetWritableSfx(sfx); + sfxp->PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1; } break; case SI_PitchSet: { // $pitchset [range maximum] - int sfx; + FSoundID sfx; sc.MustGetString(); sfx = soundEngine->FindSoundTentative(sc.String); sc.MustGetFloat(); - S_sfx[sfx].DefPitch = (float)sc.Float; + auto sfxp = soundEngine->GetWritableSfx(sfx); + sfxp->DefPitch = (float)sc.Float; if (sc.CheckFloat()) { - S_sfx[sfx].DefPitchMax = (float)sc.Float; + sfxp->DefPitchMax = (float)sc.Float; } else { - S_sfx[sfx].DefPitchMax = 0; + sfxp->DefPitchMax = 0; } } break; @@ -1064,23 +913,25 @@ static void S_AddSNDINFO (int lump) case SI_Volume: { // $volume - int sfx; + FSoundID sfx; sc.MustGetString(); sfx = soundEngine->FindSoundTentative(sc.String); sc.MustGetFloat(); - S_sfx[sfx].Volume = (float)sc.Float; + auto sfxp = soundEngine->GetWritableSfx(sfx); + sfxp->Volume = (float)sc.Float; } break; case SI_Attenuation: { // $attenuation - int sfx; + FSoundID sfx; sc.MustGetString(); sfx = soundEngine->FindSoundTentative(sc.String); sc.MustGetFloat(); - S_sfx[sfx].Attenuation = (float)sc.Float; + auto sfxp = soundEngine->GetWritableSfx(sfx); + sfxp->Attenuation = (float)sc.Float; } break; @@ -1089,18 +940,19 @@ static void S_AddSNDINFO (int lump) // Using * for the name makes it the default for sounds that don't specify otherwise. FRolloffInfo *rolloff; int type; - int sfx; + FSoundID sfx; sc.MustGetString(); if (sc.Compare("*")) { - sfx = -1; + sfx = INVALID_SOUND; rolloff = &soundEngine->GlobalRolloff(); } else { sfx = soundEngine->FindSoundTentative(sc.String); - rolloff = &S_sfx[sfx].Rolloff; + auto sfxp = soundEngine->GetWritableSfx(sfx); + rolloff = &sfxp->Rolloff; } type = ROLLOFF_Doom; if (!sc.CheckFloat()) @@ -1136,11 +988,11 @@ static void S_AddSNDINFO (int lump) list.Clear (); sc.MustGetString (); - uint32_t Owner = S_AddSound (sc.String, -1, &sc); + FSoundID Owner = S_AddSound (sc.String, -1, &sc); sc.MustGetStringName ("{"); while (sc.GetString () && !sc.Compare ("}")) { - uint32_t sfxto = soundEngine->FindSoundTentative (sc.String); + FSoundID sfxto = soundEngine->FindSoundTentative (sc.String); if (sfxto == random.Owner) { Printf("Definition of random sound '%s' refers to itself recursively.\n", sc.String); @@ -1150,8 +1002,9 @@ static void S_AddSNDINFO (int lump) } if (list.Size() == 1) { // Only one sound: treat as $alias - S_sfx[Owner].link = list[0]; - S_sfx[Owner].NearLimit = -1; + auto sfxp = soundEngine->GetWritableSfx(Owner); + sfxp->link = list[0]; + sfxp->NearLimit = -1; } else if (list.Size() > 1) { // Only add non-empty random lists @@ -1245,6 +1098,15 @@ static void S_AddSNDINFO (int lump) else { // Got a logical sound mapping FString name (sc.String); + if (wantassigns == -1) + { + wantassigns = sc.CheckString("="); + } + else if (wantassigns) + { + sc.MustGetStringName("="); + } + sc.MustGetString (); S_AddSound (name, sc.String, &sc); } @@ -1274,7 +1136,7 @@ static void S_AddStrifeVoice (int lumpnum) // (player class, gender, and ref id) //========================================================================== -static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, int &refid) +static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, FSoundID &refid) { sc.MustGetString (); pclass = sc.String; @@ -1282,21 +1144,22 @@ static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender gender = D_GenderToInt (sc.String); sc.MustGetString (); refid = soundEngine->FindSoundNoHash (sc.String); - auto &S_sfx = soundEngine->GetSounds(); - if (refid != 0 && !(S_sfx[refid].UserData[0] & SND_PlayerReserve) && !S_sfx[refid].bTentative) + auto sfx = soundEngine->GetWritableSfx(refid); + if (refid.isvalid() && sfx && !(sfx->UserData[0] & SND_PlayerReserve) && !sfx->bTentative) { sc.ScriptError ("%s has already been used for a non-player sound.", sc.String); } - if (refid == 0) + if (refid == NO_SOUND) { refid = S_AddSound (sc.String, -1, &sc); - S_sfx[refid].bTentative = true; + sfx = soundEngine->GetWritableSfx(refid); + sfx->bTentative = true; } - if (S_sfx[refid].bTentative) + if (sfx->bTentative) { - S_sfx[refid].link = NumPlayerReserves++; - S_sfx[refid].bTentative = false; - S_sfx[refid].UserData[0] |= SND_PlayerReserve; + sfx->link = FSoundID::fromInt(NumPlayerReserves++); + sfx->bTentative = false; + sfx->UserData[0] |= SND_PlayerReserve; } sc.MustGetString (); } @@ -1432,20 +1295,11 @@ static int SortPlayerClasses (const void *a, const void *b) // Returns the sound for the given player class, gender, and sound name. //========================================================================== -int S_LookupPlayerSound (const char *pclass, int gender, const char *name) +FSoundID S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid) { - int refid = S_FindSound (name); - if (refid != 0) - { - refid = S_LookupPlayerSound (pclass, gender, refid); - } - return refid; -} + auto sfxp = soundEngine->GetWritableSfx(refid); -int S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid) -{ - auto &S_sfx = soundEngine->GetSounds(); - if (!(S_sfx[refid].UserData[0] & SND_PlayerReserve)) + if (sfxp && !(sfxp->UserData[0] & SND_PlayerReserve)) { // Not a player sound, so just return this sound return refid; } @@ -1453,9 +1307,8 @@ int S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid) return S_LookupPlayerSound (S_FindPlayerClass (pclass), gender, refid); } -static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid) +static FSoundID S_LookupPlayerSound (int classidx, int gender, FSoundID refid) { - auto &S_sfx = soundEngine->GetSounds(); int ingender = gender; if (classidx == -1) @@ -1479,19 +1332,22 @@ static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid) { return S_LookupPlayerSound (DefPlayerClass, gender, refid); } - return 0; + return NO_SOUND; } gender = g; } + auto sfxp = soundEngine->GetWritableSfx(refid); + if (!sfxp) return NO_SOUND; - int sndnum = PlayerSounds[listidx].LookupSound (S_sfx[refid].link); + FSoundID sndnum = PlayerSounds[listidx].LookupSound (sfxp->link); + sfxp = soundEngine->GetWritableSfx(sndnum); // If we're not done parsing SNDINFO yet, assume that the target sound is valid if (PlayerClassesIsSorted && - (sndnum == 0 || - ((S_sfx[sndnum].lumpnum == -1 || S_sfx[sndnum].lumpnum == sfx_empty) && - S_sfx[sndnum].link == sfxinfo_t::NO_LINK && - !(S_sfx[sndnum].UserData[0] & SND_PlayerSilent)))) + (!sfxp || sndnum == NO_SOUND || + ((sfxp->lumpnum == -1 || sfxp->lumpnum == sfx_empty) && + sfxp->link == sfxinfo_t::NO_LINK && + !(sfxp->UserData[0] & SND_PlayerSilent)))) { // This sound is unavailable. if (ingender != 0) { // Try "male" @@ -1515,7 +1371,7 @@ static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid) // //========================================================================== -static void S_SavePlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool alias) +static void S_SavePlayerSound (const char *pclass, int gender, FSoundID refid, int lumpnum, bool alias) { FSavedPlayerSoundInfo spi; @@ -1534,7 +1390,7 @@ static void S_RestorePlayerSounds() FSavedPlayerSoundInfo * spi = &SavedPlayerSounds[i]; if (spi->alias) { - S_AddPlayerSoundExisting(spi->pclass.GetChars(), spi->gender, spi->refid, spi->lumpnum); + S_AddPlayerSoundExisting(spi->pclass.GetChars(), spi->gender, spi->refid, FSoundID::fromInt(spi->lumpnum)); } else { @@ -1550,26 +1406,20 @@ static void S_RestorePlayerSounds() // Returns true if two sounds are essentially the same thing //========================================================================== -bool S_AreSoundsEquivalent (AActor *actor, const char *name1, const char *name2) -{ - return S_AreSoundsEquivalent (actor, S_FindSound (name1), S_FindSound (name2)); -} - -bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2) +bool S_AreSoundsEquivalent (AActor *actor, FSoundID id1, FSoundID id2) { sfxinfo_t *sfx; - auto &S_sfx = soundEngine->GetSounds(); if (id1 == id2) { return true; } - if (id1 == 0 || id2 == 0) + if (!id1.isvalid() || !id2.isvalid()) { return false; } // Dereference aliases, but not random or player sounds - while ((sfx = &S_sfx[id1])->link != sfxinfo_t::NO_LINK) + while (sfx = soundEngine->GetWritableSfx(id1), sfx->link != sfxinfo_t::NO_LINK) { if (sfx->UserData[0] & SND_PlayerReserve) { @@ -1584,7 +1434,7 @@ bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2) id1 = sfx->link; } } - while ((sfx = &S_sfx[id2])->link != sfxinfo_t::NO_LINK) + while (sfx = soundEngine->GetWritableSfx(id2), sfx->link != sfxinfo_t::NO_LINK) { if (sfx->UserData[0] & SND_PlayerReserve) { @@ -1631,7 +1481,7 @@ const char *S_GetSoundClass(AActor *pp) // Calls S_LookupPlayerSound, deducing the class and gender from actor. //========================================================================== -int S_FindSkinnedSound (AActor *actor, FSoundID refid) +FSoundID S_FindSkinnedSound (AActor *actor, FSoundID refid) { const char *pclass; int gender = 0; @@ -1656,7 +1506,7 @@ int S_FindSkinnedSound (AActor *actor, FSoundID refid) // Tries looking for both "name-extendedname" and "name" in that order. //========================================================================== -int S_FindSkinnedSoundEx (AActor *actor, const char *name, const char *extendedname) +FSoundID S_FindSkinnedSoundEx (AActor *actor, const char *name, const char *extendedname) { FString fullname; @@ -1664,11 +1514,11 @@ int S_FindSkinnedSoundEx (AActor *actor, const char *name, const char *extendedn fullname = name; fullname += '-'; fullname += extendedname; - FSoundID id = fullname; + FSoundID id = S_FindSound(fullname); - if (id == 0) + if (!id.isvalid()) { // Look for "name" - id = name; + id = S_FindSound(name); } return S_FindSkinnedSound (actor, id); } @@ -1708,18 +1558,17 @@ void S_MarkPlayerSounds (AActor *player) CCMD (soundlinks) { - auto &S_sfx = soundEngine->GetSounds(); unsigned int i; - for (i = 0; i < S_sfx.Size (); i++) + for (i = 0; i < soundEngine->GetNumSounds(); i++) { - const sfxinfo_t *sfx = &S_sfx[i]; + const sfxinfo_t* sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); if (sfx->link != sfxinfo_t::NO_LINK && !sfx->bRandomHeader && !(sfx->UserData[0] & SND_PlayerReserve)) { - Printf ("%s -> %s\n", sfx->name.GetChars(), S_sfx[sfx->link].name.GetChars()); + Printf ("%s -> %s\n", sfx->name.GetChars(), soundEngine->GetSfx(sfx->link)->name.GetChars()); } } } @@ -1732,19 +1581,19 @@ CCMD (soundlinks) CCMD (playersounds) { - auto &S_sfx = soundEngine->GetSounds(); const char *reserveNames[256]; unsigned int i; int j, k, l; // Find names for the player sounds memset (reserveNames, 0, sizeof(reserveNames)); - for (i = j = 0; j < NumPlayerReserves && i < S_sfx.Size(); ++i) + for (i = j = 0; j < NumPlayerReserves && i < soundEngine->GetNumSounds(); ++i) { - if (S_sfx[i].UserData[0] & SND_PlayerReserve) + auto sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); + if (sfx->UserData[0] & SND_PlayerReserve) { ++j; - reserveNames[S_sfx[i].link] = S_sfx[i].name; + reserveNames[sfx->link.index()] = sfx->name.GetChars(); } } @@ -1757,7 +1606,9 @@ CCMD (playersounds) Printf ("\n%s, %s:\n", PlayerClassLookups[i].Name.GetChars(), GenderNames[j]); for (k = 0; k < NumPlayerReserves; ++k) { - Printf (" %-16s%s\n", reserveNames[k], S_sfx[PlayerSounds[l].LookupSound (k)].name.GetChars()); + auto sndid = PlayerSounds[l].LookupSound(FSoundID::fromInt(k)); + auto sfx = soundEngine->GetSfx(sndid); + Printf (" %-16s%s\n", reserveNames[k], sfx->name.GetChars()); } } } @@ -1840,7 +1691,7 @@ DEFINE_ACTION_FUNCTION(AAmbientSound, Tick) loop = CHANF_LOOP; } - if (ambient->sound != FSoundID(0)) + if (ambient->sound != NO_SOUND) { // The second argument scales the ambient sound's volume. // 0 and 100 are normal volume. The maximum volume level @@ -1909,7 +1760,7 @@ DEFINE_ACTION_FUNCTION(AAmbientSound, Activate) { if ((amb->type & 3) == 0 && amb->periodmin == 0) { - if (amb->sound == 0) + if (!amb->sound.isvalid()) { self->Destroy (); return 0; diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index c8cbd4bb8..697fdcc3a 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -70,9 +70,6 @@ // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FBoolCVar noisedebug("noise", false, 0); // [RH] Print sound debugging info? - - static FString LastLocalSndInfo; static FString LastLocalSndSeq; void S_AddLocalSndInfo(int lump); @@ -84,15 +81,15 @@ class DoomSoundEngine : public SoundEngine void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID soundid, FVector3* pos, FVector3* vel, FSoundChan *) override; bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel); TArray ReadSound(int lumpnum); - int PickReplacement(int refid); + FSoundID PickReplacement(FSoundID refid); FSoundID ResolveSound(const void *ent, int type, FSoundID soundid, float &attenuation) override; void CacheSound(sfxinfo_t* sfx) override; void StopChannel(FSoundChan* chan) override; - int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2) override + FSoundID AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2) override { auto ndx = SoundEngine::AddSoundLump(logicalname, lump, CurrentPitchMask, resid, nearlimit); - S_sfx[ndx].UserData.Resize(1); - S_sfx[ndx].UserData[0] = 0; + S_sfx[ndx.index()].UserData.Resize(1); + S_sfx[ndx.index()].UserData[0] = 0; return ndx; } bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel, float attenuation) override @@ -454,7 +451,7 @@ void DoomSoundEngine::CacheSound(sfxinfo_t* sfx) FSoundID DoomSoundEngine::ResolveSound(const void * ent, int type, FSoundID soundid, float &attenuation) { - auto sfx = &S_sfx[soundid]; + auto sfx = &S_sfx[soundid.index()]; if (sfx->UserData[0] & SND_PlayerReserve) { AActor *src; @@ -623,7 +620,7 @@ void S_PlaySound(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, void A_StartSound(AActor *self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime) { - S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, (float)pitch, (float)startTime); + S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), FSoundID::fromInt(soundid), (float)volume, (float)attenuation, (float)pitch, (float)startTime); } void A_PlaySound(AActor* self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch) @@ -730,17 +727,17 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch) // Is a sound being played by a specific emitter? //========================================================================== -bool S_GetSoundPlayingInfo (const AActor *actor, int sound_id) +bool S_GetSoundPlayingInfo (const AActor *actor, FSoundID sound_id) { return soundEngine->GetSoundPlayingInfo(SOURCE_Actor, actor, sound_id); } -bool S_GetSoundPlayingInfo (const sector_t *sec, int sound_id) +bool S_GetSoundPlayingInfo (const sector_t *sec, FSoundID sound_id) { return soundEngine->GetSoundPlayingInfo(SOURCE_Sector, sec, sound_id); } -bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id) +bool S_GetSoundPlayingInfo (const FPolyObj *poly, FSoundID sound_id) { return soundEngine->GetSoundPlayingInfo(SOURCE_Polyobj, poly, sound_id); } @@ -751,7 +748,7 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id) // //========================================================================== -int S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) +bool S_IsActorPlayingSomething (AActor *actor, int channel, FSoundID sound_id) { if (compatflags & COMPATF_MAGICSILENCE) { @@ -844,6 +841,8 @@ static FSerializer &Serialize(FSerializer &arc, const char *key, FSoundChan &cha ("rolloffmax", chan.Rolloff.MaxDistance) ("limitrange", chan.LimitRange); + if (SaveVersion < 4560) chan.Pitch /= 128.f; + switch (chan.SourceType) { case SOURCE_None: break; @@ -920,51 +919,6 @@ void S_SerializeSounds(FSerializer &arc) GSnd->UpdateSounds(); } -//========================================================================== -// -// S_SetSoundPaused -// -// Called with state non-zero when the app is active, zero when it isn't. -// -//========================================================================== - -void S_SetSoundPaused(int state) -{ - if (state) - { - if (paused == 0) - { - S_ResumeSound(true); - if (GSnd != nullptr) - { - GSnd->SetInactive(SoundRenderer::INACTIVE_Active); - } - } - } - else - { - if (paused == 0) - { - S_PauseSound(false, true); - if (GSnd != nullptr) - { - GSnd->SetInactive(gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL ? - SoundRenderer::INACTIVE_Complete : - SoundRenderer::INACTIVE_Mute); - } - } - } - if (!netgame -#ifdef _DEBUG - && !demoplayback -#endif - ) - { - pauseext = !state; - } -} - - //========================================================================== // // CalcSectorSoundOrg @@ -1004,11 +958,11 @@ static void CalcSectorSoundOrg(const DVector3& listenpos, const sector_t* sec, i // Set sound vertical position based on channel. if (channum == CHAN_FLOOR) { - pos.Y = (float)MIN(sec->floorplane.ZatPoint(listenpos), listenpos.Z); + pos.Y = (float)min(sec->floorplane.ZatPoint(listenpos), listenpos.Z); } else if (channum == CHAN_CEILING) { - pos.Y = (float)MAX(sec->ceilingplane.ZatPoint(listenpos), listenpos.Z); + pos.Y = (float)max(sec->ceilingplane.ZatPoint(listenpos), listenpos.Z); } else if (channum == CHAN_INTERIOR) { @@ -1225,11 +1179,11 @@ TArray DoomSoundEngine::ReadSound(int lumpnum) //========================================================================== static FRandom pr_randsound("RandSound"); -int DoomSoundEngine::PickReplacement(int refid) +FSoundID DoomSoundEngine::PickReplacement(FSoundID refid) { - while (S_sfx[refid].bRandomHeader) + while (S_sfx[refid.index()].bRandomHeader) { - const FRandomSoundList* list = &S_rnd[S_sfx[refid].link]; + const FRandomSoundList* list = &S_rnd[S_sfx[refid.index()].link.index()]; refid = list->Choices[pr_randsound(list->Choices.Size())]; } return refid; @@ -1286,7 +1240,7 @@ void DoomSoundEngine::NoiseDebug() color = (chan->ChanFlags & CHANF_LOOP) ? CR_BROWN : CR_GREY; // Name - fileSystem.GetFileShortName(temp, S_sfx[chan->SoundID].lumpnum); + fileSystem.GetFileShortName(temp, S_sfx[chan->SoundID.index()].lumpnum); temp[8] = 0; DrawText(twod, NewConsoleFont, color, 0, y, temp, TAG_DONE); @@ -1366,9 +1320,10 @@ void DoomSoundEngine::NoiseDebug() } } -void S_NoiseDebug(void) +ADD_STAT(sounddebug) { static_cast(soundEngine)->NoiseDebug(); + return ""; } @@ -1380,21 +1335,20 @@ void S_NoiseDebug(void) void DoomSoundEngine::PrintSoundList() { - auto &S_sfx = soundEngine->GetSounds(); char lumpname[9]; unsigned int i; lumpname[8] = 0; - for (i = 0; i < S_sfx.Size(); i++) + for (i = 0; i < soundEngine->GetNumSounds(); i++) { - const sfxinfo_t* sfx = &S_sfx[i]; + const sfxinfo_t* sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); if (sfx->bRandomHeader) { Printf("%3d. %s -> #%d {", i, sfx->name.GetChars(), sfx->link); - const FRandomSoundList* list = &S_rnd[sfx->link]; + const FRandomSoundList* list = &S_rnd[sfx->link.index()]; for (auto& me : list->Choices) { - Printf(" %s ", S_sfx[me].name.GetChars()); + Printf(" %s ", S_sfx[me.index()].name.GetChars()); } Printf("}\n"); } @@ -1409,7 +1363,7 @@ void DoomSoundEngine::PrintSoundList() } else if (S_sfx[i].link != sfxinfo_t::NO_LINK) { - Printf("%3d. %s -> %s\n", i, sfx->name.GetChars(), S_sfx[sfx->link].name.GetChars()); + Printf("%3d. %s -> %s\n", i, sfx->name.GetChars(), S_sfx[sfx->link.index()].name.GetChars()); } else { @@ -1434,8 +1388,8 @@ CCMD (playsound) { if (argv.argc() > 1) { - FSoundID id = argv[1]; - if (id == 0) + FSoundID id = S_FindSound(argv[1]); + if (!id.isvalid()) { Printf("'%s' is not a sound\n", argv[1]); } @@ -1456,8 +1410,8 @@ CCMD (loopsound) { if (players[consoleplayer].mo != nullptr && !netgame && argv.argc() > 1) { - FSoundID id = argv[1]; - if (id == 0) + FSoundID id = S_FindSound(argv[1]); + if (!id.isvalid()) { Printf("'%s' is not a sound\n", argv[1]); } @@ -1472,111 +1426,8 @@ CCMD (loopsound) } } -//========================================================================== -// -// CCMD cachesound -// -//========================================================================== - -CCMD (cachesound) -{ - if (argv.argc() < 2) - { - Printf ("Usage: cachesound ...\n"); - return; - } - for (int i = 1; i < argv.argc(); ++i) - { - FSoundID sfxnum = argv[i]; - if (sfxnum != FSoundID(0)) - { - soundEngine->CacheSound(sfxnum); - } - } -} - - -CCMD(listsoundchannels) -{ - Printf("%s", soundEngine->ListSoundChannels().GetChars()); -} - -// intentionally moved here to keep the s_music include out of the rest of the file. - -//========================================================================== -// -// S_PauseSound -// -// Stop music and sound effects, during game PAUSE. -//========================================================================== -#include "s_music.h" - -void S_PauseSound (bool notmusic, bool notsfx) -{ - if (!notmusic) - { - S_PauseMusic(); - } - if (!notsfx) - { - soundEngine->SetPaused(true); - GSnd->SetSfxPaused (true, 0); - } -} - -DEFINE_ACTION_FUNCTION(DObject, S_PauseSound) -{ - PARAM_PROLOGUE; - PARAM_BOOL(notmusic); - PARAM_BOOL(notsfx); - S_PauseSound(notmusic, notsfx); - return 0; -} - -//========================================================================== -// -// S_ResumeSound -// -// Resume music and sound effects, after game PAUSE. -//========================================================================== - -void S_ResumeSound (bool notsfx) -{ - S_ResumeMusic(); - if (!notsfx) - { - soundEngine->SetPaused(false); - GSnd->SetSfxPaused (false, 0); - } -} - -DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound) -{ - PARAM_PROLOGUE; - PARAM_BOOL(notsfx); - S_ResumeSound(notsfx); - return 0; -} - - -CCMD (snd_status) -{ - GSnd->PrintStatus (); -} - -CCMD (snd_reset) +CCMD(snd_reset) { S_SoundReset(); } -CCMD (snd_listdrivers) -{ - GSnd->PrintDriversList (); -} - -ADD_STAT (sound) -{ - return GSnd->GatherStats (); -} - - diff --git a/src/sound/s_doomsound.h b/src/sound/s_doomsound.h index e826c69de..b6c6dc336 100644 --- a/src/sound/s_doomsound.h +++ b/src/sound/s_doomsound.h @@ -16,10 +16,18 @@ void S_PrecacheLevel(FLevelLocals* l); // Start sound for thing at void S_Sound(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); +inline void S_Sound(int channel, EChanFlags flags, const char* 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); void S_Sound (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); +inline void S_Sound(AActor* ent, int channel, EChanFlags flags, const char* sfxid, float volume, float attenuation) +{ + S_Sound(ent, channel, flags, S_FindSound(sfxid), volume, attenuation); +} void S_SoundMinMaxDist (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float mindist, float maxdist); void S_Sound (const FPolyObj *poly, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); void S_Sound (const sector_t *sec, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); @@ -40,11 +48,11 @@ void S_StopActorSounds(AActor *actor, int chanmin, int chanmax); void S_RelinkSound (AActor *from, AActor *to); // Is the sound playing on one of the emitter's channels? -bool S_GetSoundPlayingInfo (const AActor *actor, int sound_id); -bool S_GetSoundPlayingInfo (const sector_t *sector, int sound_id); -bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id); +bool S_GetSoundPlayingInfo (const AActor *actor, FSoundID sound_id = INVALID_SOUND); +bool S_GetSoundPlayingInfo (const sector_t *sector, FSoundID sound_id = INVALID_SOUND); +bool S_GetSoundPlayingInfo (const FPolyObj *poly, FSoundID sound_id = INVALID_SOUND); -int S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id); +bool S_IsActorPlayingSomething (AActor *actor, int channel, FSoundID sound_id = INVALID_SOUND); // Change a playing sound's volume void S_ChangeActorSoundVolume(AActor *actor, int channel, double volume); @@ -55,6 +63,7 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch); // Stores/retrieves playing channel information in an archive. void S_SerializeSounds(FSerializer &arc); +// these must retain their integer sound IDs because they are direct native functions for ZScript. void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch); void A_StartSound(AActor* self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime = 0.); static void S_SetListener(AActor *listenactor); diff --git a/src/sound/s_sndseq.cpp b/src/sound/s_sndseq.cpp index abe16c3c8..99b58a8f9 100644 --- a/src/sound/s_sndseq.cpp +++ b/src/sound/s_sndseq.cpp @@ -34,6 +34,7 @@ #include "po_man.h" #include "gi.h" #include "c_dispatch.h" +#include "i_interface.h" #include "g_level.h" #include "serializer_doom.h" @@ -154,7 +155,7 @@ public: } bool IsPlaying() { - return m_CurrentSoundID != 0 && S_GetSoundPlayingInfo (m_Poly, m_CurrentSoundID); + return m_CurrentSoundID.isvalid() && S_GetSoundPlayingInfo (m_Poly, m_CurrentSoundID); } void *Source() { @@ -183,7 +184,7 @@ public: } bool IsPlaying() { - return m_CurrentSoundID != 0 && S_GetSoundPlayingInfo (m_Sector, m_CurrentSoundID); + return m_CurrentSoundID.isvalid() && S_GetSoundPlayingInfo (m_Sector, m_CurrentSoundID); } void *Source() { @@ -312,7 +313,7 @@ void DSeqNode::Serialize(FSerializer &arc) unsigned int i; FName seqName = NAME_None; int delayTics = 0; - FSoundID id = 0; + FSoundID id = NO_SOUND; float volume; float atten = ATTN_NORM; int seqnum; @@ -569,7 +570,7 @@ void S_ParseSndSeq (int levellump) char seqtype = ':'; FName seqname = NAME_None; FName slot = NAME_None; - int stopsound; + FSoundID stopsound; int delaybase; float volumebase; int curseq = -1; @@ -580,7 +581,7 @@ void S_ParseSndSeq (int levellump) S_ClearSndSeq(); // be gone, compiler warnings - stopsound = 0; + stopsound = NO_SOUND; memset (SeqTrans, -1, sizeof(SeqTrans)); lastlump = 0; @@ -617,7 +618,7 @@ void S_ParseSndSeq (int levellump) Sequences.Push (NULL); } ScriptTemp.Clear(); - stopsound = 0; + stopsound = NO_SOUND; slot = NAME_None; if (seqtype == '[') { @@ -635,7 +636,7 @@ void S_ParseSndSeq (int levellump) if (sc.String[0] == ']') { // End of this definition ScriptTemp[0] = MakeCommand(SS_CMD_SELECT, (ScriptTemp.Size()-1)/2); - AddSequence (curseq, seqname, slot, stopsound, ScriptTemp); + AddSequence (curseq, seqname, slot, stopsound.index(), ScriptTemp); curseq = -1; sc.SetCMode (false); } @@ -660,30 +661,30 @@ void S_ParseSndSeq (int levellump) { case SS_STRING_PLAYUNTILDONE: sc.MustGetString (); - ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String))); + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String).index())); ScriptTemp.Push(MakeCommand(SS_CMD_WAITUNTILDONE, 0)); break; case SS_STRING_PLAY: sc.MustGetString (); - ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String))); + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String).index())); break; case SS_STRING_PLAYTIME: sc.MustGetString (); - ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String))); + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String).index())); sc.MustGetNumber (); ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc.Number)); break; case SS_STRING_PLAYREPEAT: sc.MustGetString (); - ScriptTemp.Push(MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc.String))); + ScriptTemp.Push(MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc.String).index())); break; case SS_STRING_PLAYLOOP: sc.MustGetString (); - ScriptTemp.Push(MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc.String))); + ScriptTemp.Push(MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc.String).index())); sc.MustGetNumber (); ScriptTemp.Push(sc.Number); break; @@ -704,7 +705,7 @@ void S_ParseSndSeq (int levellump) delaybase = sc.Number; ScriptTemp.Push(MakeCommand(SS_CMD_DELAYRAND, sc.Number)); sc.MustGetNumber (); - ScriptTemp.Push(MAX(1, sc.Number - delaybase + 1)); + ScriptTemp.Push(max(1, sc.Number - delaybase + 1)); break; case SS_STRING_VOLUME: // volume is in range 0..100 @@ -732,7 +733,7 @@ void S_ParseSndSeq (int levellump) break; case SS_STRING_NOSTOPCUTOFF: - stopsound = -1; + stopsound = INVALID_SOUND; ScriptTemp.Push(MakeCommand(SS_CMD_STOPSOUND, 0)); break; @@ -758,7 +759,7 @@ void S_ParseSndSeq (int levellump) break; case SS_STRING_END: - AddSequence (curseq, seqname, slot, stopsound, ScriptTemp); + AddSequence (curseq, seqname, slot, stopsound.index(), ScriptTemp); curseq = -1; break; @@ -795,13 +796,13 @@ static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, c Sequences[curseq] = (FSoundSequence *)M_Malloc (sizeof(FSoundSequence) + sizeof(uint32_t)*ScriptTemp.Size()); Sequences[curseq]->SeqName = seqname; Sequences[curseq]->Slot = slot; - Sequences[curseq]->StopSound = FSoundID(stopsound); + Sequences[curseq]->StopSound = FSoundID::fromInt(stopsound); memcpy (Sequences[curseq]->Script, &ScriptTemp[0], sizeof(uint32_t)*ScriptTemp.Size()); Sequences[curseq]->Script[ScriptTemp.Size()] = MakeCommand(SS_CMD_END, 0); } DSeqNode::DSeqNode (FLevelLocals *l, int sequence, int modenum) -: m_CurrentSoundID(0), m_ModeNum(modenum), m_SequenceChoices(0) +: m_CurrentSoundID(NO_SOUND), m_ModeNum(modenum), m_SequenceChoices(0) { Level = l; ActivateSequence (sequence); @@ -827,15 +828,15 @@ void DSeqNode::ActivateSequence (int sequence) m_Sequence = sequence; m_DelayTics = 0; m_StopSound = Sequences[sequence]->StopSound; - m_CurrentSoundID = 0; + m_CurrentSoundID = NO_SOUND; m_Volume = 1; // Start at max volume... m_Atten = ATTN_IDLE; // ...and idle attenuation } -DSeqActorNode::DSeqActorNode (AActor *actor, int sequence, int modenum) - : DSeqNode (actor->Level, sequence, modenum), - m_Actor (actor) +DSeqActorNode::DSeqActorNode(AActor* actor, int sequence, int modenum) + : DSeqNode(actor->Level, sequence, modenum) { + m_Actor = actor; } DSeqPolyNode::DSeqPolyNode (FPolyObj *poly, int sequence, int modenum) @@ -1126,27 +1127,27 @@ void SN_DoStop (FLevelLocals *Level, void *source) void DSeqActorNode::OnDestroy () { - if (m_StopSound >= 0) + if (m_StopSound != INVALID_SOUND) S_StopSound (m_Actor, CHAN_BODY); - if (m_StopSound >= 1) + if (m_StopSound.isvalid()) MakeSound (0, m_StopSound); Super::OnDestroy(); } void DSeqSectorNode::OnDestroy () { - if (m_StopSound >= 0) + if (m_StopSound != INVALID_SOUND) S_StopSound (m_Sector, Channel & 7); - if (m_StopSound >= 1) + if (m_StopSound.isvalid()) MakeSound (0, m_StopSound); Super::OnDestroy(); } void DSeqPolyNode::OnDestroy () { - if (m_StopSound >= 0) + if (m_StopSound != INVALID_SOUND) S_StopSound (m_Poly, CHAN_BODY); - if (m_StopSound >= 1) + if (m_StopSound.isvalid()) MakeSound (0, m_StopSound); Super::OnDestroy(); } @@ -1203,7 +1204,7 @@ void DSeqNode::Tick () case SS_CMD_PLAY: if (!IsPlaying()) { - m_CurrentSoundID = FSoundID(GetData(*m_SequencePtr)); + m_CurrentSoundID = FSoundID::fromInt(GetData(*m_SequencePtr)); MakeSound (0, m_CurrentSoundID); } m_SequencePtr++; @@ -1213,7 +1214,7 @@ void DSeqNode::Tick () if (!IsPlaying()) { m_SequencePtr++; - m_CurrentSoundID = 0; + m_CurrentSoundID = NO_SOUND; } else { @@ -1225,7 +1226,7 @@ void DSeqNode::Tick () if (!IsPlaying()) { // Does not advance sequencePtr, so it will repeat as necessary. - m_CurrentSoundID = FSoundID(GetData(*m_SequencePtr)); + m_CurrentSoundID = FSoundID::fromInt(GetData(*m_SequencePtr)); MakeSound (CHANF_LOOP, m_CurrentSoundID); } return; @@ -1233,7 +1234,7 @@ void DSeqNode::Tick () case SS_CMD_PLAYLOOP: // Like SS_CMD_PLAYREPEAT, sequencePtr is not advanced, so this // command will repeat until the sequence is stopped. - m_CurrentSoundID = FSoundID(GetData(m_SequencePtr[0])); + m_CurrentSoundID = FSoundID::fromInt(GetData(m_SequencePtr[0])); MakeSound (0, m_CurrentSoundID); m_DelayTics = m_SequencePtr[1]; return; @@ -1272,13 +1273,13 @@ void DSeqNode::Tick () case SS_CMD_DELAY: m_DelayTics = GetData(*m_SequencePtr); m_SequencePtr++; - m_CurrentSoundID = 0; + m_CurrentSoundID = NO_SOUND; return; case SS_CMD_DELAYRAND: m_DelayTics = GetData(m_SequencePtr[0]) + pr_sndseq(m_SequencePtr[1]); m_SequencePtr += 2; - m_CurrentSoundID = 0; + m_CurrentSoundID = NO_SOUND; return; case SS_CMD_VOLUME: @@ -1382,7 +1383,7 @@ void SN_StopAllSequences (FLevelLocals *Level) for (node = Level->SequenceListHead; node; ) { DSeqNode *next = node->NextSequence(); - node->m_StopSound = 0; // don't play any stop sounds + node->m_StopSound = NO_SOUND; // don't play any stop sounds node->Destroy (); node = next; } @@ -1443,7 +1444,7 @@ void SN_MarkPrecacheSounds(int sequence, seqtype_t type) int cmd = GetCommand(seq->Script[i]); if (cmd == SS_CMD_PLAY || cmd == SS_CMD_PLAYREPEAT || cmd == SS_CMD_PLAYLOOP) { - soundEngine->MarkUsed(GetData(seq->Script[i])); + soundEngine->MarkUsed(FSoundID::fromInt(GetData(seq->Script[i]))); } } } @@ -1467,7 +1468,7 @@ DEFINE_ACTION_FUNCTION(DSeqNode, MarkPrecacheSounds) //========================================================================== void SN_ChangeNodeData (FLevelLocals *Level, int nodeNum, int seqOffset, int delayTics, float volume, - int currentSoundID) + FSoundID currentSoundID) { int i; DSeqNode *node; diff --git a/src/sound/s_sndseq.h b/src/sound/s_sndseq.h index d87ede324..11c5d68e1 100644 --- a/src/sound/s_sndseq.h +++ b/src/sound/s_sndseq.h @@ -56,7 +56,7 @@ protected: int m_Sequence; FSoundID m_CurrentSoundID; - int m_StopSound; + FSoundID m_StopSound; int m_DelayTics; float m_Volume; float m_Atten; diff --git a/src/sound/s_sound.h b/src/sound/s_sound.h index c4c0655cf..eb1800913 100644 --- a/src/sound/s_sound.h +++ b/src/sound/s_sound.h @@ -66,17 +66,15 @@ extern MusicAliasMap MusicAliases; void S_ClearSoundData(); void S_ParseSndInfo (bool redefine); -bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2); -bool S_AreSoundsEquivalent (AActor *actor, const char *name1, const char *name2); -int S_LookupPlayerSound (const char *playerclass, int gender, const char *logicalname); -int S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid); +bool S_AreSoundsEquivalent (AActor *actor, FSoundID id1, FSoundID id2); +FSoundID S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid); const char *S_GetSoundClass(AActor *pp); -int S_FindSkinnedSound (AActor *actor, FSoundID refid); -int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname); -int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL); // Add sound by lumpname -int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname); -int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false); -int S_AddPlayerSoundExisting (const char *playerclass, const int gender, int refid, int aliasto, bool fromskin=false); +FSoundID S_FindSkinnedSound (AActor *actor, FSoundID refid); +FSoundID S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname); +FSoundID S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL); // Add sound by lumpname +FSoundID S_AddPlayerSound (const char *playerclass, const int gender, FSoundID refid, const char *lumpname); +FSoundID S_AddPlayerSound (const char *playerclass, const int gender, FSoundID refid, int lumpnum, bool fromskin=false); +FSoundID S_AddPlayerSoundExisting (const char *playerclass, const int gender, FSoundID refid, FSoundID aliasto, bool fromskin=false); void S_MarkPlayerSounds (AActor *player); void S_ShrinkPlayerSoundLists (); unsigned int S_GetMSLength(FSoundID sound); diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp index 59e28d590..9fd7500cc 100644 --- a/src/st_stuff.cpp +++ b/src/st_stuff.cpp @@ -35,9 +35,9 @@ #include "doomstat.h" #include "g_level.h" #include "g_levellocals.h" +#include "d_main.h" EXTERN_CVAR (Bool, ticker); -EXTERN_CVAR (Bool, noisedebug); EXTERN_CVAR (Int, am_cheat); EXTERN_CVAR (Int, cl_blockcheats); @@ -524,7 +524,6 @@ static bool Cht_Ticker (cheatseq_t *cheat) static bool Cht_Sound (cheatseq_t *cheat) { - noisedebug = !noisedebug; - Printf ("%s\n", GStrings(noisedebug ? "TXT_CHEATSOUNDON" : "TXT_CHEATSOUNDOFF")); + AddCommandString("stat sounddebug"); return true; } diff --git a/src/st_stuff.h b/src/st_stuff.h index cb4098804..fed2dc796 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -5,8 +5,4 @@ struct event_t; bool ST_Responder(event_t* ev); -// [RH] Base blending values (for e.g. underwater) -extern int BaseBlendR, BaseBlendG, BaseBlendB; -extern float BaseBlendA; - #endif diff --git a/src/utility/nodebuilder/nodebuild.cpp b/src/utility/nodebuilder/nodebuild.cpp index a097efd43..0efe38b0e 100644 --- a/src/utility/nodebuilder/nodebuild.cpp +++ b/src/utility/nodebuilder/nodebuild.cpp @@ -150,10 +150,10 @@ int FNodeBuilder::CreateNode (uint32_t set, unsigned int count, fixed_t bbox[4]) D(PrintSet (2, set2)); node.intchildren[0] = CreateNode (set1, count1, node.nb_bbox[0]); node.intchildren[1] = CreateNode (set2, count2, node.nb_bbox[1]); - bbox[BOXTOP] = MAX (node.nb_bbox[0][BOXTOP], node.nb_bbox[1][BOXTOP]); - bbox[BOXBOTTOM] = MIN (node.nb_bbox[0][BOXBOTTOM], node.nb_bbox[1][BOXBOTTOM]); - bbox[BOXLEFT] = MIN (node.nb_bbox[0][BOXLEFT], node.nb_bbox[1][BOXLEFT]); - bbox[BOXRIGHT] = MAX (node.nb_bbox[0][BOXRIGHT], node.nb_bbox[1][BOXRIGHT]); + bbox[BOXTOP] = max (node.nb_bbox[0][BOXTOP], node.nb_bbox[1][BOXTOP]); + bbox[BOXBOTTOM] = min (node.nb_bbox[0][BOXBOTTOM], node.nb_bbox[1][BOXBOTTOM]); + bbox[BOXLEFT] = min (node.nb_bbox[0][BOXLEFT], node.nb_bbox[1][BOXLEFT]); + bbox[BOXRIGHT] = max (node.nb_bbox[0][BOXRIGHT], node.nb_bbox[1][BOXRIGHT]); return (int)Nodes.Push (node); } else @@ -643,7 +643,7 @@ int FNodeBuilder::Heuristic (node_t &node, uint32_t set, bool honorNoSplit) frac = 1 - frac; } int penalty = int(1 / frac); - score = MAX(score - penalty, 1); + score = std::max(score - penalty, 1); D(Printf ("Penalized splitter by %d for being near endpt of seg %d (%f).\n", penalty, i, frac)); } diff --git a/src/utility/nodebuilder/nodebuild.h b/src/utility/nodebuilder/nodebuild.h index 0618f7247..f9f6b018a 100644 --- a/src/utility/nodebuilder/nodebuild.h +++ b/src/utility/nodebuilder/nodebuild.h @@ -173,8 +173,8 @@ class FNodeBuilder fixed64_t MinX, MinY, MaxX, MaxY; int BlocksWide, BlocksTall; - enum { BLOCK_SHIFT = 8 + FRACBITS }; - enum { BLOCK_SIZE = 1 << BLOCK_SHIFT }; + static constexpr int BLOCK_SHIFT = 8 + FRACBITS; + static constexpr int BLOCK_SIZE = 1 << BLOCK_SHIFT; int InsertVertex (FPrivVert &vert); inline int GetBlock (fixed64_t x, fixed64_t y) diff --git a/src/utility/nodebuilder/nodebuild_utility.cpp b/src/utility/nodebuilder/nodebuild_utility.cpp index d94f84d07..30ead3424 100644 --- a/src/utility/nodebuilder/nodebuild_utility.cpp +++ b/src/utility/nodebuilder/nodebuild_utility.cpp @@ -698,10 +698,10 @@ int FNodeBuilder::FVertexMap::InsertVertex (FNodeBuilder::FPrivVert &vert) // If a vertex is near a block boundary, then it will be inserted on // both sides of the boundary so that SelectVertexClose can find // it by checking in only one block. - fixed64_t minx = MAX (MinX, fixed64_t(vert.x) - VERTEX_EPSILON); - fixed64_t maxx = MIN (MaxX, fixed64_t(vert.x) + VERTEX_EPSILON); - fixed64_t miny = MAX (MinY, fixed64_t(vert.y) - VERTEX_EPSILON); - fixed64_t maxy = MIN (MaxY, fixed64_t(vert.y) + VERTEX_EPSILON); + fixed64_t minx = max (MinX, fixed64_t(vert.x) - VERTEX_EPSILON); + fixed64_t maxx = min (MaxX, fixed64_t(vert.x) + VERTEX_EPSILON); + fixed64_t miny = max (MinY, fixed64_t(vert.y) - VERTEX_EPSILON); + fixed64_t maxy = min (MaxY, fixed64_t(vert.y) + VERTEX_EPSILON); int blk[4] = { diff --git a/src/version.h b/src/version.h index 736285da5..7ee35abb7 100644 --- a/src/version.h +++ b/src/version.h @@ -41,20 +41,20 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.8pre" +#define VERSIONSTR "4.11pre" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,7,9999,0 -#define RC_PRODUCTVERSION 4,7,9999,0 +#define RC_FILEVERSION 4,10,9999,0 +#define RC_PRODUCTVERSION 4,10,9999,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 8 +#define VER_MINOR 11 #define VER_REVISION 0 // This should always refer to the GZDoom version a derived port is based on and not reflect the derived port's version number! #define ENG_MAJOR 4 -#define ENG_MINOR 8 +#define ENG_MINOR 11 #define ENG_REVISION 0 // Version identifier for network games. @@ -65,7 +65,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 "222" +#define LASTRUNVERSION "223" // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. @@ -88,7 +88,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4559 +#define SAVEVER 4560 // This is so that derivates can use the same savegame versions without worrying about engine compatibility #define GAMESIG "QZDOOM" @@ -110,6 +110,8 @@ const char *GetVersionString(); #define GAME_DIR ".config/" GAMENAMELOWERCASE #endif +#define DEFAULT_DISCORD_APP_ID "951303644597325885" + const int SAVEPICWIDTH = 216; const int SAVEPICHEIGHT = 162; const int VID_MIN_WIDTH = 320; diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 0172223ec..a37073a43 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -93,6 +93,7 @@ static const char *WI_Cmd[] = { "NoAutostartMap", "Screensize", + "TileBackground", NULL }; @@ -142,7 +143,7 @@ class DInterBackground : public DObject int period; // period in tics between animations yahpt_t loc; // location of animation int data; // ALWAYS: n/a, RANDOM: period deviation (<256) - TArray frames; // actual graphics for frames of animations + TArray frames; // actual graphics for frames of animations // following must be initialized to zero before use! int nexttic; // next value of bcnt (used in conjunction with period) @@ -165,13 +166,14 @@ private: TArray lnodes; TArray anims; int bcnt = 0; // used for timing of background animation - TArray yah; // You Are Here graphic - FGameTexture* splat = nullptr; // splat - FGameTexture *background = nullptr; + TArray yah; // You Are Here graphic + FTextureID splat{}; // splat + FTextureID background{}; wbstartstruct_t *wbs; level_info_t *exitlevel; int bgwidth = -1; int bgheight = -1; + bool tilebackground = false; public: @@ -215,7 +217,7 @@ private: // //==================================================================== - void drawOnLnode(int n, FGameTexture * c[], int numc, double backwidth, double backheight) + void drawOnLnode(int n, FTextureID c[], int numc, double backwidth, double backheight) { int i; for (i = 0; iGetDisplayWidth(); - bottom = c[i]->GetDisplayHeight(); - left = lnodes[n].x - c[i]->GetDisplayLeftOffset(); - top = lnodes[n].y - c[i]->GetDisplayTopOffset(); + auto tex = TexMan.GetGameTexture(c[i]); + right = tex->GetDisplayWidth(); + bottom = tex->GetDisplayHeight(); + left = lnodes[n].x - tex->GetDisplayLeftOffset(); + top = lnodes[n].y - tex->GetDisplayTopOffset(); right += left; bottom += top; if (left >= 0 && right < 320 && top >= 0 && bottom < 200) { - DrawTexture(twod, c[i], lnodes[n].x, lnodes[n].y, DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidthF, backwidth, DTA_VirtualHeightF, backheight, TAG_DONE); + DrawTexture(twod, tex, lnodes[n].x, lnodes[n].y, DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidthF, backwidth, DTA_VirtualHeightF, backheight, TAG_DONE); break; } } @@ -266,8 +268,8 @@ DEFINE_ACTION_FUNCTION(DInterBackground, Create) bool DInterBackground::LoadBackground(bool isenterpic) { - const char *lumpname = nullptr; - const char *exitpic = nullptr; + const char* lumpname = nullptr; + const char* exitpic = nullptr; char buffer[10]; in_anim_t an; lnode_t pt; @@ -276,16 +278,25 @@ bool DInterBackground::LoadBackground(bool isenterpic) bcnt = 0; + if (!isenterpic) tilebackground = false; texture.SetInvalid(); - level_info_t * li = FindLevelInfo(wbs->current); - if (li != nullptr) exitpic = li->ExitPic; + level_info_t* li = FindLevelInfo(wbs->current); + if (li != nullptr) + { + exitpic = li->ExitPic; + if (li->ExitPic.IsNotEmpty()) tilebackground = false; + } lumpname = exitpic; if (isenterpic) { - level_info_t * li = FindLevelInfo(wbs->next); - if (li != NULL) lumpname = li->EnterPic; + level_info_t* li = FindLevelInfo(wbs->next); + if (li != NULL) + { + lumpname = li->EnterPic; + if (li->EnterPic.IsNotEmpty()) tilebackground = false; + } } // Try to get a default if nothing specified @@ -298,11 +309,12 @@ 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 : wbs->current; if (IsExMy(levelname)) { mysnprintf(buffer, countof(buffer), "$IN_EPI%c", levelname[1]); lumpname = buffer; + tilebackground = false; } } if (!lumpname) @@ -326,6 +338,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) } } lumpname = "INTERPIC"; + tilebackground = false; } break; @@ -336,12 +349,14 @@ bool DInterBackground::LoadBackground(bool isenterpic) { mysnprintf(buffer, countof(buffer), "$IN_HTC%c", wbs->next[1]); lumpname = buffer; + tilebackground = false; } } if (!lumpname) { if (isenterpic) return false; lumpname = "FLOOR16"; + tilebackground = true; } break; @@ -355,20 +370,21 @@ bool DInterBackground::LoadBackground(bool isenterpic) // Strife doesn't have an intermission pic so choose something neutral. if (isenterpic) return false; lumpname = gameinfo.BorderFlat; + tilebackground = true; break; } } if (lumpname == NULL) { // shouldn't happen! - background = NULL; + background.SetInvalid(); return false; } lnodes.Clear(); anims.Clear(); yah.Clear(); - splat = NULL; + splat.SetInvalid(); // a name with a starting '$' indicates an intermission script if (*lumpname != '$') @@ -394,13 +410,13 @@ bool DInterBackground::LoadBackground(bool isenterpic) case 1: // Splat sc.MustGetString(); - splat = TexMan.GetGameTextureByName(sc.String); + splat = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny); break; case 2: // Pointers while (sc.GetString() && !sc.Crossed) { - yah.Push(TexMan.GetGameTextureByName(sc.String)); + yah.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny)); } if (sc.Crossed) sc.UnGet(); @@ -467,6 +483,10 @@ bool DInterBackground::LoadBackground(bool isenterpic) bgheight = sc.Number; break; + case 16: // tilebackground + tilebackground = true; + break; + readanimation: sc.MustGetString(); an.LevelName = sc.String; @@ -500,14 +520,14 @@ bool DInterBackground::LoadBackground(bool isenterpic) if (!sc.CheckString("{")) { sc.MustGetString(); - an.frames.Push(TexMan.GetGameTextureByName(sc.String)); + an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny)); } else { while (!sc.CheckString("}")) { sc.MustGetString(); - an.frames.Push(TexMan.GetGameTextureByName(sc.String)); + an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny)); } } an.ctr = -1; @@ -522,7 +542,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) an.loc.y = sc.Number; sc.MustGetString(); an.frames.Reserve(1); // allocate exactly one element - an.frames[0] = TexMan.GetGameTextureByName(sc.String); + an.frames[0] = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny); anims.Push(an); break; @@ -538,7 +558,11 @@ bool DInterBackground::LoadBackground(bool isenterpic) texture = TexMan.GetTextureID("INTERPIC", ETextureType::MiscPatch); } } - background = TexMan.GetGameTexture(texture); + background = texture; + auto tex = TexMan.GetGameTexture(texture); + // extremely small textures will always be tiled. + if (tex && tex->GetDisplayWidth() < 128 && tex->GetDisplayHeight() < 128) + tilebackground = true; return noautostartmap; } @@ -605,25 +629,26 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe double animwidth = bgwidth; // For a flat fill or clear background scale animations to 320x200 double animheight = bgheight; - if (background) + if (background.isValid()) { + auto bgtex = TexMan.GetGameTexture(background); // background - if (background->isMiscPatch()) + if (!tilebackground) { // if no explicit size was set scale all animations below to fit the size of the base pic // The base pic is always scaled to fit the screen so this allows // placing the animations precisely where they belong on the base pic if (bgwidth < 0 || bgheight < 0) { - animwidth = background->GetDisplayWidth(); - animheight = background->GetDisplayHeight(); + animwidth = bgtex->GetDisplayWidth(); + animheight = bgtex->GetDisplayHeight(); if (animheight == 200) animwidth = 320; // deal with widescreen replacements that keep the original coordinates. } - DrawTexture(twod, background, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE); + DrawTexture(twod, bgtex, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE); } else { - twod->AddFlatFill(0, 0, twod->GetWidth(), twod->GetHeight(), background, (inter_classic_scaling ? -1 : 0)); + twod->AddFlatFill(0, 0, twod->GetWidth(), twod->GetHeight(), bgtex, (inter_classic_scaling ? -1 : 0)); } } else @@ -674,7 +699,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe break; } if (a->ctr >= 0) - DrawTexture(twod, a->frames[a->ctr], a->loc.x, a->loc.y, + DrawTexture(twod, a->frames[a->ctr], false, a->loc.x, a->loc.y, DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, DTA_FullscreenScale, FSMode_ScaleToFit43, TAG_DONE); } @@ -708,66 +733,13 @@ DEFINE_ACTION_FUNCTION(DInterBackground, drawBackground) IMPLEMENT_CLASS(DInterBackground, true, false) -DObject *WI_Screen; - -//==================================================================== -// -// -// -//==================================================================== - -void WI_Ticker() -{ - if (WI_Screen) - { - ScaleOverrider s(twod); - IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Ticker) - { - VMValue self = WI_Screen; - VMCall(func, &self, 1, nullptr, 0); - } - } -} - -//==================================================================== -// -// Called by main loop, -// draws the intermission directly into the screen buffer. -// -//==================================================================== - -void WI_Drawer() -{ - if (WI_Screen) - { - ScaleOverrider s(twod); - IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Drawer) - { - twod->ClearClipRect(); - twod->ClearScreen(); - VMValue self = WI_Screen; - VMCall(func, &self, 1, nullptr, 0); - twod->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. - - // The internal handling here is somewhat poor. After being set to 'LeavingIntermission' - // the screen is needed for one more draw operation so we cannot delete it right away but only here. - if (WI_Screen->IntVar("CurState") == LeavingIntermission) - { - WI_Screen->Destroy(); - GC::DelSoftRoot(WI_Screen); - WI_Screen = nullptr; - } - } - } -} - //==================================================================== // // Setup for an intermission screen. // //==================================================================== -void WI_Start(wbstartstruct_t *wbstartstruct) +DObject* WI_Start(wbstartstruct_t *wbstartstruct) { FName screenclass = deathmatch ? gameinfo.statusscreen_dm : multiplayer ? gameinfo.statusscreen_coop : gameinfo.statusscreen_single; auto cls = PClass::FindClass(screenclass); @@ -784,7 +756,7 @@ void WI_Start(wbstartstruct_t *wbstartstruct) } } - WI_Screen = cls->CreateNew(); + auto WI_Screen = cls->CreateNew(); ScaleOverrider s(twod); @@ -814,7 +786,7 @@ void WI_Start(wbstartstruct_t *wbstartstruct) } } - GC::AddSoftRoot(WI_Screen); + return WI_Screen; } //==================================================================== @@ -831,7 +803,7 @@ DEFINE_ACTION_FUNCTION(DStatusScreen, GetPlayerWidths) if (numret > 0) ret[0].SetInt(maxnamewidth); if (numret > 1) ret[1].SetInt(maxscorewidth); if (numret > 2) ret[2].SetInt(maxiconheight); - return MIN(numret, 3); + return min(numret, 3); } //==================================================================== diff --git a/src/wi_stuff.h b/src/wi_stuff.h index 453fe4a1e..869348698 100644 --- a/src/wi_stuff.h +++ b/src/wi_stuff.h @@ -81,17 +81,7 @@ struct wbstartstruct_t }; -// Intermission stats. -// Parameters for world map / intermission. - -// Called by main loop, animate the intermission. -void WI_Ticker (); - -// Called by main loop, -// draws the intermission directly into the screen buffer. -void WI_Drawer (); - // Setup for an intermission screen. -void WI_Start (wbstartstruct_t *wbstartstruct); +DObject* WI_Start (wbstartstruct_t *wbstartstruct); #endif diff --git a/src/win32/i_steam.cpp b/src/win32/i_steam.cpp index 862cb584b..056b59364 100644 --- a/src/win32/i_steam.cpp +++ b/src/win32/i_steam.cpp @@ -71,7 +71,7 @@ #include "d_net.h" #include "g_game.h" #include "c_dispatch.h" -#include "templates.h" + #include "gameconfigfile.h" #include "v_font.h" #include "g_level.h" @@ -144,6 +144,13 @@ TArray I_GetGogPaths() result.Push(path); // directly in install folder } + // Look for Doom I Enhanced + gamepath = gogregistrypath + L"\\2015545325"; + if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) + { + result.Push(path + "/DOOM_Data/StreamingAssets"); // in a subdirectory + } + // Look for Doom II gamepath = gogregistrypath + L"\\1435848814"; if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) @@ -152,6 +159,13 @@ TArray I_GetGogPaths() // If direct support for the Master Levels is ever added, they are in path + /master/wads } + // Look for Doom II Enhanced + gamepath = gogregistrypath + L"\\1426071866"; + if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) + { + result.Push(path + "/DOOM II_Data/StreamingAssets"); // in a subdirectory + } + // Look for Final Doom gamepath = gogregistrypath + L"\\1435848742"; if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) @@ -222,7 +236,8 @@ TArray I_GetSteamPath() "DOOM 3 BFG Edition/base/wads", "Strife", "Ultimate Doom/rerelease/DOOM_Data/StreamingAssets", - "Doom 2/rerelease/DOOM II_Data/StreamingAssets" + "Doom 2/rerelease/DOOM II_Data/StreamingAssets", + "Doom 2/finaldoombase" }; FString path; diff --git a/src/win32/zdoom.rc b/src/win32/zdoom.rc index f4144ee83..2210c52b6 100644 --- a/src/win32/zdoom.rc +++ b/src/win32/zdoom.rc @@ -228,9 +228,8 @@ BEGIN #ifdef HAVE_VULKAN CONTROL "&Vulkan",IDC_WELCOME_VULKAN2,"Button",BS_AUTORADIOBUTTON,13,176,37,10 #endif - CONTROL "&SoftPoly",IDC_WELCOME_VULKAN3,"Button",BS_AUTORADIOBUTTON,13,185,43,10 #ifdef HAVE_GLES2 - CONTROL "OpenGL &ES",IDC_WELCOME_VULKAN4,"Button",BS_AUTORADIOBUTTON,13,194,53,10 + CONTROL "OpenGL &ES",IDC_WELCOME_VULKAN4,"Button",BS_AUTORADIOBUTTON,13,185,53,10 #endif END diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 0e908d94a..635e27d70 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -24,7 +24,6 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 { stairs maskedmidtex - corpsegibs vileghosts } @@ -99,12 +98,15 @@ C7A2FAFB0AFB2632C50AD625CDB50E51 // Reverie map18 1E998262EE319B7D088E01DE782E6B41 // Mayhem 2013 map05 A81E2734F735A82720D8E0F1442BA0C9 // Imp's [sic] are Ghost Gods map01 { - corpsegibs vileghosts } // invert the sorting order of overlapping sprites at the same spot 551D6B416EB3324790BC0F0F74B49600 // Strain map13 +{ + spritesort +} + 2F49C29691F8565F0B99B27FCF2627E6 // Astrostein 1 MAP01 55A741F9C2955C2B06F2387E45ED6C62 // MAP02 4E7286B735671A942C54FAC6CB52A8C3 // MAP03 @@ -133,6 +135,14 @@ AB1A6C1D3898D4259C0645306939374C // map15 CA267398C9B3A8F79349D3394F8B2106 // map20 { spritesort + nombf21 +} + +62C723647C531A15F5647BA8B4818392 // riii.wad map11 +178605D81D8E8C4B78D91BC72C8A89ED // ht.wad map31 +F1EAD555B8AF5CB97D42BA632C0FA165 // cchest2.wad map19 +{ + nombf21 } 1D9E43988940CCD3555724E15DD8B1AB // Happy Time Circus map01 has bad teleporters @@ -187,6 +197,7 @@ E0E5517B7928E88B88F6A5B77AC449DF // Darken2.wad map23 - Nodes go out of bounds/b 3DEE4EFEFAF3260C800A30734F54CE75 // Hellbound, map14 5FAA25F5A6AAB3409CAE0AF87F910341 // DOOM.wad e1m6 94893A0DC429A22ADC4B3A73DA537E16 // DOOM2.WAD map25 +9D84B423D8FD28553DDE23B55F97CF4A // PLUTONIA.WAD map25 D5F64E02679A81B82006AF34A6A8EAC3 // plutonia.wad map32 BA4860C7A2F5D705DB32A1A38DB77EC4 // pl2.wad map10 EDA5CE7C462BD171BF8110AC56B67857 // pl2.wad map11 @@ -198,6 +209,15 @@ A9A9A728E689266939C1B71655F320CA // pl2.wad map25 F73A74BD9346AD3B6AF8246F7B389A1E // Memento Mori map20 9D7288F7235157D8478E409CD7AE9F68 // akeldama.wad map26 DEABADC01FE74273B7616F744EDF66D0 // dbimpact.wad e1m3 +4FDDBEED4FC6092095955FAE82C059EE // 1024.wad map02 +984A24A876E2530AEA9FD10481C362AF // sdoom2.wad map18 +40EE423E612AAAD6921AD803F62A6FCC // sdoom2.wad map23 +DCC92553625E34F94B2ED1B2719A2CB6 // sdoom2.wad map24 +D04E38921EC29D8665EA4F019F9921E5 // njdoom1.wad e1m6 +A139B45A843E26EAAFBE88093723D795 // njdoom2.wad map13 +EB61E33DDB0BABA174DF2D4C06E5536E // njdoom1.wad e3m4 +718D80A751F33558EDB0315668FDCD7F // njdoom2.wad map23 +5366DD3789F5B6E3CA455B949455F458 // tnt2fix2.wad map01 { rebuildnodes } diff --git a/wadsrc/static/dehsupp.txt b/wadsrc/static/dehsupp.txt index 8525d1164..59858975f 100644 --- a/wadsrc/static/dehsupp.txt +++ b/wadsrc/static/dehsupp.txt @@ -1199,7 +1199,7 @@ Aliases A_MonsterMeleeAttack, MBF21_MonsterMeleeAttack, A_RadiusDamage, A_RadiusDamage, A_HealChase, MBF21_HealChase, - A_SeekTracer, A_SeekerMissile, + A_SeekTracer, MBF21_SeekTracer, A_FindTracer, A_FindTracer, A_JumpIfHealthBelow, MBF21_JumpIfHealthBelow, A_JumpIfTargetInSight, MBF21_JumpIfTargetInSight, diff --git a/wadsrc/static/fonts/consolefont/0490.png b/wadsrc/static/fonts/consolefont/0490.png new file mode 100644 index 000000000..e02d0d80a Binary files /dev/null and b/wadsrc/static/fonts/consolefont/0490.png differ diff --git a/wadsrc/static/graphics/bal7scr1.png b/wadsrc/static/graphics/bal7scr1.png index c3c215191..cc7fdf367 100644 Binary files a/wadsrc/static/graphics/bal7scr1.png and b/wadsrc/static/graphics/bal7scr1.png differ diff --git a/wadsrc/static/graphics/bal7scr2.png b/wadsrc/static/graphics/bal7scr2.png index 04ff042c7..1aac4c47c 100644 Binary files a/wadsrc/static/graphics/bal7scr2.png and b/wadsrc/static/graphics/bal7scr2.png differ diff --git a/wadsrc/static/language.0 b/wadsrc/static/language.0 index 65e61be98..3e95136be 100644 --- a/wadsrc/static/language.0 +++ b/wadsrc/static/language.0 @@ -1,16 +1,18 @@ -default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,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,pl,pt,ptg,ro,ru,sr -,,Miscellaneous,,,,,,,,,,,,,,,,,,,,, +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,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,pl,pt,ptg,ro,ru,sr,bg +,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,, Press Y or N.,PRESSYN,,,,Stiskni Y nebo N.,Drücke Y oder N.,"Πάτα Y ή N -",Premu Y aŭ N.,Presiona Y ó 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.,Wciśnij Y lub N.,Aperte Y ou N.,Carrega Y ou N.,Apasă Y sau N.,Нажмите Y или N.,Притисните Y или N. -Yes,TXT_YES,,,,Ano,Ja,Ναι,Jes,Sí,,Kyllä,Oui,Igen,Si,はい,네,Ja,Tak,Sim,,Da,Да,Да -No,TXT_NO,,,,Ne,Nein,Όχι,Ne,No,,Ei,Non,Nem,No,いいえ,아니요,Nee,Nie,Não,,Nu,Нет,Не +",Premu Y aŭ N.,Presiona Y ó 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.,Wciśnij Y lub N.,Aperte Y ou N.,Carrega Y ou N.,Apasă Y sau N.,Нажмите Y или N.,Притисните Y или N.,Натисни Y или N. +Yes,TXT_YES,,,,Ano,Ja,Ναι,Jes,Sí,,Kyllä,Oui,Igen,Si,はい,네,Ja,Tak,Sim,,Da,Да,Да,Да +No,TXT_NO,,,,Ne,Nein,Όχι,Ne,No,,Ei,Non,Nem,No,いいえ,아니요,Nee,Nie,Não,,Nu,Нет,Не,Не "You can't save if you aren't playing! -Press a key.",SAVEDEAD,,,,"Nemůžeš ukládat pokud nehraješ! +Press a key.",SAVEDEAD,,,,"Mimo hru nelze ukládat! Stiskni libovolnou klávesu.","Du kannst nicht speichern, wenn du nicht spielst. -Drücke eine Taste",,"Vi ne povas konservi se vi ne ludas! +Drücke eine Taste","Δεν μπορείς να αποθηκέυσης αμα δεν παίζεις ! + +Πάτα ενα κουμπί.","Vi ne povas konservi se vi ne ludas! Premu klavon.","¡No puedes guardar si no estás jugando! @@ -40,14 +42,16 @@ Apasă o tastă.","Невозможно сохранить игру, не нач Нажмите любую клавишу.","Не можете сачувати игру ако не играте! -Притисните тастер." -Do you really want to do this?,SAFEMESSAGE,,,,Vážně to chceš udělat?,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 meg akarod tenni?,Sei sicuro di volerlo fare?,本当に実行するのか?,정말로 정하시겠습니까?,Wil je dit echt doen?,Naprawdę chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,Ești sigur că vrei să faci asta?,Вы уверены?,Да ли заиста желите то да урадите? -Not set,NOTSET,,,,Není nastavené,Nicht gesetzt,,Ne agordita,No Asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Nie ustawiono,Não definido,,Nesetat,Не задан,Није намештено +Притисните тастер.","Не може да запазите играта, ако не играете! + +Натиснете клавиш." +Do you really want to do this?,SAFEMESSAGE,,,,Vážně to chceš udělat?,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?,Naprawdę chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,Ești sigur că vrei să faci asta?,Вы уверены?,Да ли заиста желите то да урадите?,Наистина ли искаш да направиш това? +Not set,NOTSET,,,,Není nastavené,Nicht gesetzt,,Ne agordita,No Asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットされてない,정하지 않음,Niet ingesteld,Nie ustawiono,Não definido,,Nesetat,Не задан,Није намештено,Не е зададено "Quicksave over your game named '%s'? -Press Y or N.",QSPROMPT,,,,"Rychle uložit přes tvoji hru s názvem +Press Y or N.",QSPROMPT,,,,"Rychle uložit přes hru s názvem '%s'? @@ -111,12 +115,16 @@ Apasă Y sau N.","Перезаписать быстрое сохранение „%s“? -Притисните Y или N." +Притисните Y или N.","Презапиши върху игра с име + +'%s'? + +Натисни Y или N." "Do you want to quickload the game named '%s'? -Press Y or N.",QLPROMPT,,,,"Přeješ si rychle načíst hru s názvem +Press Y or N.",QLPROMPT,,,,"Rychle načíst hru s názvem '%s'? @@ -180,617 +188,641 @@ Apasă Y sau N.","Загрузить быстрое сохранение „%s“? -Притисните Y или N." -%s cheats,TXT_X_CHEATS,This is a gender sensitive message where %s represents the player,,,%s cheatuje,%s schummelt,@[art_gr] %s απατάει,%s trompas,%s hace trampas,,%s huijaa,%s triche.,%s csal,%s imbroglia,%s はチート使用,%s 이(가) 치트를 사용 함,%s bedriegt,%s oszukuje,%s está trapaceando,%s está a fazer batota,%s trișează,%s использует чит-коды,%s вара -Messages: OFF,MSGOFF,,,,Zprávy ZAP,Meldungen AUS,Μηνύματα ΚΛΕΙΣΤΑ,Mesaĝoj: MALŜALTITA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Üzenetek KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 끔,Berichten UIT,Wiadomości WYŁĄCZONE,Mensagens DESATIVADAS,,Mesaje OPRITE,Сообщения ОТКЛЮЧЕНЫ,Поруке ИСКЉУЧЕНЕ -Messages: ON,MSGON,,,,Zprávy VYP,Meldungen AN,Μηνύματα ΑΝΟΙΧΤΑ,Mesaĝoj: ŜALTITA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Üzenetek BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,Wiadomości WŁĄCZONE,Mensagens ATIVADAS,,Mesaje PORNITE,Сообщения ВКЛЮЧЁНЫ,Поруке УКЉУЧЕНЕ -Say:,TXT_SAY,,,,Říct:,Sage:,Πές:,Diri:,,,Sano:,Parler:,Üzenet:,Parla:,発言:,,Zeg:,Powiedz:,Dizer:,Diz:,Vorbește:,Чат:,Пиши: -,,Savegame,,,,,,,,,,,,,,,,,,,,, -Empty slot,EMPTYSTRING,,,,Prázdný slot,nicht belegt,,Malplena konservludujo,Ranura Vacía,,Tyhjä lokero,Emplacement Vide,Üres,Slot libero,空きスロット,빈 슬롯,Lege sleuf,Puste miejsce,Espaço vazio,,Loc disponibil,Пустой слот,Празни слот -,NEWSAVE,,,,,,,,,,,,<Új mentés>,,<新規セーブ>,<새로운 게임 저장>,,,,,,<Новое сохранение>,<Нова сачувана игра> -Game saved.,GGSAVED,,,,Hra uložena.,Spielstand gespeichert.,,Ludo konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Gioco salvato.,セーブ完了。,게임이 저장됨.,Spel opgeslagen.,Gra zapisana.,Jogo salvo.,Jogo gravado.,Joc salvat.,Игра сохранена.,Игра сачувана. -Time,SAVECOMMENT_TIME,,,,Čas,Zeit,,Tempo,Tiempo,,Aika,Temps,Idő,Tempo,"時間 -",시간,Tijd,Czas,Tempo,,Timp,Время,Време -Load Game,MNU_LOADGAME,,,,Načíst hru,Spiel laden,,Ŝargi Ludon,Cargar Partida,,Lataa peli,Chargement,Játék betöltése,Carica gioco,ロード,게임 불러오기,Laden spel,Wczytaj Grę,Carregar jogo,,Încărcare Joc,Загрузка,Учитај игру -Save Game,MNU_SAVEGAME,,,,Uložit hru,Spiel sichern,,Konservi Ludon,Guardar Partida,,Tallenna peli,Sauvegarde,Játék mentése,Salva gioco,セーブ,게임 저장하기,Opslaan spel,Zapisz Grę,Salvar jogo,Gravar,Salvare Joc,Сохранение,Сачувај игру -No Picture,MNU_NOPICTURE,,,,Bez obrázku,Kein Bild,,Neniu Bildo,Sin Imagen,,Ei kuvaa,Pas d'image,Nincs kép,Nessuna immagine,画像無し,사진 없음,Geen beeld,Brak obrazka,Sem imagem,,Lipsă Imagine,"Нет -изображения",Нема слике -Different Version,MNU_DIFFVERSION,,,,Jiná verze,Falsche Version,,Malsama Versio,Versión Diferente,,Eri versio,Version Différente,Eltérő verzió,Versione differente,"別バージョンの -データ",다른 버젼,Anders Versie,Inna Wersja,Versão diferente,,Versiune Diferită,Другая версия,Другачија верзија -No files,MNU_NOFILES,,,,Žádné soubory,Keine Dateien,,Neniuj dosieroj,Sin archivos,,Ei tiedostoja,Pas de fichiers,Nincsenek fájlok,Nessun file,ファイル無し,파일 없음,Geen bestanden,Brak plików,Vazio,,Niciun fișiier,Нет файлов,Нема фајлова +Притисните Y или N.","Искате ли да заредите бързо играта с име + +'%s'? + +Натисни Y или N." +%s cheats,TXT_X_CHEATS,This is a gender sensitive message where %s represents the player,,,%s podvádí,%s schummelt,@[art_gr] %s απατάει,%s trompas,%s hace trampas,,%s huijaa,%s triche.,%s csal,%s imbroglia,%s はチート使用,%s 이(가) 치트를 사용 함,%s bedriegt,%s oszukuje,%s está trapaceando,%s está a fazer batota,%s trișează,%s использует чит-коды,%s вара,%s измамен код +Messages: OFF,MSGOFF,,,,Oznámení ZAP.,Meldungen AUS,Μηνύματα ΚΛΕΙΣΤΑ,Mesaĝoj: MALŜALTITA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Üzenetek: KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 끔,Berichten UIT,Wiadomości WYŁĄCZONE,Mensagens DESATIVADAS,,Mesaje OPRITE,Сообщения ОТКЛЮЧЕНЫ,Поруке ИСКЉУЧЕНЕ,Съобщения: Изкл +Messages: ON,MSGON,,,,Oznámení VYP.,Meldungen AN,Μηνύματα ΑΝΟΙΧΤΑ,Mesaĝoj: ŜALTITA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Üzenetek: BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,Wiadomości WŁĄCZONE,Mensagens ATIVADAS,,Mesaje PORNITE,Сообщения ВКЛЮЧЕНЫ,Поруке УКЉУЧЕНЕ,Съобщения: Вкл +Say:,TXT_SAY,,,,Říct:,Sage:,Πές:,Diri:,,,Sano:,Parler:,Üzenet:,Parla:,発言:,,Zeg:,Powiedz:,Dizer:,Diz:,Vorbește:,Чат:,Пиши:,Пиши: +,,Savegame,,,,,,,,,,,,,,,,,,,,,, +Empty slot,EMPTYSTRING,,,,Prázdný slot,nicht belegt,,Malplena konservludujo,Ranura Vacía,,Tyhjä lokero,Emplacement Vide,Üres,Slot libero,空きスロット,빈 슬롯,Lege sleuf,Puste miejsce,Espaço vazio,,Loc disponibil,Пустой слот,Празни слот,Празен слот +,NEWSAVE,,,,,,,,,,,,<Új mentés>,,<新規セーブ>,<새로운 게임 저장>,,,,,,<Новое сохранение>,<Нова сачувана игра>,<Нов запис на играта> +Game saved.,GGSAVED,,,,Hra uložena.,Spielstand gespeichert.,Παχνίδι αποθηκέυτηκε.,Ludo konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Partita salvata.,セーブ完了。,게임이 저장됨.,Spel opgeslagen.,Gra zapisana.,Jogo salvo.,Jogo gravado.,Joc salvat.,Игра сохранена.,Игра сачувана.,Играта е записана +Time,SAVECOMMENT_TIME,,,,Čas,Zeit,Χρόνος,Tempo,Tiempo,,Aika,Temps,Idő,Tempo,"時間 +",시간,Tijd,Czas,Tempo,,Timp,Время,Време,Време +Load Game,MNU_LOADGAME,,,,Načíst hru,Spiel laden,Φώρτωσε παιχνίδι,Ŝargi Ludon,Cargar Partida,,Lataa peli,Chargement,Játék betöltése,Carica partita,ロード,게임 불러오기,Laden spel,Wczytaj Grę,Carregar jogo,,Încărcare Joc,Загрузка,Учитај игру,Зареди игра +Save Game,MNU_SAVEGAME,,,,Uložit hru,Spiel sichern,Αποθήκευσε παιχνίδι,Konservi Ludon,Guardar Partida,,Tallenna peli,Sauvegarde,Játék mentése,Salva partita,セーブ,게임 저장하기,Opslaan spel,Zapisz Grę,Salvar jogo,Gravar,Salvare Joc,Сохранение,Сачувај игру,Запази игра +No Picture,MNU_NOPICTURE,,,,Bez obrázku,Kein Bild,Καμία εικόνα,Neniu Bildo,Sin Imagen,,Ei kuvaa,Pas d'image,Nincs kép,Nessuna immagine,画像無し,사진 없음,Geen beeld,Brak obrazka,Sem imagem,,Lipsă Imagine,"Нет +изображения",Нема слике,Без изображение +Different Version,MNU_DIFFVERSION,,,,Jiná verze,Falsche Version,Διαφορετική έκδοση,Malsama Versio,Versión Diferente,,Eri versio,Version Différente,Eltérő verzió,Versione differente,"別バージョンの +データ",다른 버젼,Anders Versie,Inna Wersja,Versão diferente,,Versiune Diferită,Другая версия,Другачија верзија,Различна версия +No files,MNU_NOFILES,,,,Žádné soubory,Keine Dateien,Καθ΄λου αρχεία ,Neniuj dosieroj,Sin archivos,,Ei tiedostoja,Pas de fichiers,Nincsenek fájlok,Nessun file,ファイル無し,파일 없음,Geen bestanden,Brak plików,Vazio,,Niciun fișier,Нет файлов,Нема фајлова,Няма файлове "Do you really want to delete the savegame? -",MNU_DELETESG,,,,Opravdu chceš smazat tuto uloženou hru?,Willst du diesen Spielstand wirklich löschen?,,Ĉu vi vere volas forigi la konservitan ludon?,"¿Realmente deseas eliminar la partida? +",MNU_DELETESG,,,,Opravdu smazat tuto uloženou hru?,Willst du diesen Spielstand wirklich löschen?,Θέλεις όντος να διαγράξεις το αποθηκευμένο παιχνίδι;,Ĉu vi vere volas forigi la konservitan ludon?,"¿Realmente deseas eliminar la partida? ",,Haluatko varmasti poistaa tallennetun pelin ,"Voulez vous vraiment effacer cette sauvegarde? -",Biztosan törlöd a mentést?,Vuoi veramente rimuovere il salvataggio,本当にこのセーブを消すのか?,저장된 게임을 정말로 삭제하시겠습니까?,Wil je echt de opgeslagen spel verwijderen?,Czy naprawdę chcesz usunąć zapis gry?,Deseja mesmo excluir o jogo salvo?,Deseja mesmo apagar o jogo,Vrei să ștergi salvarea?,"Вы действительно хотите удалить сохранение -",Да ли стварно желите да избришете сачувану игру -,,General,,,,,,,,,,,,,,,,,,,,, -Off,OPTVAL_OFF,,,,Vyp,Aus,,Malŝaltita,Desactivado,,Pois,,Ki,Disattivo,オフ,끔,Uit,Wyłączone,Não,,Pornit,Откл.,Искљ. -On,OPTVAL_ON,,,,Zap,An,,Ŝaltita,Activado,,Päällä,,Be,Attivo,オン,켬,Aan,Włączone,Sim,,Oprit,Вкл.,Укљ. -Auto,OPTVAL_AUTO,,,,,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,자동,,Automatycznie,Automático,,,Авто,Аутоматски -Options,OPTMNU_TITLE,,,,Možnosti,Optionen,,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Opcje,Opções,,Opțiuni,Настройки,Подешавања -Customize Controls,OPTMNU_CONTROLS,,,,Nastavení ovládání,Steuerung einstellen,,Adapti Regilojn,Personalizar Controles,,Ohjausasetukset,Modifier les Contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare Setări Control,Управление,Контроле -Mouse Options,OPTMNU_MOUSE,,,,Nastavení myši,Mauseinstellungen,,Muso-Agordoj,Opciones de Ratón,,Hiiriasetukset,Options de la Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,Setări Mouse,Мышь,Миш -Controller Options,OPTMNU_JOYSTICK,,,,Nastavení ovladače,Joystickeinstellungen,,Ludregilo-Agordoj,Opciones de Mando,,Peliohjainasetukset,Options de la Manette,Játékvezérlő beállítások,Opzioni Joystick,コントローラーオプション,조이스틱 설정,Controller opties,Opcje Kontrolera,Opções de controle,,Setări Controller,Контроллер,Контролер -Player Setup,OPTMNU_PLAYER,,,,Nastavení hráče,Spieler einrichten,,Ludanto-Agordaĵo,Config. del Jugador,,Pelaaja-asetukset,Options du Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Ustawienia Gracza,Configurações de jogador,Configurações do Jogador,Personalizare Jucător,Игрок,Играч -Gameplay Options,OPTMNU_GAMEPLAY,,,,Nastavení herních mechanik,Spieleinstellungen,,Ludado-Agordoj,Opciones de Jugabilidad,,Pelattavuusasetukset,Options du Gameplay,Játékmenet beállítások,Opzioni Gameplay,ゲームプレイ オプション,게임 설정,Gameplay-opties,Opcje Rozgrywki,Opções de jogabilidade,,Setări pe timp de joc,Геймплей,Гејмплеј -Automap Options,OPTMNU_AUTOMAP,,,,Nastavení automapy,Automapeinstellungen,,Aŭtomapo-Agordoj,Opciones del Automapa,,Automaattikartan asetukset,Options de la Carte,Térkép beállítások,Opzioni Automappa,オートマップ オプション,오토맵 설정,Automap-opties,Opcje Mapy,Opções de automapa,,Hartă computerizată,Автокарта,Аутомапа -HUD Options,OPTMNU_HUD,,,,Nastavení HUD,HUD Einstellungen,,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,Opcje Paska HUD,Opções de HUD,,Setări HUD,HUD,HUD -Miscellaneous Options,OPTMNU_MISCELLANEOUS,,,,Ostatní nastavení,Verschiedene Einstellungen,,Diversaĵaj Agordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni miste,その他のオプション,그 외 설정,Diverse opties,Różne Opcje,Outras opções,,Setări diverse,Дополнительно,Разно -Sound Options,OPTMNU_SOUND,,,,Nastavení zvuku,Soundeinstellungen,,Sono-Agordoj,Opciones de Sonido,,Ääniasetukset,Options du Son,Hang beállítások,Opzioni Suono,サウンド オプション,음향 설정,Geluidsopties,Opcje Dźwięku,Opções de som,,Setări sunet,Звук,Звук -Display Options,OPTMNU_DISPLAY,,,,Nastavení grafiky,Anzeigeeinstellungen,,Ekrano-Agordoj,Opciones de Visualización,,Näyttöasetukset,Options de l'Affichage,Megjelenítés beállítások,Opzioni Display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Экран,Приказ -Set video mode,OPTMNU_VIDEO,,,,Nastavit režim displeje,Videomodus,,Agordi videoreĝimon,Modos de Vídeo,,Aseta videotila,Choisir Mode D'Affichage,Videó beállítások,Settaggio modalità video,ビデオ 調整,화면 설정,Videomodus instellen,Ustaw tryb wideo,Definir modo de vídeo,,Setare mod video,Видеорежим,Видео мод -Reset to defaults,OPTMNU_DEFAULTS,,,,Obnovit původní,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,Resetuj do domyślnych,Redefinir para configurações padrão,,Revenire la setări implicite,Сбросить все настройки,Врати подразумевано -Reset to last saved,OPTMNU_RESETTOSAVED,,,,Obnovit naposledy uložené,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,Resetuj do ostatnio zapisanych,Redefinir para a última configuração salva,Redefinir para última configuração gravada,Revenire la ultimele setări salvate,Вернуть предыдущие настройки,Врати задње сачувано -Save current settings,OPTMNU_WRITEINI,,,,Uložit současná nastavení,Aktuelle Einstellungen speichern,,Konservi nunajn reĝimojn,,,Tallenna nykyiset asetukset,,Jelenlegi beállítások mentése,,現在の設定を保存,,Huidige instellingen opslaan ,Zapisz aktualne opcje,Salvar configurações atuais,,Salvează setările curente,, -Go to console,OPTMNU_CONSOLE,,,,Jít do konzole,Öffne Konsole,,Iri al konzolo,Ir a la consola,,Mene konsoliin,Ouvrir la console,Konzol megnyitása,Vai alla console,コンソールを開く,콘솔로 이동,Ga naar de console,Przejdź do konsoli,Abrir console,Abrir consola,Mergi la consolă,Открыть консоль,Отвори конзолу -Network Options,OPTMNU_NETWORK,,,,Nastavení sítě,Netzwerkeinstellungen,Ρυθμίσεις Δικτύου,Reto-Agordoj,Opciones de Red,,Verkkoasetukset,Options Réseau,Hálózati beállítások,Opzioni Network,ネットワーク オプション,네트워크 설정,Netwerkopties,Opcje Sieciowe,Opções de rede,,Setări de Rețea,Сеть,Мрежа -Reverb environment editor,OPTMNU_REVERB,,,,Editor zvukové ozvěny,Hall-Editor,Επεξεργαστής περιβαλλόντων απόσβεσης,Redaktoro pri resonmedio,Editor de Amb. de Reverb.,,Kaikutilaeditori,Editeur environement de révérb.,Visszhangkörnyezet-szerkesztő,Editor ambiente reverb,リバーブ環境エディタ,울림 환경 편집기,Reverb-omgeving editor,Edytor pogłosu środowiska,Editor de ambiente de reverberação,,Setări Reverb,Редактор реверберации,Уредник одјека у околини -,,Customize controls,,,,,,,,,,,,,,,,,,,,, -Customize Controls,CNTRLMNU_TITLE,,,,Nastavení ovládání,Steuerung einstellen,,Adapti Regilojn,Personalizar Controles ,,Ohjausasetukset,Modifier contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare schemă control,Настройки управления,Подешавања контрола -"ENTER to change, BACKSPACE to clear",CNTRLMNU_SWITCHTEXT1,,,,"ENTER pro změnu, BACKSPACE pro smazání",ENTER: Editieren BACKSPACE: Löschen,,"ENTER por ŝanĝi, BACKSPACE por forigi","ENTER para cambiar, RETROCESO 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 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 за чишћење" -"Press new key for control, ESC to cancel",CNTRLMNU_SWITCHTEXT2,,,,"Zmáčkni novou klávesu pro nastavení, ESC pro storno",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.","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 за отказивање" -Controls,CNTRLMNU_CONTROLS,,,,Ovládání,Steuerung,,Regiloj,Controles,,Ohjaimet,Contrôles,Irányítás,Controlli,操作系統,조작,Bedieningselementen,Klawisze,Comandos,Controlos,Control,Управление,Контроле -Fire,CNTRLMNU_ATTACK,,,,Střelba,Feuer,,Pafi,Fuego,,Tuli,Tirer,Tűz,Fuoco,撃つ,공격,Vuur,Strzał,Atirar,,Foc,Атака,Нападни -Secondary Fire,CNTRLMNU_ALTATTACK,,,,Sekundární střelba,Alternativfeuer,,Pafi Duarange,Fuego secundario,,Vaihtoehtoistuli,Tir Secondaire,Másodlagos tüzelés,Fuoco secondario,セカンダリ,보조 공격,Secundaire vuur,Strzał Alternatywny,Tiro secundário,,Foc Secundar,Вторичная атака,Секундарни напад -Weapon Reload,CNTRLMNU_RELOAD,,,,Přebít zbraň,Waffe nachladen,Επαναφόρτωση Όπλου,Reŝargi Armilon,Recargar Arma,,Aseen lataus,Recharger Arme,Fegyver újratöltése,Ricarica dell'arma,リロード,무기 장전,Wapenherladen,Przeładowanie Broni,Recarregar arma,,Încărcare Armă,Перезарядка,Напуни -Use / Open,CNTRLMNU_USE,,,,Použít / otevřít,Benutzen / Öffnen,,Uzi / Malfermi,Usar / Abrir,,Käytä / Avaa,Utiliser/Ouvrir,Akciógomb/Nyitás,Usa / Apri,開く / スイッチ等使用,사용/열기,Gebruik / Openen,Użyj / Otwórz,Usar / Abrir,,Folosește / Deschide,Использовать/открыть,Користи / Отвори -Move forward,CNTRLMNU_FORWARD,,,,Pohyb vpřed,Vorwärts bewegen,,Movi anatŭen,Avanzar,,Liiku eteenpäin,Avancer,Előre mozgás,Movimento in Avanti,前進,앞으로 이동,Voorwaarts bewegen,Idź do przodu,Mover-se para frente,,Deplasare în față,Движение вперёд,Крећи се напред -Move backward,CNTRLMNU_BACK,,,,Pohyb vzad,Rückwarts bewegen,,Movi malantaŭen,Retroceder,,Liiku taaksepäin,Reculer,Hátra mozgás,Movimento in Indietro,後退,뒤로 이동,Achteruit bewegen,Idź do tyłu,Mover-se para trás,,Deplasare în spate,Движение назад,Крећи се уназад -Strafe left,CNTRLMNU_MOVELEFT,,,,Pohyb doleva,Nach links bewegen,,Flankmovi maldekstren,Moverse a la izquierda,,Astu sivuun vasemmalle,Aller à Gauche,Balra oldalazás,Movimento laterale a sinistra,左移動,왼쪽으로 이동,Verplaats naar links,Unik w lewo,Mover-se para a esquerda,,Deplasare diagonală stânga,Движение влево,Крећи се лево -Strafe right,CNTRLMNU_MOVERIGHT,,,,Pohyb doprava,Nach rechts bewegen,,Flankmovi dekstren,Moverse a la derecha,,Astu sivuun oikealle,Aller à Droite,Jobbra oldalazás,Movimento laterale a destra,右移動,오른쪽으로 이동,Verplaats naar rechts,Unik w prawo,Mover-se para a direita,,Deplasare diagonală dreapta,Движение вправо,Крећи се десно -Turn left,CNTRLMNU_TURNLEFT,,,,Otočení vlevo,Nach links drehen,,Turni maldekstren,Girar a la izquierda,,Käänny vasemmalle,Tourner à Gauche,Balra fordul,"Gira a sinistra -",左を向く,왼쪽으로 회전,Draai naar links,Obróć się w lewo,Girar para a esquerda,,Întoarcere stânga,Поворот налево,Окрени се лево -Turn right,CNTRLMNU_TURNRIGHT,,,,Otočení vpravo,Nach rechts drehen,,Turni dekstren,Girar a la derecha,,Käänny oikealle,Tourner à Droite,Jobbra fordul,Gira a destra,右を向く,오른쪽으로 회전,Draai naar rechts,Obróć się w prawo,Girar para a direita,,Întoarcere dreapta,Поворот направо,Окрени се десно -Quick Turn,CNTRLMNU_TURN180,,,,Rychlé otočení,Schnelle Drehung,,Rapida Turno,Giro rápido,,Pikakäännös,Faire un 180,Megfordulás,Rotazione rapida,背後を向く,빠른 회전,Snelle draai,Nagły Obrót,Giro rápido,,Întoarcere rapidă,Быстрый разворот,Брзи окрет -Jump,CNTRLMNU_JUMP,,,,Skok,Springen,,Salti,Saltar,,Hyppää,Sauter,Ugrás,Salta,ジャンプ,점프,Springen,Skok,Pular,Saltar,Salt,Прыжок,Скок -Crouch,CNTRLMNU_CROUCH,,,,Kleknutí,Ducken,,Kaŭri,Agacharse,,Kyyristy,S'accroupir (tenir),Guggolás,Abbassati,屈む,숙이기,Hurken,Kucnięcie,Agachar,,Ghemuire,Приседание,Чучни -Crouch Toggle,CNTRLMNU_TOGGLECROUCH,,,,Zap. / Vyp. kleknutí,Ducken an/aus,,Kaŭrobaskuli,Alternar agachado,,Kyyristymisen vaihtokytkin,S'accroupir (alterner),Guggolási kapcsoló,Toggle abbassamento,屈む切替,숙이기 토글,Hurken Toggle,Włącz / Wyłącz kucnięcie,Agachar (alternar),,Comutator ghemuire,Сесть/встать,Чучни (без држања) -Mouse look,CNTRLMNU_MOUSELOOK,,,,Pohled myší,Maus-Blick,,Musrigardo,Vista con ratón,,Hiirikatselu,Vue à la souris,Egérrel való nézelődés,Modalità vista col mouse,マウス視点上下化,마우스 룩,Muis-look,Rozglądanie się myszką,Visão com o mouse,Vista com o rato,Privire în jur cu mouse,Обзор мышью,Гледај мишем -Look up,CNTRLMNU_LOOKUP,Look doesn't change the aim! It only alters the view pitch,,,Pohled vzhůru,Nach oben schauen,,Rigardi supren,Mirar arriba,,Katso ylös,Regarder en haut,Felfele nézés,Guarda sopra,視点を上げる,위로 보기,Kijk omhoog,Patrz w górę,Olhar para cima,,Privire în sus,Смотреть вверх,Гледај горе -Look down,CNTRLMNU_LOOKDOWN,,,,Pohled dolů,Nach unten schauen,,Rigardi malsupren,Mirar abajo,,Katso alas,Regarder en bas,Lefele nézés,Guarda sotto,視点を下げる,아래로 보기,Kijk naar beneden,Patrz w dół,Olhar para baixo,,Privire în jos,Смотреть вниз,Гледај доле -Center view,CNTRLMNU_CENTERVIEW,,,Centre view,Vystředit pohled,Ansicht zentrieren,,Centrigi vidon,Centrar vista,,Keskitä katse,Recentrer Vue,Nézet középreigazítása,Sguardo centrato,視点を戻す,중앙 시점으로 보기,Middenaanzicht,Wyśrodkuj widok,Olhar para o centro,,Centrare privire,Отцентрировать взгляд,Централизирај поглед -Run,CNTRLMNU_RUN,,,,Běh,Rennen,,Kuri,Correr,,Juokse,Courir (tenir),Futás,Corri,駆け足,달리기,Rennen,Bieg,Correr,,Fugă,Бег,Трчи -Toggle Run,CNTRLMNU_TOGGLERUN,,,,Zap. / Vyp. běh,Rennen an/aus,,Baskuligi Kuron,Alternar Correr,,Juoksun vaihtokytkin,Courir (alterner),Futás kapcsoló,Toggle corsa,常時駆け足切替,달리기 토글,Rennen aan/uit,Włącz / Wyłącz bieg,Correr (alternar),,Comutator fugă,Бежать/идти,Трчи (без држања) -Strafe,CNTRLMNU_STRAFE,,,,Pohyb vlevo/vpravo,Seitwärts,,Flankmovi,Desplazamiento,,Astu sivuttain,Pas de côté,Oldalazás,Spostamento laterale,横移動化,양옆으로 이동,Zijdelings bewegen,Uniki,Deslocamento lateral,,Deplasare în diagonală,Движение боком,Кретање у страну -Show Scoreboard,CNTRLMNU_SCOREBOARD,,,,Zobrazit tabulku skóre,Punktetafel anzeigen,,Montri poentotabulon,Mostrar Marcador,,Näytä pistetaulu,Afficher Scores (tenir),Eredményjelző megjelenítése,Mostra la tabella punteggio,スコアボード表示,점수창 표시,Scorebord tonen,Pokaż tablicę wyników,Exibir placar,,Afișare tabelă de marcaj,Таблица очков,Табела -Action,CNTRLMNU_ACTION,,,,Akce,Aktion,,Ago,Acción,,Toiminta,,Akció,Azione,アクション,동작,Actie,Akcja,Ação,,Acțiuni,Основное,Радња -Customize Action Controls,CNTRLMNU_ACTION_TITLE,,,,Nastavit ovládání akcí,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,Ustaw Klawisze Akcji,Personalizar comandos de ação,Configurar Controlos de Ação,Personalizare schemă acțiuni,Основные клавиши управления,Контроле радње -Chat,CNTRLMNU_CHAT,,,,Chat,Chat,,Babili,Chat,,Keskustelu,Chat,Chat,Chat,チャット,채팅,Chat,Czat,Bate-papo,Conversar,Conversație,Чат,Ћаскање -Multiplayer,MNU_MULTIPLAYER,,,,,Mehrspieler,,Plurludanta,Multijugador,,Moninpeli,Multijoueur,Többjátékos,,マルチプレイヤー,,,Tryb Wieloosobowy,Multijogador,,Joc Online,, -Say,CNTRLMNU_SAY,,,,Říct,Reden,,Diri,Hablar,,Sano,Parler,Üzenet ,Parla,発言,채팅하기,Zeg,Powiedz,Dizer,Falar,Vorbește,Сообщение,Пиши -Customize Chat Controls,CNTRLMNU_CHAT_TITLE,,,,Nastavit ovládání chatu,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,Ustaw Klawisze Czatu,Personalizar comandos do bate-papo,Configurar Controlos de Chat,Personalizare control scriere,Клавиши управления чатом,Контроле ћаскања -Customize Weapon Controls,CNTRLMNU_WEAPONS_TITLE,,,,Nastavit ovládání zbraní,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,Ustaw Klawisze Broni,Personalizar comandos de arma,Configurar Controlos de Armas,Personalizare control arme,Клавиши управления оружием,Контроле оружја -Customize Inventory Controls,CNTRLMNU_INVENTORY_TITLE,,,,Nastavit ovládání inventáře,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,Ustaw Klawisze Ekwipunku,Personalizar comandos do inventário,Configurar Controlos de Inventário,Personalizare control inventar,Клавиши управления инвентарём,Контроле складишта -Customize Other Controls,CNTRLMNU_OTHER_TITLE,,,,Nastavit ostatní ovládání,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,Ustaw Inne Klawisze,Personalizar outros comandos,Configurar Outros Controlos,Personalizare scheme de control diverse,Прочие клавиши,Друге контроле -Weapons,CNTRLMNU_WEAPONS,,,,Zbraně,Waffen,,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기,Wapens,Bronie,Armas,,Arme,Оружие,Оружје -Next weapon,CNTRLMNU_NEXTWEAPON,,,,Další zbraň,Nächste Waffe,,Sekva armilo,Arma siguiente,,Seuraava ase,Arme Suivante,Következő fegyver,Arma successiva,次の武器,다음 무기,Volgende wapen,Następna broń,Arma seguinte,,Arma următoare,Следующее оружие,Следеће оружје -Previous weapon,CNTRLMNU_PREVIOUSWEAPON,,,,Předchozí zbraň,Vorherige Waffe,,Antaŭa armilo,Arma anterior,,Edellinen ase,Arme Précédente,Előző fegyver,Arma precedente,前の武器,이전 무기,Vorige wapen,Poprzednia broń,Arma anterior,,Arma anterioară,Предыдущее оружие,Претходно оружје -Weapon 1,CNTRLMNU_SLOT1,Todo - make game specific,,,Slot zbraně 1,Waffe 1,,Armilo 1,Arma 1,,Aselokero 1,Emplacement D'Arme 1,1. fegyver,Slot arma 1,武器スロット 1,무기 슬롯 1,Wapenslot 1,Broń 1,Arma 1,,Arma 1,Оружие 1,Оружје 1 +",Biztosan törlöd a mentést?,Vuoi veramente cancellare il salvataggio?,本当にこのセーブを消すのか?,저장된 게임을 정말로 삭제하시겠습니까?,Wil je echt de opgeslagen spel verwijderen?,Czy naprawdę chcesz usunąć zapis gry?,Deseja mesmo excluir o jogo salvo?,Deseja mesmo apagar o jogo,Vrei să ștergi salvarea?,"Вы действительно хотите удалить сохранение +",Да ли стварно желите да избришете сачувану игру,Найстина ли искаш да изтриеш запазената игра +,,General,,,,,,,,,,,,,,,,,,,,,, +Off,OPTVAL_OFF,,,,Vyp.,Aus,,Malŝaltita,Desactivado,,Pois,,Ki,Disattivo,オフ,끔,Uit,Wyłączone,Não,,Pornit,Откл.,Искљ.,Изкл. +On,OPTVAL_ON,,,,Zap.,An,,Ŝaltita,Activado,,Päällä,,Be,Attivo,オン,켬,Aan,Włączone,Sim,,Oprit,Вкл.,Укљ.,Вкл. +Auto,OPTVAL_AUTO,,,,,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,자동,,Automatycznie,Automático,,,Авто,Аутоматски,Автоматично +Options,OPTMNU_TITLE,,,,Možnosti,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Opcje,Opções,,Opțiuni,Настройки,Подешавања,Настройки +Customize Controls,OPTMNU_CONTROLS,,,,Ovládání,Steuerung einstellen,,Adapti Regilojn,Personalizar Controles,,Ohjausasetukset,Modifier les Contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare Setări Control,Управление,Контроле,Управление +Mouse Options,OPTMNU_MOUSE,,,,Myš,Mauseinstellungen,Ρυθμίσεις ποντικίου,Muso-Agordoj,Opciones de Ratón,,Hiiriasetukset,Options de la Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,Setări Mouse,Мышь,Миш,Мишка +Controller Options,OPTMNU_JOYSTICK,,,,Ovladač,Joystickeinstellungen,,Ludregilo-Agordoj,Opciones de Mando,,Peliohjainasetukset,Options de la Manette,Játékvezérlő beállítások,Opzioni Joystick,コントローラーオプション,조이스틱 설정,Controller opties,Opcje Kontrolera,Opções de controle,,Setări Controller,Контроллер,Контролер,Контролер +Player Setup,OPTMNU_PLAYER,,,,Hráč,Spieler einrichten,Ρυθμίσεις παίχτη,Ludanto-Agordaĵo,Config. del Jugador,,Pelaaja-asetukset,Options du Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Ustawienia Gracza,Configurações de jogador,Configurações do Jogador,Personalizare Jucător,Игрок,Играч,Играч +Gameplay Options,OPTMNU_GAMEPLAY,,,,Herní mechaniky,Spieleinstellungen,,Ludado-Agordoj,Opciones de Jugabilidad,,Pelattavuusasetukset,Options du Gameplay,Játékmenet beállítások,Opzioni Gameplay,ゲームプレイ オプション,게임 설정,Gameplay-opties,Opcje Rozgrywki,Opções de jogabilidade,,Setări pe timp de joc,Игра,Гејмплеј,Игра +Automap Options,OPTMNU_AUTOMAP,,,,Automapa,Automapeinstellungen,,Aŭtomapo-Agordoj,Opciones del Automapa,,Automaattikartan asetukset,Options de la Carte,Térkép beállítások,Opzioni Automappa,オートマップ オプション,오토맵 설정,Automap-opties,Opcje Mapy,Opções de automapa,,Hartă computerizată,Автокарта,Аутомапа,Автокарта +HUD Options,OPTMNU_HUD,,,,Rozhraní a HUD,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,Opcje HUD,Opções de HUD,,Setări HUD,Интерфейс,HUD,Интерфейс +Miscellaneous Options,OPTMNU_MISCELLANEOUS,,,,Ostatní,Verschiedene Einstellungen,Διάφορες ρυθμίσεις,Diversaĵaj Agordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni Miste,その他のオプション,그 외 설정,Diverse opties,Różne Opcje,Outras opções,,Setări diverse,Дополнительно,Разно,Други настройки +Sound Options,OPTMNU_SOUND,,,,Zvuk,Soundeinstellungen,Ρυθμίσεις ήχου,Sono-Agordoj,Opciones de Sonido,,Ääniasetukset,Options du Son,Hang beállítások,Opzioni Suono,サウンド オプション,음향 설정,Geluidsopties,Opcje Dźwięku,Opções de som,,Setări sunet,Звук,Звук,Звука +Display Options,OPTMNU_DISPLAY,,,,Grafika,Anzeigeeinstellungen,,Ekrano-Agordoj,Opciones de Visualización,,Näyttöasetukset,Options de l'Affichage,Megjelenítés beállítások,Opzioni Display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Экран,Приказ,Екрана +Set video mode,OPTMNU_VIDEO,,,,Obrazový výstup,Videomodus,Άλλαξε λειτουργία βίντεο,Agordi videoreĝimon,Modos de Vídeo,,Aseta videotila,Choisir Mode D'Affichage,Videó beállítások,Settaggio modalità video,ビデオ 調整,화면 설정,Videomodus instellen,Ustaw tryb wideo,Definir modo de vídeo,,Setare mod video,Видеорежим,Видео мод,Видеорежим +Reset to defaults,OPTMNU_DEFAULTS,,,,Obnovit původní,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,Resetuj do domyślnych,Redefinir para configurações padrão,,Revenire la setări implicite,Сбросить все настройки,Врати подразумевано,Нулирай до стандартни +Reset to last saved,OPTMNU_RESETTOSAVED,,,,Obnovit naposledy uložené,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,Resetuj do ostatnio zapisanych,Redefinir para a última configuração salva,Redefinir para última configuração gravada,Revenire la ultimele setări salvate,Вернуть предыдущие настройки,Врати задње сачувано,Нулирай до последно запазената игра +Save current settings,OPTMNU_WRITEINI,,,,Uložit současná nastavení,Aktuelle Einstellungen speichern,Αποθήκευσε της τορινές ρυθμίσεις,Konservi nunajn reĝimojn,,,Tallenna nykyiset asetukset,,Jelenlegi beállítások mentése,Salva le impostazioni correnti,現在の設定を保存,현재 설정 적용,Huidige instellingen opslaan ,Zapisz aktualne opcje,Salvar configurações atuais,,Salvează setările curente,Сохранить текущие настройки,,Запази сегашните настройки +Go to console,OPTMNU_CONSOLE,,,,Otevřít konzoli,Öffne Konsole,Μπές στη κονσόλα,Iri al konzolo,Ir a la consola,,Mene konsoliin,Ouvrir la console,Konzol megnyitása,Vai alla console,コンソールを開く,콘솔로 이동,Ga naar de console,Przejdź do konsoli,Abrir console,Abrir consola,Mergi la consolă,Открыть консоль,Отвори конзолу,Отвори конзолата +Network Options,OPTMNU_NETWORK,,,,Síť,Netzwerkeinstellungen,Ρυθμίσεις Δικτύου,Reto-Agordoj,Opciones de Red,,Verkkoasetukset,Options Réseau,Hálózati beállítások,Opzioni Network,ネットワーク オプション,네트워크 설정,Netwerkopties,Opcje Sieciowe,Opções de rede,,Setări de Rețea,Сеть,Мрежа,Мрежа +Reverb environment editor,OPTMNU_REVERB,,,,Editor zvukové ozvěny,Hall-Editor,Επεξεργαστής περιβαλλόντων απόσβεσης,Redaktoro pri resonmedio,Editor de Amb. de Reverb.,,Kaikutilaeditori,Editeur environement de révérb.,Visszhangkörnyezet-szerkesztő,Editor ambiente reverb,リバーブ環境エディタ,울림 환경 편집기,Reverb-omgeving editor,Edytor pogłosu środowiska,Editor de ambiente de reverberação,,Setări Reverb,Редактор реверберации,Уредник одјека у околини,Редактор на среда за реверберация +,,Customize controls,,,,,,,,,,,,,,,,,,,,,, +Customize Controls,CNTRLMNU_TITLE,,,,Nastavení ovládání,Steuerung einstellen,,Adapti Regilojn,Personalizar Controles ,,Ohjausasetukset,Modifier contrôles,Irányítás testreszabása,Personalizza i controlli,キー配置変更,조작 사용자 지정,Instellen van de controle,Ustaw Klawisze,Personalizar comandos,Configurar Controlos,Personalizare schemă control,Настройки управления,Подешавања контрола,Настройки на управлвние +"ENTER to change, BACKSPACE to clear",CNTRLMNU_SWITCHTEXT1,,,,"ENTER pro změnu, BACKSPACE pro smazání",ENTER: Editieren BACKSPACE: Löschen,,"ENTER por ŝanĝi, BACKSPACE por forigi","ENTER para cambiar, RETROCESO 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 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 — промяна, BACKSPACE — изчистване" +"Press new key for control, ESC to cancel",CNTRLMNU_SWITCHTEXT2,,,,"Zmáčkni novou klávesu, nebo ESC pro storno",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.","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 за отказивање","Натисни нов клавиш за управление, ESC за отмяна" +Controls,CNTRLMNU_CONTROLS,,,,Ovládání,Steuerung,,Regiloj,Controles,,Ohjaimet,Contrôles,Irányítás,Controlli,操作系統,조작,Bedieningselementen,Klawisze,Comandos,Controlos,Control,Управление,Контроле,Управление +Fire,CNTRLMNU_ATTACK,,,,Střelba,Feuer,Πυροβόλα,Pafi,Fuego,,Tuli,Tirer,Tűz,Fuoco,撃つ,공격,Vuur,Strzał,Atirar,,Foc,Атака,Нападни,Атака +Secondary Fire,CNTRLMNU_ALTATTACK,,,,Sekundární střelba,Alternativfeuer,,Pafi Duarange,Fuego secundario,,Vaihtoehtoistuli,Tir Secondaire,Másodlagos tüzelés,Fuoco secondario,セカンダリ,보조 공격,Secundaire vuur,Strzał Alternatywny,Tiro secundário,,Foc Secundar,Дополнительная атака,Секундарни напад,Допълнителна атака +Weapon Reload,CNTRLMNU_RELOAD,,,,Přebít zbraň,Waffe nachladen,Επαναφόρτωση Όπλου,Reŝargi Armilon,Recargar Arma,,Aseen lataus,Recharger Arme,Fegyver újratöltése,Ricarica dell'arma,リロード,무기 장전,Wapenherladen,Przeładowanie Broni,Recarregar arma,,Încărcare Armă,Перезарядка,Напуни,Презареди +Use / Open,CNTRLMNU_USE,,,,Použít/otevřít,Benutzen / Öffnen,,Uzi / Malfermi,Usar / Abrir,,Käytä / Avaa,Utiliser/Ouvrir,Akciógomb/Nyitás,Usa/Apri,開く / スイッチ等使用,사용/열기,Gebruik / Openen,Użyj / Otwórz,Usar / Abrir,,Folosește / Deschide,Использовать/открыть,Користи / Отвори,Използвай / Отвори +Move forward,CNTRLMNU_FORWARD,,,,Vpřed,Vorwärts bewegen,,Movi anatŭen,Avanzar,,Liiku eteenpäin,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 이동,Voorwaarts bewegen,Idź do przodu,Mover-se para frente,,Deplasare în față,Движение вперёд,Крећи се напред,Движение напред +Move backward,CNTRLMNU_BACK,,,,Vzad,Rückwarts bewegen,,Movi malantaŭen,Retroceder,,Liiku taaksepäin,Reculer,Hátra mozgás,Movimento in indietro,後退,뒤로 이동,Achteruit bewegen,Idź do tyłu,Mover-se para trás,,Deplasare în spate,Движение назад,Крећи се уназад,Движение назад +Strafe left,CNTRLMNU_MOVELEFT,,,,Úkrok vlevo,Nach links bewegen,,Flankmovi maldekstren,Moverse a la izquierda,,Astu sivuun vasemmalle,Aller à Gauche,Balra oldalazás,Movimento laterale a sinistra,左移動,왼쪽으로 이동,Verplaats naar links,Unik w lewo,Mover-se para a esquerda,,Deplasare diagonală stânga,Движение влево,Крећи се лево,Движение в ляво +Strafe right,CNTRLMNU_MOVERIGHT,,,,Úkrok vpravo,Nach rechts bewegen,,Flankmovi dekstren,Moverse a la derecha,,Astu sivuun oikealle,Aller à Droite,Jobbra oldalazás,Movimento laterale a destra,右移動,오른쪽으로 이동,Verplaats naar rechts,Unik w prawo,Mover-se para a direita,,Deplasare diagonală dreapta,Движение вправо,Крећи се десно,Движение в дясно +Turn left,CNTRLMNU_TURNLEFT,,,,Otočení vlevo,Nach links drehen,Γύρνα αριστερά,Turni maldekstren,Girar a la izquierda,,Käänny vasemmalle,Tourner à Gauche,Balra fordul,"Gira a sinistra +",左を向く,왼쪽으로 회전,Draai naar links,Obróć się w lewo,Girar para a esquerda,,Întoarcere stânga,Поворот налево,Окрени се лево,Обръщане в ляво +Turn right,CNTRLMNU_TURNRIGHT,,,,Otočení vpravo,Nach rechts drehen,Γύρνα δεξιά,Turni dekstren,Girar a la derecha,,Käänny oikealle,Tourner à Droite,Jobbra fordul,Gira a destra,右を向く,오른쪽으로 회전,Draai naar rechts,Obróć się w prawo,Girar para a direita,,Întoarcere dreapta,Поворот направо,Окрени се десно,Обръщане в дясно +Quick Turn,CNTRLMNU_TURN180,,,,Rychlé otočení,Schnelle Drehung,Γρήγορη γύριση,Rapida Turno,Giro rápido,,Pikakäännös,Faire un 180,Megfordulás,Rotazione rapida,背後を向く,빠른 회전,Snelle draai,Szybki Obrót,Giro rápido,,Întoarcere rapidă,Быстрый разворот,Брзи окрет,Бързо обръщане +Jump,CNTRLMNU_JUMP,,,,Skok,Springen,Πήδα,Salti,Saltar,,Hyppää,Sauter,Ugrás,Salto,ジャンプ,점프,Springen,Skok,Pular,Saltar,Salt,Прыжок,Скок,Скок +Crouch,CNTRLMNU_CROUCH,,,,Kleknutí,Ducken,,Kaŭri,Agacharse,,Kyyristy,S'accroupir (tenir),Guggolás,Abbassarsi,屈む,숙이기,Hurken,Kucnięcie,Agachar,,Ghemuire,Приседание,Чучни,Клякане +Crouch Toggle,CNTRLMNU_TOGGLECROUCH,,,,Přepnout kleknutí,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,Сесть/встать,Чучни (без држања),Клякане постоянно +Mouse look,CNTRLMNU_MOUSELOOK,,,,Pohled myší,Maus-Blick,Κοίτα με το ποντίκι,Musrigardo,Vista con ratón,,Hiirikatselu,Vue à la souris,Egérrel való nézelődés,Modalità vista col mouse,マウス視点上下化,마우스 룩,Muis-look,Rozglądanie się myszką,Visão com o mouse,Vista com o rato,Privire în jur cu mouse,Обзор мышью,Гледај мишем,Поглед с мишката +Look up,CNTRLMNU_LOOKUP,Look doesn't change the aim! It only alters the view pitch,,,Pohled vzhůru,Nach oben schauen,Κοίτα απάνω,Rigardi supren,Mirar arriba,,Katso ylös,Regarder en haut,Felfele nézés,Guarda sopra,視点を上げる,위로 보기,Kijk omhoog,Patrz w górę,Olhar para cima,,Privire în sus,Смотреть вверх,Гледај горе,Поглед нагоре +Look down,CNTRLMNU_LOOKDOWN,,,,Pohled dolů,Nach unten schauen,Κοίτα κάτω,Rigardi malsupren,Mirar abajo,,Katso alas,Regarder en bas,Lefele nézés,Guarda sotto,視点を下げる,아래로 보기,Kijk naar beneden,Patrz w dół,Olhar para baixo,,Privire în jos,Смотреть вниз,Гледај доле,Поглед надолу +Center view,CNTRLMNU_CENTERVIEW,,,Centre view,Vystředit pohled,Ansicht zentrieren,,Centrigi vidon,Centrar vista,,Keskitä katse,Recentrer Vue,Nézet középreigazítása,Sguardo centrato,視点を戻す,중앙 시점으로 보기,Middenaanzicht,Wyśrodkuj widok,Olhar para o centro,,Centrare privire,Отцентрировать взгляд,Централизирај поглед,Центриране на погледа +Run,CNTRLMNU_RUN,,,,Běh,Rennen,Τρέχα,Kuri,Correr,,Juokse,Courir (tenir),Futás,Corri,駆け足,달리기,Rennen,Bieg,Correr,,Fugă,Бег,Трчи,Бягане +Toggle Run,CNTRLMNU_TOGGLERUN,,,,Přepnout běh,Rennen an/aus,Ενεργοποίηση τρέξιμου,Baskuligi Kuron,Alternar Correr,,Juoksun vaihtokytkin,Courir (alterner),Futás kapcsoló,Abilita/disabilita corsa,常時駆け足切替,달리기 토글,Rennen aan/uit,Przełącz bieg,Correr (alternar),,Comutator fugă,Бежать/идти,Трчи (без држања),Бягане постоянно +Strafe,CNTRLMNU_STRAFE,,,,Pohyb do stran,Seitwärts,,Flankmovi,Desplazamiento,,Astu sivuttain,Pas de côté,Oldalazás,Spostamento laterale,横移動化,양옆으로 이동,Zijdelings bewegen,Uniki,Deslocamento lateral,,Deplasare în diagonală,Движение боком,Кретање у страну,Странично движение +Show Scoreboard,CNTRLMNU_SCOREBOARD,,,,Zobrazit tabulku skóre,Punktetafel anzeigen,,Montri poentotabulon,Mostrar Marcador,,Näytä pistetaulu,Afficher Scores (tenir),Eredményjelző megjelenítése,Mostra la tabella punteggio,スコアボード表示,점수창 표시,Scorebord tonen,Pokaż tablicę wyników,Exibir placar,,Afișare tabelă de marcaj,Таблица очков,Табела,Покажи резултати +Action,CNTRLMNU_ACTION,,,,Akce,Aktion,Δράσεις,Ago,Acción,,Toiminta,,Akció,Azione,アクション,동작,Actie,Akcja,Ação,,Acțiuni,Основное,Радња,Действие +Customize Action Controls,CNTRLMNU_ACTION_TITLE,,,,Nastavení ovládání akcí,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,Ustaw Klawisze Akcji,Personalizar comandos de ação,Configurar Controlos de Ação,Personalizare schemă acțiuni,Основные клавиши управления,Контроле радње,Персонализиране на контролите за действие +Chat,CNTRLMNU_CHAT,,,,Chat,Chat,Μίλα,Babili,Chat,,Keskustelu,Chat,Chat,Chat,チャット,채팅,Chat,Czat,Bate-papo,Conversar,Conversație,Чат,Ћаскање,Чат +Multiplayer,MNU_MULTIPLAYER,,,,,Mehrspieler,,Plurludanta,Multijugador,,Moninpeli,Multijoueur,Többjátékos,Multigiocatore,マルチプレイヤー,,,Tryb Wieloosobowy,Multijogador,,Joc Online,Сетевая игра,,Онлайн игра +Say,CNTRLMNU_SAY,,,,Říct,Reden,Πές,Diri,Hablar,,Sano,Parler,Üzenet ,Parla,発言,채팅하기,Zeg,Powiedz,Falar,,Vorbește,Сообщение,Пиши,Съобщение +Customize Chat Controls,CNTRLMNU_CHAT_TITLE,,,,Nastavení ovládání chatu,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,Ustaw Klawisze Czatu,Personalizar comandos do bate-papo,Configurar Controlos de Chat,Personalizare control scriere,Клавиши управления чатом,Контроле ћаскања,Персонализиране на контролите за чата +Customize Weapon Controls,CNTRLMNU_WEAPONS_TITLE,,,,Nastavení ovládání zbraní,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,Ustaw Klawisze Broni,Personalizar comandos de arma,Configurar Controlos de Armas,Personalizare control arme,Клавиши управления оружием,Контроле оружја,Персонализиране на контролите за оръжия +Customize Inventory Controls,CNTRLMNU_INVENTORY_TITLE,,,,Nastavení ovládání inventáře,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,Ustaw Klawisze Ekwipunku,Personalizar comandos do inventário,Configurar Controlos de Inventário,Personalizare control inventar,Клавиши управления инвентарём,Контроле складишта,Персонализиране на контролите за инвентара +Customize Other Controls,CNTRLMNU_OTHER_TITLE,,,,Nastavení ostatních ovládání,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,Ustaw Inne Klawisze,Personalizar outros comandos,Configurar Outros Controlos,Personalizare scheme de control diverse,Прочие клавиши,Друге контроле,Персонализиране на други контроли +Weapons,CNTRLMNU_WEAPONS,,,,Zbraně,Waffen,Όπλα,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기,Wapens,Bronie,Armas,,Arme,Оружие,Оружје,Оръжия +Next weapon,CNTRLMNU_NEXTWEAPON,,,,Další zbraň,Nächste Waffe,Επόμενο όπλο,Sekva armilo,Arma siguiente,,Seuraava ase,Arme Suivante,Következő fegyver,Arma successiva,次の武器,다음 무기,Volgende wapen,Następna broń,Arma seguinte,,Arma următoare,Следующее оружие,Следеће оружје,Следващо оръжие +Previous weapon,CNTRLMNU_PREVIOUSWEAPON,,,,Předchozí zbraň,Vorherige Waffe,Προηγούμενο όπλο,Antaŭa armilo,Arma anterior,,Edellinen ase,Arme Précédente,Előző fegyver,Arma precedente,前の武器,이전 무기,Vorige wapen,Poprzednia broń,Arma anterior,,Arma anterioară,Предыдущее оружие,Претходно оружје,Предишно оръжие +Weapon 1,CNTRLMNU_SLOT1,Todo - make game specific,,,Slot zbraně 1,Waffe 1,Όπλο 1,Armilo 1,Arma 1,,Aselokero 1,Emplacement D'Arme 1,1. fegyver,Slot arma 1,武器スロット 1,무기 슬롯 1,Wapenslot 1,Broń 1,Arma 1,,Arma 1,Оружие 1,Оружје 1,Оръжие 1 Weapon 2,CNTRLMNU_SLOT2,"only show appropriate slots per game -",,,Slot zbraně 2,Waffe 2,,Armilo 2,Arma 2,,Aselokero 2,Emplacement D'Arme 2,2. fegyver,Slot arma 2,武器スロット 2,무기 슬롯 2,Wapenslot 2,Broń 2,Arma 2,,Arma 2,Оружие 2,Оружје 2 -Weapon 3,CNTRLMNU_SLOT3,,,,Slot zbraně 3,Waffe 3,,Armilo 3,Arma 3,,Aselokero 3,Emplacement D'Arme 3,3. fegyver,Slot arma 3,武器スロット 3,무기 슬롯 3,Wapenslot 3,Broń 3,Arma 3,,Arma 3,Оружие 3,Оружје 3 -Weapon 4,CNTRLMNU_SLOT4,,,,Slot zbraně 4,Waffe 4,,Armilo 4,Arma 4,,Aselokero 4,Emplacement D'Arme 4,4. fegyver,Slot arma 4,武器スロット 4,무기 슬롯 4,Wapenslot 4,Broń 4,Arma 4,,Arma 4,Оружие 4,Оружје 4 -Weapon 5,CNTRLMNU_SLOT5,,,,Slot zbraně 5,Waffe 5,,Armilo 5,Arma 5,,Aselokero 5,Emplacement D'Arme 5,5. fegyver,Slot arma 5,武器スロット 5,무기 슬롯 5,Wapenslot 5,Broń 5,Arma 5,,Arma 5,Оружие 5,Оружје 5 -Weapon 6,CNTRLMNU_SLOT6,,,,Slot zbraně 6,Waffe 6,,Armilo 6,Arma 6,,Aselokero 6,Emplacement D'Arme 6,6. fegyver,Slot arma 6,武器スロット 6,무기 슬롯 6,Wapenslot 6,Broń 6,Arma 6,,Arma 6,Оружие 6,Оружје 6 -Weapon 7,CNTRLMNU_SLOT7,,,,Slot zbraně 7,Waffe 7,,Armilo 7,Arma 7,,Aselokero 7,Emplacement D'Arme 7,7. fegyver,Slot arma 7,武器スロット 7,무기 슬롯 7,Wapenslot 7,Broń 7,Arma 7,,Arma 7,Оружие 7,Оружје 7 -Weapon 8,CNTRLMNU_SLOT8,,,,Slot zbraně 8,Waffe 8,,Armilo 8,Arma 8,,Aselokero 8,Emplacement D'Arme 8,8. fegyver,Slot arma 8,武器スロット 8,무기 슬롯 8,Wapenslot 8,Broń 8,Arma 8,,Arma 8,Оружие 8,Оружје 8 -Weapon 9,CNTRLMNU_SLOT9,,,,Slot zbraně 9,Waffe 9,,Armilo 9,Arma 9,,Aselokero 9,Emplacement D'Arme 9,9. fegyver,Slot arma 9,武器スロット 9,무기 슬롯 9,Wapenslot 9,Broń 9,Arma 9,,Arma 9,Оружие 9,Оружје 9 -Weapon 10,CNTRLMNU_SLOT0,,,,Slot zbraně 10,Waffe 10,,Armilo 10,Arma 10,,Aselokero 0,Emplacement D'Arme 0,0. fegyver,Slot arma 0,武器スロット 0,무기 슬롯 0,Wapenslot 0,Broń 10,Arma 0,,Arma 0,Оружие 0,Оружје 0 -Inventory,CNTRLMNU_INVENTORY,,,,Inventář,Inventar,,Inventaro,Inventario,,Varusteet,Inventaire,Eszköztár beállítások testreszabása,Inventario,所持品,인벤토리,Inventaris,Ekwipunek,Inventário,,Inventar,Инвентарь,Инвентар -Activate item,CNTRLMNU_USEITEM,,,,Aktivovat předmět,Gegenstand aktivieren,,Aktivigi objekton,Activar objeto,,Aktivoi varuste,Activer objet,Eszköz használata,Attiva oggetto,アイテムを使用,선택한 아이템 사용,Item activeren,Użyj przedmiot,Ativar item,,Activează obiectul,Использовать предмет,Активирај предмет -Activate all items,CNTRLMNU_USEALLITEMS,,,,Aktivovat všechny předměty,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,Użyj wszystkie przedmioty,Ativar todos os itens,,Activează tot inventarul,Использовать все предметы,Активирај све предмете -Next item,CNTRLMNU_NEXTITEM,,,,Další předmět,Nächster Gegenstand,,Sekva objekto,Objeto siguiente,,Seuraava varuste,Objet suivant,Következő eszköz,Oggetto successivo,次のアイテム,다음 아이템,Volgende item,Następny przedmiot,Item seguinte,,Următorul obiect,Следующий предмет,Следећи предмет -Previous item,CNTRLMNU_PREVIOUSITEM,,,,Předchozí předmět,Vorheriger Gegenstand,,Antaŭa objekto,Objeto anterior,,Edellinen varuste,Objet précédent,Előző eszköz,Oggetto precedente,前のアイテム,이전 아이템,Vorige item,Poprzedni przedmiot,Item anterior,,Obiect anterior,Предыдущий предмет,Претходни предмет -Customize Map Controls,MAPCNTRLMNU_TITLE,most are not used yet but will be,,,Nastavení ovládání mapy,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,Ustaw klawisze mapy,Peronalizar comandos de mapa,,Personalizare schemă de control a hărții,Клавиши управления автокартой,Промени контроле мапе -Map Controls,MAPCNTRLMNU_CONTROLS,,,,Ovládání mapy,Automapsteuerung,,Map-Regiloj,Controles del mapa,,Kartanohjaus,Contrôles de la carte,Térkép irányítása,Controlli mappa,マップコントロール,미니맵 조정,Kaartcontroles,Klawisze mapy,Comandos do mapa,,Schemă de control a hărtii,Автокарта,Контроле мапе -Pan left,MAPCNTRLMNU_PANLEFT,,,,Posun vlevo,Nach links,,Alturni maldekstren,Mover a la izquierda,,Panoroi vasemmalle,Aller à gauche,Balra igazítás,Sposta a sinistra,左に振る,왼쪽으로 이동,Pan links,Przesuń w lewo,Mover para a esquerda,,Mutare spre stânga,Сдвиг влево,Лево -Pan right,MAPCNTRLMNU_PANRIGHT,,,,Posun vpravo,Nach rechts,,Alturni dekstren,Mover a la derecha,,Panoroi oikealle,Aller à droite,Jobbra igazítás,Sposta a destra,右に振る,오른쪽으로 이동,Pan rechts,Przesuń w prawo,Mover para a direita,,Mutare spre dreapta,Сдвиг вправо,Десно -Pan up,MAPCNTRLMNU_PANUP,,,,Posun nahoru,Nach oben,,Alturni supren,Mover hacia arriba,,Panoroi ylös,Aller en haut,Felfele igazítás,Sposta sopra,上に振る,위쪽으로 이동,Pan omhoog,Przesuń w górę,Mover para cima,,Mutare în sus,Сдвиг вверх,Горе -Pan down,MAPCNTRLMNU_PANDOWN,,,,Posun dolů,Nach unten,,Alturni malsupren,Mover hacia abajo,,Panoroi alas,Aller en bas,Lefele igazítás,Sposta sotto,下に振る,아래쪽으로 이동,Pan neer,Przesuń w dół,Mover para baixo,,Mutare în jos,Сдвиг вниз,Доле -Zoom in,MAPCNTRLMNU_ZOOMIN,,,,Přiblížit,Reinzoomen,,Zomi,Acercar,,Lähennä,Zoom avant,Ráközelítés,Ingrandisci,ズームイン,줌 확대,Inzoomen,Przybliż,Ampliar,,Apropriere Cameră,Увеличить масштаб,Увеличати -Zoom out,MAPCNTRLMNU_ZOOMOUT,,,,Oddálit,Rauszoomen,,Malzomi,Alejar,,Loitonna,Zoom arrière,Távolítás,Rimpicciolisci,ズームアウト,줌 축소,Uitzoomen,Oddal,Afastar,,Depărtare Cameră,Уменьшить масштаб,Одзумирати -Toggle zoom,MAPCNTRLMNU_TOGGLEZOOM,,,,Zoom vyp./zap.,Zoom an/aus,,Baskuligi zomon,Alternar zoom,,Zoomauksen vaihtokytkin,Alterner zoom,Közelítés átkapcsolása,Abilita/disabilita zoom,ズーム切替,표준배율 조정,Omschakelen van de zoom,Przełącz przybliżanie,Ativar/desativar zoom,,Comutator Zoom,Переключить зум,Укључи зум -Toggle follow,MAPCNTRLMNU_TOGGLEFOLLOW,,,,Následování hráče vyp./zap.,Folgen an/aus,,Baskuligi sekvon,Alternar seguimiento,,Seuraamistilan vaihtokytkin,Alterner suivi,Követés átkapcsolása,Abilita/disabilita scorrimento mappa,追従切替,추적모드 조정,Schakelen volgen,Przełącz śledzenie,Ativar/desativar seguimento,,Comutator urmărire jucător,Переключить привязку к игроку,Укључи праћење -Toggle grid,MAPCNTRLMNU_TOGGLEGRID,,,,Mřížka vyp./zap.,Gitter an/aus,,Baskuligi kradon,Alternar cuadrícula,Alternar rejilla,Ruudukon vaihtokytkin,Alterner grille,Rács kapcsolása,Abilita/disabilita la griglia,グリッド切替,그리드 조정,Kiesnet,Przełącz siatkę,Ativar/desativar grade,,Comutator grilă,Переключить сетку,Укључи координатну мрежу -Toggle rotate,MAPCNTRLMNU_ROTATE,,,,Rotace vyp./zap.,Rotation an/aus,,Baskuligi turnadon,Alternar rotación,,Kääntämisen vaihtokytkin,,Forgás kapcsolása,,回転切替,,,Przełącz Obracanie,Ativar/desativar rotação,,Comutator rotire,, -Toggle texture,MAPCNTRLMNU_TOGGLETEXTURE,,,,Textury vyp./zap.,Texturen an/aus,,Baskuligi teksturon,Alternar textura,,Pintakuvioinnin vaihtokytkin,Alterner texture,Textúra kapcsolása,Abilita/disabilita le texture,テクスチャ切替,미니맵 텍스쳐 조정,Toggle textuur,Przełącz tekstury,Ativar/desativar texturas,,Comutator mod texturat,Переключить текстуры,Укључи текстуру -Toggle automap,CNTRLMNU_AUTOMAP,,,,Zap. / Vyp. automapu,Automap an/aus,,Baskuligi aŭtomapo,Alternar automapa,,Kytke automaattikartta päälle/pois,Activer Carte,Térkép ki/bekapcsolása,Toggle automappa,オートマップの切替,오토맵 조정,Automap aan/uit,Włącz mapę,Ativar/desativar automapa,,Comutator hartă computerizată,Открыть автокарту,Прикажи аутомапу -Chasecam,CNTRLMNU_CHASECAM,,,,Kamera z třetí osoby,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 de terceira pessoa,Câmera em terceira-pessoa,Cameră urmăritoare,Вид от 3-го лица (Chasecam),Чејс-кем -Screenshot,CNTRLMNU_SCREENSHOT,,,,Pořídit snímek obrazovky,,,Ekrankopio,Captura de pantalla,,Kuvakaappaus,Capture d'écran,Képernyő lefényképezése,Cattura schermo,画面キャプチャ,스크린샷,,Zrzut ekranu,Captura de tela,,Captură ecran,Скриншот,Усликај -Open console,CNTRLMNU_CONSOLE,,,,Otevřít konzoli,Konsole öffnen,,Malfermi konzolon,Abrir consola,,Avaa konsoli,Ouvrir Console,Konzol megnyitása,Apri la console,コンソールを開く,콘솔 열기,Open console,Otwórz konsolę,Abrir console,Abrir consola,Deschide consola,Открыть консоль,Отвори консолу -Pause,CNTRLMNU_PAUSE,,,,Pauza,,,Paŭzo,Pausa,,Tauko,,Szünet,Pausa,ポーズ,일시정지,Pauze,Pauza,Pausar,,Pauză,Пауза,Пауза -Increase Display Size,CNTRLMNU_DISPLAY_INC,,,,Zvětšit velikost displeje,Anzeige vergrößern,,Kreskigi Ekrangrandon,Agrandar Ventana,,Suurenna näytön kokoa,Agrandir l'affichage,Képméret növelése,Incrementa la dimensione del display,画面サイズを拡大,화면 크기 늘리기,Vergroot het display,Powiększ Rozmiar Wyświetlania,Aumentar tamanho da exibição,Aumentar Tamanho do Ecrã,Mărire ecran,Увеличить размер экрана,Повећајте величину екрана -Decrease Display Size,CNTRLMNU_DISPLAY_DEC,,,,Zmenšit velikost displeje,Anzeige verkleinern,,Malkreskigi Ekrangrandon,Reducir Ventana,,Pienennä näytön kokoa,Réduire l'affichage,Képméret csökkentése,Decrementa la dimensione del display,画面サイズを縮小,화면 크기 줄이기,Verlaag het display,Pomniejsz Rozmiar Wyświetlania,Reduzir tamanho da exibição,Diminuir Tamanho do Ecrã,Micșorare ecran,Уменьшить размер экрана,Смањите величину екрана -Open Help,CNTRLMNU_OPEN_HELP,,,,Otevřít nápovědu,Hilfe öffnen,,Malfermi Helpon,Abrir Ayuda,,Avaa ohje,Ouvrir Aide,Segítség előhozása,Apri l'aiuto,"ヘルプを開く -",도움말 열기,Open hulp,Otwórz Pomoc,Abrir ajuda,,Deschide Ajutor,Экран помощи,Отвори помоћ -Open Save Menu,CNTRLMNU_OPEN_SAVE,,,,Otevřít menu pro uložení,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,Otwórz Menu Zapisu,Abrir menu de salvar,Abrir Menu de Gravação,Deschide meniul de salvare,Сохранение игры,Отвори сачуване игре -Open Load Menu,CNTRLMNU_OPEN_LOAD,,,,Otevřít menu pro načtení,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,Otwórz Menu Wczytania,Abrir menu de carregar,,Deschide meniul de încărcare,Загрузка игры,Отвори игре за учитати -Open Options Menu,CNTRLMNU_OPEN_OPTIONS,,,,Otevřít nastavení,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,Otwórz Menu Opcji,Abrir menu de opções,,Deschide setările,Главное меню настроек,Отвори мени опција -Open Display Menu,CNTRLMNU_OPEN_DISPLAY,,,,Otevřít nastavení grafiky,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,Otwórz Menu Wyświetlania,Abrir menu de vídeo,,Deschide setările de afișare,Меню настроек видео,Отвори мени приказа -Quicksave,CNTRLMNU_QUICKSAVE,,,,Rychlé uložení,Schnellspeichern,,Rapidkonservo,Guardado Rápido,,Pikatallenna,Sauv. Rapide,Gyorsmentés,Salvataggio rapido,クイックセーブ,빠른 저장,Snel opslaan,Szybki Zapis,Salvar rapidamente,Gravação rápida,Salvare rapidă,Быстрое сохранение,Брзо-сачувај -Quickload,CNTRLMNU_QUICKLOAD,,,,Rychlé načtení,Schnellladen,,Rapidŝargo,Cargado Rápido,,Pikalataa,Charg. Rapide,Gyorstöltés,Caricamento rapido,クイックロード,빠른 불러오기,Snel laden,Szybkie Wczytanie,Carregar rapidamente,,Încărcare rapidă,Быстрая загрузка,Брзо-учитај -Exit to Main Menu,CNTRLMNU_EXIT_TO_MAIN,,,,Odejít do hlavního menu,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,Wyjdź do Głównego Menu,Sair para o menu principal,,Revenire la meniul principal,Выход в главное меню,Изађи у главни мени -Toggle Messages,CNTRLMNU_TOGGLE_MESSAGES,,,,Zap. / Vyp. zprávy,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,Włącz / Wyłącz Wiadomości,Ativar/desativar mensagens,,Comutator mesaje,Переключение сообщений,Таглави поруке -Quit Game,CNTRLMNU_MENU_QUIT,,,,Odejít ze hry,Spiel beenden,,Forlasi Ludon,Salir del Juego,,Lopeta peli,Quitter le Jeu,Kilépés a játékból,Esci dal gioco,ゲームを終了,게임 종료,Stop het spel,Wyjdź z Gry,Sair do jogo,,Ieși din Joc,Выход,Изађи из игре -Adjust Gamma,CNTRLMNU_ADJUST_GAMMA,,,,Nastavit gamu,Gamma-Anpassung,,Agordi Gamaon,Ajustar Gamma,,Säädä gammaa,Ajuster Gamma,Gamma állítása,Aggiustamento Gamma,ガンマ値を調整,감마 조정,Gamma aanpassen,Dostosuj Gammę,Ajustar gama,,Ajustare gamma,Настройка гаммы,Подесите осветљење -,,Mouse,,,,,,,,,,,,,,,,,,,,, -Mouse Options,MOUSEMNU_TITLE,,,,Nastavení myši,Mausoptionen,,Muso-Agordoj,Opciones del Ratón,,Hiiriasetukset,Options Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,Setări mouse,Настройки мыши,Миш -Enable mouse,MOUSEMNU_ENABLEMOUSE,,,,Povolit myš,Maus aktiv,,Ebligi muson,Habilitar ratón,,Ota hiiri käyttöön,Activer Souris,Egér engedélyezése,Abilita il mouse,マウスの使用,마우스 사용,Muis inschakelen,Włącz myszkę,Ativar mouse,Permitir uso do rato,Activare mouse,Использовать мышь,Укључи миш -Enable mouse in menus,MOUSEMNU_MOUSEINMENU,,,,Povolit myš v nabídkách,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,Włącz myszkę w menu,Ativar mouse nos menus,Permitir rato nos menus,Activare mouse în meniuri,Использовать мышь в меню,Укључи миш у менијима -Show back button,MOUSEMNU_SHOWBACKBUTTON,,,,Zobrazit tlačítko zpět,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,Pokaż przycisk powrotu,Exibir botão de voltar,,Afișare buton de întoarcere,Расположение кнопки «назад»,Прикажи тастер за назад -Cursor,MOUSEMNU_CURSOR,,,,Kurzor,,,Musmontrilo,,,Osoitin,Curseur,Egérmutató,Cursore,カーソル,커서,,Kursor,Cursor,,,Курсор,Курсор -Horizontal sensitivity,MOUSEMNU_SENSITIVITY_X,,,,Horizontální citlivost,Horizontale Empfindlichkeit,Οριζόντια ευαισθησία,Horizontala sentemo,Sensibilidad horizontal,,Vaakasuuntainen herkkyys,Sensibilité horizontale,Vízszintes érzékenység,Sensibilità orizzontale,水平感度,수평 감도,Horizontale gevoeligheid,Czułość pozioma,Sensibilidade horizontal,,Sensibilitate orizontală,Горизонтальная чувствительность,Хоризонтална осетљивост -Vertical sensitivity,MOUSEMNU_SENSITIVITY_Y,,,,Vertikální citlivost,Vertikale Empfindlichkeit,Κάθετη ευαισθησία,Vertikala sentemo,Sensibilidad vertical,,Pystysuuntainen herkkyys,Sensibilité verticale,Függőleges érzékenység,Sensibilità verticale,垂直感度,수직 감도,Verticale gevoeligheid,Czułość pionowa,Sensibilidade vertical,,Sensibilitate verticală,Вертикальная чувствительность,Вертикална осетљивост -Smooth mouse movement,MOUSEMNU_SMOOTHMOUSE,,,,Vyhladit pohyb myši,Mausbewegung glätten,,Glata musmovo,Mov. fluido del ratón,,Sulava hiiren liike,Lissage Souris,Egyenletes egérmozdulatok,Movimento del mouse liscio,マウス操作を滑らかにする,부드러운 움직임,Vlotte muisbeweging,Gładki ruch myszki,Movimento suave de mouse,Movimento fluído do rato,Mișcare mouse fină,Плавное перемещение,Глатки окрет -Turning speed,MOUSEMNU_TURNSPEED,,,,Rychlost otáčení,Umdrehgeschwindigkeit,,Turnorapido,Velocidad de giro,,Kääntymisnopeus,Vitesse pour tourner,Fordulás sebessége,Velocità di rotazione,旋回速度,회전 속도,Draaisnelheid,Szybkość obracania się,Velocidade de giro,,Viteză rotire,Скорость поворота,Брзина окрета -Mouselook speed,MOUSEMNU_MOUSELOOKSPEED,,,,Rychlost pohledu nahoru/dolů,Mausblick-Geschwindigkeit,,Musrigarda rapido,Veloc. de vista con ratón,,Katselunopeus,Vitesse Vue Souris,Egérrel való nézés sebessége,Velocità di rotazione della vista,上下視点速度,마우스룩 속도,Mouselook snelheid,Szybkość rozglądania się myszką,Velocidade da visão com mouse,Velocidade de vista com rato,Viteză privire în jur cu mouse,Скорость обзора,Брзина гледања мишем +",,,Slot zbraně 2,Waffe 2,Όπλο 2,Armilo 2,Arma 2,,Aselokero 2,Emplacement D'Arme 2,2. fegyver,Slot arma 2,武器スロット 2,무기 슬롯 2,Wapenslot 2,Broń 2,Arma 2,,Arma 2,Оружие 2,Оружје 2,Оръжие 2 +Weapon 3,CNTRLMNU_SLOT3,,,,Slot zbraně 3,Waffe 3,Όπλο 3,Armilo 3,Arma 3,,Aselokero 3,Emplacement D'Arme 3,3. fegyver,Slot arma 3,武器スロット 3,무기 슬롯 3,Wapenslot 3,Broń 3,Arma 3,,Arma 3,Оружие 3,Оружје 3,Оръжие 3 +Weapon 4,CNTRLMNU_SLOT4,,,,Slot zbraně 4,Waffe 4,Όπλο 4,Armilo 4,Arma 4,,Aselokero 4,Emplacement D'Arme 4,4. fegyver,Slot arma 4,武器スロット 4,무기 슬롯 4,Wapenslot 4,Broń 4,Arma 4,,Arma 4,Оружие 4,Оружје 4,Оръжие 4 +Weapon 5,CNTRLMNU_SLOT5,,,,Slot zbraně 5,Waffe 5,Όπλο 5,Armilo 5,Arma 5,,Aselokero 5,Emplacement D'Arme 5,5. fegyver,Slot arma 5,武器スロット 5,무기 슬롯 5,Wapenslot 5,Broń 5,Arma 5,,Arma 5,Оружие 5,Оружје 5,Оръжие 5 +Weapon 6,CNTRLMNU_SLOT6,,,,Slot zbraně 6,Waffe 6,Όπλο 6,Armilo 6,Arma 6,,Aselokero 6,Emplacement D'Arme 6,6. fegyver,Slot arma 6,武器スロット 6,무기 슬롯 6,Wapenslot 6,Broń 6,Arma 6,,Arma 6,Оружие 6,Оружје 6,Оръжие 6 +Weapon 7,CNTRLMNU_SLOT7,,,,Slot zbraně 7,Waffe 7,Όπλο 7,Armilo 7,Arma 7,,Aselokero 7,Emplacement D'Arme 7,7. fegyver,Slot arma 7,武器スロット 7,무기 슬롯 7,Wapenslot 7,Broń 7,Arma 7,,Arma 7,Оружие 7,Оружје 7,Оръжие 7 +Weapon 8,CNTRLMNU_SLOT8,,,,Slot zbraně 8,Waffe 8,Όπλο 8,Armilo 8,Arma 8,,Aselokero 8,Emplacement D'Arme 8,8. fegyver,Slot arma 8,武器スロット 8,무기 슬롯 8,Wapenslot 8,Broń 8,Arma 8,,Arma 8,Оружие 8,Оружје 8,Оръжие 8 +Weapon 9,CNTRLMNU_SLOT9,,,,Slot zbraně 9,Waffe 9,Όπλο 9,Armilo 9,Arma 9,,Aselokero 9,Emplacement D'Arme 9,9. fegyver,Slot arma 9,武器スロット 9,무기 슬롯 9,Wapenslot 9,Broń 9,Arma 9,,Arma 9,Оружие 9,Оружје 9,Оръжие 9 +Weapon 10,CNTRLMNU_SLOT0,,,,Slot zbraně 10,Waffe 10,Όπλο 0,Armilo 10,Arma 10,,Aselokero 0,Emplacement D'Arme 0,0. fegyver,Slot arma 0,武器スロット 0,무기 슬롯 0,Wapenslot 0,Broń 10,Arma 0,,Arma 0,Оружие 0,Оружје 0,Оръжие 10 +Inventory,CNTRLMNU_INVENTORY,,,,Inventář,Inventar,Άντικείμενα,Inventaro,Inventario,,Varusteet,Inventaire,Eszköztár beállítások testreszabása,Inventario,所持品,인벤토리,Inventaris,Ekwipunek,Inventário,,Inventar,Инвентарь,Инвентар,Инвентар +Activate item,CNTRLMNU_USEITEM,,,,Aktivovat předmět,Gegenstand aktivieren,Ενεργοποίηση αντικείμενου,Aktivigi objekton,Activar objeto,,Aktivoi varuste,Activer objet,Eszköz használata,Attiva oggetto,アイテムを使用,선택한 아이템 사용,Item activeren,Użyj przedmiot,Ativar item,,Activează obiectul,Использовать предмет,Активирај предмет,Използвай предмета +Activate all items,CNTRLMNU_USEALLITEMS,,,,Aktivovat všechny předměty,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,Użyj wszystkie przedmioty,Ativar todos os itens,,Activează tot inventarul,Использовать все предметы,Активирај све предмете,Използвай всички предмети +Next item,CNTRLMNU_NEXTITEM,,,,Další předmět,Nächster Gegenstand,Επόμενο αντικείμενο,Sekva objekto,Objeto siguiente,,Seuraava varuste,Objet suivant,Következő eszköz,Oggetto successivo,次のアイテム,다음 아이템,Volgende item,Następny przedmiot,Item seguinte,,Următorul obiect,Следующий предмет,Следећи предмет,Следващ предмет +Previous item,CNTRLMNU_PREVIOUSITEM,,,,Předchozí předmět,Vorheriger Gegenstand,Προηγούμενο αντικείμενο,Antaŭa objekto,Objeto anterior,,Edellinen varuste,Objet précédent,Előző eszköz,Oggetto precedente,前のアイテム,이전 아이템,Vorige item,Poprzedni przedmiot,Item anterior,,Obiect anterior,Предыдущий предмет,Претходни предмет,Предишен предмет +Customize Map Controls,MAPCNTRLMNU_TITLE,most are not used yet but will be,,,Nastavení ovládání mapy,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,Ustaw klawisze mapy,Peronalizar comandos de mapa,,Personalizare schemă de control a hărții,Клавиши управления автокартой,Промени контроле мапе,Персонализиране контролите за картата +Map Controls,MAPCNTRLMNU_CONTROLS,,,,Mapa,Automapsteuerung,,Map-Regiloj,Controles del mapa,,Kartanohjaus,Contrôles de la carte,Térkép irányítása,Controlli mappa,マップコントロール,미니맵 조정,Kaartcontroles,Klawisze mapy,Comandos do mapa,,Schemă de control a hărtii,Автокарта,Контроле мапе,Контроли за карта +Pan left,MAPCNTRLMNU_PANLEFT,,,,Doleva,Nach links,,Alturni maldekstren,Mover a la izquierda,,Panoroi vasemmalle,Aller à gauche,Balra igazítás,Sposta a sinistra,左に振る,왼쪽으로 이동,Pan links,Przesuń w lewo,Mover para a esquerda,,Mutare spre stânga,Сдвиг влево,Лево,Преместване наляво +Pan right,MAPCNTRLMNU_PANRIGHT,,,,Doprava,Nach rechts,,Alturni dekstren,Mover a la derecha,,Panoroi oikealle,Aller à droite,Jobbra igazítás,Sposta a destra,右に振る,오른쪽으로 이동,Pan rechts,Przesuń w prawo,Mover para a direita,,Mutare spre dreapta,Сдвиг вправо,Десно,Преместване на дясно +Pan up,MAPCNTRLMNU_PANUP,,,,Nahoru,Nach oben,,Alturni supren,Mover hacia arriba,,Panoroi ylös,Aller en haut,Felfele igazítás,Sposta sopra,上に振る,위쪽으로 이동,Pan omhoog,Przesuń w górę,Mover para cima,,Mutare în sus,Сдвиг вверх,Горе,Преместване на горе +Pan down,MAPCNTRLMNU_PANDOWN,,,,Dolů,Nach unten,,Alturni malsupren,Mover hacia abajo,,Panoroi alas,Aller en bas,Lefele igazítás,Sposta sotto,下に振る,아래쪽으로 이동,Pan neer,Przesuń w dół,Mover para baixo,,Mutare în jos,Сдвиг вниз,Доле,Преместване на долу +Zoom in,MAPCNTRLMNU_ZOOMIN,,,,Přiblížit,Reinzoomen,,Zomi,Acercar,,Lähennä,Zoom avant,Ráközelítés,Ingrandisci,ズームイン,줌 확대,Inzoomen,Przybliż,Ampliar,,Apropriere Cameră,Приблизить,Увеличати,Приближи +Zoom out,MAPCNTRLMNU_ZOOMOUT,,,,Oddálit,Rauszoomen,,Malzomi,Alejar,,Loitonna,Zoom arrière,Távolítás,Rimpicciolisci,ズームアウト,줌 축소,Uitzoomen,Oddal,Afastar,,Depărtare Cameră,Отдалить,Одзумирати,Отдалечи +Toggle zoom,MAPCNTRLMNU_TOGGLEZOOM,,,,Přiblížení vyp./zap.,Zoom an/aus,,Baskuligi zomon,Alternar zoom,,Zoomauksen vaihtokytkin,Alterner zoom,Közelítés átkapcsolása,Abilita/disabilita zoom,ズーム切替,표준배율 조정,Omschakelen van de zoom,Przełącz przybliżanie,Ativar/desativar zoom,,Comutator Zoom,Приближение (перекл.),Укључи зум,Приближи постоянно +Toggle follow,MAPCNTRLMNU_TOGGLEFOLLOW,,,,Sledování hráče vyp./zap.,Folgen an/aus,,Baskuligi sekvon,Alternar seguimiento,,Seuraamistilan vaihtokytkin,Alterner suivi,Követés átkapcsolása,Abilita/disabilita scorrimento mappa,追従切替,추적모드 조정,Schakelen volgen,Przełącz śledzenie,Ativar/desativar seguimento,,Comutator urmărire jucător,Привязка к игроку (перекл.),Укључи праћење,Следвай постаянно +Toggle grid,MAPCNTRLMNU_TOGGLEGRID,,,,Mřížka vyp./zap.,Gitter an/aus,,Baskuligi kradon,Alternar cuadrícula,Alternar rejilla,Ruudukon vaihtokytkin,Alterner grille,Rács kapcsolása,Abilita/disabilita la griglia,グリッド切替,그리드 조정,Kiesnet,Przełącz siatkę,Ativar/desativar grade,,Comutator grilă,Сетка (перекл.),Укључи координатну мрежу, +Toggle rotate,MAPCNTRLMNU_ROTATE,,,,Otáčení vyp./zap.,Rotation an/aus,,Baskuligi turnadon,Alternar rotación,,Kääntämisen vaihtokytkin,Alterner rotation,Forgás kapcsolása,Abilita/disabilita la rotazione,回転切替,,Toggle rotatie,Przełącz obracanie,Ativar/desativar rotação,,Comutator rotire,Вращение (перекл.),Укључи ротацију, +Toggle texture,MAPCNTRLMNU_TOGGLETEXTURE,,,,Textury vyp./zap.,Texturen an/aus,,Baskuligi teksturon,Alternar textura,,Pintakuvioinnin vaihtokytkin,Alterner texture,Textúra kapcsolása,Abilita/disabilita le texture,テクスチャ切替,미니맵 텍스쳐 조정,Toggle textuur,Przełącz tekstury,Ativar/desativar texturas,,Comutator mod texturat,Текстуры (перекл.),Укључи текстуру, +Toggle automap,CNTRLMNU_AUTOMAP,,,,Otevřít/zavřít automapu,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,Włącz mapę,Ativar/desativar automapa,,Comutator hartă computerizată,Автокарта (перекл.),Прикажи аутомапу, +Chasecam,CNTRLMNU_CHASECAM,,,,Kamera z třetí osoby,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 de terceira pessoa,Câmera em terceira-pessoa,Cameră urmăritoare,Вид от 3-го лица (камера преследования),Чејс-кем, +Screenshot,CNTRLMNU_SCREENSHOT,,,,Pořídit snímek obrazovky,,,Ekrankopio,Captura de pantalla,,Kuvakaappaus,Capture d'écran,Képernyő lefényképezése,Cattura schermo,画面キャプチャ,스크린샷,,Zrzut ekranu,Captura de tela,,Captură ecran,Скриншот,Усликај, +Open console,CNTRLMNU_CONSOLE,,,,Otevřít konzoli,Konsole öffnen,,Malfermi konzolon,Abrir consola,,Avaa konsoli,Ouvrir Console,Konzol megnyitása,Apri la console,コンソールを開く,콘솔 열기,Open console,Otwórz konsolę,Abrir console,Abrir consola,Deschide consola,Открыть консоль,Отвори консолу, +Pause,CNTRLMNU_PAUSE,,,,Pauza,,Πάυση,Paŭzo,Pausa,,Tauko,,Szünet,Pausa,ポーズ,일시정지,Pauze,Pauza,Pausar,,Pauză,Пауза,Пауза, +Increase Display Size,CNTRLMNU_DISPLAY_INC,,,,Zvětšit velikost obrazovky,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,Powiększ Rozmiar Wyświetlania,Aumentar tamanho da exibição,Aumentar Tamanho do Ecrã,Mărire ecran,Увеличить размер экрана,Повећајте величину екрана, +Decrease Display Size,CNTRLMNU_DISPLAY_DEC,,,,Zmenšit velikost obrazovky,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,Pomniejsz Rozmiar Wyświetlania,Reduzir tamanho da exibição,Diminuir Tamanho do Ecrã,Micșorare ecran,Уменьшить размер экрана,Смањите величину екрана, +Open Help,CNTRLMNU_OPEN_HELP,,,,Nápověda,Hilfe öffnen,Άνοιγμα βοήθειας,Malfermi Helpon,Abrir Ayuda,,Avaa ohje,Ouvrir Aide,Segítség előhozása,Apri la guida,"ヘルプを開く +",도움말 열기,Open hulp,Otwórz Pomoc,Abrir ajuda,,Deschide Ajutor,Экран помощи,Отвори помоћ, +Open Save Menu,CNTRLMNU_OPEN_SAVE,,,,Uložit hru,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,Otwórz Menu Zapisu,Abrir menu de salvar,Abrir Menu de Gravação,Deschide meniul de salvare,Сохранение игры,Отвори сачуване игре, +Open Load Menu,CNTRLMNU_OPEN_LOAD,,,,Načíst hru,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,Otwórz Menu Wczytania,Abrir menu de carregar,,Deschide meniul de încărcare,Загрузка игры,Отвори игре за учитати, +Open Options Menu,CNTRLMNU_OPEN_OPTIONS,,,,Nastavení,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,Otwórz Menu Opcji,Abrir menu de opções,,Deschide setările,Главное меню настроек,Отвори мени опција, +Open Display Menu,CNTRLMNU_OPEN_DISPLAY,,,,Nastavení grafiky,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,Otwórz Menu Wyświetlania,Abrir menu de vídeo,,Deschide setările de afișare,Меню настроек видео,Отвори мени приказа, +Quicksave,CNTRLMNU_QUICKSAVE,,,,Rychlé uložení,Schnellspeichern,,Rapidkonservo,Guardado Rápido,,Pikatallenna,Sauv. Rapide,Gyorsmentés,Salvataggio rapido,クイックセーブ,빠른 저장,Snel opslaan,Szybki Zapis,Salvar rapidamente,Gravação rápida,Salvare rapidă,Быстрое сохранение,Брзо-сачувај, +Quickload,CNTRLMNU_QUICKLOAD,,,,Rychlé načtení,Schnellladen,,Rapidŝargo,Cargado Rápido,,Pikalataa,Charg. Rapide,Gyorstöltés,Caricamento rapido,クイックロード,빠른 불러오기,Snel laden,Szybkie Wczytanie,Carregar rapidamente,,Încărcare rapidă,Быстрая загрузка,Брзо-учитај, +Exit to Main Menu,CNTRLMNU_EXIT_TO_MAIN,,,,Odejít do hlavního menu,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,Wyjdź do Głównego Menu,Sair para o menu principal,,Revenire la meniul principal,Выход в главное меню,Изађи у главни мени, +Toggle Messages,CNTRLMNU_TOGGLE_MESSAGES,,,,Povolit/skrýt oznámení,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,Włącz / Wyłącz Wiadomości,Ativar/desativar mensagens,,Comutator mesaje,Переключение сообщений,Таглави поруке, +Quit Game,CNTRLMNU_MENU_QUIT,,,,Ukončit hru,Spiel beenden,Στάματα το παιχνίδι,Forlasi Ludon,Salir del Juego,,Lopeta peli,Quitter le Jeu,Kilépés a játékból,Esci dal gioco,ゲームを終了,게임 종료,Stop het spel,Wyjdź z Gry,Sair do jogo,,Ieși din Joc,Выход,Изађи из игре, +Adjust Gamma,CNTRLMNU_ADJUST_GAMMA,,,,Nastavit gamu,Gamma-Anpassung,,Agordi Gamaon,Ajustar Gamma,,Säädä gammaa,Ajuster Gamma,Gamma állítása,Aggiustamento Gamma,ガンマ値を調整,감마 조정,Gamma aanpassen,Dostosuj Gammę,Ajustar gama,,Ajustare gamma,Настройка гаммы,Подесите осветљење, +,,Mouse,,,,,,,,,,,,,,,,,,,,,, +Mouse Options,MOUSEMNU_TITLE,,,,Nastavení myši,Mausoptionen,,Muso-Agordoj,Opciones del Ratón,,Hiiriasetukset,Options Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,Setări mouse,Настройки мыши,Миш, +Enable mouse,MOUSEMNU_ENABLEMOUSE,,,,Povolit myš,Maus aktiv,Ενεργοποίηση ποντικιόυ,Ebligi muson,Habilitar ratón,,Ota hiiri käyttöön,Activer Souris,Egér engedélyezése,Abilita il mouse,マウスの使用,마우스 사용,Muis inschakelen,Włącz myszkę,Ativar mouse,Permitir uso do rato,Activare mouse,Использовать мышь,Укључи миш, +Enable mouse in menus,MOUSEMNU_MOUSEINMENU,,,,Povolit myš v nabídkách,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,Włącz myszkę w menu,Ativar mouse nos menus,Permitir rato nos menus,Activare mouse în meniuri,Использовать мышь в меню,Укључи миш у менијима, +Show back button,MOUSEMNU_SHOWBACKBUTTON,,,,Zobrazit tlačítko zpět,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,Pokaż przycisk powrotu,Exibir botão de voltar,,Afișare buton de întoarcere,Расположение кнопки «назад»,Прикажи тастер за назад, +Cursor,MOUSEMNU_CURSOR,,,,Kurzor,,,Musmontrilo,,,Osoitin,Curseur,Egérmutató,Cursore,カーソル,커서,,Kursor,Cursor,,,Курсор,Курсор, +Horizontal sensitivity,MOUSEMNU_SENSITIVITY_X,,,,Horizontální citlivost,Horizontale Empfindlichkeit,Οριζόντια ευαισθησία,Horizontala sentemo,Sensibilidad horizontal,,Vaakasuuntainen herkkyys,Sensibilité horizontale,Vízszintes érzékenység,Sensibilità orizzontale,水平感度,수평 감도,Horizontale gevoeligheid,Czułość pozioma,Sensibilidade horizontal,,Sensibilitate orizontală,Горизонтальная чувствительность,Хоризонтална осетљивост, +Vertical sensitivity,MOUSEMNU_SENSITIVITY_Y,,,,Vertikální citlivost,Vertikale Empfindlichkeit,Κάθετη ευαισθησία,Vertikala sentemo,Sensibilidad vertical,,Pystysuuntainen herkkyys,Sensibilité verticale,Függőleges érzékenység,Sensibilità verticale,垂直感度,수직 감도,Verticale gevoeligheid,Czułość pionowa,Sensibilidade vertical,,Sensibilitate verticală,Вертикальная чувствительность,Вертикална осетљивост, +Smooth mouse movement,MOUSEMNU_SMOOTHMOUSE,,,,Vyhladit pohyb myši,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,Gładki ruch myszki,Movimento suave de mouse,Movimento fluído do rato,Mișcare mouse fină,Плавное перемещение,Глатки окрет, +Turning speed,MOUSEMNU_TURNSPEED,,,,Rychlost otáčení,Umdrehgeschwindigkeit,,Turnorapido,Velocidad de giro,,Kääntymisnopeus,Vitesse pour tourner,Fordulás sebessége,Velocità di rotazione,旋回速度,회전 속도,Draaisnelheid,Szybkość obracania się,Velocidade de giro,,Viteză rotire,Скорость поворота,Брзина окрета, +Mouselook speed,MOUSEMNU_MOUSELOOKSPEED,,,,Rychlost pohledu nahoru/dolů,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,Szybkość rozglądania się myszką,Velocidade da visão com mouse,Velocidade de vista com rato,Viteză privire în jur cu mouse,Скорость обзора,Брзина гледања мишем, Forward/Backward speed,MOUSEMNU_FORWBACKSPEED,,,,Rychlost pohybu vpřed/vzad,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,Szybkość chodzenia do przodu/do tyłu,Velocidade de deslocamento para frente/trás,,Viteză deplasare față/spate,Скорость передвижения,Брзина окрета напред/уназад -Strafing speed,MOUSEMNU_STRAFESPEED,,,,Rychlost pohybu do stran,Seitwärtsgeschwindigkeit,,Flankmova rapido,Veloc. de mov. lateral,,Sivuttaisastunnan nopeus,Vitesse Gauche/Droite,Oldalazás sebessége,Velocità movimento laterale,横移動速度,좌진/우진 속도,Zijdelings snelheid,Szybkość uników,Velocidade de deslocamento lateral,,Viteză deplasare în diagonală,Скорость движения боком,Брзина стрејфа -Always Mouselook,MOUSEMNU_ALWAYSMOUSELOOK,,,,Vždy se rozhlížet myší,Mausblick immer an,,Ĉiam Musrigardi,Siempre mirar con ratón,,Jatkuva hiirikatselu,Toujours vue Souris,Mindig nézelődés az egérrel,Vista col mouse,常に上下視点をオン,마우스룩 사용,Altijd Mouselook,Zawsze zezwalaj na rozglądanie się myszką,Visão com mouse sempre ativada,Vista com rato sempre ligada,Privire în jur cu mouse permanentă,Обзор мышью,Гледање мишем -Invert Mouse Y,MOUSEMNU_INVERTMOUSE,,,,Inverzní myš 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,Odwróć Myszkę Y,Inverter eixo Y do mouse,Inverter rato,Inversare axă mouse Y,Инвертирование мыши Y,Инвертуј миш Y -Invert Mouse X,MOUSEMNU_INVERTMOUSEX,,,,Inverzní myš 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,Odwróć Myszkę X,Inverter eixo X do mouse,Inverter rato X,Inversare axă mouse X,Инвертирование мыши X,Инвертуј миш X -Upper left,OPTVAL_UPPERLEFT,,,,Vlevo nahoře,Oben links,,Supra maldekstre,Sup. izquierda,,Ylävasemmalla,Supérieur gauche,Balra fent,Superiore sinistro,左上,왼쪽 위,Linksboven,Lewy górny róg,Esquerda superior,,Stânga sus,Вверху слева,Горње лево -Upper right,OPTVAL_UPPERRIGHT,,,,Vpravo nahoře,Oben rechts,,Supra dekstre,Sup. derecha,,Yläoikealla,Supérieur droite,Jobbra fent,Superiore destro,右上,오른쪽 위,Rechtsboven,Prawy górny róg,Direita superior,,Dreapta sus,Вверху справа,Горње десно -Lower left,OPTVAL_LOWERLEFT,,,,Vlevo dole,Unten links ,,Suba maldekstre,Inf. izquierda,,Alavasemmalla,Inférieur gauche,Balra lent,Inferiore sinistro,左下,왼쪽 밑,Linksonder,Lewy dolny róg,Esquerda inferior,,Stânga jos,Внизу слева,Доње лево -Lower right,OPTVAL_LOWERRIGHT,,,,Vpravo dole,Unten rechts,,Suba dekstre,Inf. derecha,,Alaoikealla,Inférieur droite,Jobbra lent,Inferiore destro,右下,오른쪽 밑,Rechtsonder,Prawy dolny róg,Direita inferior,,Dreapta jos,Внизу справа,Доње десно -Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,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,Jak ekrean dotykowy,Estilo touchscreen,,Precum touchscreen,Как сенсорный экран,Као додирни екран -Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Einfacher Pfeil,,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,Sima nyíl,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Prosta strzałka,Flecha simples,Cursor simples,Săgeată simplă,Стрелка,Стрелица -System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,Rendszer egérmutatója,Cursore di sistema,システム,시스템 커서,Systeemcursor,Kursor systemu,Cursor do sistema,,Cursor simplu,Системный курсор,Системска стрелица -Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,,Defaŭlta,Por defecto,,Oletus,Défaut,Alapbeállítás,,デフォルト,기본 설정,Standaard,Domyślne,Padrão,,Implicit,По умолчанию,Подраз. -,,Controller,,,,,,,,,,,,,,,,,,,,, -Configure Controller,JOYMNU_TITLE,,,,Konfigurovat ovladač,Controller konfigurieren,,Agordi Ludregilon,Configurar Mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構成:,컨트롤러 구성,Controller configureren,Konfiguruj Kontroler,Configurar controle,Configurar Comando,Configurare controller,Настроить контроллер,Конфигурација контролера -Controller Options,JOYMNU_OPTIONS,,,,Nastavení ovladače,Controlleroptionen,,Ludregilo-Agordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállítások,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Opcje Kontrolera,Opções de controle,Opções do Comando,Setări controller,Настройки контроллера,Подешавања контролера -Block controller input in menu,JOYMNU_NOMENU,,,,Zakázat ovladač v nabídkách,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,Blokuj wejście kontrolera w menu,Bloquear controle no menu,Bloquear comando no menu,Blocare comenzi controller în meniu,Отключить контроллер в меню,Блокирај улаз контролера у менију -Enable controller support,JOYMNU_ENABLE,,,,Povolit podporu pro ovladače,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,Włącz wsparcie kontrolera,Ativar suporte a controles,,Activare support controller,Включить поддержку контроллера,Омогући подршку за контролере -Enable DirectInput controllers,JOYMNU_DINPUT,,,,Povolit ovladače DirectInput,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,Włącz kontrolery DirectInput,Ativar controles DirectInput,,Activare controlere DirectInput,Включить контроллеры DirectInput,Омогући директинпут контролере -Enable XInput controllers,JOYMNU_XINPUT,,,,Povolit ovladače XInput,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,Włącz kontrolery XInput,Ativar controles XInput,,Activare controlere XInput,Включить контроллеры XInput,Омогући Иксинпут контролере -Enable raw PlayStation 2 adapters,JOYMNU_PS2,,,,Povolit ovladače PlayStation 2,Erlaube Playstation 2-Controller,,Ŝalti krudajn PlayStation 2 adaptilojn,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,Włącz adaptery PlayStation 2,Ativar adaptadores de PlayStation 2,,Activare adaptoare PS2,Использовать адаптеры PlayStation 2 напрямую,Омогући сирове Плејстејшн 2 адаптере -No controllers detected,JOYMNU_NOCON,,,,Nenalezeny žádné ovladače,Keine Controller gefunden,,Neniuj ludregiloj detektitaj,No hay mandos detectados,,Ei havaittuja ohjaimia,Aucun Contrôleur détecté.,Nem érzékelhető kontroller,Nessun controller trovato,コントローラーが見つかりません,인식된 컨트롤러 없음,Geen controllers gedetecteerd,Nie wykryto kontrolerów,Nenhum controle detectado,Nenhum comando foi detectado,Niciun controller detectat,Контроллеры не обнаружены,Нема детектованих контролера -Configure controllers:,JOYMNU_CONFIG,,,,Nastavit ovladače:,Controller konfigurieren,,Agordi ludregilojn:,Configurar controles:,,Mukauta ohjaimia:,Configurer contrôleurs:,Kontrollerek konfigurációja:,Configura i controller:,コントローラー構成:,컨트롤러 설정:,Configureer controllers:,Konfiguruj kontrolery:,Configurar controles:,Configurar comandos,Configurare controlere:,Настроить контроллер:,Подешавања контролере: -Controller support must be,JOYMNU_DISABLED1,,,,Podpora ovladačů musí být,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,Wsparcie kontrolera musi być,Suporte a controles deve ser,Suporte a comandos devem ser,Supportul pentru controller trebuie,Включите поддержку контроллера,Омогућите подржавање контролера -enabled to detect any,JOYMNU_DISABLED2,Supposed to be empty in Russian and Serbian.,,,zapnuta pro jejich detekování,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.,Włączony by wykryć jakikolwiek,ativado para detectar algum,,activat pentru a le detecta, \n, \n -Invalid controller specified for menu,JOYMNU_INVALID,,,,Vybrán nesprávný ovladač pro nabídky,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,Niewłaściwy kontroler określony dla menu,Controle inválido especificado para o menu,Comando inválido,Controller pentru meniu invalid,Недопустимый контроллер выбран для меню,Невалидан контролер специфиран за мени -Overall sensitivity,JOYMNU_OVRSENS,,,,Celková citlivost,Allgemeine Empfindlichkeit,,Tuta sentemeco,Sensibilidad general,,Yleisherkkyys,Sensibilité générale,Teljes érzékenység,Sensibilità generale,全体的な感度,전체 민감도,Algemene gevoeligheid,Ogólna Czułość,Sensibilidade geral,,Sensibilitate în ansamblu,Общая чувствительность,Уупна сензитивност -Axis Configuration,JOYMNU_AXIS,,,,Nastavení os,Achsenkonfiguration,,Akso-Agordoj,Configuración del eje,,Akseleiden säätäminen,Configuration des axes,,Configurazione assi,軸構成,축 구성,Asconfiguratie,Konfiguruj Oś,Configuração de eixo,,Configurare axă,Конфигурация осей,Конфигурација осе -Invert,JOYMNU_INVERT,,,,Obrátit,Invertieren,,Inversigi,Invertir,,Käännä,Inverser,Megfordítás,Inverti,反転,순서 바꿈,Omkeren,Odwróć,Inverter,,Inversare,Инвертировать,Инвертовано -Dead zone,JOYMNU_DEADZONE,,,,Mrtvá zóna,Totzone,,Mortozono,Zona muerta,,Kuollut alue,Zone neutre,Holttér,Zona cieca,デッドゾーン,불감대,Dode zone,Martwa strefa,Zona morta,,Zonă moartă,Мёртвая зона,Мртва зона -No configurable axes,JOYMNU_NOAXES,,,,Žádné nastavitelné osy,Keine konfigurierbaren Achsen,,Neniuj agordeblaj aksoj,No hay ejes configurables,,Ei säädettäviä akseleita,Aucun axe à configurer,,Nessun asse configurabile,軸構成を無効,설정할 방향키가 없습니다.,Geen configureerbare assen,Brak osi do skonfigurowania,Nenhum eixo configurável,,Nicio axă configurabilă,Нет настраиваемых осей,Нема конфигурационих оса -None,OPTVAL_NONE,,,,Žádný,Kein,,Neniu,Ninguno,,Ei mitään,Aucun,Semmi,Nessuno,無し,없음,Geen,Żaden,Nenhum,,Niciuna,Откл.,Ништа -Turning,OPTVAL_TURNING,,,,Otáčení,Umdrehen,,Turnanta,Girar,,Kääntyminen,Tourner,Elfordulás,Rotazione,旋回,회전,Draaien,Obracanie się,Girar,,Rotire,Поворот,Скретање -Looking Up/Down,OPTVAL_LOOKINGUPDOWN,,,,Dívání se nahoru/dolů,Hoch/runterblicken,,Rigardanta Supren/Malsupren,Mirar hacia Arriba/Abajo,,Ylös/Alas katsominen,Vue haut/bas,Fel-/lenézés,Sguardo Sopra/Sotto,視点上下,위/아래로 보기,Omhoog/omlaag zoeken,Patrzenie w górę/w dół,Olhar para cima/baixo,,Privire Sus/Jos,Взгляд вверх/вниз,Гледање горе/доле -Moving Forward,OPTVAL_MOVINGFORWARD,,,,Pohyb vpřed,Vorwärtsbewegung,,Movanta Antaŭen,Avanzar,,Eteenpäin liikkuminen,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 전진,Voorwaarts bewegen,Poruszanie się do przodu,Mover-se para a frente,,Deplasare în Față,Движение вперёд,Кретање напред -Strafing,OPTVAL_STRAFING,,,,Pohyb do stran,Seitwärtsbewegung,,Flankmovanta,Desplazarse,,Sivuttaisastunta,Pas de côté,Oldalazás,Movimento laterale,横移動,양옆으로 이동,Strafelen,Uniki,Deslocamento lateral,,Deplasare în Diagonală,Движение боком,Кретање у страну -Moving Up/Down,OPTVAL_MOVINGUPDOWN,,,,Pohyb nahoru/dolů,Auf/abwärtsbewegung,,Movanta Supren/Malsupren,Moverse hacia Arriba/Abajo,,Ylös/Alas liikkuminen,Mouvement haut/bas,Felfele/Lefele mozgás,Movimento Sopra/Sotto,前進後退,위/아래로 이동,Naar boven/beneden bewegen,Poruszanie się w górę/w dół,Mover-se para cima/baixo,,Mișcare Sus/Jos,Движение вверх/вниз,Кретање горе/доле -Inverted,OPTVAL_INVERTED,,,,Inverzní,Invertiert,,Inversigita,Invertido,,Käännetty,Inversé,Felcserélve,Invertito,反転する,반전,Omgekeerd,Odwrócony,Invertido,,Inversat,Инвертировано,Обрнуто -Not Inverted,OPTVAL_NOTINVERTED,,,,Nikoliv inverzní,nicht invertiert,,Ne Inversigita,No invertido,,Ei käännetty,Non Inversé,Nincs felcserélve,Non invertito,反転しない,반전되지 않음,Niet omgekeerd,Nieodwrócony,Não invertido,,Neinversat,Прямо,Не обрнуто -,,Player Menu,,,,,,,,,,,,,,,,,,,,, -Player Setup,MNU_PLAYERSETUP,,,,Nastavení hráče,Spielereinstellungen,,Ludanto-Agordaĵo,Config. del jugador,,Pelaaja-asetukset,Options Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Ustawienia Gracza,Definições de jogador,,Configurare jucător,Настройки игрока,Подешавања играча -Blue,TXT_COLOR_BLUE,,,,Modrá,Blau,,Blua,Azul,,Sininen,Bleu,Kék,Blu,青,청색,Blauw,Niebieski,Azul,,Albastru,Синий,Плава -Red,TXT_COLOR_RED,,,,Červená,Rot,,Ruĝa,Rojo,,Punainen,Rouge,Vörös,Rosso,赤,적색,Rood,Czerwony,Vermelho,,Roșu,Красный,Црвена -Green,TXT_COLOR_GREEN,,,,Zelená,Grün,,Verda,Verde,,Vihreä,Vert,Zöld,Verde,緑,녹색,Groen,Zielony,Verde,,Verde,Зелёный,Зелена -Gray,TXT_COLOR_GRAY,,,Grey,Šedá,Grau,,Griza,Gris,,Harmaa,Gris,Szürke,Grigio,灰,회색,Grijs,Szary,Cinza,,Gri,Серый,Сива +",전진/후진 속도,Voorwaartse/achterwaartse snelheid,Szybkość chodzenia do przodu/do tyłu,Velocidade de deslocamento para frente/trás,,Viteză deplasare față/spate,Скорость передвижения,Брзина окрета напред/уназад, +Strafing speed,MOUSEMNU_STRAFESPEED,,,,Rychlost pohybu do stran,Seitwärtsgeschwindigkeit,,Flankmova rapido,Veloc. de mov. lateral,,Sivuttaisastunnan nopeus,Vitesse Gauche/Droite,Oldalazás sebessége,Velocità movimento laterale,横移動速度,좌진/우진 속도,Zijdelings snelheid,Szybkość uników,Velocidade de deslocamento lateral,,Viteză deplasare în diagonală,Скорость движения боком,Брзина стрејфа, +Always Mouselook,MOUSEMNU_ALWAYSMOUSELOOK,,,,Vždy se rozhlížet myší,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,Zawsze zezwalaj na rozglądanie się myszką,Visão com mouse sempre ativada,Vista com rato sempre ligada,Privire în jur cu mouse permanentă,Обзор мышью,Гледање мишем, +Invert Mouse Y,MOUSEMNU_INVERTMOUSE,,,,Vertikálně obrátit myš,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,Odwróć Myszkę - Oś Y,Inverter eixo Y do mouse,Inverter rato,Inversare axă mouse Y,Инвертирование мыши Y,Инвертуј миш Y, +Invert Mouse X,MOUSEMNU_INVERTMOUSEX,,,,Horizontálně obrátit myš,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,Odwróć Myszkę - Oś X,Inverter eixo X do mouse,Inverter rato X,Inversare axă mouse X,Инвертирование мыши X,Инвертуј миш X, +Upper left,OPTVAL_UPPERLEFT,,,,Vlevo nahoře,Oben links,,Supra maldekstre,Sup. izquierda,,Ylävasemmalla,Supérieur gauche,Bal fent,Superiore sinistro,左上,왼쪽 위,Linksboven,Lewy górny róg,Esquerda superior,,Stânga sus,Вверху слева,Горње лево, +Upper right,OPTVAL_UPPERRIGHT,,,,Vpravo nahoře,Oben rechts,,Supra dekstre,Sup. derecha,,Yläoikealla,Supérieur droite,Jobb fent,Superiore destro,右上,오른쪽 위,Rechtsboven,Prawy górny róg,Direita superior,,Dreapta sus,Вверху справа,Горње десно, +Lower left,OPTVAL_LOWERLEFT,,,,Vlevo dole,Unten links ,,Suba maldekstre,Inf. izquierda,,Alavasemmalla,Inférieur gauche,Bal lent,Inferiore sinistro,左下,왼쪽 밑,Linksonder,Lewy dolny róg,Esquerda inferior,,Stânga jos,Внизу слева,Доње лево, +Lower right,OPTVAL_LOWERRIGHT,,,,Vpravo dole,Unten rechts,,Suba dekstre,Inf. derecha,,Alaoikealla,Inférieur droite,Jobb lent,Inferiore destro,右下,오른쪽 밑,Rechtsonder,Prawy dolny róg,Direita inferior,,Dreapta jos,Внизу справа,Доње десно, +Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,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,Jak ekrean dotykowy,Estilo touchscreen,,Precum touchscreen,Как сенсорный экран,Као додирни екран, +Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Einfacher Pfeil,,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,Sima nyíl,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Prosta strzałka,Flecha simples,Cursor simples,Săgeată simplă,Стрелка,Стрелица, +System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,Δείκτης συστήματος,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,Rendszer egérmutatója,Cursore di sistema,システム,시스템 커서,Systeemcursor,Kursor systemu,Cursor do sistema,,Cursor simplu,Системный курсор,Системска стрелица, +Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,Προεπιλογή,Defaŭlta,Por defecto,,Oletus,Défaut,Alapbeállítás,Predefinito,デフォルト,기본 설정,Standaard,Domyślne,Padrão,,Implicit,По умолчанию,Подраз., +,,Controller,,,,,,,,,,,,,,,,,,,,,, +Configure Controller,JOYMNU_TITLE,,,,Konfigurace ovladače,Controller konfigurieren,,Agordi Ludregilon,Configurar Mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構成:,컨트롤러 구성,Controller configureren,Konfiguruj Kontroler,Configurar controle,Configurar Comando,Configurare controller,Настроить контроллер,Конфигурација контролера, +Controller Options,JOYMNU_OPTIONS,,,,Ovladač,Controlleroptionen,,Ludregilo-Agordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállítások,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Opcje Kontrolera,Opções de controle,Opções do Comando,Setări controller,Настройки контроллера,Подешавања контролера, +Block controller input in menu,JOYMNU_NOMENU,,,,Zakázat ovladač v nabídkách,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,Blokuj wejście kontrolera w menu,Bloquear controle no menu,Bloquear comando no menu,Blocare comenzi controller în meniu,Отключить контроллер в меню,Блокирај улаз контролера у менију, +Enable controller support,JOYMNU_ENABLE,,,,Povolit podporu pro ovladače,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,Włącz wsparcie kontrolera,Ativar suporte a controles,,Activare support controller,Включить поддержку контроллера,Омогући подршку за контролере, +Enable DirectInput controllers,JOYMNU_DINPUT,,,,Povolit ovladače DirectInput,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,Włącz kontrolery DirectInput,Ativar controles DirectInput,,Activare controlere DirectInput,Включить контроллеры DirectInput,Омогући директинпут контролере, +Enable XInput controllers,JOYMNU_XINPUT,,,,Povolit ovladače XInput,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,Włącz kontrolery XInput,Ativar controles XInput,,Activare controlere XInput,Включить контроллеры XInput,Омогући Иксинпут контролере, +Enable raw PlayStation 2 adapters,JOYMNU_PS2,,,,Povolit ovladače PlayStation 2,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,Włącz adaptery PlayStation 2,Ativar adaptadores de PlayStation 2,,Activare adaptoare PS2,Использовать адаптеры PlayStation 2 напрямую,Омогући сирове Плејстејшн 2 адаптере, +No controllers detected,JOYMNU_NOCON,,,,Nenalezeny žádné ovladače.,Keine Controller gefunden,,Neniuj ludregiloj detektitaj,No hay mandos detectados,,Ei havaittuja ohjaimia,Aucun Contrôleur détecté.,Nem érzékelhető kontroller,Nessun controller trovato,コントローラーが見つかりません,인식된 컨트롤러 없음,Geen controllers gedetecteerd,Nie wykryto kontrolerów,Nenhum controle detectado,Nenhum comando foi detectado,Niciun controller detectat,Контроллеры не обнаружены,Нема детектованих контролера, +Configure controllers:,JOYMNU_CONFIG,,,,Nastavit ovladače:,Controller konfigurieren,,Agordi ludregilojn:,Configurar controles:,,Mukauta ohjaimia:,Configurer contrôleurs:,Kontrollerek konfigurációja:,Configura i controller:,コントローラー構成:,컨트롤러 설정:,Configureer controllers:,Konfiguruj kontrolery:,Configurar controles:,Configurar comandos,Configurare controlere:,Настроить контроллер:,Подешавања контролере:, +Controller support must be,JOYMNU_DISABLED1,,,,Pro nalezení ovladačů musí,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,Wsparcie kontrolera musi być,Suporte a controles deve ser,Suporte a comandos devem ser,Supportul pentru controller trebuie,Включите поддержку контроллера,Омогућите подржавање контролера, +enabled to detect any,JOYMNU_DISABLED2,Supposed to be empty in Russian and Serbian.,,,být zapnuta jejich podpora.,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.,Włączony by wykryć jakikolwiek,ativado para detectar algum,,activat pentru a putea fi detectate, \n, \n, +Invalid controller specified for menu,JOYMNU_INVALID,,,,Vybrán nesprávný ovladač pro nabídky,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,Niewłaściwy kontroler określony dla menu,Controle inválido especificado para o menu,Comando inválido,Controller pentru meniu invalid,Недопустимый контроллер выбран для меню,Невалидан контролер специфиран за мени, +Overall sensitivity,JOYMNU_OVRSENS,,,,Celková citlivost,Allgemeine Empfindlichkeit,,Tuta sentemeco,Sensibilidad general,,Yleisherkkyys,Sensibilité générale,Teljes érzékenység,Sensibilità generale,全体的な感度,전체 민감도,Algemene gevoeligheid,Ogólna Czułość,Sensibilidade geral,,Sensibilitate în ansamblu,Общая чувствительность,Уупна сензитивност, +Axis Configuration,JOYMNU_AXIS,,,,Nastavení os,Achsenkonfiguration,,Akso-Agordoj,Configuración del eje,,Akseleiden säätäminen,Configuration des axes,Tengely konfigurálása,Configurazione assi,軸構成,축 구성,Asconfiguratie,Konfiguruj Oś,Configuração de eixo,,Configurare axă,Конфигурация осей,Конфигурација осе, +Invert,JOYMNU_INVERT,,,,Obrátit,Invertieren,,Inversigi,Invertir,,Käännä,Inverser,Megfordítás,Inverti,反転,순서 바꿈,Omkeren,Odwróć,Inverter,,Inversare,Инвертировать,Инвертовано, +Dead zone,JOYMNU_DEADZONE,,,,Mrtvá zóna,Totzone,,Mortozono,Zona muerta,,Kuollut alue,Zone neutre,Holttér,Zona cieca,デッドゾーン,불감대,Dode zone,Martwa strefa,Zona morta,,Zonă moartă,Мёртвая зона,Мртва зона, +No configurable axes,JOYMNU_NOAXES,,,,Žádné nastavitelné osy,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,Brak osi do skonfigurowania,Nenhum eixo configurável,,Nicio axă configurabilă,Нет настраиваемых осей,Нема конфигурационих оса, +None,OPTVAL_NONE,,,,Žádný,Kein,,Neniu,Ninguno,,Ei mitään,Aucun,Nincs,Nessuno,無し,없음,Geen,Żaden,Nenhum,,Niciuna,Откл.,Ништа, +Turning,OPTVAL_TURNING,,,,Otáčení,Umdrehen,,Turnanta,Girar,,Kääntyminen,Tourner,Fordulás,Rotazione,旋回,회전,Draaien,Obracanie się,Girar,,Rotire,Поворот,Скретање, +Looking Up/Down,OPTVAL_LOOKINGUPDOWN,,,,Dívání se nahoru/dolů,Hoch/runterblicken,,Rigardanta Supren/Malsupren,Mirar hacia Arriba/Abajo,,Ylös/Alas katsominen,Vue haut/bas,Fel-/lenézés,Sguardo Sopra/Sotto,視点上下,위/아래로 보기,Omhoog/omlaag zoeken,Patrzenie w górę/w dół,Olhar para cima/baixo,,Privire Sus/Jos,Взгляд вверх/вниз,Гледање горе/доле, +Moving Forward,OPTVAL_MOVINGFORWARD,,,,Pohyb vpřed,Vorwärtsbewegung,,Movanta Antaŭen,Avanzar,,Eteenpäin liikkuminen,Avancer,Előre mozgás,Movimento in avanti,前進,앞으로 전진,Voorwaarts bewegen,Poruszanie się do przodu,Mover-se para a frente,,Deplasare în Față,Движение вперёд,Кретање напред, +Strafing,OPTVAL_STRAFING,,,,Pohyb do stran,Seitwärtsbewegung,,Flankmovanta,Desplazarse,,Sivuttaisastunta,Pas de côté,Oldalazás,Movimento laterale,横移動,양옆으로 이동,Strafelen,Uniki,Deslocamento lateral,,Deplasare în Diagonală,Движение боком,Кретање у страну, +Moving Up/Down,OPTVAL_MOVINGUPDOWN,,,,Pohyb nahoru/dolů,Auf/abwärtsbewegung,,Movanta Supren/Malsupren,Moverse hacia Arriba/Abajo,,Ylös/Alas liikkuminen,Mouvement haut/bas,Felfele/Lefele mozgás,Movimento Sopra/Sotto,前進後退,위/아래로 이동,Naar boven/beneden bewegen,Poruszanie się w górę/w dół,Mover-se para cima/baixo,,Mișcare Sus/Jos,Движение вверх/вниз,Кретање горе/доле, +Inverted,OPTVAL_INVERTED,,,,Inverzní,Invertiert,,Inversigita,Invertido,,Käännetty,Inversé,Felcserélve,Invertito,反転する,반전,Omgekeerd,Odwrócony,Invertido,,Inversat,Инвертировано,Обрнуто, +Not Inverted,OPTVAL_NOTINVERTED,,,,Neinverzní,nicht invertiert,,Ne Inversigita,No invertido,,Ei käännetty,Non Inversé,Nincs felcserélve,Non invertito,反転しない,반전되지 않음,Niet omgekeerd,Nieodwrócony,Não invertido,,Neinversat,Прямо,Не обрнуто, +,,Player Menu,,,,,,,,,,,,,,,,,,,,,, +Player Setup,MNU_PLAYERSETUP,,,,Nastavení hráče,Spielereinstellungen,Στήση παίχτη,Ludanto-Agordaĵo,Config. del jugador,,Pelaaja-asetukset,Options Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーの特徴,플레이어 설정,Speler instellen,Ustawienia Gracza,Definições de jogador,,Configurare jucător,Настройки игрока,Подешавања играча, +Blue,TXT_COLOR_BLUE,,,,Modrá,Blau,Μπλέ,Blua,Azul,,Sininen,Bleu,Kék,Blu,青,청색,Blauw,Niebieski,Azul,,Albastru,Синий,Плава, +Red,TXT_COLOR_RED,,,,Červená,Rot,Κόκκινο,Ruĝa,Rojo,,Punainen,Rouge,Vörös,Rosso,赤,적색,Rood,Czerwony,Vermelho,,Roșu,Красный,Црвена, +Green,TXT_COLOR_GREEN,,,,Zelená,Grün,Πράσινο,Verda,Verde,,Vihreä,Vert,Zöld,Verde,緑,녹색,Groen,Zielony,Verde,,Verde,Зелёный,Зелена, +Gray,TXT_COLOR_GRAY,,,Grey,Šedá,Grau,Γκρί,Griza,Gris,,Harmaa,Gris,Szürke,Grigio,灰,회색,Grijs,Szary,Cinza,,Gri,Серый,Сива, Dark gray,TXT_COLOR_DARKGRAY,,,"Dark grey -",Tmavě šedá,Dunkelgrau,,Malhelgriza,Gris Oscuro,,Tummanharmaa,Gris sombre,Sötétszürke,Grigio scuro,鉛,치색,Donkergrijs,Ciemnoszary,Cinza escuro,,Gri închis,Тёмно-серый,Тамно сива -Dark Green,TXT_COLOR_DARKGREEN,,,,Tmavě zelená,Dunkelgrün,,Malhelverda,Verde Oscuro,,Tummanvihreä,Vert sombre,Sötétzöld,Verde scuro,深,흑녹색,Donkergroen,Ciemnozielony,Verde escuro,,Verde închis,Тёмно-зелёный,Тамна зелена -Brown,TXT_COLOR_BROWN,,,,Hnědá,Braun,,Bruna,Marrón,,Ruskea,Brun,Barna,Marrone,茶,갈색,Bruin,Brązowy,Marrom,,Maro,Коричневый,Браон -Dark Blue,TXT_COLOR_DARKBLUE,,,,Tmavě modrá,Dunkelblau,,Malhelblua,Azul Oscuro,,Tummansininen,Bleu sombre,Sötétkék,Blu scuro,紺,,Donkerblauw,Ciemnoniebieski,Azul escuro,,Albastru închis,Тёмно-Синий,Тамна Плава -Light Red,TXT_COLOR_LIGHTRED,,,,Světle červená,Hellrot,,Helruĝa,Rojo Claro,,Vaaleanpunainen,Rouge clair,Világospiros,Rosso chiaro,丹,옅은 적색,Licht Rood,Jasnoczerwony,Vermelho claro,,Roșu deschis,Светло-красный,Светло црвена -Yellow,TXT_COLOR_YELLOW,,,,Žlutá,Gelb,,Flava,Amarillo,,Keltainen,Jaune,Sárga,Giallo,黄,노란색,Geel,Żółty,Amarelo,,Galben,Жёлтый,Жута -Purple,TXT_COLOR_PURPLE,,,,Fialová,Violett,,Purpura,Morado,,Purppura,Violet,Lila,Viola,紫,보라색,Paars,Fioletowy,Roxo,,Mov,Фиолетовый,Љубичаста -Olive,TXT_COLOR_DULLGREEN,,,,Bledě zelená,Blassgrün,,Olivkolora,Oliva,,Haaleanvihreä,Vert pâle,Olíva,Verde pallido,苔,암녹색,Saaie groen,Matowa Zieleń,Verde oliva,,Măsliniu,Мутно-зелёный,Тупа зелена -Beige,TXT_COLOR_BEIGE,,,,Béžová,,Μπέζ,Flavgriza,Beis,,Beesi,,Bézs,,淡,담갈색,Beige,Beżowy,Bege,,Bej,Бежевый,Беж -Light Green,TXT_COLOR_LIGHTGREEN,,,,Světle zelená,Hellgrün,Ανοιχτό Πράσινο,Helverda,Verde Claro,,Vaaleanvihreä,Vert clair,Világoszöld,Verde chiaro,葵,옅은 녹색,Licht groen,Jasonzielony,Verde claro,,Verde Deschis,Светло-зелёный,Светло зелена -Light Blue,TXT_COLOR_LIGHTBLUE,,,,Světle modrá,Hellblau,Γαλάζιο,Helblua,Azul Claro,,Vaaleansininen,Bleu clair,Világoskék,Blu chiaro,空,옅은 청색,Licht blauw,Jasnoniebieski,Azul claro,,Albastru Deschis,Светло-синий,Светло плава -Light Gray,TXT_COLOR_LIGHTGRAY,,,Light Grey,Světle šedá,Hellgrau,Ανοιχτό Γκρι,Helgriza,Gris Claro,,Vaaleanharmaa,Gris clair,Világosszürke,Grigio chiaro,鉛,옅은 회색,Lichtgrijs,Jasnoszary,Cinza claro,,Gri Deschis,Светло-серый,Светло сива -Light Brown,TXT_COLOR_LIGHTBROWN,,,,Světle hnědá,Hellbraun,Ανοιχτό Καφέ,Helbruna,Marrón Claro,,Vaaleanruskea,Brun clair,Világosbarna,Marrone chiaro,褐,옅은 고동색,Lichtbruin,Jasnobrązowy,Marrom claro,,Maro Deschis,Светло-коричневый,Светло браон -Gold,TXT_COLOR_GOLD,,,,Zlatá,,Χρυσό,Orkolora,Dorado,,Kulta,Or,Arany,Oro,金,금색,Goud,Złoty,Dourado,,Auriu,Золотой,Златна -Bright Green,TXT_COLOR_BRIGHTGREEN,,,,Jasně zelená,Hellgrün,Φωτινό Πράσινο,Brilverda,Verde Claro,,Vaaleanvihreä,Vert clair,Fényeszöld,Verde chiaro,鮮,밝은 녹색,Helder groen,Jasnozielony,Verde claro,,Verde Deschis,Ярко-зелёный,Светла зелена -Rust,TXT_COLOR_RUST,,,,Rez,Rostbraun,Σκουριά,Rustokolora,Óxido,,Ruoste,Rouille,Rozsda,Arrugginito,錆,주황 적갈색,Roest,Rdzawy,Ferrugem,,Ruginiu,Ржавый,Рђа -Name,PLYRMNU_NAME,,,,Jméno,,,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Imię,Nome,,Nume,Имя,Надимак -Team,PLYRMNU_TEAM,,,,Tým,,,Teamo,Equipo,,Joukkue,Equipe,Csapat,Squadra,チーム,팀,Team,Drużyna,Equipe,Equipa,Echipă,Команда,Тим -Color,PLYRMNU_PLAYERCOLOR,,,Colour,Barva,Farbe,,Koloro,,,Väri,Couleur,Szín,Colore,色,색상,Kleur,Kolor,Cor,,Culoare,Цвет,Боја -Gender,PLYRMNU_PLAYERGENDER,,,,Pohlaví,Geschlecht,,Genro,Género,,Sukupuoli,Genre,Nem,Sesso,性別,성별,Geslacht,Płeć,Gênero,,Sex,Пол,Пол -Male,OPTVAL_MALE,,,,Muž,Männlich,,Vira,Masculino,,Miespuolinen,Masculin,Férfi,Maschio,男,남성,Man,Mężczyzna,Masculino,,Masculin,Мужской,Мушко -Female,OPTVAL_FEMALE,,,,Žena,Weiblich,,Ina,Femenino,,Naispuolinen,Féminin,Nő,Femmina,女,여성,Vrouw,Kobieta,Feminino,,Feminin,Женский,Женско -Neutral,OPTVAL_NEUTRAL,,,,Neutrální,Neutral,,Neŭtra (Ri),Neutro,,Sukupuoleton,Neutre,Semleges,Neutrale,中間,중성,Neutraal,Neutralne,Neutro,,Neutru,Нейтральный,Неутрално -Object,OPTVAL_OTHER,,,,Objekt,Objekt,,Objekto (Ĝi),Objeto,,Olio,Objet,Tárgy,Oggetto,物体,기타,Doel,Obiekt,Objeto,,Obiect,Предмет,Предмет -Gameplay Options,GMPLYMNU_TITLE,,,,Nastavení herních mechanik,Gameplay-Optionen,,Ludado-Agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options Gameplay,Játékmenet beállításai,Opzioni gameplay,ゲームプレイ オプション,게임플레이 설정,Gameplay-opties,Opcje Rozgrywki,Opções de jogabilidade,,Setări de Joc,Настройки геймплея,Подешавања гејмплеја -Always,OPTVAL_ALWAYS,,,,Vždy,Immer,,Ĉiam,Siempre,,Aina,Toujours,Mindig,Sempre,常に,언제나,Altijd,Zawsze,Sempre,,Mereu,Всегда,Увек -Never,OPTVAL_NEVER,,,,Nikdy,Nie,,Neniam,Nunca,,Ei koskaan,Jamais,Soha,Mai,しない,없음,Nooit,Nigdy,Nunca,,Niciodată,Никогда,Никад -Autoaim,PLYRMNU_AUTOAIM,,,,Automatické míření,Automatisch zielen,,Celasisto,Autoapuntar,,Automaattitähtäys,Auto-visée,Automatikus célzás,Mira automatica,自動照準,자동 조준,Autoaim,Automatyczne Celowanie,Mira automática,,Autoțintire,Автоприцеливание,Аутоматско циљање -Always Run,PLYRMNU_ALWAYSRUN,,,,Vždy běžet,Immer Rennen,,Ĉiam Kuri,Siempre correr,,Jatkuva juoksu,Toujours courir,Mindig fusson,Corri sempre,常に駆け足,달리기 토글,Altijd lopen,Zawsze Biegaj,Sempre correr,Correr Sempre,Fugă în permanență,Постоянный бег,Увек трчи -,,Display,,,,,,,,,,,,,,,,,,,,, -Display Options,DSPLYMNU_TITLE,,,,Nastavení grafiky,Anzeigeoptionen,,Ekrano-Agordoj,Opciones de visualización,,Näyttöasetukset,Options Affichage,Megjelenítés beállítások,Opzioni display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Настройки экрана,Подешавања приказа -Screen size,DSPLYMNU_SCREENSIZE,,,,Velikost obrazovky,Bildschirmgröße,,Ekrangrando,Tamaño de pantalla,,Näytön koko,Taille de l'écran,Képernyő mérete,Dimensione della schermata,画面サイズ,화면 크기,Schermgrootte,Rozmiar Ekranu,Tamanho de tela,Tamanho do ecrã,Mărime ecran,Размер экрана,Величина екрана -Vertical Sync,DSPLYMNU_VSYNC,,,,Vertikální synchronizace,Vertikale Synchronisation,,Vertikala-Sinkronigo,Sincr. vertical,,Pystytahdistys,Synchronisation Verticale,Függőleges szinkronizálás,Sync verticale,垂直同期,수직 동기화,Verticale Sync,Synchronizacja Pionowa,Sincronização vertical,,Sincronizare Verticală,Вертикальная синхронизация,Вертикална синхорнизација -Models,DSPLYMNU_MODELS,,,,Modely,Modelle,,Modeloj,Modelos,,Mallit,Modèles,3D modellek,Modelli,モデル,모델,Modellen,Modele,Modelos,,Modele,Модели,Модели -Scale crosshair,DSPLYMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt méretezése,Scala del mirino,照準スケール,조준점 크기,Dradenkruis schalen,Skala celownika,Escala da mira,,Scară țintă,Масштабирование прицела,Размера нишана -Brightness,DSPLYMNU_BRIGHTNESS,,,,Jas,Helligkeit,,Brileco,Brillo,,Kirkkaus,Luminosité,Fényerő,Luminosità,明るさ,밝기,Helderheid,Jasność,Brilho,,Luminozitate,Яркость,Осветљење -Gamma correction,DSPLYMNU_GAMMA,,,,Korekce gama,Gammakorrektur,,Gamaa korektado,Corrección gamma,,Gammakorjaus,Correction Gamma,Gamma korrekció,Correzione gamma,ガンマ値,감마 조정,Gamma correctie,Korekta gammy,Correção de gama,,Gamma,Гамма-коррекция,Корекција светлости -Contrast,DSPLYMNU_CONTRAST,,,,Kontrast,Kontrast,,Kontrasto,Contraste,,Sävykkyys,Contraste,Kontraszt,Contrasto,コントラスト,대비,,Kontrast,Contraste,,,Контраст,Контраст -Saturation,DSPLYMNU_SATURATION,,,,Sytost,Sättigung,,Satureco,Saturación,,Värikylläisyys,,Telítettség,Saturazione,サチュレーション,채도,Verzadiging,Nasycenie,Saturação,,Saturație,Насыщенность,Сатурација -Status Bar Scale,DSPLYMNU_SBSCALE,,,,Velikost stavového panelu,Statusleistengröße,,Skalo de Stata Breto,Escala de Barra de Estado,,Tilapalkin skaalaus,Mise à l'échelle HUD,Állapotjelző mérete,,ステータススケール,,Statusbalkschaal,Skala paska statusu,Escala da barra de estado,,Scară bară de stare,, -Messages,DSPLYMNU_MESSAGES,,,,Zprávy,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке -Center messages,MSGMNU_CENTERMESSAGES,,,Centre messages,Vycentrovat zprávy,Nachrichten zentrieren,,Centrigi mesaĝojn,Centrar mensajes,,Keskitä viestit,Messages centrés,Üzenetek középre,Messaggi centrati,メッセージを中央に,메시지 중간에 위치,Berichten centreren,Wyśrodkuj wiadomości,Centralizar mensagens,Centrar mensagens,Mesaje centrate,Центрирование сообщений,Централне поруке -Pulsating message Display,MSGMNU_PULSEMESSAGES,,,,Pulzující zprávy,Pulsierende Nachrichtenanzeige,,Pulsanta Mesaĝ-montrejo,Mostrar Mensajes Pulsantes,,Sykkivät viestit,Messages pulsés,Pulzáló üzenetjelző,,取得時等の文を明滅,,Pulserende berichtendisplay,Pulsujące wyświetlanie wiadomości,Exibir mensagem pulsante,,Afișare Mesaje Pulsante,, -Message Scale,MSGMNU_MESSAGESCALE,,,,Velikost zpráv,Nachrichtengröße,,Skalo de Mesaĝoj,Escala de Mensajes,,Viestien skaalaus,Mise à l'échelle Messages,Üzenet mérete,,メッセージスケール,,Berichtschaal,Skalowanie Wiadomości,Escala da mensagem,,Scară Mesaje,, -,,Automap,,,,,,,,,,,,,,,,,,,,, -Select Color,MNU_COLORPICKER,,,Select Colour,Vyber barvu,Farbe auswählen,Επιλογή Χρώματος,Elektu Koloron:,Elige un color,,Valitse väri,Choisir Couleur,Szín választása,Scegli il colore,色選択,색상을 고르시오,Selecteer Kleur,Wybierz Kolor,Selecione a cor,,Alege o Culoare,Выбор цвета,Изабери боју -Automap Options,AUTOMAPMNU_TITLE,,,,Nastavení automapy,Automapoptionen,,Aŭtomapo-Agordoj,Opciones del Automapa,,Automaattikartan asetukset,Options Carte,Térkép beállításai,Opzioni automappa,オートマップ オプション,오토맵 설정,Automap-opties,Opcje Mapy,Opções de automapa,,Setări Hartă Computerizată,Настройки автокарты,Подешавања аутомапе -Rotate automap,AUTOMAPMNU_ROTATE,,,,Otáčet automapu,Rotiere Automap,,Turni aŭtomapon,Rotar automapa,,Kiertyvä automaattikartta,Rotation de la Carte,Térkép forgatása,Ruota l'automappa,オートマップの回転表示,오토맵 회전,Automatisch roteren,Obracaj mapę,Girar automapa,,Rotire hartă computerizată,Вращающаяся автокарта,Ротирај аутомапу -Follow player,AUTOMAPMNU_FOLLOW,,,,Následovat hráče,Folge dem Spieler,,Sekvi ludanton,Seguir jugador,,Seuraa pelaajaa,Suivre le joueur,Kövesse a játékost,Segui il giocatore,プレイヤー追従,플레이어 추적,Volg de speler,Podążaj za graczem,Seguir jogador,,Urmărire jucător,Привязка к игроку,Прати играча -Customize Map Colors,MAPCOLORMNU_TITLE,,,Customize Map Colours,Nastavení barev mapy,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,Ustaw kolory mapy,Personalizar cores do mapa,,Personalizare culori hartă,Настройки цветов автокарты,Промени боју мапе -Restore default custom colors,MAPCOLORMNU_DEFAULTMAPCOLORS,,,Restore default custom colours,Obnovit původní vlastní barvy,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,Przywróć domyślne kolory,Restaurar cores personalizadas padrão,,Revenire la culorile implicite,Вернуть стандартные цвета,Врати уобичајене разне боје -,,Sound,,,,,,,,,,,,,,,,,,,,, -Sound enabled,SNDMNU_SNDENABLED,,,,Zvuk zapnut,Sound aktiv,,Sono ŝaltita,Sonido Activado,,Ääni päällä,Son activé,Hang engedélyezve,,サウンド有効,,Geluid actief,Dźwięk włączony,Som ativado,,Sunet activat,, -Music enabled,SNDMNU_MUSENABLED,,,,Hudba zapnuta,Musik aktiv,,Muziko ŝaltita,Música Activada,,Musiikki päällä,Musique activée,Zene engedélyezve,,音楽有効,,Muziek actief ,Muzyka włączona,Música ativada,,Muzică activată,, -4000 Hz,OPTVAL_4000HZ,,,,,,,,,,,,,,,,,,4000 Hz,,,4000 Гц, -8000 Hz,OPTVAL_8000HZ,,,,,,,,,,,,,,,,,,8000 Hz,,,8000 Гц, -11025 Hz,OPTVAL_11025HZ,,,,,,,,,,,,,,,,,,11025 Hz,,,11025 Гц, -22050 Hz,OPTVAL_22050HZ,,,,,,,,,,,,,,,,,,22050 Hz,,,22050 Гц, -32000 Hz,OPTVAL_32000HZ,,,,,,,,,,,,,,,,,,32000 Hz,,,32000 Гц, -44100 Hz,OPTVAL_44100HZ,,,,,,,,,,,,,,,,,,44100 Hz,,,44100 Гц, -48000 Hz,OPTVAL_48000HZ,,,,,,,,,,,,,,,,,,48000 Hz,,,48000 Гц, -64 samples,OPTVAL_64SAMPLES,,,,64 vzorků,,,64 specimenoj,64 Muestras,,64 näytettä,,,,,64 샘플,,64 sample,64 amostras,,64 monstre,64 семпла,64 узорка -128 samples,OPTVAL_128SAMPLES,,,,128 vzorků,,,128 specimenoj,128 Muestras,,128 näytettä,,,,,128 샘플,,128 sampli,128 amostras,,128 monstre,128 семплов,128 узорка -256 samples,OPTVAL_256SAMPLES,,,,256 vzorků,,,256 specimenoj,256 Muestras,,256 näytettä,,,,,256 샘플,,256 sampli,256 amostras,,256 monstre,256 семплов,256 узорка -512 samples,OPTVAL_512SAMPLES,,,,512 vzorků,,,512 specimenoj,512 Muestras,,512 näytettä,,,,,512 샘플,,512 sampli,512 amostras,,512 monstre,512 семплов,512 узорка -1024 samples,OPTVAL_1024SAMPLES,,,,1024 vzorků,,,1024 specimenoj,1024 Muestras,,1024 näytettä,,,,,1024 샘플,,1024 sampli,1.024 amostras,,1024 monstre,1024 семпла,1024 узорка -2048 samples,OPTVAL_2048SAMPLES,,,,2048 vzorků,,,2048 specimenoj,2048 Muestras,,2048 näytettä,,,,,2048 샘플,,2048 sampli,2.048 amostras,,2048 monstre,2048 семплов,2048 узорка -4096 samples,OPTVAL_4096SAMPLES,,,,4096 vzorků,,,4096 specimenoj,4096 Muestras,,4096 näytettä,,,,,4096 샘플,,4096 sampli,4.096 amostras,,4096 monstre,4096 семплов,4096 узорка -Auto,OPTSTR_AUTO,,,,,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,오토,,Automatycznie,Automático,,,Авто,Аутоматски -Mono,OPTSTR_MONO,,,,,,,Monofonia,,,,,Monó,,モノラル,모노,,,Mono,,,Моно,Монотоно -Stereo,OPTSTR_STEREO,,,,,,,Stereofonia,Estereo,,,Stéréo,Sztereó,,ステレオ,스테레오,,,Estéreo,,,Стерео,Стереотоно -Dolby Pro Logic Decoder,OPTSTR_PROLOGIC,,,,,,,Malkodilo de Dolby Pro Logic ,,,,,,,ドルビー プロロジック デコーダー,돌비 프로 로직 디코더,,,Decodificador Dolby Pro Logic,,Decodor Pro Logic Dolby,Декодер Dolby Pro Logic, -Quad,OPTSTR_QUAD,,,,,,,Kvadratofonia,Cuádruple,,Dolby Pro Logic -dekooderi,,,,クァッド,쿼드,,Cztery kanały,Quadrifônico,,,Четырёхканальный,Четвородупло -5 speakers,OPTSTR_SURROUND,,,,5 reproduktorů,5 Lautsprecher,,5 Laŭtparoliloj,5 altavoces,5 Bocinas,5 kaiutinta,5 enceintes,5 hangfal,,5 スピーカー,5 스피커,5 luidsprekers,Głośniki 5,5 alto-falantes,,5 boxe,5 динамиков,5 спикер -5.1 speakers,OPTSTR_5POINT1,,,,Reproduktory 5.1,5.1 Lautsprecher,,5.1 Laŭtparoliloj,Altavoces 5.1,Bocinas 5.1,5.1 kaiutinta,Enceintes 5.1,5.1 hangrendszer,,5.1 スピーカー,5.1 스피커,5.1 luidsprekers,Głośniki 5.1,Auto-falantes 5.1,,Boxe 5.1,Динамики 5.1,5.1 спикер -7.1 speakers,OPTSTR_7POINT1,,,,Reproduktory 7.1,7.1 Lautsprecher,,7.1 Laůtparoliloj,Altavoces 7.1,Bocinas 7.1,7.1 kaiutinta,Enceintes 7.1,7.1 hangrendszer,,7.1 スピーカー,7.1스피커,7.1 luidsprekers,Głośniki 7.1,Auto-falantes 7.1,,Boxe 7.1,Динамики 7.1,7.1 спикер -OpenAL Options,OPENALMNU_TITLE,,,,Nastavení OpenAL,OpenAL Optionen,,OpenAL Agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállítások,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања -Playback device,OPENALMNU_PLAYBACKDEVICE,,,,Přehravací zařízení,Wiedergabegerät,,Ludado-aparato,Dispositivo de reproducción,,Äänitoistolaite,Sortie sonore,Visszajátszó eszköz,Dispositivo di playback,プレイバック デバイス,재생 장치,Afspeelapparaat,Urządzenie odtwarzania,Dispositivo de reprodução,,Dispozitiv de redare,Устройство воспроизведения,Аудио уређај -Enable EFX,OPENALMNU_ENABLEEFX,,,,Povolit EFX,EFX aktiv,,Ŝalti EFX,Permitir EFX,,Ota käyttöön EFX,Activer EFX,EFX engedélyezése,Abilita EFX,EFXを有効化,EFX 켬,EFX inschakelen,Pozwól na EFX,Ativar EFX,,Activare EFX,Включить EFX,Укључи EFX -Resampler,OPENALMNU_RESAMPLER,,,,,,,Respecimenilo,,,Näytteenottotaajuusmuunnin,,,,リサンプラー,재배열 기기,,Resampler,Reamostrador,,,Ресэмплер,Ресемплер -Sound Options,SNDMNU_TITLE,,,,Nastavení zvuku,Soundeinstellungen,,Sono-Agordoj,Opciones de sonido,,Ääniasetukset,Options Sonores,Hangbeállítások,Opzioni del suono,サウンド オプション,음향 설정,Geluidsopties,Opcje Dźwięku,Opções de áudio,,Setări Sunet,Настройки звука,Звучна подешавања -Sounds volume,SNDMNU_SFXVOLUME,,,,Hlasitost zvuků,Effektlautstärke,,Sona laŭteco,Volumen de sonido,,Äänitehosteiden voimakkuus,Volume des Sons,Effektek hangereje,Volume suoni,効果音音量,효과음 음량,Geluidsvolume,Głośność Dźwięku,Volume de sons,,Volum efecte,Громкость звука,Јачина звука -Menu volume,SNDMNU_MENUVOLUME,,,,Hlasitost nabídek,Menülautstärke,,Menuo-laŭteco,Volumen del menú,,Valikon äänenvoimakkuus,Volume du Menu,Menü hangereje,Volume menu,メニュー音量,메뉴 음량,Menu volume,Głośność Menu,Volume do menu,,Volum meniu,Громкость меню,Јачина менија -Music volume,SNDMNU_MUSICVOLUME,,,,Hlasitost hudby,Musiklautstärke,,Muzika laŭteco,Volumen de la Música,,Musiikin äänenvoimakkuus,Volume Musique,Zene hangereje,Volume musica,音楽音量,배경음 음량,Muziekvolume,Głośność Muzyki,Volume da música,,Volum muzică,Громкость музыки,Јачина музике -MIDI device,SNDMNU_MIDIDEVICE,,,,MIDI zařízení,MIDI-Gerät,,MIDI-aparato,Dispositivo MIDI,,MIDI-laite,Sortie MIDI,MIDI eszköz,Dispositivo MIDI,MIDIデバイス,MIDI 장치,MIDI-apparaat,Urządzenie MIDI,Dispositivo MIDI,,Dispozitiv MIDI,MIDI проигрыватель,MIDI уређај -Sound in Background,SNDMNU_BACKGROUND,,,,Zvuk na pozadí,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,Dźwięk w Tle,Som de fundo,,Sunet pe fundal,Звуки в фоне,Звуци у позадини -Underwater reverb,SNDMNU_UNDERWATERREVERB,,,,Ozvěna pod vodou,Unterwasserhall,,Subakva resono,Reverb. bajo el agua,,Vedenalaiskaiku,Reverbération sous l'eau,Vízalatti visszhang,Reverb sott'acqua,水中反響音,수중 울림효과,Onderwater nagalm,Pogłos pod wodą,Reverberação debaixo d'água,Reverberação debaixo de água,Reverb subacvatic,Эффект под водой,Подводни одјек -Randomize pitches,SNDMNU_RANDOMIZEPITCHES,,,,Náhodné výšky tónu,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,Losuj tonacje,Aleatorizar tons,Tons aleatórios,Ton sunete aleatoriu,Изменять высоту,Рандомизација тонова -Sound channels,SNDMNU_CHANNELS,,,,Počet zvukových kanálů,Soundkanäle,,Sonokanaloj,Canales de sonido,,Äänikanavat,Canaux sonores,Hangcsatorna,Numero canali del suono,サウンド チャンネル,음향 채널,Geluidskanalen,Kanały dźwiękowe,Canais de som,,Canale de sunet,Количество каналов,Звучни канали -Sound backend,SNDMNU_BACKEND,,,,Zvukový systém,Soundsystem,,Sonoservilo,Sistema de sonido,,Äänijärjestelmä,Traitement Son,Hang backend,Backend suono,サウンド バックエンド,음향 말미,Geluidsarme achterkant,System dźwiękowy,Sistema de som,,Sistem de sunet,Звуковая система,Звучни бекенд -OpenAL options,SNDMNU_OPENAL,,,,Nastavení OpenAL,OpenAL Optionen,,OpenAL agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállításai,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања -Restart sound,SNDMNU_RESTART,,,,Restartovat zvuk,Sound neu starten,,Rekomenci sonon,Reiniciar sonido,,Käynnistä ääni uudelleen,Redémarrer moteur sonore,Hang újraindítása,Resetta il suono,サウンド再起動,음향 재시작,Herstart geluid,Zresetuj dźwięk,Reiniciar som,,Reinițializare sunet,Перезапустить звук,Поново покрени звук -Advanced options,SNDMNU_ADVANCED,,,,Pokročilá nastavení,Erweiterte Optionen,,Altnivelaj agordoj,Opciones avanzadas,,Edistyneet asetukset,Options avancées,Haladó beállítások,Opzioni avanzate,高度なオプション,고급 설정,Geavanceerde opties,Zaawansowane Opcje,Opções avançadas,,Setări avansate,Расширенные настройки,Напредна подешавања -Module replayer options,SNDMNU_MODREPLAYER,,,,Nastavení přehrávače modulů,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,Opcje Modułu Odtwarzacza,Opções de reprodutor de módulos,,Setări de redare a modulelor,Параметры воспроизведения модулей,Подешавања модулног риплејера -Midi player options,SNDMNU_MIDIPLAYER,,,,Nastavení MIDI přehrávače,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,Opcje Odtwarzacza Midi,Opções de reprodutor MIDI,,Setări player MIDI,Настройки MIDI-проигрывателя,MIDI плејер подешавања -Sound in Menus,SNDMNU_MENUSOUND,,,,Zvuk v menu,Sound in Menüs,,Sono en Menuoj,,,Ääni valikoissa,,Hang a menükben,,メニューでのサウンド,,Geluid in menu's,Dźwięk w Menu,Som em menus,,Sunet in meniuri,, -Advanced Sound Options,ADVSNDMNU_TITLE,,,,Pokročilá nastavení zvuku,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,Zaawansowane Opcje Dźwięku,Opções de áudio avançadas,,Setări de sunet avansate,Расширенные настройки,Напредна подешавања звука -Sample rate,ADVSNDMNU_SAMPLERATE,,,,Vzorkovací frekvence,Samplerate,,Specimenrapideco,Frecuencia de muestreo,,Näytteenottotaajuus,Cadence de Sampling,Mintavételezési ráta,,サンプルレート,샘플링레이트,Steekproeftarief,Częstotliwość próbkowania,Taxa de amostragem,,Frecvență de eșantionare,Частота дискретизации,Фреквенција узорковања -HRTF,ADVSNDMNU_HRTF,,,,,,,,,,,,,,,머리전달함수,,HRTF,HRTF,,HRTF,, -OPL Synthesis,ADVSNDMNU_OPLSYNTHESIS,,,,Emulace OPL,OPL Synthese,,OPL-Sintezo,Síntesis OPL,,OPL-synteesi,Synthèse OPL,OPL szintézis,,OPLシンセサイズ,OPL 합성,OPL synthese,Synteza OPL,Síntese OPL,,Sinteză OPL,Синтез OPL,OPL синтеза -Number of emulated OPL chips,ADVSNDMNU_OPLNUMCHIPS,,,,Počet emulovaných OPL čipů,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,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri OPL emulate,Количество эмулируемых OPL чипов,Број емулираних OPL чипа -Full MIDI stereo panning,ADVSNDMNU_OPLFULLPAN,,,,Plné MIDI stereo,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,Pełne efekty stereo dla MIDI,Lateralidade estéreo completa para MIDI,,Panoramă stereo pentru MIDI,Полная стереопанорама для MIDI,Пуно MIDI стерео каналисање -OPL Emulator Core,ADVSNDMNU_OPLCORES,,,,Emulační jádro OPL,OPL Emulatorkern,,OPL Imitilkerno,Núcleo de emulador OPL,,OPL-emulaattoriydin,Cœur émulateur OPL,,,OPL エミュレート コア,OPL 에뮬레이터 코어,OPL Emulator Kern,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL језгро емулације -MIDI voices,ADVSNDMNU_MIDIVOICES,,,,Počet MIDI hlasů,MIDI Stimmen,,MIDI voĉoj,Voces MIDI,,MIDI-äänet,Voix MIDI,MIDI hangok,Voci MIDI,MIDI ボイス,MIDI 최대 음색 양,MIDI-stemmen,Głosy MIDI,Vozes MIDI,,Voci MIDI,MIDI-голоса,MIDI гласови -FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,FluidSynth,,,, -Global,ADVSNDMNU_GLOBAL,,,,Globální,,,Malloka,Global,,Yleinen,,,Globale,グローバル,전반적,Globaal,Globalne,Global,,,Общие,Глобално -Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,フリーバーブ,프리버브,,,Freeverb,,,, -Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローバル フリーバーブ,전반적 프리버브,Globale Freeverb,Globalny Freeverb,Freeverb global,,Freeverb Global,Глобальный Freeverb,Глобални Freeverb -Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッチ セット,패치 세트,,Zestaw patchów,Banco de sons,,Set patch,Патч-набор,Печ сет -Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,,,ゲイン,쌓기,Relatief volume,Wzmocnienie,Ganho,,Amplificare,Усиление,Појачање -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,Poziom pogłosu,Nível de reverberação,,Nivel Reverb,Уровень реверберации,Ниво одјека -Chorus,ADVSNDMNU_CHORUS,,,,,,,Koruso,,,,,,,コーラス,코러스,,,Chorus,,Cor,Хорус,Корус -Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,Timidity++,,,, -ADLMidi,ADVSNDMNU_ADLMIDI,,,,,,,,,,,,,,,,,,ADLMidi,,,, -OPNMidi,ADVSNDMNU_OPNMIDI,,,,,,,,,,,,,,,,,,OPNMidi,,,, -Timidity config file,ADVSNDMNU_TIMIDITYCONFIG,,,,Konfigurační soubor Timidity,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 Timidity config,Timidity コンフィグファイル,Timidity 코딩 파일,Timidity++ configuratiebestand,Plik konfiguracyjny Timidity,Arquivo de configuração do Timidity,,Fișier configurație Timidity,Файл конфигурации Timidity,Timidity конфигурациона датотека -Relative volume,ADVSNDMNU_TIMIDITYVOLUME,,,,Relativní hlasitost,Relative Lautstärke,,Relativa volumeno,Volumen relativo,,Suhteellinen äänenvoimakkuus,Volume Relatif,Relatív hangerő,Volume relativo,相対音量,비교적인 볼륨,Relatief volume,Względna głośność,Volume relativo,,Volum relativ,Относительная громкость,Релативна јачина -WildMidi,ADVSNDMNU_WILDMIDI,,,,,,,,,,,,,,,,,,WildMidi,,,, -WildMidi config file,ADVSNDMNU_WILDMIDICONFIG,,,,Konfigurační soubor WildMidi,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,Plik konfiguracyjny WildMidi,Arquivo de configuração do WildMidi,,Fișier configurație WildMidi,Файл конфигурации WildMidi,WildMidi конфигурациона датотека -Select configuration,ADVSNDMNU_SELCONFIG,,,,Vybrat konfiguraci,Konfiguration wählen,,Elekti agordojn,Seleccionar configuración,,Valitse kokoonpano,Sélectionner configuration,Konfiguráció kiválasztása,Seleziona la configurazione,構成選択,설정을 고르시오,Selecteer configuratie,Wybierz konfigurację,Selecionar configuração,,Selectare configurație,Выбор конфигурации,Изабери конфигурацију -Advanced Resampling,ADVSNDMNU_ADVRESAMPLING,,,,Pokročilé převzorkování,Erweitertes Resampling,,Altnivela respecimenado,Resampleo Avanzado,,Kehittynyt näytteenottotaajuuden muuntaminen,Resampling Avancé,,Resampling avanzato,高度なリサンプリング,향상된 리샘플링,Geavanceerde herbemonstering,Zaawansowane Próbkowanie,Reamostragem avançada,,Resempling avansat,Продвинутый ресэмплинг,Напредно ресампловање -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 Emulator Core,ADVSNDMNU_ADLOPLCORES,,,,Emulační jádro OPL,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,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL емулационо језгро -Run emulator at PCM rate,ADVSNDMNU_RUNPCMRATE,,,,Emulátor používá PCM vzorkovací frekvenci,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,Uruchom emulator w częstotliwości PCM,Rodar emulador em taxa PCM,,Utilizare cu frecvența PCM,Использовать с частотой PCM,Покрени емулацију на PCM стопи -Number of emulated OPL chips,ADVSNDMNU_ADLNUMCHIPS,,,,Počet emulovaných OPL čipů,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,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri GUS emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипова -Volume model,ADVSNDMNU_VLMODEL,,,,Model hlasitosti,Lautstärkemodell,,Modelo de volumeno,Modelo de Volumen,,Äänenvoimakkuusmalli,Modèle de Volume,Hangmodell,Modello di volume,音量モデル,모델 볼륨,Volume model,Model głośności,Modelo de volume,,Model volum,Модель громкости,Волумски модел -OPN2 Emulator Core,ADVSNDMNU_OPNCORES,,,,Emulační jádro OPN2,OPN2 Emulatorkern,,OPN2 Imitilkerno,Núcleo de emulador OPN2,,OPN2-emulaattoriydin,Cœur émulateur OPN2,,,OPN2 エミュレート コア,OPN2 에뮬레이터 코어,OPN2 Emulatorkern van de OPN2-emulator,Rdzeń Emulatora OPN2,Núcleo do emulador de OPN2,,Nucleu de emulare OPN2,Ядро эмуляции OPN2,OPN2 језгро емулације -GUS Emulation,ADVSNDMNU_GUSEMULATION,,,,Emulace GUS,GUS Emulation,,GUS Imitado,Emulación GUS,,GUS-emulaatio,Emulation GUS,GUS Emuláció,,GUS エミュレーション,GUS 에뮬레이션,GUS-emulatie,Emulacja GUS,Emulação de GUS,,Emulare GUS,Эмуляция GUS,GUS емулација -GUS config file,ADVSNDMNU_GUSCONFIG,,,,Konfigurační soubor GUS,GUS Konfigurationsdatei,,Agorda dosiero de GUS,Archivo de config. GUS,,GUS-config-tiedosto,Fichier Config. GUS,GUS konfig fájl,File GUS config,GUS コンフィグファイル,GUS 코딩 파일,GUS-configuratiebestand,Plik konfiguracyjny GUS,Arquivo de configuração do GUS,,Fișier configurație GUS,Файл конфигурации для GUS,GUS конфигурациона датотека -Read DMXGUS lumps,ADVSNDMNU_DMXGUS,,,,Načíst DMXGUS soubory,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,Czytaj pliki DMXGUS,Ler lumps DMXGUS,,Citire fișiere DMXGUS,Читать файлы DMXGUS,Читај DMXGUS фајлове -GUS memory size,ADVSNDMNU_GUSMEMSIZE,,,,Velikost paměti GUS,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,Rozmiar pamięci GUS,Tamanho de memória do GUS,,Memorie alocată pentru GUS,Размер памяти GUS,GUS величина памћења -Number of emulated OPN chips,ADVSNDMNU_OPNNUMCHIPS,,,,Počet emulovaných OPN čipů,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,Liczba emulowanych czipów OPN,Número de chips OPN emulados,,Număr de cipuri OPN emulate,Количество эмулируемых чипов OPN,Број емулираних OPN чипова -Use custom WOPL bank,ADVSNDMNU_ADLCUSTOMBANK,,,,Použít vlastní WOPL sadu,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,Użyj niestandardowego banku WOPL,Usar banco WOPL personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPL,Користи прилагођенуу WOPL банку -WOPL Bank file,ADVSNDMNU_OPLBANKFILE,,,,Soubor WOPL sady,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,Plik banku WOPL,Banco WOPL,,Fișier WOPN bank,Файл с банком WOPL,WOPL фајл банка -Use custom WOPN bank,ADVSNDMNU_OPNCUSTOMBANK,,,,Použít vlastní WOPN sadu,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,Użyj niestandardowego banku WOPN,Usar banco WOPN personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPN,Користи прилагођену WOPN банку -WOPN Bank file,ADVSNDMNU_OPNBANKFILE,,,,Soubor WOPN sady,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,Plik banku WOPN,Banco WOPN,,Fișier WOPN bank,Файл с банком WOPN,WOPN фајл банка -Aliasing,OPTVAL_ALIASING,,,,,,,Krenelaro,,,,,,,エイリアシング,에일리어싱,,,,,Dedublare,Алиасинг,Преклапање -Linear,OPTVAL_LINEAR_1,This setting is duplicated threefold in order to allow for different grammatical gender endings,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowy,Linear,,Liniar,Линейное,Линеаран -Linear,OPTVAL_LINEAR_2,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowa,Linear,,Liniar,Линейная,Линеаран -Linear,OPTVAL_LINEAR_3,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowe,Linear,,Liniar,Линейный,Линеаран -Nearest,OPTVAL_NEAREST,,,,Nejbližší,Nächster Nachbar,,Plej proksima,Cercano,,Lähin,Nearest,Legközelebbi,Il più vicino,最寄り,가까이,Naast,Najbiższe,Mais próximo,,Cel mai apropriat,Ближайший,Најближе -PCF (Low),OPTVAL_PCF_LOW,,,,PCF (nízké),PCF (niedrig),,PCF (Malalta),PCF (Bajo),,PCF (matala),PCF (Low),PCF (Alacsony),PCF (basso),PCF (低),PCF (하급),PCF (Laag),PCF (Niski),PCF (Baixo),,PCF (Scăzut),PCF (низкий),PCF (ниско) -PCF (Medium),OPTVAL_PCF_MEDIUM,,,,PCF (střední),PCF (mittel),,PCF (Meza),PCF (Medio),,PCF (keskitaso),PCF (Medium),PCF (Közepes),PCF (medio),PCF (中),PCF (중급),PCF (Medium),PCF (Średni),PCF (Médio),,PCF (Mediu),PCF (средний),PCF (средње) -PCF (High),OPTVAL_PCF_HIGH,,,,PCF (vysoké),PCF (hoch),,PCF (Alta),PCF (Alto),,PCF (korkea),PCF (High),PCF (Magas),PCF (alto),PCF (高),PCF (상급),PCF (Hoog),PCF (Wysoki),PCF (Alto),,PCF (Ridicat),PCF (высокий),PCF (високо) -Cubic,OPTVAL_CUBIC,,,,Kubická,Kubisch,,Kuba,Cúbico,,Kuutio,Cubique,,Cubico,キュービック,큐빅,Kubieke,Sześcienny,Cúbico,,Cub,Кубическое,Кубан -Band-limited step,OPTVAL_BLEP,,,,Omezené krokování,Bandbegrenzte Schritte,,Bendo-limigita paŝo,Paso limitado por banda,,Kaistarajoitettu askel,Step limité par bande,,Passo limitato dalla banda,帯域制限ステップ,제한된 단계별 밴드,Bandbeperkte stap,Krok ograniczony pasmem,Passo limitado por banda,,Limitare frecvență pas-cu-pas,Пошаговое ограничение частоты,Постепено ограничење фреквенције -Linear (Slower),OPTVAL_LINEARSLOW,,,,Lineární (pomalejší),Linear (langsamer),,Lineara (Pli malrapida),Lineal (más lento),,Lineaarinen (hitaampi),Linéaire (Lent),Lineáris (Lassabb),Lineare (più lento),リニア(遅め),선형 (느리게),Lineair (langzamer),Liniowy (wolniejszy),Linear (mais lento),,Liniar (Mai lent),Линейное (медленнее),Линеаран (спорије) -Band-limited linear,OPTVAL_BLAM,,,,Omezená lineární,Bandbegrenzt linear,,Bendo-limigita lineara,Lineal limitado por banda,,Kaistarajoitettu lineaarinen,Linéaire limité par bande,,Lineare limitato dalla banda,帯域制限リニア,밴드 제한 식 선형,Band-beperkt lineair,Liniowy ograniczony pasmem,Linear limitado por banda,,Limitare frecvență liniară,Линейное ограничение частоты,Линеарно ограничење фреквенције -Cubic (Slower),OPTVAL_CUBICSLOW,,,,Kubická (pomalejší),Kubisch (langsamer),,Kuba (Pli malrapida),Cúbico (más lento),,Kuutio (hitaampi),Cubique (Lent),,Cubico (più lento),キュービック (遅め),큐빅 (느리게),Kubieke (langzamer),Sześcienny (wolniejszy),Cúbico (mais lento),,Cub (Mai lent),Кубическое (медленнее),Кубан (спорије) -Sinc,OPTVAL_SINC,,,,,,,,Seno cardinal,,,,,,シンク,싱크,,,Seno cardinal,,Sinus cardinal,Кардинальный синус,Синк -Note on/off only,OPTVAL_NOTEONOFFONLY,,,,Pouze začátek/konec noty,Nur für Note an/aus ,,Nur noto ek/for,Sólo 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,Tylko dla włączonych/wyłączonych notatek,Somente notas ligadas/desligadas,,Numai la activarea/oprirea notelor,Только при включении/отключении нот,Само током укључења/искључења ноте -Full ramping,OPTVAL_FULLRAMPING,,,,Plný náběh,,,Plena pligrandigado,Aumento completo,,Täysi kerrytys,Rampe complète,,Ramping completo,フルランピング,최대 램핑,Volledige helling,Pełne zwiększenie,Rampa completa,,Creștere completă,Полное наращивание,Пуно појачање -Module Replayer Options,MODMNU_TITLE,,,,Nastavení přehrávače modulů,Modul-Spieler-Optionen,,Agordoj por Modulo-reludilo,Opciones de reproductor de módulos,,Moduulisoitinasetukset,Options Lecteur de Module,Modul lejátszó beállításai,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 재생 설정,Module-Speler-Opties,Opcje Odtwarzacza Modułów,Opções de reprodutor de módulos,,Setări de redare module,Параметры воспроизведения модулей,Подешавања модуларног реплејера -Master volume,MODMNU_MASTERVOLUME,,,,Celková hlasitost,Grundlautstärke,,Ĉeflaŭteco,Volumen maestro,,Yleisäänenvoimakkuus,Volume maître,Fő hangerő,Volume master,全体音量,마스터 볼륨,Hoofdvolume,Całkowita głośność,Volume geral,,Volum general,Общая громкость,Глацни звук -Quality,MODMNU_QUALITY,,,,Kvalita,Qualität,,Kvaliteco,Calidad,,Laatu,Qualité,Minőség,Qualità,クオリティ,품질,Kwaliteit,Jakość,Qualidade,,Calitate,Качество,Квалитет -Volume ramping,MODMNU_VOLUMERAMPING,,,,Křivka hlasitosti,Lautstärkeverhalten,,Laŭteco-pligrandigado,Aumento gradual de Volumen,,Äänenvoimakkuuden kertyminen,Rampe du volume,,Ramping volume,音量ランピング,볼륨 램핑,Volume-aanvulling,Zwiększenie głośności,Rampa de volume,,Creștere volum,Наращивание громкости,Појачавање звука -Chip-o-matic,MODMNU_CHIPOMATIC,,,,,,,,,,,,,,チップ オー マチック,칩-오-매틱,,,Chip-o-matic,,,, -MAME OPL2,OPTVAL_MAMEOPL2,,,,,,,,,,,,,,,마메 OPL2,,,MAME OPL2,,,, -DOSBox OPL3,OPTVAL_DOSBOXOPL3,,,,,,,,,,,,,,,도스박스 OPL3,,,DOSBox OPL3,,,, -Java OPL3,OPTVAL_JAVAOPL3,,,,,,,,,,,,,,,자바 OPL3,,,Java OPL3,,,, -Nuked OPL3,OPTVAL_NUKEDOPL3,,,,,,,,,,,,,,,,,,Nuked OPL3,,,, -MAME YM2612,OPTVAL_MAMEOPN2,,,,,,,,,,,,,,,마메 YM2612,,,MAME YM2612,,,, -Neko Project II Kai OPNA,OPTVAL_NP2OPNA,,,,,,,,,,,,,,,,,,Neko Project II Kai OPNA,,,, -MAME YM2608,OPTVAL_MAMEOPNA,,,,,,,,,,,,,,,마메 YM2608,,,MAME YM2608,,,, -PMDWin OPNA,OPTVAL_PMDWINOPNA,,,,,,,,,,,,,,,,,,PMDWin OPNA,,,, -Opal OPL3,OPTVAL_OPALOPL3,,,,,,,,,,,,,,,,,,Opal OPL3,,,, -Nuked OPL3 v1.7.4,OPTVAL_NUKEDOPL3174,,,,,,,,,,,,,,,,,,Nuked OPL3 v1.7.4,,,, -Nuked OPN2,OPTVAL_NUKEDOPN2,,,,,,,,,,,,,,,,,,Nuked OPN2,,,, -GENS YM2612,OPTVAL_GENSOPN2,,,,,,,,,,,,,,,,,,GENS YM2612,,,, -Auto (Use setup of bank),ADLVLMODEL_AUTO,,,,Auto (použít nastavení sady),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),Automatycznie (Użyj ustawień banku),Automático (usar definições de banco),,Auto (configurare din bancă),Авто (настройка из банка),Аутоматски (користи намештену банку) -Generic,ADLVLMODEL_GENERIC,,,,Standardní,Allgemein,,Komuna,Genérico,,Yleinen,Générique,Általános,Generico,一般的,전형적,Algemeen,Ogólne,Genérico,,,Общий,Генерично -OPL Native,ADLVLMODEL_NATIVE,,,,Nativní OPL,OPL Nativ,,Nativa OPL,Nativo OPL,,Luontainen OPL,OPL Natif,,,OPLネイティブ,고유 OPL,OPL Native,Natywne OPL,Nativo OPL,,OPL propriu,Встроенная OPL,OPL домаћи -"DMX (Accurate, with AM bug)",ADLVLMODEL_DMX,,,,"DMX (Přesný, s AM chybou)",,,,,,,,,,,데이터 마이닝 확장,"DMX (accuraat, met AM bug)",,"DMX (preciso, com bug de AM)",,"DMX (Precis, cu probleme în AM)","DMX (Точная, с багом АМ)", -"Apogee (Accurate, with AM bug)",ADLVLMODEL_APOGEE,,,,"Apogee (Přesný, s AM chybou)",,,,,,,,,,,어포지,"Apogee (accuraat, met AM bug)",,"Apogee (preciso, com bug de AM)",,"Apogee (Precis, cu probleme în AM)","Apogee (Точная, с багом АМ)", -Win9X-like (SB16),ADLVLMODEL_WIN9X,,,,Jako Windows 9X (SB16),Wie Windows 9X (SB16),,Kiel Win9X (SB16),Como Win9X (SB16),,Win9x-kaltainen (SB16),,,,Win9X式 (SB16),Win9X 같게 (SB16),Win9X-achtig (SB16),Jak w Win9X (SB16),Estilo Win9X (SB16),,Similar cu Win9X (SB16),Похожая на Win9X (Вариант SB16),Као у Win9X-у (SB16) -Win9X-like (Generic FM),ADLVLMODEL_WIN9XGENERIC,,,,Jako Windows 9X (Generic FM),Wie Windows 9X (Generic FM),,Kiel Win9X (Generic FM),Como Win9X (Generic FM),,Win9x-kaltainen (Generic FM),,,,Win9X式 (Generic FM),Win9X 같게 (Generic FM),Win9X-achtig (Generic FM),Jak w Win9X (Generic FM),Estilo Win9X (FM genérico),,Similar cu Win9X (Generic FM),Похожая на Win9X (Вариант Generic FM),Као у Win9X-у (Generic FM) -DMX (Without AM voice bug),ADLVLMODEL_DMX_FIXED,,,,DMX (Bez AM hlasové chyby),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 (bez głosowego błędu AM),DMX (sem bug de voz de AM),,DMX (Fără probleme în AM),DMX (Без бага АМ), -Apogee (Without AM voice bug),ADLVLMODEL_APOGEE_FIXED,,,,Apogee (Bez AM hlasové chyby),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 (bez głosowego błędu AM),Apogee (sem bug de voz de AM),,Apogee (Fără probleme în AM),Apogee (Без бага АМ), -IBM Audio Library Interface,ADLVLMODEL_AIL,,,,,,,IBM Aŭdbibiloteka Interfaco,,,,,,,,,,Interfejs Biblioteki Dźwięków IBM,Interface de Biblioteca de Áudio IBM,,Interfață de Bibliotecă IBM,, -HMI Sound Operating System,ADLVLMODEL_HMI,,,,,,,HMI Sonoperaciumo,,,,,,,,,,System Operacyjny Dźwięków HMI,Sistema Operacional de Som HMI,,Sistem Sonor HMI,, -"HMI SOS (Old, with bugs)",ADLVLMODEL_HMIOLD,,,,"HMI SOS (Starý, s chybami)","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 (Stare, z błędami)","SOS HMI (antigo, com bugs)",,"HMI SOS (Vechi, cu probleme)",HMI SOS (Старый вариант с багами), -Unlimited,OPTVAL_UNLIMITED,,,,Neomezený,Unlimitiert,,Senlima,Ilimitado,,Rajoittamaton,Illimité,Végtelen,Illimitato,無制限,무제한,Onbeperkt,Nieskończone,Sem limites,,Nelimitat,Без ограничений,Бескрајно -256K,OPTVAL_256K,,,,,,,,,,,,,,,,,,256K,,,256К, -512K,OPTVAL_512K,,,,,,,,,,,,,,,,,,512K,,,512К, -768K,OPTVAL_768K,,,,,,,,,,,,,,,,,,768K,,,768К, -1024K,OPTVAL_1024K,,,,,,,,,,,,,,,,,,1024K,,,1024К, -,,Postprocessing,,,,,,,,,,,,,,,,,,,,, -Uncharted 2,OPTVAL_UNCHARTED2,,,,,,,,,,,,,,,,,,Uncharted 2,,,, -Hejl Dawson,OPTVAL_HEJLDAWSON,,,,,,,,,,,,,,,,,,Hejl Dawson,,,, -Reinhard,OPTVAL_REINHARD,,,,,,,,,,,,,,,,,,Reinhard,,,, -Palette,OPTVAL_PALETTE,,,,Paleta,,,Paletro,Paleta,,Paletti,,Paletta,Palette,パレット,팔레트,Palet,Paleta,Paleta,Palete,Paletă,Палитра игры,Палет -Low,OPTVAL_LOW,,,,Nízká,Niedrig,Χαμηλό,Malalta,Bajo,,Matala,Bas,Alacsony,Basso,低,낮음,Laag,Niskie,Baixo,,Scăzut,Низкое,Ниско -Medium,OPTVAL_MEDIUM,,,,Střední,Mittel,Μεσαίο,Meza,Medio,,Keskitaso,Moyen,Közepes,Medio,中,중간,Middel,Średnie,Médio,,Mediu,Среднее,Средње -High,OPTVAL_HIGH,,,,Vysoká,Hoch,Υψηλό,Alta,Alto,,Korkea,Haut,Magas,Alto,高,높음,Hoog,Wysokie,Alto,,Ridicat,Высокое,Високо -Extreme,OPTVAL_EXTREME,,,,Extrémní,Extrem,Ακράιο,Ekstrema,Extremo,,Äärimmäinen,Extrême,Extrém,Estremo,最高,매우 높음,Extreem,Ekstremalne,Extremo,,Extrem,Максимальное,Екстремно -Obverse,OPTVAL_OBVERSEFIRST,,,,Vpřed (obvers),Obvers,Παρατήρησε,Antaŭa,Anverso,,Etupuoli,,,Dritto,正面,앞면,Obvers,Awers,Obverso,,Avers,Прямой,Супротно -Reverse,OPTVAL_REVERSEFIRST,,,,Vzad (revers),Revers,Αντίστροφο,Inversa,Inverso,,Käänteinen,Inverse,Fordított,Contrario,反転,반전,Revers,Rewers,Reverso,,Invers,Обратный,Обрнуто -Postprocessing,GLMNU_POSTPROCESS,,,,,,Μετα-επεξεργασία,Postprocezado,Postprocesado,,Jälkikäsittely,,,,ポストプロセッシング,포스트프로세싱 적용,Nabewerking,Przetwarzanie końcowe,Pós-processamento,,Postprocesare,Постобработка,Пост обрада -Tonemap Mode,GLPREFMNU_TONEMAP,,,,Režim tónovací mapy,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,Tryb Mapowania Tonów,Tipo de tonemap,,Mod Tonemap,Режим тоун-мэппинга,Тонирано-мапни мод -Lens distortion effect,GLPREFMNU_LENS,,,,Efekt distorze čočky,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,Efekt zniekształcenia obiektywu,Distorção de lente,Efeito de distorção da lente,Efect de distorsionare,Искажение линзы,Дисторзија објектива ефект -FXAA Quality,GLPREFMNU_FXAA,,,,Kvalita FXAA,FXAA Qualität,,Kvaliteco de FXAA,Calidad FXAA,,FXAA-laatu,Qualité FXAA,FXAA minősége,Qualità FXAA,FXAA品質,FXAA 품질,FXAA-kwaliteit,Jakość FXAA,Qualidade de FXAA,,Calitate FXAA,Качество FXAA,FXAA квалитет -Dither output,GLPREFMNU_DITHER,,,,Dithering,Dithering,,Punktismo,Dither de salida,,Sekoitussävytyksen (dithering) ulostulo,Dithering,Árnyalás kimenet,Dithering,ディザー出力,떨림 효과 출력,Dither output,Dygotanie,Saída de dithering,,Putere Dithering,Дизеринг,Учестаност трептања -Tonemap Palette Order,GLPREFMNU_PALTONEMAPORDER,,,,Pořadí palety tónovací mapy,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,Kolejność Palet Mapowania Tonów,Ordem da paleta de tonemap,,Ordine paletă Tonemap,Порядок палитры тоун-мэпа,Тонирано-мапни палетни ред -Tonemap Palette Exponent,GLPREFMNU_PALTONEMAPPOWER,,,,Exponent palety tónovací mapy,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,Wykładnik Palet Mapowania Tonów,Expoente da paleta de tonemap,,Exponent paletă Tonemap,Экспонента палитры тоун-мэпа,Тонирано-мапни палетни експонент -Multisample,GLPREFMNU_MULTISAMPLE,,,,Multisampling,Multisampling,,Plurspecimeno,Multisampling,,Moninäytteistys,,,,マルチサンプル,멀티샘플,,Multipróbkowanie,Multiamostragem,,Multisampling,Мультисэмплинг,Мулти-узорак -Bloom effect,GLPREFMNU_BLOOM,,,,Efekt bloom,Bloom Effekt,,Lumŝmiro-efiko,Efecto Bloom,,Hehkutehoste (bloom),Effet surbrillance,Bloom effekt,Effetto Bloom,ブルーム エフェクト,블룸 효과,Bloom-effect,Effekt Bloom,Bloom,,Efect Bloom,Режим блум,Мутан вид ефект -Ambient occlusion quality,GLPREFMNU_SSAO,,,,Kvalita ambient occlusion,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,Jakość okluzji otoczenia,Qualidade de oclusão de ambiente,,Calitate ocluzie ambientală,Качество ambient occlusion,Оклузија амбијента ефект -Portals with AO,GLPREFMNU_SSAO_PORTALS,,,,Portály s 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,Portale z okluzją otoczenia,Portais com oclusão de ambiente,,Portaluri cu ocluzie ambientală,"Порталы с ambient occlusion -",Портали са AO -Menu Blur,GLPREFMNU_MENUBLUR,,,,Rozostření pozadí v menu,Menüunschärfe,,Malklarigo de Menuo ,Difuminación de Menú,,Valikon sumennus,Flou menu,Menü homály,Blur del menu,メニューブラー,메뉴 흐림 효과,Menu vervagen,Rozmycie w Menu,Desfoque do menu,Desfocagem do Menu,Neclaritate Meniu,Размытие фона меню,Блур мениа -,,Textures,,,,,,,,,,,,,,,,,,,,, -Texture Filter mode,GLTEXMNU_TEXFILTER,,,,Režim filtrování textur,Texturfiltermodus,,Reĝimo por Teksturfiltrado,Modo de filtro de texturas,,Pintakuviointien suodatustapa,Mode de Filtrage Texture,Textúraszűrés módja,Modalità filtro texture,テクスチャーフィルター モード,텍스쳐 필터 모드,Textuurfiltermodus,Tryb Filtrowania Tekstur,Modo de filtro de textura,,Mod Filtrare Texturi,Фильтрация текстур,Текстурни филтер мод -Anisotropic filter,GLTEXMNU_ANISOTROPIC,,,,Anisotropické filtrování,Anisotropische Filterung,,Anizotropa filtro,Filtro anisotrópico,,Anisotrooppinen suodatus,Filtre Anisotropique,Anizotropikus szűrő,Filtro anisotropico,異方性フィルター,이방성 필터,Anisotroopfilter,Filtr anizotropowy,Filtro anisotrópico,,Filtrare Anizotropică,Анизотропная фильтрация,Анизотропни фолтер -None (nearest mipmap),OPTVAL_NONENEARESTMIPMAP,,,,Žádné (nejbližší mipmapa),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),Brak (najbliższa mipmapa),Nenhum (mipmap mais próximo),,Niciuna (mipmap de apropriere),Нет (ближайший мипмап),Ништа (најближи мипмап) -None (linear mipmap),OPTVAL_NONELINEARMIPMAP,,,,Žádné (lineární mipmapa),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),Brak (liniowa mipmapa),Nenhum (mipmap linear),,Niciuna (mipmap liniar),Нет (линейный мипмап),Ништа (линеаран мипмап) -None (trilinear),OPTVAL_NONETRILINEAR,,,,Žádné (trilineární),Aus (trilinear),,Nenio (trilinia),Ninguno (trilineal),,Ei mitään (trilineaarinen),Aucun (mipmap trilinéaire),Semmilyen (trilineáris),Nessuno (mipmap trilineare),なし(トライリニア),없음 (삼선형),Geen (trilineair),Brak (trzyliniowe),Nenhum (trilinear),,Niciuna (trilinar),Нет (трилинейная),Ништа (трилинеарно) -Bilinear,OPTVAL_BILINEAR,,,,Bilineární,,,Dulinia,Bilineal,,Bilineaarinen,Bilinéaire,Bilineáris,Bilineare,バイリニア,쌍선형,Bilineair,Dwuliniowe,Bilinear,,Biliniar,Билинейная,Билинеарно -Trilinear,OPTVAL_TRILINEAR,,,,Trilineární,,,Trilinia,Trilineal,,Trilineaarinen,Trilinéaire,Trilineáris,Trilineare,トライリニア,삼선형,Trilineair,Trzyliniowe,Trilinear,,Triliniar,Трилинейная,Трилинеарно -2x,OPTVAL_2X,,,,,,,2-oble,,,,,,,,,,,2x,,,, -4x,OPTVAL_4X,,,,,,,4-oble,,,,,,,,,,,4x,,,, -8x,OPTVAL_8X,,,,,,,8-oble,,,,,,,,,,,8x,,,, -16x,OPTVAL_16X,,,,,,,16-oble,,,,,,,,,,,16x,,,, -32x,OPTVAL_32X,,,,,,,32-oble,,,,,,,,,,,32x,,,, -Texture Options,GLTEXMNU_TITLE,,,,Nastavení textur,Texturoptionen,,Agordoj de Teksturoj,Opciones de texturas,,Pintakuviointiasetukset,Options Textures,Textúra Beállítások,Opzioni Texture,テクスチャー オプション,텍스쳐 설정,Textuur Opties,Opcje Tekstur,Opções de Textura,,Setări Texturi,Настройки текстур,Подешавања текстура -Textures enabled,GLTEXMNU_TEXENABLED,,,,Povolit textury,Texturen an,,Teksturoj ŝaltitaj,Texturas activadas,,Pintakuvioinnit otettu käyttöön,Textures activées,Textúrák bekapcsolása,Texture abilitate,テクスチャー有効,텍스쳐 사용,Texturen ingeschakeld,Tekstury włączone,Texturas ativadas,,Texturi Activate,Включить текстуры,Текстуре омогућене -Enable hires textures,GLTEXMNU_ENABLEHIRES,,,,Povolit textury ve vysokém rozlišení,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,Włącz tekstury wysokiej jakości,Habilitar texturas de alta resolução,,Texturi de înaltă rezoluție,Текстуры с высоким разрешением,Омогући текстуре велике резолуције -High Quality Resize mode,GLTEXMNU_HQRESIZE,,,,Režim zvětšovače textur,Texturskalierungsmodus,,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,Tryb Wysokiej Jakości Zmieniania Rozmiaru,Modo de Redimensionamento de Alta Qualidade,,Mod Redimensionare de Înaltă Calitate,Масштабирование текстур,Промена величине високог квалитета мод -High Quality Resize multiplier,GLTEXMNU_HQRESIZEMULT,,,,Faktor zvětšovače textur,Texturskaluerungsfaktor,,Skalilo Obligilo,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,Mnożnik Wysokiej Jakośći Rozmiaru,Multiplicador de Redimensionamento de Alta Qualidade,,Factor de Scalare,Множитель масштабирования,Промена величине високог квалитета мултипликатор -This mode requires %d times more video memory,GLTEXMNU_HQRESIZEWARN,,,,Tento režim potřebuje %dkrát více paměti,Dieser Modus benötigt das %d-fache an Videospeicher,,Tio reĝimo bezonas %d-oble pli ekranmemoron.,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.,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 пута више видео меморије -Resize textures,GLTEXMNU_RESIZETEX,,,,Škálovat textury,Texturen skalieren,,Regrandigi teksturojn,Ajustar texturas,,Muuta pintakuviointien kokoa,Mise à l'échelle textures,Textúrák újraméretezése,Resize delle texture,リサイズ テクスチャー,텍스쳐 리사이징,Texturen schalen,Zmień rozmiar tekstur,Redimensionar texturas,,Redimensionare texturi,Масштабирование текстур,Промена величине текстура -Resize sprites,GLTEXMNU_RESIZESPR,,,,Škálovat sprity,Sprites skalieren,,Regrandigi spritojn,Ajustar sprites,,Muuta spritejen kokoa,Mise à l'échelle sprites,Sprite-ok újraméretezése,Resize degli sprite,リサイズ スプライト,스프라이트 리사이징,Sprites schalen,Zmień rozmiar sprite'ów,Redimensionar sprites,,Redimensionare sprite-uri,Масштабирование спрайтов,Промена величине спрајтова -Resize fonts,GLTEXMNU_RESIZEFNT,,,,Škálovat fonty,Zeichensätze skalieren,,Regrandigi tiparojn,Ajustar fuentes,,Muuta kirjasinten kokoa,Mise à l'échelle texte,Betűk újraméretezése,Resize dei font,リサイズ フォント,폰트 리사이징,Lettertypen schalen,Zmień rozmiar czcionek,Redimensionar fontes,,Redimensionare fonturi,Масштабирование шрифтов,Промена величине фонта -Resize model skins,GLTEXMNU_RESIZESKN,,,,Škálovat skiny modelů,,,Regrandigi haŭtojn de modeloj,Ajustar texturas de modelo,,Muuta ulkoasujen kokoa,,Model fazon újraméretezése,,,,,,Redimensionar skins de modelos,,Redimensionare modele,, -Precache GL textures,GLTEXMNU_PRECACHETEX,,,,Přednačíst GL textury do cache,GL Texturen zwischenspeichern,,Antaŭkaŝmemorigi GL-teksturojn,Precaché de texturas GL,,Kirjoita GL-pintakuvioinnit välimuistiin,Mise en cache des textures,,Precache texture GL,プリキャッシュ GLテクスチャー,지엘 텍스쳐 미리 캐싱함,Precache GL texturen,Tekstury GL pamięci podręcznej,Precachê de texturas GL,,Preîncărcarcă texturile GL,Кэшировать GL-текстуры,Прикеширане GL текстуре -Video Mode,VIDMNU_TITLE,,,,Režim displeje,Videomodus,,Video-Reĝimo,Modos de video,,Videotila,Mode Vidéo,Videó mód,Modalità video,ビデオ 調整,화면 설정,Videomodus,Tryb Wideo,Modo de vídeo,,Mod Video,Настройки видеорежима,Видео мод -Notebook Switchable GPU,DSPLYMNU_GPUSWITCH,,,,Přepínatelné GPU pro notebooky,GPU Umschaltung für Notebooks,,Kajero-Ŝanĝebla GPU,GPU Altern. 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,Zmiana GPU Notebooka,Placa de vídeo alternável de notebook,,Placă Video Alternativă pentru Notebook,Использование GPU ноутбука,Користи GPU ноутбук -Scaled (Nearest),OPTVAL_SCALENEAREST,,,,Škálován (nejbližší),Skaliert (nächster Nachbar),,Skalita (Plej proksime),Escalado (Cercano),,Skaalattu (läheisin),Mis à l'échelle (Proche Voisin),Átméretezett (Közeli),Scalato (più vicino),スケーリング (最寄り),확대 (가깝게),Geschaald (Dichtstbijzijnd),Przeskalowany (Najbliższy),Redimensionado (mais próximo),Redimensionado (Apróximado),Redimensionat (Cel mai aproape),Масштабировать (ближайшее),Скалиран (најближи) -Scaled (Linear),OPTVAL_SCALELINEAR,,,,Škálován (lineární),Skaliert(linear),,Skalita (Linia),Escalado (Lineal),,Skaalattu (lineaarinen),Mis à l'échelle (Linéaire),Átméretezett (Lineáris),Scalato (lineare),スケーリング (リニア),확대 (선형 식),Geschaald (Lineair),Przeskalowany (Liniowy),Redimensionado (linear),,Redimensionat (Liniar),Масштабировать (линейное),Скалиран (линеарно) -Letterbox,OPTVAL_LETTERBOX,,,,,,,Leterkesto,Barras Negras,,Mustat reunat,,Levágott,Bande nere,レターボックス,레터박스,Brievenbus,,Barras pretas,,Ecran Parțial,Экранное каше,Поштанско сандуче -Stretch,OPTVAL_STRETCH,,,,Roztažený,Strecken,,Streĉi,Estrechado,Estrecho,Venytetty,Etirer,Nyújtott,Disteso,伸縮,늘림,Rek,Rozciągnięty,Esticado,,Lărgire,Растянутый,Растегнуто -Render Mode,VIDMNU_RENDERMODE,,,,Režim renderování,Rendermodus,,Bildigo-Reĝimo,Modo de Renderizado,,Hahmonnustila,Mode de Rendu,Render Mód,Modalità motore grafico,レンダラー,렌더링 설정,Rendermodus,Tryb Renderowania,Modo de renderização,,Mod Video,Режим рендеринга,Рендер мод -Fullscreen,VIDMNU_FULLSCREEN,,,,Přes celou obrazovku,Vollbild,,Plena ekrano,Pantalla completa,,Koko näyttö,Plein écran,Teljes Képernyő,Schermata piena,全画面,전체화면,Volledig scherm,Pełen Ekran,Tela cheia,Ecrã cheio,Ecran Complet,Полный экран,Цео екран -Retina/HiDPI support,VIDMNU_HIDPI,,,,Podpora Retiny/HiDPI,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,Wsparcie Retina/HiDPI,Suporte para Retina/HiDPI,,Suport Retina/HiDPI,Поддержка Retina/HiDPI,Retina/HiDPI подршка -Aspect ratio,VIDMNU_ASPECTRATIO,,,,Poměr stran,Seitenverhältnis,,Ekran-proporcio,Relación de aspecto,,Kuvasuhde,Rapport D'Aspect,Képarány,Proporzioni,アスペクト比,종횡비,Beeldverhouding,Wpółczynnik proporcji,Proporção de tela,Proporção de ecrã,Aspect Imagine,Соотношение сторон,Однос гледишта -Force aspect ratio,VIDMNU_FORCEASPECT,,,,Vynutit poměr stran,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,アスペクト比に従う,강제 종횡비,Geforceerde beeldverhouding,Wymuś współczynnik proporcji,Forçar proporção de tela,Forçar proporcção de ecrã,Forțează aspectul imaginii,Принудительное соотношение сторон,Присили однос гледишта -Forced ratio style,VIDMNU_CROPASPECT,,,,Vynucený poměr stran,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,Wymuszony styl współczynnika,Estilo de proporção forçado,,Forțează tipul proporțiilor,Тип принудительного соотношения сторон,Присиљен стил односа -Enable 5:4 aspect ratio,VIDMNU_5X4ASPECTRATIO,,,,Povolit poměr stran 5:4,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,Włącz współczynnik proporcji 5:4,Ativar proporção de tela 5:4,,Activează formatul 5:4,Включить соотношение сторон 5:4,Омогући 5:4 однос гледишта -Resolution scale,VIDMNU_SCALEMODE,,,,Škálování rozlišení,Skalierung,,Distingivo-skalo,Escala de Resolución,,Resoluution skaalaus,Echelle de Résolution,Felbontás mérete,Scala di risoluzione,画面スケール,해상도 크기,Resolutieschaal,Skala rozdzielczości,Escala de resolução,,Scară rezoluție,Масштабирование,Резолуцијска скала -Scale Factor,VIDMNU_SCALEFACTOR,,,,Faktor rozlišení,Skalierungsfaktor,,Skalfaktoro,Factor de Escala,,Skaalauskerroin,Facteur d'échelle,Méretezési Faktor,Fattore di scala,スケール倍率,축척 펙터,Schaalfactor,Współczynnik Skali,Fator de escala,,Factor Scalare,Значение масштаба,Фактор скалирања -Use Linear Scaling (Fullscreen),VIDMNU_USELINEAR,,,,Použít lineární škálování (přes celou obrazovku),Lineare Skalierung (Vollbild),,Uzi Linian Skaladon (Plena ekrano),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),Użyj Liniowego Skalowania (Pełen Ekran),Usar escala linear (tela cheia),Usar escala linear (ecrã cheio),Folosește Scalarea Liniară (Ecran Complet),Линейное масштабирование (полный экран),Користи линеарно скалирање (цео екран) -Custom Pixel Scaling,VIDMNU_CUSTOMRES,,,,Vlastní škálování pixelů,Benutzerdefinierte Skalierung,,Adaptita Bildero-Skalo,Escalado de Pixel Personalizado,,Mukautettu skaalaus,Résolution Personalisée,Egyéni Pixelméretezés,Scaling dei pixel personalizzato,カスタム ピクセルスケール,사용자 지정 픽셀 크기 조정,Aangepaste pixelschaalvergroting,Niestandardowe Skalowanie Pikseli,Escala de pixels personalizada,,Scară Pixeli Personalizată,Масштабирование пикселов,Пиксел скалирање -Custom Width,VIDMNU_CUSTOMX,,,,Vlastní šířka,Benutzerdefinierte Breite,,Adaptita Larĝo,Ancho Personalizado,,Mukautettu leveys,Largeur Personalisée,Egyéni szélesség,Lunghezza,カスタム 幅,사용자 지정 너비,Aangepaste breedte,Niestandardowa Szerokość,Largura personalizada,,Lățime Personalizată,Длина,Ширина -Custom Height,VIDMNU_CUSTOMY,,,,Vlastní výška,Benutzerdefinierte Höhe,,Adaptita Alto,Alto Personalizado,,Mukautettu korkeus,Hauteur Personalisée,Egyéni magasság,Altezza,カスタム 高さ,사용자 지정 높이,Aangepaste hoogte,Niestandardowa Wysokość,Altura personalizada,,Înălțime Personalizată,Высота,Висина -Apply Changes (Windowed),VIDMNU_APPLYW,,,,Použít změny (v okně),Änderungen anwenden (Fenster),,Apliki Ŝanĝojn (Fenestrito),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),Zatwierdź Zmiany (Okno),Aplicar alterações (janela),,Aplică Schimbările (Mod Fereastră),Сохранить изменения (оконный режим),Примени промене (прозор) -Apply Changes (Fullscreen),VIDMNU_APPLYFS,,,,Použít změny (přes celou obrazovku),Änderungen anwenden (Vollbild),,Apliki Ŝanĝojn (Plena ekrano),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),Zatwierdź Zmiany (Pełen Ekran),Aplicar alterações (tela cheia),Aplicar alterações (ecrã cheio),Aplică Schimbările (Mod Ecran Complet),Сохранить изменения (полный экран),Примени промене (цели екран) -Choose Resolution Preset,VIDMNU_RESPRESET,,,,Vybrat přednastavené rozlišení,Auflösungsvoreinstellung,,Elektu Agordaĵon por Distingivo,Seleccionar Preset de Resolución,,Valitse ennalta määritetty resoluutio,Choisir paramètre personalisé,Felbontási Sablon Kiválasztása,Scegli preset di risoluzione,解像度プリセットを選ぶ,해상도 사전 설정 선택,Kies een vooraf ingestelde resolutie,Wybierz Zestaw Rozdzielczości,Escolher resolução predefinida,,Alege Rezoluția Predefinită,Выбор пресета разрешения,Резолуцијска подешавања -Custom Resolution Presets,VIDMNU_RESPRESETTTL,,,,Vlastní přednastavení rozlišení,Benutzerdefinierte Auflösungsvoreinstellungen,,Adaptitaj Antaŭagordoj por Distingivo,Seleccionar Preset de Resoluciones,,Ennalta määritetyt mukautetut resoluutiot,Résolutions Personalisée,Egyéni Felbontási Sablonok,Preset di risoluzione personalizzati,カスタム解像度プリセット,사용자 지정 해상도 미리 조정,Vooraf ingestelde aangepaste resoluties,Niestandardowe Zestawy Rozdzielczości,Predefinições de resolução personalizadas,,Rezoluții Personalizate,Пользовательские пресеты,Резолуцијска подешавања -Preset Resolution Modes,VIDMNU_RESPRESETHEAD,,,,Přednastavená rozlišení,Vordefinierte Auflösungsmodi,,Antaŭagordaj Distingivo-Reĝimoj,Modos de Preset de Resolución,,Ennalta määritetyt resoluutiotilat,Choisir mode de Résolution,Felbontási Sablon Módok,Modalità preset di risoluzione,解像度モードの調整,해상도 미리 조정 모드,Vooraf ingestelde resolutiemodi,Tryby Zestawów Rozdzielczości,Modos de resolução predefinidas,,Rezoluții Predefinite,Доступные разрешения,Постављени резолуцијски модови -4:3 Aspect,VIDMNU_ASPECT43,,,,Poměr stran 4:3,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,Proporcje 4:3,Proporção 4:3,,Aspect 4:3,Соотношение сторон 4:3,4:3 гледиште -5:4 Aspect,VIDMNU_ASPECT54,,,,Poměr stran 5:4,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,Proporcje 5:4,Proporção 5:4,,Aspect 5:4,Соотношение сторон 5:4,5:4 гледиште -16:9 Aspect,VIDMNU_ASPECT169,,,,Poměr stran 16:9,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,Proporcje 16:9,Proporção 16:9,,Aspect 16:9,Соотношение сторон 16:9,16:9 гледиште -16:10 Aspect,VIDMNU_ASPECT1610,,,,Poměr stran 16:10,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,Proporcje 16:10,Proporção 16:10,,Aspect 16:10,Соотношение сторон 16:10,16:10 гледиште -21:9 Aspect,VIDMNU_ASPECT219,,,,Poměr stran 21:9,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,Proporcje 21:9,Proporção 21:9,,Aspect 21:9,Соотношение сторон 21:9,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,Kleinstmögliche Auflösung,,Plej Malpli Ebla Skalo,Menor Escala Posible,,Pienin mahdollinen skaalaus,Echelle la plus faible,Lehető legkisebb méret,,可能な限り最小,,Laagst mogelijk schaal,Najniższa możliwa skala,Menor escala possível,,Cea mai Mică Scară Posibilă,, -Custom,OPTVAL_CUSTOM,,,,Vlastní,Benutzerdefiniert,,Adaptita,Personalizado,,Mukautettu,Modifié,Egyéni,Personalizzato,カスタム,사용자 지정,Gebruikergedefinieerd,Niestandardowe,Personalizado,,Personalizat,Польз.,Прилагођ. -Max FPS,VIDMNU_MAXFPS,,,,Maximální FPS,,,Maksimumaj Kadroj Sekunde,Límite de FPS,,Kuvataajuuden rajoitin,,,,最大FPS値,,Max FPS,Maksymalna ilość klatek,FPS máximo,,Cadre pe secundă,, -60 fps,OPTVAL_60FPS,,,,,,,,,,60 kuvaa/s,,,,,,,,60 FPS,,,, -75 fps,OPTVAL_75FPS,,,,,,,,,,75 kuvaa/s,,,,,,,,75 FPS,,,, -90 fps,OPTVAL_90FPS,,,,,,,,,,90 kuvaa/s,,,,,,,,90 FPS,,,, -120 fps,OPTVAL_120FPS,,,,,,,,,,120 kuvaa/s,,,,,,,,120 FPS,,,, -144 fps,OPTVAL_144FPS,,,,,,,,,,144 kuvaa/s,,,,,,,,144 FPS,,,, -200 fps,OPTVAL_200FPS,,,,,,,,,,200 kuvaa/s,,,,,,,,200 FPS,,,, -Preferred Rendering API,VIDMNU_PREFERBACKEND,,,,Upřednostňované renderovací 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,Preferowany interfejs API renderowania,API de renderização preferida,,API Video Preferat,Предпочтительный интерфейс рендеринга,Преферред АПИ приказивања -OpenGL,OPTVAL_OPENGL,,,,,,,,,,,,,,,,,,OpenGL,,,, -Vulkan,OPTVAL_VULKAN,,,,,,,,,,,,,,,,,,Vulkan,,,, -SoftPoly,OPTVAL_SOFTPOLY,,,,,,,,,,,,,,,,,,SoftPoly,,,, -,,Miscellaneous Options,,,,,,,,,,,,,,,,,,,,, -Miscellaneous Options,MISCMNU_TITLE,,,,Ostatní nastavení,Verschiedene Optionen,,Diversaĵaj Agordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni miste,その他のオプション,그 외 설정,Diverse opties,Różne Opcje,Outras opções,,Setări Suplimentare,Дополнительные настройки,Разна подешавања -Merge left+right Alt/Ctrl/Shift,MISCMNU_MERGEKEYS,,,,Zkombinovat pravý a levý Alt/Ctrl/Shift,Linke und rechte Umschalt/Strg/Alt zusammenfassen,,Kunigi maldekstran+dekstran Alt/Ctrl/Shift,Combinar izq.+der. Alt/Ctrl/Mayús,,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,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 -Alt-Enter toggles fullscreen,MISCMNU_WINFULLSCREENTOGGLE,,,,Alt-Enter přepíná celou obrazovku,Alt-Enter schaltet Vollbild an/aus,,Alt+Enter klavo 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 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 пребацује на цео екран -Command-F toggles fullscreen,MISCMNU_MACFULLSCREENTOGGLE,,,,Command-F přepíná celou obrazovku,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,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 пребацује на цео екран -Enable autosaves,MISCMNU_ENABLEAUTOSAVES,,,,Povolit automatické ukládání,Automatisches Speichern,,Ŝalti aŭtokonservojn,Activar autoguardado,,Ota käyttöön automaattiset tallennukset,Activer Sauvegardes auto,Automentések engedélyezése,Abilita i salvataggi automatici,オートセーブを有効化,빠른 저장 허용,Automatisch opslaan inschakelen,Włącz autozapis,Ativar salvamento automático,Permitir gravação automática,Permite salvări automate,Автосохранения,Омогући аутосејвове -Number of autosaves,MISCMNU_AUTOSAVECOUNT,,,,Počet automatických uložených her,Anzahl von automatischen Speicherständen,,Kvanto da aŭtokonservoj,Número de autoguardados,,Automaattisten tallennusten lukumäärä,Total de sauvegardes auto,Automentések száma,Numero di salvataggi automatici,オートセーブの最大数,빠른 저장 수,Aantal auto-opslagen,Liczba autozapisów,Número de salvamentos automáticos,Número de gravações automáticos,Număr salvări automate,Количество автосохранений,Број аутоматских чувања -Save/Load confirmation,MISCMNU_SAVELOADCONFIRMATION,,,,Potvrzení o uložení/načtení,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,Potwierdzenie zapisu/wczytania,Confirmação ao salvar/carregar,Confirmação ao gravar/carregar,Dialog de confirmare la Salvare/Încărcare,Подтверждение при сохранении/загрузке,Потврђивање током чувања/учитавања -Disable keyboard cheats,MISCMNU_NOCHEATS,,,,Vypnout cheaty z klávesnice,Tastatur-Cheats deaktivieren,,Malvalidigi klavarajn trompojn,Desactivar trucos por teclado,,Poista näppäinhuijaukset,,Billentyűs csalások letiltása,,キーボードからのチート無効,,Schakel cheats uit,Wyłącz Oszustwa z Klawiatury,Desativar trapaças de teclado,,Dezactivează codurile din tastatură,, -Quicksave rotation,MISCMNU_QUICKSAVEROTATION,,,,Rotace rychle uložených her,Schnellspeicherrotation,,Rotacio de rapidkonservo,Rotación de Salvado Rápido,,Pikatallennuskierto,Rotation Sauvegardes Rapides,Gyorsmentés forgás,Rotazione rapide della quicksave,クイックセーブ間隔,빠른 저장 간격,Rouleer snelopslag,Rotacja szybkich zapisów,Rotação de salvamentos rápidos,,Rotație salvări automate,Чередовать слоты для быстрых сохранений,Окретање брзих чувања -Number of quicksaves in rotation,MISCMNU_QUICKSAVECOUNT,,,,Počet rychle uložených her v rotaci,Anzahl Schnellspeicherplätze,,Nombro da rapidkonservitaj ludoj en rotaciado,Número de Salvados Rápidos en Rotación,,Pikatallennusten määrä kierrossa,Nombre de sauvegardes en rotation,Gyorsmentések száma a forgásban,Numero di quicksaves in rotazione,間隔クイックセーブの数,빠른 저장 간격의 수,Aantal roulerende snelopslagplekken,Ilość szybkich zapisów w rotacji,Número de salvamentos rápidos em rotação,,Număr salvări rapide în rotație,Кол-во слотов для быстрых сохранений,Број брзих чувања у окретању -Disable Menu Clean Scaling,MISCMNU_CLEANMENU,,,,Zakázat čisté škálování nabídek,Gleichmäßige Menüskalierung deaktivieren,,Malebligi Puran Skaladon en Menuoj,,,Poista käytöstä valikon siisti skaalautuminen,Ne pas utilisé mise à l'échelle menu propre,,,メニュー画面を伸縮させない,,Schakel uniforme menuschaling uit,Wyłącz Czyste Skalowanie Menu,Desativar escala limpa do menu,,Dezactivează Scara Nouă a Meniurilor,, -Default Crosshair,HUDMNU_CROSSHAIR,,,,Výchozí zaměřovač,Standard-Fadenkreuz,,Defaŭlta Reteto,Retícula por defecto,,Oletustähtäin,Viseur par défaut,Alap célkereszt,Mirino di default,デフォルトの照準,기본 조준점,Standaard dradenkruis,Domyślny celownik,Mira padrão,,Țintă implicită,Тип прицела,Уобичајени нишан -Crosshair color,HUDMNU_CROSSHAIRCOLOR,,,Crosshair colour,Barva zaměřovače,Fadenkreuzfarbe,,Retetokoloro,Color de la retícula,,Tähtäimen väri,Couleur Viseur,Célkereszt színe,Colore mirino,照準色,조준점 색깔,Dradenkruis kleur,Kolor celownika,Cor da mira,,Culoare țintă,Цвет прицела,Боја нишана -Crosshair shows health,HUDMNU_CROSSHAIRHEALTH,,,,Zaměřovač zobrazuje zdraví,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,Celownik pokazuje zdrowie,Mostrar saúde na mira,Mostra vida na mira,Ținta afișează starea sănătății,Цвет прицела по состоянию здоровья,Нишан приказује здравље -Scale crosshair,HUDMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,Fadenkreuz skalieren,,Skali reteton,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,Célkereszt mérete,Scala del mirino,照準サイズ,조준점 크기,Dradenkruis schalen,Skala celownika,Redimensionar mira,,Dimensiune țintă,Масштабирование прицела,Размера нишана -Standard,OPTVAL_YES_STANDARD,copied from elsewhere,,,Standardní,,Πρότυπο,Norma,Estándar,,Normaali,,Alap,,標準,기본,Standaard,Standard,Padrão,,,Стандартный,Стандардни -Enhanced,OPTVAL_YES_ENHANCED,,,,Vylepšené,Verbessert,Ενισχυομένο,Bonigita,Mejorado,,Paranneltu,Amélioré,Fejlesztett,Migliorata,強調,고급,Verbeterd,Ulepszone,Melhorado,,Îmbunătățită,Улучшенный,Побољшани -Language,OPTMNU_LANGUAGE,,,,Jazyk,Sprache,Γλώσσα,Lingvo,Idioma,,Kieli,Langage,Nyelv,Lingua,言語設定,언어,Taal,Język,Idioma,,Limbă,Язык,Језик -,,Reverb editor,,,,,,,,,,,,,,,,,,,,, -Undo Changes,TXT_UNDOCHANGES,,,,Zrušit změny,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,Cofnij Zmiany,Desfazer alterações,,Anulează Modificările,Отменить изменения,Поништи промене -Select Environment,REVMNU_SELECT,,,,Vybrat prostředí,Umgebung wählen,Επιλογή Περιβάλλοντος,Elekti Medion,Seleccionar Ambiente,,Valitse tila,Sélectionner un environnement,Környezet Kiválasztása,Seleziona ambiente,反響選択,환경 선택,Selecteer omgeving,Wybierz Środowisko,Selecione o ambiente,,Alegere Mediu,Выбрать окружение,Изабери окружење -Test Environment,REVMNU_TEST,,,,Testovat prostředí,Umgebung testen,Δοκιμαστκό Περιβάλλον,Provi Medion,Probar Ambiente,,Testaa tilaa,Tester un environnement,Környezet Tesztelése,Testare ambiente,反響テスト,환경 테스트,Test omgeving,Testuj Środowisko,Testar ambiente,,Testare Mediu,Тестировать окружение,Тестирај окружење -Edit Environment,REVMNU_EDIT,,,,Upravit prostředí,Umgebung editieren,Επεξεργασία Περιβάλλοντος,Modifi Medion,Editar Ambiente,,Muokkaa tilaa,Modifier un environnement,Környezet Szerkesztése,Modifica ambiente,反響編集,환경 편집,Omgeving bewerken,Edytuj Środowisko,Editar ambiente,,Editare Mediu,Редактировать окружение,Уреди окружење -New Environment,REVMNU_NEW,,,,Nové prostředí,Neue Umgebung,Νέο Περιβάλλον,Nova Medio,Nuevo Ambiente,,Uusi tila,Nouveau environnement,Új Környezet,Nuovo ambiente,新規反響設定,새로운 환경 생성,Nieuwe omgeving,Nowe Środowisko,Novo ambiente,,Mediu Nou,Новое окружение,Ново окружење -Revert settings,REVMNU_REVERT,,,,Obnovit nastavení,Zurücksetzen,Επαναφορά Ρυθμίσεων,Malfari agordojn,Revertir Configuración,,Palauta asetukset,Réinitialiser les paramètres,Változtatások elvetése,Ripristina impostazioni,設定を戻す,설정 되돌리기,Instellingen terugzetten,Przywróć ustawienia,Reverter configurações,,Revenire la setările precedente,Настройки по умолчанию,Врати подешавања -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,,,反響サイズ,공간 크기,,Rozmiar Środowiska,Tamanho do ambiente,,,, -Environment Diffusion,REVMNU_ENVIRONMENT_DIFFUSION,,,,,,Διάχυση Περιβάλλοντος,Medidifuzo,Difusión de Ambiente,,Tilan äänen hajautuminen,Diffusion Environnement,,,反響伝播,공간 잔향 확산,,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,,,,,,,Aerabsorbo 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 Refrenco,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 Refrenco,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,Basierend auf,Βασισμένο σε,Bazita de,Basado En,,Perustana,Basé sur,Minta,Basato su,音響の元,음향 원본,Gebaseerd op,Bazowane na,Baseado em,,Bazat pe,Основано на,Засновано на -Name,REVMNU_Name,,,,Název,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Name,名前,이름,Naam,Nazwa,Nome,,Nume,Название,Назив -ID #1,REVMNU_ID_1,,,,,,ID #1,ID #1,ID Nº1,,,,,,,아이디 #1,,ID #1,ID #1,,,, -ID #2,REVMNU_ID_2,,,,,,ID #2,ID #2,ID Nº2,,,,,,,아이디 #2,,ID #2,ID #2,,,, -Create,REVMNU_Create,,,,Vytvořit,Erstellen,Δημιουργία,Krei,Crear,,Luo,Créer,Készítés,Creare,作成,생성,Aanmaken,Stwórz,Criar,,Creare,Создать,Направи -Save...,REVMNU_Save,,,,Uložit...,Speichern...,Αποθήκευση,Konservi...,Guardar...,,Tallenna...,Sauvegarder...,Mentés,Salvare...,セーブする...,저장 하기...,Opslaan...,Zapisz...,Salvar...,,Salvare...,Сохранить...,Сачувај... -File name,REVMNU_File_name,,,,Název souboru,Dateiname,Όνομα αρχείου,Dosiernomo,Nombre de Archivo,,Tiedostonimi,Nom de fichier,Fájlnév,Nome del file,ファイル名,파일 이름,Bestandsnaam,Nazwa pliku,Nome do arquivo,,Nume fișier,Название файла,Назив фајла -Environments to save,REVMNU_Environments_to_save,,,,Prostředí k uložení,Zu speichernde Umgebungen,Περιβάλλοντα για αποθήκευση,Medioj por konservi,Ambientes para Guardar,,Tallennettavat tilat,Environnements à sauvegarder,Mentendő Környezetek,Ambienti da salvare,音響を保存,저장할 공간,Omgevingen om op te slaan,Środowiska do zapisu,Ambientes para salvar,,Medii de salvat,Сохранить окружения...,Окружења за чување -,,Vulkan,,,,,,,,,,,,,,,,,,,,, -Vulkan Options (Experimental),DSPLYMNU_VKOPT,,,,Nastavení Vulkanu (Experimentální),Vulkan Optionen (Experimentell),Vulka Ρυθμίσεις (Πειραματικές),Vulkan Agordoj (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),Opcje Vulkan (Eksperymentalne),Opções de Vulkan (experimental),,Setări Mod Vulkan (În curs de testare),Настройки Vulkan (экспериментальные),Vulkan подешавања (експериментална) -Vulkan Options,VK_TITLE,,,,Nastavení Vulkanu,Vulkan Optionen,Vulkan Ρυθμίσεις,Vulkan Agordoj,Opciones de Vulkan,,Vulkan-asetukset,Options Vulkan (Expérimental),Vulkan Beállítások,Opzioni Vulkan,Vulkan機能オプション,벌칸 설정,Vulkan-opties,Opcje Vulkan,Opções de Vulkan,,Setări Mod Vulkan,Настройки Vulkan,Vulkan подешавања -Enable Vulkan,VKMNU_ENABLE,,,,Povolit Vulkan,Aktiviere Vulkan,Ενεργοποιηση του Vulkan,Ŝalti Vulkan,Activar Vulkan,,Ota käyttöön Vulkan,Activer Vulkan,Vulkan Engedélyezése,Abilita Vulkan,Vulkanを有効化,벌칸 렌더러 사용,Vulkan inschakelen,Włącz Vulkan,Ativar Vulkan,,Activează modul video Vulkan,Включить Vulkan,Омогући Vulkan -Vulkan Device ID,VKMNU_DEVICE,,,,ID zařízení Vulkanu,Vulkan Geräte ID,Vulkan ID Συσκευής,Vulkan Aparato ID,ID de Dispositivo Vulkan,,Vulkan-laitetunniste,ID du périphérique Vulkan,Vulkan Eszköz ID,Dispositivo ID Vulkan,Vulkanデバイス ID,벌칸 장치 아이디,Vulkan apparaat-ID,ID urządzenia Vulkan,ID do dispositivo Vulkan,,ID Dispozitiv Vulkan,ID устройства Vulkan,Vulkan ID уређаја -High Dynamic Range,VKMNU_HDR,,,,Vysoký dynamický rozsah (HDR),,Υψηλό Δυναμική Εμβέλεια,Alta Dinamika Intervalo,Alto Rango Dinámico,,Korkea dynamiikka-alue (HDR),,,,ハイダイナミックレンジ,하이 다이나믹 레인지,Hoog dynamisch bereik,Obraz HDR,Alto alcance dinâmico (HDR),,HDR,HDR,HDR -Warning: The Vulkan renderer is highly experimental!,VK_WARNING,,,,Varování: Vulkan renderer je velmi experimentální!,Achtung: Der Vulkan Renderer ist noch sehr experimentell!,Προειδοποίηση: Ο Vulkan renderer είναι υψηλά πειραματικός!,Averto: La Vulkan bildigilo 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!,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 рендерер је врло експерименталан! -These options will require a restart to take effect.,VK_RESTART,,,,Tato nastavení vyžadují restart hry.,Diese Option erfordert einen Neustart!,Αυτές η ρυθμίσεις θα χρειαστούνε επανεκκίνηση για να ισχύσουν,Ĉi tiuj agordoj bezonos rekomencon 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.,"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 да би промене ступиле на снагу. -Select Vulkan Device,VKMNU_DEVICESELECT,This is not yet implemented - but it is planned,,,Vyber zařízení Vulkanu,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,Wybierz Urządzenie Vulkan,Selecione o dispositivo Vulkan,,Selectare Dispozitiv Vulkan,Выберите устройство Vulkan,Изаберите Vulkan уређај -,,Texture scaling,,,,,,,,,,,,,,,,,,,,, -ScaleNx,OPTVAL_SCALENX,,,,,,,,,,,,,,,,,,ScaleNx,,,, -NormalNx,OPTVAL_NORMALNX,,,,,,,,,,,,,,,,,,NormalNx,,,, -hqNx,OPTVAL_HQNX,,,,,,,,,,,,,,,,,,hqNx,,,, -hqNx MMX,OPTVAL_HQNXMMX,,,,,,,,,,,,,,,,,,hqNx MMX,,,, -xBRZ,OPTVAL_NXBRZ,,,,,,,,,,,,,,,,,,xBRZ,,,, -Old xBRZ,OPTVAL_OLD_NXBRZ,,,,xBRZ (starší),xBRZ alt,Παλίο xBRZ,Malnova xBRZ,Antíguo xBRZ,,Vanha xBRZ,Ancien xBRZ,Régi xBRZ,Vecchio xBRZ,旧xBRZ,구형 xBRZ,Oud xBRZ,Stare xBRZ,Antigo xBRZ,,Vechiul xBRZ,Старый xBRZ,Стари xBRZ -,,Option Search,,,,,,,,,,,,,,,,,,,,, -Option Search,OS_TITLE,,,,Vyhledávání možností,Optionssuche,Αναζήτηση Ρυθμίσεων,Agorda Serĉo,Buscar Opciones,,Asetushaku,Recherche Option,Beállítások keresése,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага -Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,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,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било који термин -Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,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,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи сваки термин -No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniuj rezultoj trovitaj.,Ningun resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результатов не найдено.,Нема резултата. -Search:,OS_LABEL,,,,Hledat:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Szukaj:,Busca:,Procura:,Caută:,Поиск:,Претрага: -,,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 hat %o zerlegt wie einen Fisch,Ο/Η %k ξεκοκάλοσε @[pro2_gr] %o σα ψάρι,%k senostigis %o kiel fiŝo,%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 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 castrated %o,TXT_OBITUARY2,,,,%o byl@[ao_cs] vykastrován@[ao_cs] hráčem %k,%k hat %o kastriert,Ο/Η %k ευνούχισε %o,%k kastris %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 wykastrował@[ao_pl] %o,%k castrou %o,,%k l-a castrat pe %o,Игрок %k кастрировал игрока %o,%k је кастрирао %o -%k creamed %o,TXT_OBITUARY3,,,,%o byl@[ao_cs] rozšlehán@[ao_cs] hráčem %k,%k hat %o eingeseift,Ο/Η %k κρέμασε @[pro2_gr] %o,%k kremigis %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 spienił@[ao_pl] %o,%k fez creme de %o,,%k l-a transformat în cremă pe %o,Игрок %k взбил игрока %o,%k је истукао %o -%k decimated %o,TXT_OBITUARY4,,,,%o byl@[ao_cs] zdecimován@[ao_cs] hráčem %k,%k hat %o dezimiert,Ο/Η %k αποδεκάτισε @[pro2_gr] %o,%k detruegis %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 przetrzebił@[ao_pl] %o,%k decimou %o,,%k l-a decimat pe %o,Игрок %k скосил игрока %o,%k је десетковао %o -%k destroyed %o,TXT_OBITUARY5,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k hat %o zerstört,Ο/Η %k κατέστεψε @[pro2_gr] %o,%k detruis %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 zniszczył@[ao_pl] %o,%k destruiu %o,,%k l-a distrus pe %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 hat %o in Würfel zerteilt,Ο/Η %k τεμάχησε @[pro2_gr] %o,%k diskubigis %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 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 disembowled %o,TXT_OBITUARY7,,,,%o byl@[ao_cs] vykuchán@[ao_cs] hráčem %k,%k hat %o ausgeweidet,Ο/Η %k ισοπέδοσε @[pro2_gr] %o,%k sentripigis %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 wypatroszył@[ao_pl] %o,%k estripou %o,,%k l-a eviscerat pe %o,Игрок %k выпотрошил игрока %o,%k је ампутирао %o -%k flattened %o,TXT_OBITUARY8,,,,%o byl@[ao_cs] zplacatěn@[ao_cs] hráčem %k,%k hat %o dem Erdboden gleichgemacht,Ο/Η %k ησοπέδοσε @[pro2_gr] %o,%k platigis %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 rozpłaszczył@[ao_pl] %o,%k achatou %o,%k espalmou %o,%k l-a făcut plat pe %o,Игрок %k сплюснул игрока %o,%k је изравнао %o -%k gave %o Anal Justice,TXT_OBITUARY9,,,,%o utržil@[ao_cs] anální spravedlnost od hráče %k,%k hat %o anale Gerechtigkeit gegeben,Ο/Η %k γάμησε @[pro2_gr] %o @[pro3_gr] κόλο,%k donis al %o Puga Justo,%k le dió Justicia Anal a %o,,%k jakoi %o paralle anaalioikeutta,%k a rendu une justice anale a %o,%k %o -nak Anális Igazságot adott,%k ha dato a %o Giustizia Anale,%k は %o のケツにぶち込んだ。,%k 은(는) %o 에게 홍콩행을 보냈다.,%k gaf %o anale rechtvaardigheid,%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 gave AnAl MaDnEsS to %o,TXT_OBITUARY10,,,,%o utrpěl@[ao_cs] AnÁlNí ŠíLeNsTvÍ od hráče %k,%k gab %o AnAlEn WaHnSiNn,Ο/Η %k έσκισε τον κόλο του/της] %o,%k donis pUgAn frEnEzOn al %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 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 killed %o,TXT_OBITUARY11,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k,%k hat %o getötet,Ο/Η %k σκότωσε @[pro2_gr] %o,%k mortigis %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 zabił@[ao_pl] %o,%k matou %o,,%k l-a omorât pe %o,Игрок %k убил игрока %o,%k је убио %o -%k made mincemeat out of %o,TXT_OBITUARY12,,,,%o byl@[ao_cs] namelen@[ao_cs] hráčem %k,%k hat %o zu Hackfleisch verarbeitet,Ο/Η %k έφτιαξε κυμά με @[pro2_gr] %o,%k farigis farĉon el %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 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 massacred %o,TXT_OBITUARY13,,,,%o byl@[ao_cs] zmasakrován@[ao_cs] hráčem %k,%k hat %o niedergemetzelt,Ο/Η %k δολοφώνησε @[pro2_gr] %o,%k masakris %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 zmasakrował@[ao_pl] %o,%k massacrou %o,,%k a fost masacrat de către %o,Игрок %k устроил бойню игроку %o,%k је масакрирао %o -%k mutilated %o,TXT_OBITUARY14,,,,%o byl@[ao_cs] zmrzačen@[ao_cs] hráčem %k,%k hat %o verstümmelt,Ο/Η %k ακρωτηριάσε @[pro2_gr] %o,%k mutilis %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 rozszarpał@[ao_pl] %o,%k mutilou %o,,%k l-a mutilat pe %o,Игрок %k изуродовал игрока %o,%k је мутилирао %o -%k reamed %o,TXT_OBITUARY15,,,,%o byl@[ao_cs] proděravěn@[ao_cs] hráčem %k,%k hat %o aufgerieben,Ο/Η %k δέσμισε @[pro2_gr] %o,%k alezis %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 rozwiercił@[ao_pl] %o,%k esquartejou %o,,%k l-a transformat într-un top de hârtie pe %o,Игрок %k просверлил игрока %o,%k је наоружао %o -%k ripped %o a new orifice,TXT_OBITUARY16,,,,%o má novou díru od hráče %k,%k hat %o eine neue Körperöffnung verpasst,Ο/Η άνοιξε μια νέα τρύπα @[pro3_gr] %o,%k ŝiris %o novan orificion,%k le hizo a %o un nuevo orificio,,%k repi %o paralle uuden aukon,%k a ouvert un nouvel orifice a %o,,%k ha aperto a %o un altro orifizio,%k は %o を切り裂いて新しい穴を作ってあげた。,%k 은(는) %o 을(를) 죽여 뜯어서 작품을 만들었다.,%k scheurde een opening uit %o,%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 slaughtered %o,TXT_OBITUARY17,,,,%o byl@[ao_cs] zavražděn@[ao_cs] hráčem %k,%k hat %o geschlachtet,Ο/Η %k έσφαξε @[pro2_gr] %o,%k buĉis %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 zarżn@[irreg_2_pl] %o,%k abateu %o,,%k l-a măcelărit pe %o,Игрок %k устроил резню игроку %o,%k је заклао %o -%k smashed %o,TXT_OBITUARY18,,,,%o byl@[ao_cs] zmlácen@[ao_cs] hráčem %k,%k hat %o zerklatscht,Ο/Η %k τσάκισε @[pro2_gr] %o,%k frakasis %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 stłukł@[ao_pl] %o,%k esmagou %o,,%k l-a spart pe %o,Игрок %k размазал игрока %o,%k је поломио %o -%k sodomized %o,TXT_OBITUARY19,,,,Hráč %k se dopustil sodomie na hráči %o,%k hat %o sodomisiert,Ο/Η %k γάμησε @[pro2_gr] %o,%k sodomizis %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 spenetrował@[ao_pl] %o,%k sodomizou %o,,%k l-a sodomizat pe %o,Игрок %k содомировал игрока %o,%k је изјебао %o -%k splattered %o,TXT_OBITUARY20,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] hráčem %k,%k hat %o zerspritzt,Ο/Η %k έσκασε @[pro2_gr] %o,%k disĵetis %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 rozbryzgał@[ao_pl] %o,%k explodiu %o,,%k l-a împrăștiat pe %o,Игрок %k разбрызгал игрока %o,%k је спљоштио %o -%k squashed %o,TXT_OBITUARY21,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] hráčem %k,%k hat %o zerquetscht,Ο/Η %k πάτησε @[pro2_gr] %o,%k premplatigis %o,%k aplastó a %o,,%k litisti %o paran,%k a écrabouillé %o,%k szétnyomta %o -t mint a csótányt,%k ha schiacciato %o,%k は %o に潰された。,%k 은(는) %o 을(를) 짓이겼다.,%k plette %o,%k zmiażdżył@[ao_pl] %o,%k espatifou %o,,%k l-a strivit pe %o,Игрок %k расплющил игрока %o,%k је згњечио %o -%k throttled %o,TXT_OBITUARY22,,,,%o byl@[ao_cs] zaškrcen@[ao_cs] hráčem %k,%k hat %o erdrosselt,Ο/Η %k κομμάτιασε @[pro2_gr] %o,%k ekbruligis %o,%k aceleró a %o,,%k polki %o paran,%k a étouffé %o,%k elnyomta %o -t,%k ha strozzato %o,%k は %o に絞られた。,%k 은(는) %o 을(를) 목 졸라 죽였다.,%k wurgde %o,"%k udusił@[ao_pl] %o -",%k estrangulou %o,,%k l-a strâns de gât pe %o,Игрок %k задушил игрока %o,%k је угушио %o -%k wasted %o,TXT_OBITUARY23,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k hat %o verbraucht,Ο/Η %k σκότωσε @[pro2_gr] %o,%k malŝparis %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 roztrwonił@[ao_pl] %o,%k detonou %o,,%k l-a risipit pe %o,Игрок %k замочил игрока %o,%k је убио %o -%k body bagged %o,TXT_OBITUARY24,,,,Hráč %k narval %o@[psn1_cs] tělo do pytle,%k hat %o eingesackt,Ο/Η %k έχωσε @[pro2_gr] %o στη κάσα του/της,%k korpo-ensakigis %o,%k embolsó a %o,,%k kääri %o paran ruumispussiin,%k a placé %o dans son linceul,%k becsomagolta %o -t,%k ha mandato %o all'obitorio,%k は %o を死体袋にした。,%k 은(는) %o 의 장례식을 치렀다.,%k stopte %o in een lijkzak,%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 sent %o to Hell,TXT_OBITUARY25,,,,%o byl@[ao_cs] poslán@[ao_cs] do pekla hráčem %k,%k hat %o zur Hölle fahren lassen,Ο/Η %k έστειλε @[pro2_gr] %o στο δίαολο,%k sendis %o al Infero,%k envió 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 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 toasted %o,TXT_OBITUARY26,,,,%o byl@[ao_cs] upečen@[ao_cs] hráčem %k,%k hat %o geröstet,Ο/Η %k έψησε @[pro2_gr] %o,%k tostis %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 stostował@[ao_pl] %o,%k tostou %o,,%k l-a prăjit pe %o,Игрок %k поджарил игрока %o,%k је тостирао %o -%k snuffed %o,TXT_OBITUARY27,,,,%o byl@[ao_cs] rozsápán@[ao_cs] hráčem %k,%k hat %o vernichtet,Ο/Η %k έσβησε @[pro2_gr] %o,%k snufis %o,%k aspiró a %o,,%k sammutti %o paran,%k a crevé %o,%k kikapcsolta %o -t,%k ha spento %o,%k は %o を処刑した。,%o 은(는) %k 에 의해 짓눌려졌다.,%k legde %o om,%k powąchał@[ao_pl] %o,%k apagou %o,,%k l-a mirosit pe %o,Игрок %k прикончил игрока %o,%k је угасио %o -%k hosed %o,TXT_OBITUARY28,,,,%o byl@[ao_cs] odstříknut@[ao_cs] hráčem %k,%k hat %o eingetütet,Ο/Η %k έονιξε @[pro2_gr] %o σε σφαίρες,%k hosis %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 załatwił@[ao_pl] %o,%k metralhou %o,,%k a pus furtunul pe %o,Игрок %k расстрелял игрока %o,%k је упскао %o -%k sprayed %o,TXT_OBITUARY29,,,,%o byl@[ao_cs] postříkán@[ao_cs] hráčem %k,%k hat %o pulverisiert,Ο/Η %k ψέκασε @[pro2_gr] %o,%k ŝprucigis %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 rozpryskał@[ao_pl] %o,%k pulverizou %o,,%k l-a pulverizat pe %o,Игрок %k распылил игрока %o,%k је испрскао %o -%k made dog meat out of %o,TXT_OBITUARY30,,,,%o byl@[ao_cs] hozen@[ao_cs] psům hráčem %k,%k hat Hundefutter aus %o gemacht,Ο/Η %k γύρισε @[pro2_gr] %o σε κιμά,%k farigis hundan viandon el %o,%k hizo comida para perro 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 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 beat %o like a cur,TXT_OBITUARY31,,,,%o byl@[ao_cs] zmlácen@[ao_cs] jako pes hráčem %k,%k hat %o wie einen Hund geschlagen,Ο/Η %k πλάκοσε @[pro2_gr] %o σαν κοπρίτης,%k batis %o kiel hundaĉo,%k pateó 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 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 is excrement,TXT_SELFOBIT1,,,,%o je exkrement,%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 został@[ao_pl] odpadkami,%o virou escremento,,%o e excrement,%o теперь экскремент,%o је сада измет -%o is hamburger,TXT_SELFOBIT2,,,,%o je 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 został@[ao_pl] hamburgerem,%o virou hambúrguer,,%o e hamburger,%o теперь гамбургер,%o је сада пљескавица -%o suffered scrotum separation,TXT_SELFOBIT3,,,,%o prodělal@[ao_cs] separaci šourku,%os Eier wurden gebraten,,%o suferis skrotan disigon,%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 doznał@[ao_pl] oddzielenia moszny,%o sofreu separação escrotal,,%o a suferit o separație de șcrot,%o страдает от потери тестикул,%o му је исечена патка -%o volunteered for population control,TXT_SELFOBIT4,,,,%o se zúčastnil@[ao_cs] čistky obyvatelstva,%o hat sich freiwillig zur Bevölkerungskontrolle gemeldet,@[art_gr] %o εθελώντησε για έλεγχο του πληθυσμού,%o volontulis por loĝantara regado,%o fue 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 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 has suicided,TXT_SELFOBIT5,,,,%o spáchal@[ao_cs] sebevraždu,%o hat Selbstmord begangen,@[art_gr] %o έχει αυτοκτονήση,%o sin mortigis,%o se ha suicidado,,%o on tehnyt itsemurhan,%o s'est suicidé,%o öngyilkos lett,%o si è suicidato,%o は勝手にくたばった。,%o 은(는) 한심하게 자살했다.,%o heeft zelfmoord gepleegd,%o popełnił@[ao_pl] samobójstwo,%o se suicidou,%o suicidou-se,%o s-a sinucis,Игрок %o самоубился,%o је убио самог себе -%o received the Darwin Award,TXT_SELFOBIT6,,,,%o dostal@[ao_cs] Darwinovu cenu,%o hat den Darwinpreis erhalten,@[art_gr] %o κέρδισε το Darwin βραβείο,%o ricevis la Darwin-Premion,%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 otrzymał@[ao_pl] Nagrodę Darwina,%o ganhou o Prêmio Darwin,,%o a primit Premiul Darwin,Игрок %o получил премию Дарвина,%o је добио Дарвиново признање -,USE_GENERIC_FONT,This is not a text to be translated but an engine switch for complex languages.,,,,,,,,,,,,,1,1,,,,,,, +",Tmavě šedá,Dunkelgrau,Σκοτεινό γρκί,Malhelgriza,Gris Oscuro,,Tummanharmaa,Gris sombre,Sötétszürke,Grigio scuro,鉛,치색,Donkergrijs,Ciemnoszary,Cinza escuro,,Gri închis,Тёмно-серый,Тамно сива, +Dark Green,TXT_COLOR_DARKGREEN,,,,Tmavě zelená,Dunkelgrün,Σκοτεινό πράσινο,Malhelverda,Verde Oscuro,,Tummanvihreä,Vert sombre,Sötétzöld,Verde scuro,深,흑녹색,Donkergroen,Ciemnozielony,Verde escuro,,Verde închis,Тёмно-зелёный,Тамна зелена, +Brown,TXT_COLOR_BROWN,,,,Hnědá,Braun,Σκούρο,Bruna,Marrón,,Ruskea,Brun,Barna,Marrone,茶,갈색,Bruin,Brązowy,Marrom,,Maro,Коричневый,Браон, +Dark Blue,TXT_COLOR_DARKBLUE,,,,Tmavě modrá,Dunkelblau,Σκοτεινό μπλέ,Malhelblua,Azul Oscuro,,Tummansininen,Bleu sombre,Sötétkék,Blu scuro,紺,,Donkerblauw,Ciemnoniebieski,Azul escuro,,Albastru închis,Тёмно-синий,Тамна Плава, +Light Red,TXT_COLOR_LIGHTRED,,,,Světle červená,Hellrot,Ανοιχτό κόκκινο,Helruĝa,Rojo Claro,,Vaaleanpunainen,Rouge clair,Világospiros,Rosso chiaro,丹,옅은 적색,Licht Rood,Jasnoczerwony,Vermelho claro,,Roșu deschis,Светло-красный,Светло црвена, +Yellow,TXT_COLOR_YELLOW,,,,Žlutá,Gelb,Κίτρινο,Flava,Amarillo,,Keltainen,Jaune,Sárga,Giallo,黄,노란색,Geel,Żółty,Amarelo,,Galben,Жёлтый,Жута, +Purple,TXT_COLOR_PURPLE,,,,Fialová,Violett,Μόβ,Purpura,Morado,,Purppura,Violet,Lila,Viola,紫,보라색,Paars,Fioletowy,Roxo,,Mov,Фиолетовый,Љубичаста, +Olive,TXT_COLOR_DULLGREEN,,,,Bledě zelená,Blassgrün,,Olivkolora,Oliva,,Haaleanvihreä,Vert pâle,Olíva,Verde pallido,苔,암녹색,Saaie groen,Matowa Zieleń,Verde oliva,,Măsliniu,Мутно-зелёный,Тупа зелена, +Beige,TXT_COLOR_BEIGE,,,,Béžová,,Μπέζ,Flavgriza,Beis,,Beesi,,Bézs,,淡,담갈색,Beige,Beżowy,Bege,,Bej,Бежевый,Беж, +Light Green,TXT_COLOR_LIGHTGREEN,,,,Světle zelená,Hellgrün,Ανοιχτό Πράσινο,Helverda,Verde Claro,,Vaaleanvihreä,Vert clair,Világoszöld,Verde chiaro,葵,옅은 녹색,Licht groen,Jasonzielony,Verde claro,,Verde Deschis,Светло-зелёный,Светло зелена, +Light Blue,TXT_COLOR_LIGHTBLUE,,,,Světle modrá,Hellblau,Γαλάζιο,Helblua,Azul Claro,,Vaaleansininen,Bleu clair,Világoskék,Blu chiaro,空,옅은 청색,Licht blauw,Jasnoniebieski,Azul claro,,Albastru Deschis,Светло-синий,Светло плава, +Light Gray,TXT_COLOR_LIGHTGRAY,,,Light Grey,Světle šedá,Hellgrau,Ανοιχτό Γκρι,Helgriza,Gris Claro,,Vaaleanharmaa,Gris clair,Világosszürke,Grigio chiaro,鉛,옅은 회색,Lichtgrijs,Jasnoszary,Cinza claro,,Gri Deschis,Светло-серый,Светло сива, +Light Brown,TXT_COLOR_LIGHTBROWN,,,,Světle hnědá,Hellbraun,Ανοιχτό Καφέ,Helbruna,Marrón Claro,,Vaaleanruskea,Brun clair,Világosbarna,Marrone chiaro,褐,옅은 고동색,Lichtbruin,Jasnobrązowy,Marrom claro,,Maro Deschis,Светло-коричневый,Светло браон, +Gold,TXT_COLOR_GOLD,,,,Zlatá,,Χρυσό,Orkolora,Dorado,,Kulta,Or,Arany,Oro,金,금색,Goud,Złoty,Dourado,,Auriu,Золотой,Златна, +Bright Green,TXT_COLOR_BRIGHTGREEN,,,,Jasně zelená,Hellgrün,Φωτινό Πράσινο,Brilverda,Verde Claro,,Vaaleanvihreä,Vert clair,Fényeszöld,Verde chiaro,鮮,밝은 녹색,Helder groen,Jasnozielony,Verde claro,,Verde Deschis,Ярко-зелёный,Светла зелена, +Rust,TXT_COLOR_RUST,,,,Rezavá,Rostbraun,Σκουριά,Rustokolora,Óxido,,Ruoste,Rouille,Rozsda,Arrugginito,錆,주황 적갈색,Roest,Rdzawy,Ferrugem,,Ruginiu,Ржавый,Рђа, +Name,PLYRMNU_NAME,,,,Jméno,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Imię,Nome,,Nume,Имя,Надимак, +Team,PLYRMNU_TEAM,,,,Tým,,Ομάδα,Teamo,Equipo,,Joukkue,Equipe,Csapat,Squadra,チーム,팀,Team,Drużyna,Equipe,Equipa,Echipă,Команда,Тим, +Color,PLYRMNU_PLAYERCOLOR,,,Colour,Barva,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore,色,색상,Kleur,Kolor,Cor,,Culoare,Цвет,Боја, +Gender,PLYRMNU_PLAYERGENDER,,,,Pohlaví,Geschlecht,Φύλο,Genro,Género,,Sukupuoli,Genre,Nem,Sesso,性別,성별,Geslacht,Płeć,Gênero,,Sex,Пол,Пол, +Male,OPTVAL_MALE,,,,Muž,Männlich,Αρσενικό,Vira,Masculino,,Miespuolinen,Masculin,Férfi,Maschio,男,남성,Man,Mężczyzna,Masculino,,Masculin,Мужской,Мушко, +Female,OPTVAL_FEMALE,,,,Žena,Weiblich,Θηλυκό,Ina,Femenino,,Naispuolinen,Féminin,Nő,Femmina,女,여성,Vrouw,Kobieta,Feminino,,Feminin,Женский,Женско, +Neutral,OPTVAL_NEUTRAL,,,,Neutrální,Neutral,Ουδέτερο,Neŭtra (Ri),Neutro,,Sukupuoleton,Neutre,Semleges,Neutrale,中間,중성,Neutraal,Neutralne,Neutro,,Neutru,Нейтральный,Неутрално, +Object,OPTVAL_OTHER,,,,Objekt,Objekt,Αντικείμενο,Objekto (Ĝi),Objeto,,Olio,Objet,Tárgy,Oggetto,物体,기타,Doel,Obiekt,Objeto,,Obiect,Предмет,Предмет, +Gameplay Options,GMPLYMNU_TITLE,,,,Nastavení herních mechanik,Gameplay-Optionen,,Ludado-Agordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options Gameplay,Játékmenet beállításai,Opzioni gameplay,ゲームプレイ オプション,게임플레이 설정,Gameplay-opties,Opcje Rozgrywki,Opções de jogabilidade,,Setări de Joc,Настройки игры,Подешавања гејмплеја, +Always,OPTVAL_ALWAYS,,,,Vždy,Immer,Πάντα,Ĉiam,Siempre,,Aina,Toujours,Mindig,Sempre,常に,언제나,Altijd,Zawsze,Sempre,,Mereu,Всегда,Увек, +Never,OPTVAL_NEVER,,,,Nikdy,Nie,Ποτέ,Neniam,Nunca,,Ei koskaan,Jamais,Soha,Mai,しない,없음,Nooit,Nigdy,Nunca,,Niciodată,Никогда,Никад, +Autoaim,PLYRMNU_AUTOAIM,,,,Automatické míření,Automatisch zielen,,Celasisto,Autoapuntar,,Automaattitähtäys,Auto-visée,Automatikus célzás,Mira automatica,自動照準,자동 조준,Autoaim,Auto-celowanie,Mira automática,,Autoțintire,Автоприцеливание,Аутоматско циљање, +Always Run,PLYRMNU_ALWAYSRUN,,,,Vždy běžet,Immer Rennen,Πάντα τρέχα,Ĉiam Kuri,Siempre correr,,Jatkuva juoksu,Toujours courir,Mindig fusson,Corri sempre,常に駆け足,달리기 토글,Altijd lopen,Zawsze Biegaj,Sempre correr,Correr Sempre,Fugă în permanență,Постоянный бег,Увек трчи, +,,Display,,,,,,,,,,,,,,,,,,,,,, +Display Options,DSPLYMNU_TITLE,,,,Nastavení grafiky,Anzeigeoptionen,,Ekrano-Agordoj,Opciones de visualización,,Näyttöasetukset,Options Affichage,Megjelenítés beállítások,Opzioni display,ディスプレイ オプション,디스플레이 설정,Weergaveopties,Opcje Wyświetlania,Opções de vídeo,,Setări afișare,Настройки экрана,Подешавања приказа, +Screen size,DSPLYMNU_SCREENSIZE,,,,Velikost obrazovky,Bildschirmgröße,Μέγεθος οθόνης,Ekrangrando,Tamaño de pantalla,,Näytön koko,Taille de l'écran,Képernyő mérete,Dimensione della schermata,画面サイズ,화면 크기,Schermgrootte,Rozmiar Ekranu,Tamanho de tela,Tamanho do ecrã,Mărime ecran,Размер экрана,Величина екрана, +Vertical Sync,DSPLYMNU_VSYNC,,,,Vertikální synchronizace,Vertikale Synchronisation,,Vertikala-Sinkronigo,Sincr. vertical,,Pystytahdistys,Synchronisation Verticale,Függőleges szinkronizálás,Sincronia verticale,垂直同期,수직 동기화,Verticale Sync,Synchronizacja Pionowa,Sincronização vertical,,Sincronizare Verticală,Вертикальная синхронизация,Вертикална синхорнизација, +Models,DSPLYMNU_MODELS,,,,Modely,Modelle,Μοντέλα,Modeloj,Modelos,,Mallit,Modèles,3D modellek,Modelli,モデル,모델,Modellen,Modele,Modelos,,Modele,Модели,Модели, +Scale crosshair,DSPLYMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,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 celownika,Escala da mira,,Scară țintă,Размер прицела,Размера нишана, +Brightness,DSPLYMNU_BRIGHTNESS,,,,Jas,Helligkeit,Φωτηνότητα,Brileco,Brillo,,Kirkkaus,Luminosité,Fényerő,Luminosità,明るさ,밝기,Helderheid,Jasność,Brilho,,Luminozitate,Яркость,Осветљење, +Gamma correction,DSPLYMNU_GAMMA,,,,Korekce gama,Gammakorrektur,,Gamaa korektado,Corrección gamma,,Gammakorjaus,Correction Gamma,Gamma korrekció,Correzione gamma,ガンマ値,감마 조정,Gamma correctie,Korekta gammy,Correção de gama,,Gamma,Гамма-коррекция,Корекција светлости, +Contrast,DSPLYMNU_CONTRAST,,,,Kontrast,Kontrast,,Kontrasto,Contraste,,Sävykkyys,Contraste,Kontraszt,Contrasto,コントラスト,대비,,Kontrast,Contraste,,,Контраст,Контраст, +Saturation,DSPLYMNU_SATURATION,,,,Sytost,Sättigung,,Satureco,Saturación,,Värikylläisyys,,Telítettség,Saturazione,サチュレーション,채도,Verzadiging,Nasycenie,Saturação,,Saturație,Насыщенность,Сатурација, +Status Bar Scale,DSPLYMNU_SBSCALE,,,,Velikost stavového panelu,Statusleistengröße,,Skalo de Stata Breto,Escala de Barra de Estado,,Tilapalkin skaalaus,Mise à l'échelle HUD,Állapotjelző mérete,Dimensioni Status Bar,ステータススケール,,Statusbalkschaal,Skala paska statusu,Escala da barra de estado,,Scară bară de stare,Размер строки состояния,, +Messages,DSPLYMNU_MESSAGES,,,,Oznámení,Nachrichten,Μηνύματα,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке, +Center messages,MSGMNU_CENTERMESSAGES,,,Centre messages,Oznámení na střed,Nachrichten zentrieren,,Centrigi mesaĝojn,Centrar mensajes,,Keskitä viestit,Messages centrés,Üzenetek középre helyezése,Messaggi centrati,メッセージを中央に,메시지 중간에 위치,Berichten centreren,Wyśrodkuj wiadomości,Centralizar mensagens,Centrar mensagens,Mesaje centrate,Центрирование сообщений,Централне поруке, +Pulsating message Display,MSGMNU_PULSEMESSAGES,,,,Pulzující oznámení,Pulsierende Nachrichtenanzeige,,Pulsanta Mesaĝ-montrejo,Mostrar Mensajes Pulsantes,,Sykkivät viestit,Messages pulsés,Pulzáló üzenet,Mostra messaggi pulsanti,取得時等の文を明滅,,Pulserende berichtendisplay,Pulsujące wyświetlanie wiadomości,Exibir mensagem pulsante,,Afișare Mesaje Pulsante,Пульсация сообщений,, +Message Scale,MSGMNU_MESSAGESCALE,,,,Velikost oznámení,Nachrichtengröße,Μέγεθος μηνύματον,Skalo de Mesaĝoj,Escala de Mensajes,,Viestien skaalaus,Mise à l'échelle Messages,Üzenet mérete,Dimensioni Messaggi,メッセージスケール,,Berichtschaal,Skalowanie Wiadomości,Escala da mensagem,,Scară Mesaje,Размер сообщений,, +,,Automap,,,,,,,,,,,,,,,,,,,,,, +Select Color,MNU_COLORPICKER,,,Select Colour,Výběr barvy,Farbe auswählen,Επιλογή Χρώματος,Elektu Koloron:,Elige un color,,Valitse väri,Choisir Couleur,Szín választása,Scegli il colore,色選択,색상을 고르시오,Selecteer Kleur,Wybierz Kolor,Selecione a cor,,Alege o Culoare,Выбор цвета,Изабери боју, +Automap Options,AUTOMAPMNU_TITLE,,,,Nastavení automapy,Automapoptionen,,Aŭtomapo-Agordoj,Opciones del Automapa,,Automaattikartan asetukset,Options Carte,Térkép beállításai,Opzioni automappa,オートマップ オプション,오토맵 설정,Automap-opties,Opcje Mapy,Opções de automapa,,Setări Hartă Computerizată,Настройки автокарты,Подешавања аутомапе, +Rotate automap,AUTOMAPMNU_ROTATE,,,,Otáčet automapu,Rotiere Automap,,Turni aŭtomapon,Rotar automapa,,Kiertyvä automaattikartta,Rotation de la Carte,Térkép forgatása,Ruota l'automappa,オートマップの回転表示,오토맵 회전,Automatisch roteren,Obracaj mapę,Girar automapa,,Rotire hartă computerizată,Вращающаяся автокарта,Ротирај аутомапу, +Follow player,AUTOMAPMNU_FOLLOW,,,,Následovat hráče,Folge dem Spieler,Ακουλούθα το παίχτη,Sekvi ludanton,Seguir jugador,,Seuraa pelaajaa,Suivre le joueur,Kövesse a játékost,Segui il giocatore,プレイヤー追従,플레이어 추적,Volg de speler,Podążaj za graczem,Seguir jogador,,Urmărire jucător,Привязка к игроку,Прати играча, +Customize Map Colors,MAPCOLORMNU_TITLE,,,Customize Map Colours,Nastavení barev mapy,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,Ustaw kolory mapy,Personalizar cores do mapa,,Personalizare culori hartă,Настройки цветов автокарты,Промени боју мапе, +Restore default custom colors,MAPCOLORMNU_DEFAULTMAPCOLORS,,,Restore default custom colours,Obnovit původní vlastní barvy,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,Przywróć domyślne kolory,Restaurar cores personalizadas padrão,,Revenire la culorile implicite,Вернуть стандартные цвета,Врати уобичајене разне боје, +,,Sound,,,,,,,,,,,,,,,,,,,,,, +Sound enabled,SNDMNU_SNDENABLED,,,,Zvuk zapnut,Sound aktiv,Ήχος ενεργοποιημένος,Sono ŝaltita,Sonido Activado,,Ääni päällä,Son activé,Hang engedélyezve,Abilita gli effetti sonori,サウンド有効,,Geluid actief,Dźwięk włączony,Som ativado,,Sunet activat,Звук включён,, +Music enabled,SNDMNU_MUSENABLED,,,,Hudba zapnuta,Musik aktiv,Μουσική ενεργοποιημένη,Muziko ŝaltita,Música Activada,,Musiikki päällä,Musique activée,Zene engedélyezve,Abilita la musica,音楽有効,,Muziek actief ,Muzyka włączona,Música ativada,,Muzică activată,Музыка включена,, +4000 Hz,OPTVAL_4000HZ,,,,,,,,,,,,,,,,,,4000 Hz,,,4000 Гц,, +8000 Hz,OPTVAL_8000HZ,,,,,,,,,,,,,,,,,,8000 Hz,,,8000 Гц,, +11025 Hz,OPTVAL_11025HZ,,,,,,,,,,,,,,,,,,11025 Hz,,,11025 Гц,, +22050 Hz,OPTVAL_22050HZ,,,,,,,,,,,,,,,,,,22050 Hz,,,22050 Гц,, +32000 Hz,OPTVAL_32000HZ,,,,,,,,,,,,,,,,,,32000 Hz,,,32000 Гц,, +44100 Hz,OPTVAL_44100HZ,,,,,,,,,,,,,,,,,,44100 Hz,,,44100 Гц,, +48000 Hz,OPTVAL_48000HZ,,,,,,,,,,,,,,,,,,48000 Hz,,,48000 Гц,, +64 samples,OPTVAL_64SAMPLES,,,,64 vzorků,,64 δείγματα,64 specimenoj,64 Muestras,,64 näytettä,,,,,64 샘플,,64 sample,64 amostras,,64 monstre,64 семпла,64 узорка, +128 samples,OPTVAL_128SAMPLES,,,,128 vzorků,,128 δείγματα,128 specimenoj,128 Muestras,,128 näytettä,,,,,128 샘플,,128 sampli,128 amostras,,128 monstre,128 семплов,128 узорка, +256 samples,OPTVAL_256SAMPLES,,,,256 vzorků,,256 δείγματα,256 specimenoj,256 Muestras,,256 näytettä,,,,,256 샘플,,256 sampli,256 amostras,,256 monstre,256 семплов,256 узорка, +512 samples,OPTVAL_512SAMPLES,,,,512 vzorků,,512 δείγματα,512 specimenoj,512 Muestras,,512 näytettä,,,,,512 샘플,,512 sampli,512 amostras,,512 monstre,512 семплов,512 узорка, +1024 samples,OPTVAL_1024SAMPLES,,,,1024 vzorků,,1024 δείγματα,1024 specimenoj,1024 Muestras,,1024 näytettä,,,,,1024 샘플,,1024 sampli,1.024 amostras,,1024 monstre,1024 семпла,1024 узорка, +2048 samples,OPTVAL_2048SAMPLES,,,,2048 vzorků,,2048 δείγματα,2048 specimenoj,2048 Muestras,,2048 näytettä,,,,,2048 샘플,,2048 sampli,2.048 amostras,,2048 monstre,2048 семплов,2048 узорка, +4096 samples,OPTVAL_4096SAMPLES,,,,4096 vzorků,,4096 δείγματα,4096 specimenoj,4096 Muestras,,4096 näytettä,,,,,4096 샘플,,4096 sampli,4.096 amostras,,4096 monstre,4096 семплов,4096 узорка, +Auto,OPTSTR_AUTO,,,,,,,Aŭtomata,Automático,,Automaattinen,,Automatikus,Automatico,自動,오토,,Automatycznie,Automático,,,Авто,Аутоматски, +Mono,OPTSTR_MONO,,,,,,,Monofonia,,,,,Monó,,モノラル,모노,,,Mono,,,Моно,Монотоно, +Stereo,OPTSTR_STEREO,,,,,,,Stereofonia,Estereo,,,Stéréo,Sztereó,,ステレオ,스테레오,,,Estéreo,,,Стерео,Стереотоно, +Dolby Pro Logic Decoder,OPTSTR_PROLOGIC,,,,,,,Malkodilo de Dolby Pro Logic ,,,,,,,ドルビー プロロジック デコーダー,돌비 프로 로직 디코더,,,Decodificador Dolby Pro Logic,,Decodor Pro Logic Dolby,Декодер Dolby Pro Logic,, +Quad,OPTSTR_QUAD,,,,,,,Kvadratofonia,Cuádruple,,Dolby Pro Logic -dekooderi,,,,クァッド,쿼드,,Cztery kanały,Quadrifônico,,,Четырёхканальный,Четвородупло, +5 speakers,OPTSTR_SURROUND,,,,5 reproduktorů,5 Lautsprecher,,5 Laŭtparoliloj,5 altavoces,5 Bocinas,5 kaiutinta,5 enceintes,5 hangfal,Surround,5 スピーカー,5 스피커,5 luidsprekers,Głośniki 5,5 alto-falantes,,5 boxe,5 динамиков,5 спикер, +5.1 speakers,OPTSTR_5POINT1,,,,Reproduktory 5.1,5.1 Lautsprecher,,5.1 Laŭtparoliloj,Altavoces 5.1,Bocinas 5.1,5.1 kaiutinta,Enceintes 5.1,5.1 hangrendszer,Surround 5.1,5.1 スピーカー,5.1 스피커,5.1 luidsprekers,Głośniki 5.1,Auto-falantes 5.1,,Boxe 5.1,Динамики 5.1,5.1 спикер, +7.1 speakers,OPTSTR_7POINT1,,,,Reproduktory 7.1,7.1 Lautsprecher,,7.1 Laůtparoliloj,Altavoces 7.1,Bocinas 7.1,7.1 kaiutinta,Enceintes 7.1,7.1 hangrendszer,Surround 7.1,7.1 スピーカー,7.1스피커,7.1 luidsprekers,Głośniki 7.1,Auto-falantes 7.1,,Boxe 7.1,Динамики 7.1,7.1 спикер, +OpenAL Options,OPENALMNU_TITLE,,,,Nastavení OpenAL,OpenAL Optionen,,OpenAL Agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállítások,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања, +Playback device,OPENALMNU_PLAYBACKDEVICE,,,,Přehravací zařízení,Wiedergabegerät,,Ludado-aparato,Dispositivo de reproducción,,Äänitoistolaite,Sortie sonore,Visszajátszó eszköz,Dispositivo di playback,プレイバック デバイス,재생 장치,Afspeelapparaat,Urządzenie odtwarzania,Dispositivo de reprodução,,Dispozitiv de redare,Устройство воспроизведения,Аудио уређај, +Enable EFX,OPENALMNU_ENABLEEFX,,,,Povolit EFX,EFX aktiv,,Ŝalti EFX,Permitir EFX,,Ota käyttöön EFX,Activer EFX,EFX engedélyezése,Abilita EFX,EFXを有効化,EFX 켬,EFX inschakelen,Pozwól na EFX,Ativar EFX,,Activare EFX,Включить EFX,Укључи EFX, +Resampler,OPENALMNU_RESAMPLER,,,,,,,Respecimenilo,,,Näytteenottotaajuusmuunnin,,,,リサンプラー,재배열 기기,,Resampler,Reamostrador,,,Передискретизатор,Ресемплер, +Sound Options,SNDMNU_TITLE,,,,Nastavení zvuku,Soundeinstellungen,Ρυθμίσεις ήχου,Sono-Agordoj,Opciones de sonido,,Ääniasetukset,Options Sonores,Hangbeállítások,Impostazioni audio,サウンド オプション,음향 설정,Geluidsopties,Opcje Dźwięku,Opções de áudio,,Setări Sunet,Настройки звука,Звучна подешавања, +Sounds volume,SNDMNU_SFXVOLUME,,,,Hlasitost zvuků,Effektlautstärke,Φονή ήχων,Sona laŭteco,Volumen de sonido,,Äänitehosteiden voimakkuus,Volume des Sons,Effektek hangereje,Volume suoni,効果音音量,효과음 음량,Geluidsvolume,Głośność Dźwięku,Volume de sons,,Volum efecte,Громкость звука,Јачина звука, +Menu volume,SNDMNU_MENUVOLUME,,,,Hlasitost nabídek,Menülautstärke,Φονή μενού,Menuo-laŭteco,Volumen del menú,,Valikon äänenvoimakkuus,Volume du Menu,Menü hangereje,Volume menù,メニュー音量,메뉴 음량,Menu volume,Głośność Menu,Volume do menu,,Volum meniu,Громкость меню,Јачина менија, +Music volume,SNDMNU_MUSICVOLUME,,,,Hlasitost hudby,Musiklautstärke,Φονή μουσικής,Muzika laŭteco,Volumen de la Música,,Musiikin äänenvoimakkuus,Volume Musique,Zene hangereje,Volume musica,音楽音量,배경음 음량,Muziekvolume,Głośność Muzyki,Volume da música,,Volum muzică,Громкость музыки,Јачина музике, +MIDI device,SNDMNU_MIDIDEVICE,,,,MIDI zařízení,MIDI-Gerät,MIDI συσκεύη,MIDI-aparato,Dispositivo MIDI,,MIDI-laite,Sortie MIDI,MIDI eszköz,Dispositivo MIDI,MIDIデバイス,MIDI 장치,MIDI-apparaat,Urządzenie MIDI,Dispositivo MIDI,,Dispozitiv MIDI,MIDI проигрыватель,MIDI уређај, +Sound in Background,SNDMNU_BACKGROUND,,,,Zvuk na pozadí,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,Dźwięk w Tle,Som de fundo,,Sunet pe fundal,Звуки в фоне,Звуци у позадини, +Underwater reverb,SNDMNU_UNDERWATERREVERB,,,,Ozvěna pod vodou,Unterwasserhall,,Subakva resono,Reverb. bajo el agua,,Vedenalaiskaiku,Reverbération sous l'eau,Vízalatti visszaverődés,Reverb sott'acqua,水中反響音,수중 울림효과,Onderwater nagalm,Pogłos pod wodą,Reverberação debaixo d'água,Reverberação debaixo de água,Reverb subacvatic,Эффект под водой,Подводни одјек, +Randomize pitches,SNDMNU_RANDOMIZEPITCHES,,,,Náhodné výšky tónu,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,Losuj tonacje,Aleatorizar tons,Tons aleatórios,Ton sunete aleatoriu,Изменять высоту,Рандомизација тонова, +Sound channels,SNDMNU_CHANNELS,,,,Počet zvukových kanálů,Soundkanäle,Κανάλια ήχου,Sonokanaloj,Canales de sonido,,Äänikanavat,Canaux sonores,Hangcsatorna,Numero canali del suono,サウンド チャンネル,음향 채널,Geluidskanalen,Kanały dźwiękowe,Canais de som,,Canale de sunet,Количество каналов,Звучни канали, +Sound backend,SNDMNU_BACKEND,,,,Zvukový systém,Soundsystem,,Sonoservilo,Sistema de sonido,,Äänijärjestelmä,Traitement Son,Hang backend,Backend suono,サウンド バックエンド,음향 말미,Geluidsarme achterkant,System dźwiękowy,Sistema de som,,Sistem de sunet,Звуковая система,Звучни бекенд, +OpenAL options,SNDMNU_OPENAL,,,,Nastavení OpenAL,OpenAL Optionen,OpenAL ρυθμίσεις,OpenAL agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállításai,Opzioni OpenAL,OpenAL オプション,오픈에이엘 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,Setări OpenAL,Настройки OpenAL,OpenAL подешавања, +Restart sound,SNDMNU_RESTART,,,,Restartovat zvuk,Sound neu starten,,Rekomenci sonon,Reiniciar sonido,,Käynnistä ääni uudelleen,Redémarrer moteur sonore,Hang újraindítása,Resetta il suono,サウンド再起動,음향 재시작,Herstart geluid,Zresetuj dźwięk,Reiniciar som,,Reinițializare sunet,Перезапустить звук,Поново покрени звук, +Advanced options,SNDMNU_ADVANCED,,,,Pokročilá nastavení,Erweiterte Optionen,Προχήρημενες ρυθμίσεις,Altnivelaj agordoj,Opciones avanzadas,,Edistyneet asetukset,Options avancées,Haladó beállítások,Opzioni avanzate,高度なオプション,고급 설정,Geavanceerde opties,Zaawansowane Opcje,Opções avançadas,,Setări avansate,Расширенные настройки,Напредна подешавања, +Module replayer options,SNDMNU_MODREPLAYER,,,,Nastavení přehrávače modulů,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,Opcje Modułu Odtwarzacza,Opções de reprodutor de módulos,,Setări de redare a modulelor,Параметры воспроизведения модулей,Подешавања модулног риплејера, +Midi player options,SNDMNU_MIDIPLAYER,,,,Nastavení MIDI přehrávače,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,Opcje Odtwarzacza Midi,Opções de reprodutor MIDI,,Setări player MIDI,Настройки MIDI-проигрывателя,MIDI плејер подешавања, +Sound in Menus,SNDMNU_MENUSOUND,,,,Zvuk v menu,Sound in Menüs,,Sono en Menuoj,,,Ääni valikoissa,,Hang a menükben,Suono nei menù,メニューでのサウンド,,Geluid in menu's,Dźwięk w Menu,Som em menus,,Sunet in meniuri,Звук в меню,, +Advanced Sound Options,ADVSNDMNU_TITLE,,,,Pokročilá nastavení zvuku,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,Zaawansowane Opcje Dźwięku,Opções de áudio avançadas,,Setări de sunet avansate,Расширенные настройки,Напредна подешавања звука, +Sample rate,ADVSNDMNU_SAMPLERATE,,,,Vzorkovací frekvence,Samplerate,,Specimenrapideco,Frecuencia de muestreo,,Näytteenottotaajuus,Cadence de Sampling,Mintavételezési ráta,,サンプルレート,샘플링레이트,Steekproeftarief,Częstotliwość próbkowania,Taxa de amostragem,,Frecvență de eșantionare,Частота дискретизации,Фреквенција узорковања, +HRTF,ADVSNDMNU_HRTF,,,,,,,,,,,,,,,머리전달함수,,HRTF,HRTF,,HRTF,,, +OPL Synthesis,ADVSNDMNU_OPLSYNTHESIS,,,,Emulace OPL,OPL Synthese,,OPL-Sintezo,Síntesis OPL,,OPL-synteesi,Synthèse OPL,OPL szintézis,,OPLシンセサイズ,OPL 합성,OPL synthese,Synteza OPL,Síntese OPL,,Sinteză OPL,Синтез OPL,OPL синтеза, +Number of emulated OPL chips,ADVSNDMNU_OPLNUMCHIPS,,,,Počet emulovaných OPL čipů,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,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri OPL emulate,Количество эмулируемых OPL чипов,Број емулираних OPL чипа, +Full MIDI stereo panning,ADVSNDMNU_OPLFULLPAN,,,,Plné MIDI stereo,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,Pełne efekty stereo dla MIDI,Lateralidade estéreo completa para MIDI,,Panoramă stereo pentru MIDI,Полная стереопанорама для MIDI,Пуно MIDI стерео каналисање, +OPL Emulator Core,ADVSNDMNU_OPLCORES,,,,Emulační jádro OPL,OPL Emulatorkern,,OPL Imitilkerno,Núcleo de emulador OPL,,OPL-emulaattoriydin,Cœur émulateur OPL,,,OPL エミュレート コア,OPL 에뮬레이터 코어,OPL Emulator Kern,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL језгро емулације, +MIDI voices,ADVSNDMNU_MIDIVOICES,,,,Počet MIDI hlasů,MIDI Stimmen,,MIDI voĉoj,Voces MIDI,,MIDI-äänet,Voix MIDI,MIDI hangok,Voci MIDI,MIDI ボイス,MIDI 최대 음색 양,MIDI-stemmen,Głosy MIDI,Vozes MIDI,,Voci MIDI,MIDI-голоса,MIDI гласови, +FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,FluidSynth,,,,, +Global,ADVSNDMNU_GLOBAL,,,,Globální,,,Malloka,Global,,Yleinen,,,Globale,グローバル,전반적,Globaal,Globalne,Global,,,Общие,Глобално, +Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,フリーバーブ,프리버브,,,Freeverb,,,,, +Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローバル フリーバーブ,전반적 프리버브,Globale Freeverb,Globalny Freeverb,Freeverb global,,Freeverb Global,Глобальный Freeverb,Глобални Freeverb, +Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッチ セット,패치 세트,,Zestaw łatek,Banco de sons,,Set patch,Патч-набор,Печ сет, +Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,Visszaverődés,,ゲイン,쌓기,Relatief volume,Wzmocnienie,Ganho,,Amplificare,Усиление,Појачање, +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,Poziom pogłosu,Nível de reverberação,,Nivel Reverb,Уровень реверберации,Ниво одјека, +Chorus,ADVSNDMNU_CHORUS,,,,,,,Koruso,,,,,,,コーラス,코러스,,,Chorus,,Cor,Хорус,Корус, +Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,Timidity++,,,,, +ADLMidi,ADVSNDMNU_ADLMIDI,,,,,,,,,,,,,,,,,,ADLMidi,,,,, +OPNMidi,ADVSNDMNU_OPNMIDI,,,,,,,,,,,,,,,,,,OPNMidi,,,,, +Timidity config file,ADVSNDMNU_TIMIDITYCONFIG,,,,Konfigurační soubor Timidity,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,Plik konfiguracyjny Timidity,Arquivo de configuração do Timidity,,Fișier configurație Timidity,Файл конфигурации Timidity,Timidity конфигурациона датотека, +Relative volume,ADVSNDMNU_TIMIDITYVOLUME,,,,Relativní hlasitost,Relative Lautstärke,,Relativa laŭteco,Volumen relativo,,Suhteellinen äänenvoimakkuus,Volume Relatif,Relatív hangerő,Volume relativo,相対音量,비교적인 볼륨,Relatief volume,Względna głośność,Volume relativo,,Volum relativ,Относительная громкость,Релативна јачина, +WildMidi,ADVSNDMNU_WILDMIDI,,,,,,,,,,,,,,,,,,WildMidi,,,,, +WildMidi config file,ADVSNDMNU_WILDMIDICONFIG,,,,Konfigurační soubor WildMidi,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,Plik konfiguracyjny WildMidi,Arquivo de configuração do WildMidi,,Fișier configurație WildMidi,Файл конфигурации WildMidi,WildMidi конфигурациона датотека, +Select configuration,ADVSNDMNU_SELCONFIG,,,,Vybrat konfiguraci,Konfiguration wählen,,Elekti agordojn,Seleccionar configuración,,Valitse kokoonpano,Sélectionner configuration,Konfiguráció kiválasztása,Seleziona la configurazione,構成選択,설정을 고르시오,Selecteer configuratie,Wybierz konfigurację,Selecionar configuração,,Selectare configurație,Выбор конфигурации,Изабери конфигурацију, +Advanced Resampling,ADVSNDMNU_ADVRESAMPLING,,,,Pokročilé převzorkování,Erweitertes Resampling,,Altnivela respecimenado,Resampleo Avanzado,,Kehittynyt näytteenottotaajuuden muuntaminen,Resampling Avancé,Fejlett Resmapling,Resampling avanzato,高度なリサンプリング,향상된 리샘플링,Geavanceerde herbemonstering,Zaawansowane Próbkowanie,Reamostragem avançada,,Resempling avansat,Продвинутый ресэмплинг,Напредно ресампловање, +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 Emulator Core,ADVSNDMNU_ADLOPLCORES,,,,Emulační jádro OPL,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,Rdzeń Emulatora OPL,Núcleo do emulador de OPL,,Nucleu de emulare OPL,Ядро эмуляции OPL,OPL емулационо језгро, +Run emulator at PCM rate,ADVSNDMNU_RUNPCMRATE,,,,Emulátor používá PCM vzorkovací frekvenci,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,Uruchom emulator w częstotliwości PCM,Rodar emulador em taxa PCM,,Utilizare cu frecvența PCM,Использовать с частотой PCM,Покрени емулацију на PCM стопи, +Number of emulated OPL chips,ADVSNDMNU_ADLNUMCHIPS,,,,Počet emulovaných OPL čipů,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,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,Număr de cipuri GUS emulate,Количество эмулируемых чипов OPL,Број емулираних OPL чипова, +Volume model,ADVSNDMNU_VLMODEL,,,,Model hlasitosti,Lautstärkemodell,,Modelo de laŭteco,Modelo de Volumen,,Äänenvoimakkuusmalli,Modèle de Volume,Hangmodell,Modello di volume,音量モデル,모델 볼륨,Volume model,Model głośności,Modelo de volume,,Model volum,Модель громкости,Волумски модел, +OPN2 Emulator Core,ADVSNDMNU_OPNCORES,,,,Emulační jádro OPN2,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,Rdzeń Emulatora OPN2,Núcleo do emulador de OPN2,,Nucleu de emulare OPN2,Ядро эмуляции OPN2,OPN2 језгро емулације, +GUS Emulation,ADVSNDMNU_GUSEMULATION,,,,Emulace GUS,GUS Emulation,,GUS Imitado,Emulación GUS,,GUS-emulaatio,Emulation GUS,GUS Emuláció,,GUS エミュレーション,GUS 에뮬레이션,GUS-emulatie,Emulacja GUS,Emulação de GUS,,Emulare GUS,Эмуляция GUS,GUS емулација, +GUS config file,ADVSNDMNU_GUSCONFIG,,,,Konfigurační soubor GUS,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,Plik konfiguracyjny GUS,Arquivo de configuração do GUS,,Fișier configurație GUS,Файл конфигурации для GUS,GUS конфигурациона датотека, +Read DMXGUS lumps,ADVSNDMNU_DMXGUS,,,,Načíst DMXGUS soubory,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,Czytaj pliki DMXGUS,Ler lumps DMXGUS,,Citire fișiere DMXGUS,Читать файлы DMXGUS,Читај DMXGUS фајлове, +GUS memory size,ADVSNDMNU_GUSMEMSIZE,,,,Velikost paměti GUS,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,Rozmiar pamięci GUS,Tamanho de memória do GUS,,Memorie alocată pentru GUS,Размер памяти GUS,GUS величина памћења, +Number of emulated OPN chips,ADVSNDMNU_OPNNUMCHIPS,,,,Počet emulovaných OPN čipů,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,Liczba emulowanych czipów OPN,Número de chips OPN emulados,,Număr de cipuri OPN emulate,Количество эмулируемых чипов OPN,Број емулираних OPN чипова, +Use custom WOPL bank,ADVSNDMNU_ADLCUSTOMBANK,,,,Použít vlastní WOPL sadu,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,Użyj niestandardowego banku WOPL,Usar banco WOPL personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPL,Користи прилагођенуу WOPL банку, +WOPL Bank file,ADVSNDMNU_OPLBANKFILE,,,,Soubor WOPL sady,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,Plik banku WOPL,Banco WOPL,,Fișier WOPN bank,Файл с банком WOPL,WOPL фајл банка, +Use custom WOPN bank,ADVSNDMNU_OPNCUSTOMBANK,,,,Použít vlastní WOPN sadu,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,Użyj niestandardowego banku WOPN,Usar banco WOPN personalizado,,Utilizați propriul bank WOPN,Использовать собственный банк WOPN,Користи прилагођену WOPN банку, +WOPN Bank file,ADVSNDMNU_OPNBANKFILE,,,,Soubor WOPN sady,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,Plik banku WOPN,Banco WOPN,,Fișier WOPN bank,Файл с банком WOPN,WOPN фајл банка, +Aliasing,OPTVAL_ALIASING,,,,,,,Krenelaro,,,,,,,エイリアシング,에일리어싱,,,,,Dedublare,Сглаживание,Преклапање, +Linear,OPTVAL_LINEAR_1,This setting is duplicated threefold in order to allow for different grammatical gender endings,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowy,Linear,,Liniar,Линейное,Линеаран, +Linear,OPTVAL_LINEAR_2,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowa,Linear,,Liniar,Линейная,Линеаран, +Linear,OPTVAL_LINEAR_3,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,Lineáris,Lineare,リニア,선형,Lineair,Liniowe,Linear,,Liniar,Линейный,Линеаран, +Nearest,OPTVAL_NEAREST,,,,Nejbližší,Nächster Nachbar,,Plej proksima,Cercano,,Lähin,Nearest,Legközelebbi,Il più vicino,最寄り,가까이,Naast,Najbiższe,Mais próximo,,Cel mai apropriat,Ближайший,Најближе, +PCF (Low),OPTVAL_PCF_LOW,,,,PCF (nízké),PCF (niedrig),,PCF (Malalta),PCF (Bajo),,PCF (matala),PCF (Low),PCF (Alacsony),PCF (basso),PCF (低),PCF (하급),PCF (Laag),PCF (Niski),PCF (Baixo),,PCF (Scăzut),PCF (низкий),PCF (ниско), +PCF (Medium),OPTVAL_PCF_MEDIUM,,,,PCF (střední),PCF (mittel),,PCF (Meza),PCF (Medio),,PCF (keskitaso),PCF (Medium),PCF (Közepes),PCF (medio),PCF (中),PCF (중급),PCF (Medium),PCF (Średni),PCF (Médio),,PCF (Mediu),PCF (средний),PCF (средње), +PCF (High),OPTVAL_PCF_HIGH,,,,PCF (vysoké),PCF (hoch),,PCF (Alta),PCF (Alto),,PCF (korkea),PCF (High),PCF (Magas),PCF (alto),PCF (高),PCF (상급),PCF (Hoog),PCF (Wysoki),PCF (Alto),,PCF (Ridicat),PCF (высокий),PCF (високо), +Cubic,OPTVAL_CUBIC,,,,Kubická,Kubisch,,Kuba,Cúbico,,Kuutio,Cubique,Négyzetes,Cubico,キュービック,큐빅,Kubieke,Sześcienny,Cúbico,,Cub,Кубическое,Кубан, +Band-limited step,OPTVAL_BLEP,,,,Omezené krokování,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,Krok ograniczony pasmem,Passo limitado por banda,,Limitare frecvență pas-cu-pas,Пошаговое ограничение частоты,Постепено ограничење фреквенције, +Linear (Slower),OPTVAL_LINEARSLOW,,,,Lineární (pomalejší),Linear (langsamer),,Lineara (Pli malrapida),Lineal (más lento),,Lineaarinen (hitaampi),Linéaire (Lent),Lineáris (Lassabb),Lineare (più lento),リニア(遅め),선형 (느리게),Lineair (langzamer),Liniowy (wolniejszy),Linear (mais lento),,Liniar (Mai lent),Линейное (медленнее),Линеаран (спорије), +Band-limited linear,OPTVAL_BLAM,,,,Omezená lineární,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,Liniowy ograniczony pasmem,Linear limitado por banda,,Limitare frecvență liniară,Линейное ограничение частоты,Линеарно ограничење фреквенције, +Cubic (Slower),OPTVAL_CUBICSLOW,,,,Kubická (pomalejší),Kubisch (langsamer),,Kuba (Pli malrapida),Cúbico (más lento),,Kuutio (hitaampi),Cubique (Lent),Négyzetes (Lassabb),Cubico (più lento),キュービック (遅め),큐빅 (느리게),Kubieke (langzamer),Sześcienny (wolniejszy),Cúbico (mais lento),,Cub (Mai lent),Кубическое (медленнее),Кубан (спорије), +Sinc,OPTVAL_SINC,,,,,,,,Seno cardinal,,,,,,シンク,싱크,,,Seno cardinal,,Sinus cardinal,Кардинальный синус,Синк, +Note on/off only,OPTVAL_NOTEONOFFONLY,,,,Pouze začátek/konec noty,Nur für Note an/aus ,,Nur noto ek/for,Sólo 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,Tylko dla włączonych/wyłączonych notatek,Somente notas ligadas/desligadas,,Numai la activarea/oprirea notelor,Только при включении/отключении нот,Само током укључења/искључења ноте, +Full ramping,OPTVAL_FULLRAMPING,,,,Plný náběh,,,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ă,Полное наращивание,Пуно појачање, +Module Replayer Options,MODMNU_TITLE,,,,Nastavení přehrávače modulů,Modul-Spieler-Optionen,,Agordoj por Modulo-reludilo,Opciones de reproductor de módulos,,Moduulisoitinasetukset,Options Lecteur de Module,Modul lejátszó beállításai,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 재생 설정,Module-Speler-Opties,Opcje Odtwarzacza Modułów,Opções de reprodutor de módulos,,Setări de redare module,Параметры воспроизведения модулей,Подешавања модуларног реплејера, +Master volume,MODMNU_MASTERVOLUME,,,,Celková hlasitost,Grundlautstärke,,Ĉeflaŭteco,Volumen maestro,,Yleisäänenvoimakkuus,Volume maître,Fő hangerő,Volume master,全体音量,마스터 볼륨,Hoofdvolume,Całkowita głośność,Volume geral,,Volum general,Общая громкость,Глацни звук, +Quality,MODMNU_QUALITY,,,,Kvalita,Qualität,,Kvaliteco,Calidad,,Laatu,Qualité,Minőség,Qualità,クオリティ,품질,Kwaliteit,Jakość,Qualidade,,Calitate,Качество,Квалитет, +Volume ramping,MODMNU_VOLUMERAMPING,,,,Křivka hlasitosti,Lautstärkeverhalten,,Laŭteco-pligrandigado,Aumento gradual de Volumen,,Äänenvoimakkuuden kertyminen,Rampe du volume,,Ramping volume,音量ランピング,볼륨 램핑,Volume-aanvulling,Zwiększenie głośności,Rampa de volume,,Creștere volum,Наращивание громкости,Појачавање звука, +Chip-o-matic,MODMNU_CHIPOMATIC,,,,,,,,,,,,,,チップ オー マチック,칩-오-매틱,,,Chip-o-matic,,,,, +MAME OPL2,OPTVAL_MAMEOPL2,,,,,,,,,,,,,,,마메 OPL2,,,MAME OPL2,,,,, +DOSBox OPL3,OPTVAL_DOSBOXOPL3,,,,,,,,,,,,,,,도스박스 OPL3,,,DOSBox OPL3,,,,, +Java OPL3,OPTVAL_JAVAOPL3,,,,,,,,,,,,,,,자바 OPL3,,,Java OPL3,,,,, +Nuked OPL3,OPTVAL_NUKEDOPL3,,,,,,,,,,,,,,,,,,Nuked OPL3,,,,, +MAME YM2612,OPTVAL_MAMEOPN2,,,,,,,,,,,,,,,마메 YM2612,,,MAME YM2612,,,,, +Neko Project II Kai OPNA,OPTVAL_NP2OPNA,,,,,,,,,,,,,,,,,,Neko Project II Kai OPNA,,,,, +MAME YM2608,OPTVAL_MAMEOPNA,,,,,,,,,,,,,,,마메 YM2608,,,MAME YM2608,,,,, +PMDWin OPNA,OPTVAL_PMDWINOPNA,,,,,,,,,,,,,,,,,,PMDWin OPNA,,,,, +Opal OPL3,OPTVAL_OPALOPL3,,,,,,,,,,,,,,,,,,Opal OPL3,,,,, +Nuked OPL3 v1.7.4,OPTVAL_NUKEDOPL3174,,,,,,,,,,,,,,,,,,Nuked OPL3 v1.7.4,,,,, +Nuked OPN2,OPTVAL_NUKEDOPN2,,,,,,,,,,,,,,,,,,Nuked OPN2,,,,, +GENS YM2612,OPTVAL_GENSOPN2,,,,,,,,,,,,,,,,,,GENS YM2612,,,,, +Auto (Use setup of bank),ADLVLMODEL_AUTO,,,,Auto (použít nastavení sady),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),Automatycznie (Użyj ustawień banku),Automático (usar definições de banco),,Auto (configurare din bancă),Авто (настройка из банка),Аутоматски (користи намештену банку), +Generic,ADLVLMODEL_GENERIC,,,,Standardní,Allgemein,,Komuna,Genérico,,Yleinen,Générique,Általános,Generico,一般的,전형적,Algemeen,Ogólne,Genérico,,,Общий,Генерично, +OPL Native,ADLVLMODEL_NATIVE,,,,Nativní OPL,OPL Nativ,,Nativa OPL,Nativo OPL,,Luontainen OPL,OPL Natif,Natív OPL,,OPLネイティブ,고유 OPL,OPL Native,Natywne OPL,Nativo OPL,,OPL propriu,Встроенная OPL,OPL домаћи, +"DMX (Accurate, with AM bug)",ADLVLMODEL_DMX,,,,"DMX (Přesný, s AM chybou)",,,,,,,,"DMX (Pontos, de AM buggal)",,,데이터 마이닝 확장,"DMX (accuraat, met AM bug)",,"DMX (preciso, com bug de AM)",,"DMX (Precis, cu probleme în AM)","DMX (Точная, с ошибкой АМ)",, +"Apogee (Accurate, with AM bug)",ADLVLMODEL_APOGEE,,,,"Apogee (Přesný, s AM chybou)",,,,,,,,"Apogee (Pontos, de AM buggal)",,,어포지,"Apogee (accuraat, met AM bug)",,"Apogee (preciso, com bug de AM)",,"Apogee (Precis, cu probleme în AM)","Apogee (Точная, с ошибкой АМ)",, +Win9X-like (SB16),ADLVLMODEL_WIN9X,,,,Jako Windows 9X (SB16),Wie Windows 9X (SB16),,Kiel Win9X (SB16),Como Win9X (SB16),,Win9x-kaltainen (SB16),,Win9X szerű (SB16),,Win9X式 (SB16),Win9X 같게 (SB16),Win9X-achtig (SB16),Jak w Win9X (SB16),Estilo Win9X (SB16),,Similar cu Win9X (SB16),Похожая на Win9X (Вариант SB16),Као у Win9X-у (SB16), +Win9X-like (Generic FM),ADLVLMODEL_WIN9XGENERIC,,,,Jako Windows 9X (Generic 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),Jak w Win9X (Generic FM),Estilo Win9X (FM genérico),,Similar cu Win9X (Generic FM),Похожая на Win9X (Вариант Generic FM),Као у Win9X-у (Generic FM), +DMX (Without AM voice bug),ADLVLMODEL_DMX_FIXED,,,,DMX (Bez AM hlasové chyby),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 (bez głosowego błędu AM),DMX (sem bug de voz de AM),,DMX (Fără probleme în AM),DMX (Без ошибки АМ),, +Apogee (Without AM voice bug),ADLVLMODEL_APOGEE_FIXED,,,,Apogee (Bez AM hlasové chyby),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 (bez głosowego błędu AM),Apogee (sem bug de voz de AM),,Apogee (Fără probleme în AM),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,, +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 SOS (Old, with bugs)",ADLVLMODEL_HMIOLD,,,,"HMI SOS (Starý, s chybami)","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 (Stare, z błędami)","SOS HMI (antigo, com bugs)",,"HMI SOS (Vechi, cu probleme)",HMI SOS (Старый вариант с ошибками),, +Unlimited,OPTVAL_UNLIMITED,,,,Neomezené,Unlimitiert,,Senlima,Ilimitado,,Rajoittamaton,Illimité,Végtelen,Illimitato,無制限,무제한,Onbeperkt,Nieskończone,Sem limites,,Nelimitat,Без ограничений,Бескрајно, +256K,OPTVAL_256K,,,,,,,,,,,,,,,,,,256K,,,256К,, +512K,OPTVAL_512K,,,,,,,,,,,,,,,,,,512K,,,512К,, +768K,OPTVAL_768K,,,,,,,,,,,,,,,,,,768K,,,768К,, +1024K,OPTVAL_1024K,,,,,,,,,,,,,,,,,,1024K,,,1024К,, +,,Postprocessing,,,,,,,,,,,,,,,,,,,,,, +Uncharted 2,OPTVAL_UNCHARTED2,,,,,,,,,,,,,,,,,,Uncharted 2,,,,, +Hejl Dawson,OPTVAL_HEJLDAWSON,,,,,,,,,,,,,,,,,,Hejl Dawson,,,,, +Reinhard,OPTVAL_REINHARD,,,,,,,,,,,,,,,,,,Reinhard,,,,, +Palette,OPTVAL_PALETTE,,,,Paleta,,Παλέτα,Paletro,Paleta,,Paletti,,Paletta,Palette,パレット,팔레트,Palet,Paleta,Paleta,Palete,Paletă,Палитра игры,Палет, +Low,OPTVAL_LOW,,,,Nízká,Niedrig,Χαμηλό,Malalta,Bajo,,Matala,Bas,Alacsony,Basso,低,낮음,Laag,Niskie,Baixo,,Scăzut,Низкое,Ниско, +Medium,OPTVAL_MEDIUM,,,,Střední,Mittel,Μεσαίο,Meza,Medio,,Keskitaso,Moyen,Közepes,Medio,中,중간,Middel,Średnie,Médio,,Mediu,Среднее,Средње, +High,OPTVAL_HIGH,,,,Vysoká,Hoch,Υψηλό,Alta,Alto,,Korkea,Haut,Magas,Alto,高,높음,Hoog,Wysokie,Alto,,Ridicat,Высокое,Високо, +Extreme,OPTVAL_EXTREME,,,,Extrémní,Extrem,Ακράιο,Ekstrema,Extremo,,Äärimmäinen,Extrême,Extrém,Estremo,最高,매우 높음,Extreem,Ekstremalne,Extremo,,Extrem,Максимальное,Екстремно, +Obverse,OPTVAL_OBVERSEFIRST,,,,Vpřed (obvers),Obvers,Παρατήρησε,Antaŭa,Anverso,,Etupuoli,,Ellentétes,Dritto,正面,앞면,Obvers,Awers,Obverso,,Avers,Прямой,Супротно, +Reverse,OPTVAL_REVERSEFIRST,,,,Vzad (revers),Revers,Αντίστροφο,Inversa,Inverso,,Käänteinen,Inverse,Fordított,Contrario,反転,반전,Revers,Rewers,Reverso,,Invers,Обратный,Обрнуто, +Postprocessing,GLMNU_POSTPROCESS,,,,,,Μετα-επεξεργασία,Postprocezado,Postprocesado,,Jälkikäsittely,,,,ポストプロセッシング,포스트프로세싱 적용,Nabewerking,Przetwarzanie końcowe,Pós-processamento,,Postprocesare,Постобработка,Пост обрада, +Tonemap Mode,GLPREFMNU_TONEMAP,,,,Režim tónovací mapy,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,Tryb Mapowania Tonów,Tipo de tonemap,,Mod Tonemap,Режим тоун-мэппинга,Тонирано-мапни мод, +Lens distortion effect,GLPREFMNU_LENS,,,,Efekt distorze čočky,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,Efekt zniekształcenia obiektywu,Distorção de lente,Efeito de distorção da lente,Efect de distorsionare,Искажение линзы,Дисторзија објектива ефект, +FXAA Quality,GLPREFMNU_FXAA,,,,Kvalita FXAA,FXAA Qualität,FXAA ποίοτητα,Kvaliteco de FXAA,Calidad FXAA,,FXAA-laatu,Qualité FXAA,FXAA minősége,Qualità FXAA,FXAA品質,FXAA 품질,FXAA-kwaliteit,Jakość FXAA,Qualidade de FXAA,,Calitate FXAA,Качество FXAA,FXAA квалитет, +Dither output,GLPREFMNU_DITHER,,,,Dithering,Dithering,,Apliki punktojn al eligo,Dither de salida,,Sekoitussävytyksen (dithering) ulostulo,Dithering,Árnyalás kimenet,Dithering,ディザー出力,떨림 효과 출력,Dither output,Dygotanie,Dithering,,Putere Dithering,Дизеринг,Учестаност трептања, +Tonemap Palette Order,GLPREFMNU_PALTONEMAPORDER,,,,Pořadí palety tónovací mapy,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,Kolejność Palet Mapowania Tonów,Ordem da paleta tonemap,,Ordine paletă Tonemap,Порядок палитры тоун-мэпа,Тонирано-мапни палетни ред, +Tonemap Palette Exponent,GLPREFMNU_PALTONEMAPPOWER,,,,Exponent palety tónovací mapy,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,Wykładnik Palet Mapowania Tonów,Expoente da paleta tonemap,,Exponent paletă Tonemap,Экспонента палитры тоун-мэпа,Тонирано-мапни палетни експонент, +Multisample,GLPREFMNU_MULTISAMPLE,,,,Multisampling,Multisampling,,Plurspecimeno,Multisampling,,Moninäytteistys,,,,マルチサンプル,멀티샘플,,Multipróbkowanie,Multiamostragem,,Multisampling,Мультисэмплинг,Мулти-узорак, +Bloom effect,GLPREFMNU_BLOOM,,,,Efekt bloom,Bloom Effekt,,Lumŝmiro-efiko,Efecto Bloom,,Hehkutehoste (bloom),Effet surbrillance,Bloom effekt,Effetto Bloom,ブルーム エフェクト,블룸 효과,Bloom-effect,Effekt Bloom,Bloom,,Efect Bloom,Свечение,Мутан вид ефект, +Ambient occlusion quality,GLPREFMNU_SSAO,,,,Kvalita ambient occlusion,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,Jakość okluzji otoczenia,Qualidade de oclusão de ambiente,,Calitate ocluzie ambientală,Качество глобального затенения,Оклузија амбијента ефект, +Portals with AO,GLPREFMNU_SSAO_PORTALS,,,,Portály s 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,Portale z okluzją otoczenia,Portais com oclusão de ambiente,,Portaluri cu ocluzie ambientală,Порталы с глобальным затенением,Портали са AO, +Menu Blur,GLPREFMNU_MENUBLUR,,,,Rozostření pozadí v menu,Menüunschärfe,Θόλοση μενού,Malklarigo de Menuo ,Difuminación de Menú,,Valikon sumennus,Flou menu,Menü mosódás,Blur del menu,メニューブラー,메뉴 흐림 효과,Menu vervagen,Rozmycie w Menu,Desfoque do menu,Desfocagem do Menu,Neclaritate Meniu,Размытие фона меню,Блур мениа, +,,Textures,,,,,,,,,,,,,,,,,,,,,, +Texture Filter mode,GLTEXMNU_TEXFILTER,,,,Režim filtrování textur,Texturfiltermodus,,Reĝimo por Teksturfiltrado,Modo de filtro de texturas,,Pintakuviointien suodatustapa,Mode de Filtrage Texture,Textúrafilter módja,Modalità filtro texture,テクスチャーフィルター モード,텍스쳐 필터 모드,Textuurfiltermodus,Tryb Filtrowania Tekstur,Modo de filtro de textura,,Mod Filtrare Texturi,Фильтрация текстур,Текстурни филтер мод, +Anisotropic filter,GLTEXMNU_ANISOTROPIC,,,,Anisotropické filtrování,Anisotropische Filterung,,Anizotropa filtro,Filtro anisotrópico,,Anisotrooppinen suodatus,Filtre Anisotropique,Anizotropikus filter,Filtro anisotropico,異方性フィルター,이방성 필터,Anisotroopfilter,Filtr anizotropowy,Filtro anisotrópico,,Filtrare Anizotropică,Анизотропная фильтрация,Анизотропни фолтер, +None (nearest mipmap),OPTVAL_NONENEARESTMIPMAP,,,,Žádné (mipmapa - nejbližší soused),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),Brak (najbliższa mipmapa),Nenhum (mipmap mais próximo),,Niciuna (mipmap de apropriere),Нет (ближайший мипмап),Ништа (најближи мипмап), +None (linear mipmap),OPTVAL_NONELINEARMIPMAP,,,,Žádné (mipmapa - lineární),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),Brak (liniowa mipmapa),Nenhum (mipmap linear),,Niciuna (mipmap liniar),Нет (линейный мипмап),Ништа (линеаран мипмап), +None (trilinear),OPTVAL_NONETRILINEAR,,,,Žádné (trilineární),Aus (trilinear),,Nenio (trilinia),Ninguno (trilineal),,Ei mitään (trilineaarinen),Aucun (mipmap trilinéaire),Semmilyen (trilineáris),Nessuno (mipmap trilineare),なし(トライリニア),없음 (삼선형),Geen (trilineair),Brak (trzyliniowe),Nenhum (trilinear),,Niciuna (trilinar),Нет (трилинейная),Ништа (трилинеарно), +Bilinear,OPTVAL_BILINEAR,,,,Bilineární,,,Dulinia,Bilineal,,Bilineaarinen,Bilinéaire,Bilineáris,Bilineare,バイリニア,쌍선형,Bilineair,Dwuliniowe,Bilinear,,Biliniar,Билинейная,Билинеарно, +Trilinear,OPTVAL_TRILINEAR,,,,Trilineární,,,Trilinia,Trilineal,,Trilineaarinen,Trilinéaire,Trilineáris,Trilineare,トライリニア,삼선형,Trilineair,Trzyliniowe,Trilinear,,Triliniar,Трилинейная,Трилинеарно, +2x,OPTVAL_2X,,,,,,,2-oble,,,,,,,,,,,2x,,,,, +4x,OPTVAL_4X,,,,,,,4-oble,,,,,,,,,,,4x,,,,, +8x,OPTVAL_8X,,,,,,,8-oble,,,,,,,,,,,8x,,,,, +16x,OPTVAL_16X,,,,,,,16-oble,,,,,,,,,,,16x,,,,, +32x,OPTVAL_32X,,,,,,,32-oble,,,,,,,,,,,32x,,,,, +Texture Options,GLTEXMNU_TITLE,,,,Nastavení textur,Texturoptionen,,Agordoj de Teksturoj,Opciones de texturas,,Pintakuviointiasetukset,Options Textures,Textúra Beállítások,Opzioni Texture,テクスチャー オプション,텍스쳐 설정,Textuur Opties,Opcje Tekstur,Opções de Textura,,Setări Texturi,Настройки текстур,Подешавања текстура, +Textures enabled,GLTEXMNU_TEXENABLED,,,,Povolit textury,Texturen an,,Teksturoj ŝaltitaj,Texturas activadas,,Pintakuvioinnit otettu käyttöön,Textures activées,Textúrák bekapcsolása,Texture abilitate,テクスチャー有効,텍스쳐 사용,Texturen ingeschakeld,Tekstury włączone,Texturas ativadas,,Texturi Activate,Включить текстуры,Текстуре омогућене, +Enable hires textures,GLTEXMNU_ENABLEHIRES,,,,Povolit textury ve vysokém rozlišení,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,Włącz tekstury wysokiej jakości,Habilitar texturas de alta resolução,,Texturi de înaltă rezoluție,Текстуры с высоким разрешением,Омогући текстуре велике резолуције, +High Quality Resize mode,GLTEXMNU_HQRESIZE,,,,Režim zvětšovače textur,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,Tryb Wysokiej Jakości Zmieniania Rozmiaru,Modo de Redimensionamento de Alta Qualidade,,Mod Redimensionare de Înaltă Calitate,Масштабирование текстур,Промена величине високог квалитета мод, +High Quality Resize multiplier,GLTEXMNU_HQRESIZEMULT,,,,Faktor zvětšovače textur,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,Mnożnik Wysokiej Jakośći Rozmiaru,Multiplicador de Redimensionamento de Alta Qualidade,,Factor de Scalare,Множитель масштабирования,Промена величине високог квалитета мултипликатор, +This mode requires %d times more video memory,GLTEXMNU_HQRESIZEWARN,,,,Tento režim potřebuje %dkrát více paměti,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.,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 пута више видео меморије, +Resize textures,GLTEXMNU_RESIZETEX,,,,Škálovat textury,Texturen skalieren,,Regrandigi teksturojn,Ajustar texturas,,Muuta pintakuviointien kokoa,Mise à l'échelle textures,Textúrák újraméretezése,Resize delle texture,リサイズ テクスチャー,텍스쳐 리사이징,Texturen schalen,Zmień rozmiar tekstur,Redimensionar texturas,,Redimensionare texturi,Масштабирование текстур,Промена величине текстура, +Resize sprites,GLTEXMNU_RESIZESPR,,,,Škálovat sprity,Sprites skalieren,,Regrandigi spritojn,Ajustar sprites,,Muuta spritejen kokoa,Mise à l'échelle sprites,Sprite-ok újraméretezése,Resize degli sprite,リサイズ スプライト,스프라이트 리사이징,Sprites schalen,Zmień rozmiar sprite'ów,Redimensionar sprites,,Redimensionare sprite-uri,Масштабирование спрайтов,Промена величине спрајтова, +Resize fonts,GLTEXMNU_RESIZEFNT,,,,Škálovat fonty,Zeichensätze skalieren,,Regrandigi tiparojn,Ajustar fuentes,,Muuta kirjasinten kokoa,Mise à l'échelle texte,Betűk újraméretezése,Resize dei font,リサイズ フォント,폰트 리사이징,Lettertypen schalen,Zmień rozmiar czcionek,Redimensionar fontes,,Redimensionare fonturi,Масштабирование шрифтов,Промена величине фонта, +Resize model skins,GLTEXMNU_RESIZESKN,,,,Škálovat skiny modelů,,,Regrandigi haŭtojn de modeloj,Ajustar texturas de modelo,,Muuta ulkoasujen kokoa,,Model fazon újraméretezése,Ridimensiona skin modello,,,,Zmień rozmiar modelu,Redimensionar skins de modelos,,Redimensionare modele,Масштабирование обликов моделей,, +Precache GL textures,GLTEXMNU_PRECACHETEX,,,,Přednačíst GL textury do cache,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,Tekstury GL pamięci podręcznej,Precachê de texturas GL,,Preîncărcarcă texturile GL,Кэшировать GL-текстуры,Прикеширане GL текстуре, +Video Mode,VIDMNU_TITLE,,,,Režim displeje,Videomodus,Λειτουργία βίντεο,Video-Reĝimo,Modos de video,,Videotila,Mode Vidéo,Videó mód,Modalità video,ビデオ 調整,화면 설정,Videomodus,Tryb Wideo,Modo de vídeo,,Mod Video,Настройки видеорежима,Видео мод, +Notebook Switchable GPU,DSPLYMNU_GPUSWITCH,,,,Přepínatelné GPU pro notebooky,GPU Umschaltung für Notebooks,,Kajero-Ŝanĝebla GPU,GPU Altern. 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,Zmiana GPU Notebooka,Placa de vídeo alternável de notebook,,Placă Video Alternativă pentru Notebook,Использование GPU ноутбука,Користи GPU ноутбук, +Scaled (Nearest),OPTVAL_SCALENEAREST,,,,Škálován (nejbližší),Skaliert (nächster Nachbar),,Skalita (Plej proksime),Escalado (Cercano),,Skaalattu (läheisin),Mis à l'échelle (Proche Voisin),Átméretezett (Közeli),Scalato (più vicino),スケーリング (最寄り),확대 (가깝게),Geschaald (Dichtstbijzijnd),Przeskalowany (Najbliższy),Redimensionado (mais próximo),Redimensionado (Apróximado),Redimensionat (Cel mai aproape),Масштабировать (ближайшее),Скалиран (најближи), +Scaled (Linear),OPTVAL_SCALELINEAR,,,,Škálován (lineární),Skaliert(linear),,Skalita (Linia),Escalado (Lineal),,Skaalattu (lineaarinen),Mis à l'échelle (Linéaire),Átméretezett (Lineáris),Scalato (lineare),スケーリング (リニア),확대 (선형 식),Geschaald (Lineair),Przeskalowany (Liniowy),Redimensionado (linear),,Redimensionat (Liniar),Масштабировать (линейное),Скалиран (линеарно), +Letterbox,OPTVAL_LETTERBOX,,,,,,,Leterkesto,Barras Negras,,Mustat reunat,,Levágott,Bande nere,レターボックス,레터박스,Brievenbus,,Barras pretas,,Ecran Parțial,Экранное каше,Поштанско сандуче, +Stretch,OPTVAL_STRETCH,,,,Roztažený,Strecken,,Streĉi,Estrechado,Estrecho,Venytetty,Etirer,Nyújtott,Disteso,伸縮,늘림,Rek,Rozciągnięty,Esticado,,Lărgire,Растянутый,Растегнуто, +Render Mode,VIDMNU_RENDERMODE,,,,Režim rendereru,Rendermodus,,Bildigo-Reĝimo,Modo de Renderizado,,Hahmonnustila,Mode de Rendu,Render Mód,Modalità rendering,レンダラー,렌더링 설정,Rendermodus,Tryb Renderowania,Modo de renderização,,Mod Video,Режим отображения,Рендер мод, +Fullscreen,VIDMNU_FULLSCREEN,,,,Přes celou obrazovku,Vollbild,Πλήρης οθόνη,Plena ekrano,Pantalla completa,,Koko näyttö,Plein écran,Teljes Képernyő,Schermata piena,全画面,전체화면,Volledig scherm,Pełen Ekran,Tela cheia,Ecrã cheio,Ecran Complet,Полный экран,Цео екран, +Retina/HiDPI support,VIDMNU_HIDPI,,,,Podpora Retiny/HiDPI,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,Wsparcie Retina/HiDPI,Suporte para Retina/HiDPI,,Suport Retina/HiDPI,Поддержка Retina/HiDPI,Retina/HiDPI подршка, +Aspect ratio,VIDMNU_ASPECTRATIO,,,,Poměr stran,Seitenverhältnis,,Ekran-proporcio,Relación de aspecto,,Kuvasuhde,Rapport D'Aspect,Képarány,Proporzioni,アスペクト比,종횡비,Beeldverhouding,Wpółczynnik proporcji,Proporção de tela,Proporção de ecrã,Aspect Imagine,Соотношение сторон,Однос гледишта, +Force aspect ratio,VIDMNU_FORCEASPECT,,,,Vynutit poměr stran,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,Wymuś współczynnik proporcji,Forçar proporção de tela,Forçar proporcção de ecrã,Forțează aspectul imaginii,Принудительное соотношение сторон,Присили однос гледишта, +Forced ratio style,VIDMNU_CROPASPECT,,,,Vynucený poměr stran,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,Wymuszony styl współczynnika,Estilo de proporção forçado,,Forțează tipul proporțiilor,Тип принудительного соотношения сторон,Присиљен стил односа, +Enable 5:4 aspect ratio,VIDMNU_5X4ASPECTRATIO,,,,Povolit poměr stran 5:4,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,Włącz współczynnik proporcji 5:4,Ativar proporção de tela 5:4,,Activează formatul 5:4,Включить соотношение сторон 5:4,Омогући 5:4 однос гледишта, +Resolution scale,VIDMNU_SCALEMODE,,,,Škálování rozlišení,Skalierung,,Distingivo-skalo,Escala de Resolución,,Resoluution skaalaus,Echelle de Résolution,Felbontás mérete,Scala di risoluzione,画面スケール,해상도 크기,Resolutieschaal,Skala rozdzielczości,Escala de resolução,,Scară rezoluție,Масштабирование,Резолуцијска скала, +Scale Factor,VIDMNU_SCALEFACTOR,,,,Faktor rozlišení,Skalierungsfaktor,,Skalfaktoro,Factor de Escala,,Skaalauskerroin,Facteur d'échelle,Méretezési Faktor,Fattore di scala,スケール倍率,축척 펙터,Schaalfactor,Współczynnik Skali,Fator de escala,,Factor Scalare,Значение масштаба,Фактор скалирања, +Use Linear Scaling (Fullscreen),VIDMNU_USELINEAR,,,,Použít lineární škálování (přes celou obrazovku),Lineare Skalierung (Vollbild),,Uzi Linian Skaladon (Plenekrana),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),Użyj Liniowego Skalowania (Pełen Ekran),Usar escala linear (tela cheia),Usar escala linear (ecrã cheio),Folosește Scalarea Liniară (Ecran Complet),Линейное масштабирование (полный экран),Користи линеарно скалирање (цео екран), +Custom Pixel Scaling,VIDMNU_CUSTOMRES,,,,Vlastní škálování pixelů,Benutzerdefinierte Skalierung,,Adaptita Bildero-Skalo,Escalado de Pixel Personalizado,,Mukautettu skaalaus,Résolution Personalisée,Egyéni Pixelméretezés,Scaling dei pixel personalizzato,カスタム ピクセルスケール,사용자 지정 픽셀 크기 조정,Aangepaste pixelschaalvergroting,Niestandardowe Skalowanie Pikseli,Escala de pixels personalizada,,Scară Pixeli Personalizată,Масштабирование пикселов,Пиксел скалирање, +Custom Width,VIDMNU_CUSTOMX,,,,Vlastní šířka,Benutzerdefinierte Breite,,Adaptita Larĝeco,Ancho Personalizado,,Mukautettu leveys,Largeur Personalisée,Egyéni szélesség,Lunghezza,カスタム 幅,사용자 지정 너비,Aangepaste breedte,Niestandardowa Szerokość,Largura personalizada,,Lățime Personalizată,Длина,Ширина, +Custom Height,VIDMNU_CUSTOMY,,,,Vlastní výška,Benutzerdefinierte Höhe,,Adaptita Alteco,Alto Personalizado,,Mukautettu korkeus,Hauteur Personalisée,Egyéni magasság,Altezza,カスタム 高さ,사용자 지정 높이,Aangepaste hoogte,Niestandardowa Wysokość,Altura personalizada,,Înălțime Personalizată,Высота,Висина, +Apply Changes (Windowed),VIDMNU_APPLYW,,,,Použít změny (v okně),Änderungen anwenden (Fenster),,Apliki Ŝanĝojn (Fenestrita),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),Zatwierdź Zmiany (Okno),Aplicar alterações (janela),,Aplică Schimbările (Mod Fereastră),Сохранить изменения (оконный режим),Примени промене (прозор), +Apply Changes (Fullscreen),VIDMNU_APPLYFS,,,,Použít změny (přes celou obrazovku),Änderungen anwenden (Vollbild),,Apliki Ŝanĝojn (Plenekrana),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),Zatwierdź Zmiany (Pełen Ekran),Aplicar alterações (tela cheia),Aplicar alterações (ecrã cheio),Aplică Schimbările (Mod Ecran Complet),Сохранить изменения (полный экран),Примени промене (цели екран), +Choose Resolution Preset,VIDMNU_RESPRESET,,,,Vybrat přednastavené rozlišení,Auflösungsvoreinstellung,,Elektu Agordaĵon por Distingivo,Seleccionar Preset de Resolución,,Valitse ennalta määritetty resoluutio,Choisir paramètre personalisé,Felbontási Sablon Kiválasztása,Scegli preset di risoluzione,解像度プリセットを選ぶ,해상도 사전 설정 선택,Kies een vooraf ingestelde resolutie,Wybierz Zestaw Rozdzielczości,Escolher resolução predefinida,,Alege Rezoluția Predefinită,Выбор пресета разрешения,Резолуцијска подешавања, +Custom Resolution Presets,VIDMNU_RESPRESETTTL,,,,Vlastní přednastavení rozlišení,Benutzerdefinierte Auflösungsvoreinstellungen,,Adaptitaj Antaŭagordoj por Distingivo,Seleccionar Preset de Resoluciones,,Ennalta määritetyt mukautetut resoluutiot,Résolutions Personalisée,Egyéni Felbontási Sablonok,Preset di risoluzione personalizzati,カスタム解像度プリセット,사용자 지정 해상도 미리 조정,Vooraf ingestelde aangepaste resoluties,Niestandardowe Zestawy Rozdzielczości,Predefinições de resolução personalizadas,,Rezoluții Personalizate,Пользовательские пресеты,Резолуцијска подешавања, +Preset Resolution Modes,VIDMNU_RESPRESETHEAD,,,,Přednastavená rozlišení,Vordefinierte Auflösungsmodi,,Antaŭagordaj Distingivo-Reĝimoj,Modos de Preset de Resolución,,Ennalta määritetyt resoluutiotilat,Choisir mode de Résolution,Felbontási Sablon Módok,Modalità preset di risoluzione,解像度モードの調整,해상도 미리 조정 모드,Vooraf ingestelde resolutiemodi,Tryby Zestawów Rozdzielczości,Modos de resolução predefinidas,,Rezoluții Predefinite,Доступные разрешения,Постављени резолуцијски модови, +4:3 Aspect,VIDMNU_ASPECT43,,,,Poměr stran 4:3,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,Proporcje 4:3,Proporção 4:3,,Aspect 4:3,Соотношение сторон 4:3,4:3 гледиште, +5:4 Aspect,VIDMNU_ASPECT54,,,,Poměr stran 5:4,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,Proporcje 5:4,Proporção 5:4,,Aspect 5:4,Соотношение сторон 5:4,5:4 гледиште, +16:9 Aspect,VIDMNU_ASPECT169,,,,Poměr stran 16:9,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,Proporcje 16:9,Proporção 16:9,,Aspect 16:9,Соотношение сторон 16:9,16:9 гледиште, +16:10 Aspect,VIDMNU_ASPECT1610,,,,Poměr stran 16:10,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,Proporcje 16:10,Proporção 16:10,,Aspect 16:10,Соотношение сторон 16:10,16:10 гледиште, +21:9 Aspect,VIDMNU_ASPECT219,,,,Poměr stran 21:9,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,Proporcje 21:9,Proporção 21:9,,Aspect 21:9,Соотношение сторон 21:9,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,Kleinstmögliche Auflösung,,Plej Malpli Ebla Skalo,Menor Escala Posible,,Pienin mahdollinen skaalaus,Echelle la plus faible,Lehető legkisebb méret,Scala minima,可能な限り最小,,Laagst mogelijk schaal,Najniższa możliwa skala,Menor escala possível,,Cea mai Mică Scară Posibilă,Наименьший возможный масштаб,, +Custom,OPTVAL_CUSTOM,,,,Vlastní,Benutzerdefiniert,,Adaptita,Personalizado,,Mukautettu,Modifié,Egyéni,Personalizzato,カスタム,사용자 지정,Gebruikergedefinieerd,Niestandardowe,Personalizado,,Personalizat,Польз.,Прилагођ., +Max FPS,VIDMNU_MAXFPS,,,,Maximální FPS,,,Maksimumaj Kadroj Sekunde,Límite de FPS,,Kuvataajuuden rajoitin,,,FPS Massimi,最大FPS値,,Max FPS,Maksymalna ilość klatek,FPS máximo,,Cadre pe secundă,Макс. частота кадров,, +60 fps,OPTVAL_60FPS,,,,,,,,,,60 kuvaa/s,,,,,,,,60 FPS,,,60 кадров,, +75 fps,OPTVAL_75FPS,,,,,,,,,,75 kuvaa/s,,,,,,,,75 FPS,,,75 кадров,, +90 fps,OPTVAL_90FPS,,,,,,,,,,90 kuvaa/s,,,,,,,,90 FPS,,,90 кадров,, +120 fps,OPTVAL_120FPS,,,,,,,,,,120 kuvaa/s,,,,,,,,120 FPS,,,120 кадров,, +144 fps,OPTVAL_144FPS,,,,,,,,,,144 kuvaa/s,,,,,,,,144 FPS,,,144 кадра,, +200 fps,OPTVAL_200FPS,,,,,,,,,,200 kuvaa/s,,,,,,,,200 FPS,,,200 кадров,, +Preferred Rendering API,VIDMNU_PREFERBACKEND,,,,Upřednostňované render 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,Preferowany interfejs API renderowania,API de renderização preferida,,API Video Preferat,Предпочтительный интерфейс отображения,Преферред АПИ приказивања, +OpenGL,OPTVAL_OPENGL,,,,,,,,,,,,,,,,,,OpenGL,,,,, +Vulkan,OPTVAL_VULKAN,,,,,,,,,,,,,,,,,,Vulkan,,,,, +SoftPoly,OPTVAL_SOFTPOLY,,,,,,,,,,,,,,,,,,SoftPoly,,,,, +,,Miscellaneous Options,,,,,,,,,,,,,,,,,,,,,, +Miscellaneous Options,MISCMNU_TITLE,,,,Ostatní nastavení,Verschiedene Optionen,,Diversaĵaj Agordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,Egyéb beállítások,Opzioni miste,その他のオプション,그 외 설정,Diverse opties,Różne Opcje,Outras opções,,Setări Suplimentare,Дополнительные настройки,Разна подешавања, +Merge left+right Alt/Ctrl/Shift,MISCMNU_MERGEKEYS,,,,Kombinovat pravý a levý Alt/Ctrl/Shift,Linke und rechte Umschalt/Strg/Alt zusammenfassen,,Kunigi maldekstran+dekstran Alt/Ctrl/Shift,Combinar izq.+der. Alt/Ctrl/Mayús,,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,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, +Alt-Enter toggles fullscreen,MISCMNU_WINFULLSCREENTOGGLE,,,,Alt-Enter přepíná celou obrazovku,Alt-Enter schaltet Vollbild an/aus,,Alt+Enter klavo 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 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 пребацује на цео екран, +Command-F toggles fullscreen,MISCMNU_MACFULLSCREENTOGGLE,,,,Command-F přepíná celou obrazovku,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,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 пребацује на цео екран, +Enable autosaves,MISCMNU_ENABLEAUTOSAVES,,,,Povolit automatické ukládání,Automatisches Speichern,,Ŝalti aŭtokonservojn,Activar autoguardado,,Ota käyttöön automaattiset tallennukset,Activer Sauvegardes auto,Automentések engedélyezése,Abilita i salvataggi automatici,オートセーブを有効化,빠른 저장 허용,Automatisch opslaan inschakelen,Włącz autozapis,Ativar salvamento automático,Permitir gravação automática,Permite salvări automate,Автосохранения,Омогући аутосејвове, +Number of autosaves,MISCMNU_AUTOSAVECOUNT,,,,Počet automaticky uložených her,Anzahl von automatischen Speicherständen,,Kvanto da aŭtokonservoj,Número de autoguardados,,Automaattisten tallennusten lukumäärä,Total de sauvegardes auto,Automentések száma,Numero di salvataggi automatici,オートセーブの最大数,빠른 저장 수,Aantal auto-opslagen,Liczba autozapisów,Número de salvamentos automáticos,Número de gravações automáticos,Număr salvări automate,Количество автосохранений,Број аутоматских чувања, +Save/Load confirmation,MISCMNU_SAVELOADCONFIRMATION,,,,Potvrzení o uložení/načtení,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,Potwierdzenie zapisu/wczytania,Confirmação ao salvar/carregar,Confirmação ao gravar/carregar,Dialog de confirmare la Salvare/Încărcare,Подтверждение при сохранении/загрузке,Потврђивање током чувања/учитавања, +Disable keyboard cheats,MISCMNU_NOCHEATS,,,,Vypnout cheaty z klávesnice,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,Wyłącz Oszustwa z Klawiatury,Desativar trapaças de teclado,,Dezactivează codurile din tastatură,Отключить клавиатурные чит-коды,, +Quicksave rotation,MISCMNU_QUICKSAVEROTATION,,,,Rotace rychle uložených her,Schnellspeicherrotation,,Rotacio de rapidkonservo,Rotación de Salvado Rápido,,Pikatallennuskierto,Rotation Sauvegardes Rapides,Gyorsmentés forgás,Rotazione del quicksave,クイックセーブ間隔,빠른 저장 간격,Rouleer snelopslag,Rotacja szybkich zapisów,Rotação de salvamentos rápidos,,Rotație salvări automate,Чередовать слоты для быстрых сохранений,Окретање брзих чувања, +Number of quicksaves in rotation,MISCMNU_QUICKSAVECOUNT,,,,Počet rychle uložených her v rotaci,Anzahl Schnellspeicherplätze,,Nombro da rapidkonservitaj ludoj en rotaciado,Número de Salvados 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,Ilość szybkich zapisów w rotacji,Número de salvamentos rápidos em rotação,,Număr salvări rapide în rotație,Кол-во слотов для быстрых сохранений,Број брзих чувања у окретању, +Disable Menu Clean Scaling,MISCMNU_CLEANMENU,,,,Zakázat čisté škálování nabídek,Gleichmäßige Menüskalierung deaktivieren,,Malebligi Puran Skaladon en Menuoj,,,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,Wyłącz Czyste Skalowanie Menu,Desativar escala limpa do menu,,Dezactivează Scara Nouă a Meniurilor,,, +Default Crosshair,HUDMNU_CROSSHAIR,,,,Výchozí zaměřovač,Standard-Fadenkreuz,,Defaŭlta Reteto,Retícula por defecto,,Oletustähtäin,Viseur par défaut,Alap célkereszt,Mirino di default,デフォルトの照準,기본 조준점,Standaard dradenkruis,Domyślny celownik,Mira padrão,,Țintă implicită,Тип прицела,Уобичајени нишан, +Crosshair color,HUDMNU_CROSSHAIRCOLOR,,,Crosshair colour,Barva zaměřovače,Fadenkreuzfarbe,,Retetokoloro,Color de la retícula,,Tähtäimen väri,Couleur Viseur,Célkereszt színe,Colore mirino,照準色,조준점 색깔,Dradenkruis kleur,Kolor celownika,Cor da mira,,Culoare țintă,Цвет прицела,Боја нишана, +Crosshair shows health,HUDMNU_CROSSHAIRHEALTH,,,,Zaměřovač zobrazuje zdraví,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,Celownik pokazuje zdrowie,Exibir saúde na mira,Mostra vida na mira,Ținta afișează starea sănătății,Цвет прицела по состоянию здоровья,Нишан приказује здравље, +Scale crosshair,HUDMNU_CROSSHAIRSCALE,,,,Velikost zaměřovače,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,Skala celownika,Redimensionar mira,,Dimensiune țintă,Размер прицела,Размера нишана, +Standard,OPTVAL_YES_STANDARD,copied from elsewhere,,,Standardní,,Πρότυπο,Norma,Estándar,,Normaali,,Alap,,標準,기본,Standaard,Standard,Padrão,,,Стандартный,Стандардни, +Enhanced,OPTVAL_YES_ENHANCED,,,,Vylepšené,Verbessert,Ενισχυομένο,Bonigita,Mejorado,,Paranneltu,Amélioré,Fejlesztett,Migliorata,強調,고급,Verbeterd,Ulepszone,Melhorado,,Îmbunătățită,Улучшенный,Побољшани, +Language,OPTMNU_LANGUAGE,,,,Jazyk,Sprache,Γλώσσα,Lingvo,Idioma,,Kieli,Langage,Nyelv,Lingua,言語設定,언어,Taal,Język,Idioma,,Limbă,Язык,Језик, +,,Reverb editor,,,,,,,,,,,,,,,,,,,,,, +Undo Changes,TXT_UNDOCHANGES,,,,Zrušit změny,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,Cofnij Zmiany,Desfazer alterações,,Anulează Modificările,Отменить изменения,Поништи промене, +Select Environment,REVMNU_SELECT,,,,Vybrat prostředí,Umgebung wählen,Επιλογή Περιβάλλοντος,Elekti Medion,Seleccionar Ambiente,,Valitse tila,Sélectionner un environnement,Környezet Kiválasztása,Seleziona ambiente,反響選択,환경 선택,Selecteer omgeving,Wybierz Środowisko,Selecione o ambiente,,Alegere Mediu,Выбрать окружение,Изабери окружење, +Test Environment,REVMNU_TEST,,,,Testovat prostředí,Umgebung testen,Δοκιμαστκό Περιβάλλον,Provi Medion,Probar Ambiente,,Testaa tilaa,Tester un environnement,Környezet Tesztelése,Testa ambiente,反響テスト,환경 테스트,Test omgeving,Testuj Środowisko,Testar ambiente,,Testare Mediu,Тестировать окружение,Тестирај окружење, +Edit Environment,REVMNU_EDIT,,,,Upravit prostředí,Umgebung editieren,Επεξεργασία Περιβάλλοντος,Modifi Medion,Editar Ambiente,,Muokkaa tilaa,Modifier un environnement,Környezet Szerkesztése,Modifica ambiente,反響編集,환경 편집,Omgeving bewerken,Edytuj Środowisko,Editar ambiente,,Editare Mediu,Редактировать окружение,Уреди окружење, +New Environment,REVMNU_NEW,,,,Nové prostředí,Neue Umgebung,Νέο Περιβάλλον,Nova Medio,Nuevo Ambiente,,Uusi tila,Nouveau environnement,Új Környezet,Nuovo ambiente,新規反響設定,새로운 환경 생성,Nieuwe omgeving,Nowe Środowisko,Novo ambiente,,Mediu Nou,Новое окружение,Ново окружење, +Revert settings,REVMNU_REVERT,,,,Obnovit nastavení,Zurücksetzen,Επαναφορά Ρυθμίσεων,Malfari agordojn,Revertir Configuración,,Palauta asetukset,Réinitialiser les paramètres,Változtatások elvetése,Ripristina le impostazioni,設定を戻す,설정 되돌리기,Instellingen terugzetten,Przywróć ustawienia,Reverter configurações,,Revenire la setările precedente,Настройки по умолчанию,Врати подешавања, +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,,,,,,,Aerabsorbo 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 Refrenco,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 Refrenco,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,Basierend auf,Βασισμένο σε,Bazita de,Basado En,,Perustana,Basé sur,Minta,Basato su,音響の元,음향 원본,Gebaseerd op,Bazowane na,Baseado em,,Bazat pe,Основано на,Засновано на, +Name,REVMNU_Name,,,,Název,,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Nazwa,Nome,,Nume,Название,Назив, +ID #1,REVMNU_ID_1,,,,,,ID #1,Identigo #1,ID Nº1,,,,,ID N°1,,아이디 #1,,ID #1,ID #1,,,ID №1,, +ID #2,REVMNU_ID_2,,,,,,ID #2,Identigo #2,ID Nº2,,,,,ID N°2,,아이디 #2,,ID #2,ID #2,,,ID №2,, +Create,REVMNU_Create,,,,Vytvořit,Erstellen,Δημιουργία,Krei,Crear,,Luo,Créer,Készítés,Creare,作成,생성,Aanmaken,Stwórz,Criar,,Creare,Создать,Направи, +Save...,REVMNU_Save,,,,Uložit...,Speichern...,Αποθήκευση,Konservi...,Guardar...,,Tallenna...,Sauvegarder...,Mentés...,Salvare...,セーブする...,저장 하기...,Opslaan...,Zapisz...,Salvar...,,Salvare...,Сохранить...,Сачувај..., +File name,REVMNU_File_name,,,,Název souboru,Dateiname,Όνομα αρχείου,Dosiernomo,Nombre de Archivo,,Tiedostonimi,Nom de fichier,Fájlnév,Nome del file,ファイル名,파일 이름,Bestandsnaam,Nazwa pliku,Nome do arquivo,,Nume fișier,Название файла,Назив фајла, +Environments to save,REVMNU_Environments_to_save,,,,Prostředí k uložení,Zu speichernde Umgebungen,Περιβάλλοντα για αποθήκευση,Medioj por konservi,Ambientes para Guardar,,Tallennettavat tilat,Environnements à sauvegarder,Mentendő Környezetek,Ambienti da salvare,音響を保存,저장할 공간,Omgevingen om op te slaan,Środowiska do zapisu,Ambientes para salvar,,Medii de salvat,Сохранить окружения...,Окружења за чување, +,,Vulkan,,,,,,,,,,,,,,,,,,,,,, +Vulkan Options (Experimental),DSPLYMNU_VKOPT,,,,Nastavení Vulkanu (Experimentální),Vulkan Optionen (Experimentell),Vulka Ρυθμίσεις (Πειραματικές),Vulkan Agordoj (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),Opcje Vulkan (Eksperymentalne),Opções de Vulkan (experimental),,Setări Mod Vulkan (În curs de testare),Настройки Vulkan (экспериментальные),Vulkan подешавања (експериментална), +Vulkan Options,VK_TITLE,,,,Nastavení Vulkanu,Vulkan Optionen,Vulkan Ρυθμίσεις,Vulkan Agordoj,Opciones de Vulkan,,Vulkan-asetukset,Options Vulkan,Vulkan Beállítások,Opzioni Vulkan,Vulkan機能オプション,벌칸 설정,Vulkan-opties,Opcje Vulkan,Opções de Vulkan,,Setări Mod Vulkan,Настройки Vulkan,Vulkan подешавања, +Enable Vulkan,VKMNU_ENABLE,,,,Povolit Vulkan,Aktiviere Vulkan,Ενεργοποιηση του Vulkan,Ŝalti Vulkan,Activar Vulkan,,Ota käyttöön Vulkan,Activer Vulkan,Vulkan Engedélyezése,Abilita Vulkan,Vulkanを有効化,벌칸 렌더러 사용,Vulkan inschakelen,Włącz Vulkan,Ativar Vulkan,,Activează modul video Vulkan,Включить Vulkan,Омогући Vulkan, +Vulkan Device ID,VKMNU_DEVICE,,,,ID zařízení Vulkanu,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,ID urządzenia Vulkan,ID do dispositivo Vulkan,,ID Dispozitiv Vulkan,ID устройства Vulkan,Vulkan ID уређаја, +High Dynamic Range,VKMNU_HDR,,,,Vysoký dynamický rozsah (HDR),,Υψηλό Δυναμική Εμβέλεια,Alta Dinamika Intervalo,Alto Rango Dinámico,,Korkea dynamiikka-alue (HDR),,,,ハイダイナミックレンジ,하이 다이나믹 레인지,Hoog dynamisch bereik,Obraz HDR,Alto alcance dinâmico (HDR),,HDR,Высокий динамический диапазон (HDR),HDR, +Warning: The Vulkan renderer is highly experimental!,VK_WARNING,,,,Varování: Vulkan renderer je velmi experimentální!,Achtung: Der Vulkan Renderer ist noch sehr experimentell!,Προειδοποίηση: Ο Vulkan renderer είναι υψηλά πειραματικός!,Averto: La Vulkan bildigilo 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!,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 рендерер је врло експерименталан!, +These options will require a restart to take effect.,VK_RESTART,,,,Tato nastavení vyžadují restart hry.,Diese Option erfordert einen Neustart!,Αυτές η ρυθμίσεις θα χρειαστούνε επανεκκίνηση για να ισχύσουν,Ĉi tiuj agordoj bezonos rekomencon 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.,"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 да би промене ступиле на снагу., +Select Vulkan Device,VKMNU_DEVICESELECT,This is not yet implemented - but it is planned,,,Vybrat zařízení Vulkanu,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,Wybierz Urządzenie Vulkan,Selecione o dispositivo Vulkan,,Selectare Dispozitiv Vulkan,Выберите устройство Vulkan,Изаберите Vulkan уређај, +,,Texture scaling,,,,,,,,,,,,,,,,,,,,,, +ScaleNx,OPTVAL_SCALENX,,,,,,,,,,,,,,,,,,ScaleNx,,,,, +NormalNx,OPTVAL_NORMALNX,,,,,,,,,,,,,,,,,,NormalNx,,,,, +hqNx,OPTVAL_HQNX,,,,,,,,,,,,,,,,,,hqNx,,,,, +hqNx MMX,OPTVAL_HQNXMMX,,,,,,,,,,,,,,,,,,hqNx MMX,,,,, +xBRZ,OPTVAL_NXBRZ,,,,,,,,,,,,,,,,,,xBRZ,,,,, +Old xBRZ,OPTVAL_OLD_NXBRZ,,,,xBRZ (starší),xBRZ alt,Παλίο xBRZ,Malnova xBRZ,Antíguo xBRZ,,Vanha xBRZ,Ancien xBRZ,Régi xBRZ,Vecchio xBRZ,旧xBRZ,구형 xBRZ,Oud xBRZ,Stare xBRZ,Antigo xBRZ,,Vechiul xBRZ,Старый xBRZ,Стари xBRZ, +,,Option Search,,,,,,,,,,,,,,,,,,,,,, +Option Search,OS_TITLE,,,,Vyhledávání možností,Optionssuche,Αναζήτηση Ρυθμίσεων,Agorda Serĉo,Buscar Opciones,,Asetushaku,Recherche Option,Beállítások keresése,Opzioni di ricerca,オプション検索,옵션 검색,Optie zoeken,Szukanie Opcji,Buscar opção,Procurar opção,Căutare Setări,Поиск настройки,Претрага, +Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,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,Szukaj jakiegokolwiek wyrażenia,Buscar por qualquer termo,Procurar por um termo qualquer,Căutare după orice termen,Искать любое из слов,Тражи било који термин, +Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,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,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи сваки термин, +No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,Keine Resultate,Δέν βρέθηκαν αποτελέσματα,Neniuj rezultoj trovitaj.,Ningun resultado.,,Ei tuloksia.,Pas de résultat trouvé,Nincs találat,Nessun risultato trovato.,見つかりませんでした。,검색 결과 없음.,Geen resultaten gevonden.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результатов не найдено.,Нема резултата., +Search:,OS_LABEL,,,,Hledat:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Szukaj:,Busca:,Procura:,Caută:,Поиск:,Претрага:, +,,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 hat %o zerlegt wie einen Fisch,Ο/Η %k ξεκοκάλοσε @[pro2_gr] %o σα ψάρι,%k senostigis %o kiel fiŝon,%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 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 castrated %o,TXT_OBITUARY2,,,,%o byl@[ao_cs] vykastrován@[ao_cs] hráčem %k,%k hat %o kastriert,Ο/Η %k ευνούχισε %o,%k kastris %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 wykastrował@[ao_pl] %o,%k castrou %o,,%k l-a castrat pe %o,%k кастрировал игрока %o,%k је кастрирао %o, +%k creamed %o,TXT_OBITUARY3,,,,%o byl@[ao_cs] rozšlehán@[ao_cs] hráčem %k,%k hat %o eingeseift,Ο/Η %k κρέμασε @[pro2_gr] %o,%k kremigis %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 spienił@[ao_pl] %o,%k fez creme de %o,,%k l-a transformat în cremă pe %o,%k взбил игрока %o,%k је истукао %o, +%k decimated %o,TXT_OBITUARY4,,,,%o byl@[ao_cs] zdecimován@[ao_cs] hráčem %k,%k hat %o dezimiert,Ο/Η %k αποδεκάτισε @[pro2_gr] %o,%k detruegis %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 przetrzebił@[ao_pl] %o,%k decimou %o,,%k l-a decimat pe %o,%k скосил игрока %o,%k је десетковао %o, +%k destroyed %o,TXT_OBITUARY5,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k hat %o zerstört,Ο/Η %k κατέστεψε @[pro2_gr] %o,%k detruis %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 zniszczył@[ao_pl] %o,%k destruiu %o,,%k l-a distrus pe %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 hat %o in Würfel zerteilt,Ο/Η %k τεμάχησε @[pro2_gr] %o,%k diskubigis %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 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 disembowled %o,TXT_OBITUARY7,,,,%o byl@[ao_cs] vykuchán@[ao_cs] hráčem %k,%k hat %o ausgeweidet,Ο/Η %k ισοπέδοσε @[pro2_gr] %o,%k sentripigis %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 wypatroszył@[ao_pl] %o,%k estripou %o,,%k l-a eviscerat pe %o,%k выпотрошил игрока %o,%k је ампутирао %o, +%k flattened %o,TXT_OBITUARY8,,,,%o byl@[ao_cs] zplacatěn@[ao_cs] hráčem %k,%k hat %o dem Erdboden gleichgemacht,Ο/Η %k ησοπέδοσε @[pro2_gr] %o,%k platigis %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 rozpłaszczył@[ao_pl] %o,%k achatou %o,%k espalmou %o,%k l-a făcut plat pe %o,%k сплюснул игрока %o,%k је изравнао %o, +%k gave %o Anal Justice,TXT_OBITUARY9,,,,%o utržil@[ao_cs] anální spravedlnost od hráče %k,%k hat %o anale Gerechtigkeit gegeben,Ο/Η %k γάμησε @[pro2_gr] %o @[pro3_gr] κόλο,%k donis al %o Puga Justo,%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 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 gave AnAl MaDnEsS to %o,TXT_OBITUARY10,,,,%o utrpěl@[ao_cs] AnÁlNí ŠíLeNsTvÍ od hráče %k,%k gab %o AnAlEn WaHnSiNn,Ο/Η %k έσκισε τον κόλο του/της] %o,%k donis pUgAn frEnEzOn al %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 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 killed %o,TXT_OBITUARY11,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k,%k hat %o getötet,Ο/Η %k σκότωσε @[pro2_gr] %o,%k mortigis %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 zabił@[ao_pl] %o,%k matou %o,,%k l-a omorât pe %o,%k убил игрока %o,%k је убио %o, +%k made mincemeat out of %o,TXT_OBITUARY12,,,,%o byl@[ao_cs] namelen@[ao_cs] hráčem %k,%k hat %o zu Hackfleisch verarbeitet,Ο/Η %k έφτιαξε κυμά με @[pro2_gr] %o,%k farigis farĉon el %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 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 massacred %o,TXT_OBITUARY13,,,,%o byl@[ao_cs] zmasakrován@[ao_cs] hráčem %k,%k hat %o niedergemetzelt,Ο/Η %k δολοφώνησε @[pro2_gr] %o,%k masakris %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 zmasakrował@[ao_pl] %o,%k massacrou %o,,%k a fost masacrat de către %o,%k устроил бойню игроку %o,%k је масакрирао %o, +%k mutilated %o,TXT_OBITUARY14,,,,%o byl@[ao_cs] zmrzačen@[ao_cs] hráčem %k,%k hat %o verstümmelt,Ο/Η %k ακρωτηριάσε @[pro2_gr] %o,%k mutilis %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 rozszarpał@[ao_pl] %o,%k mutilou %o,,%k l-a mutilat pe %o,%k изуродовал игрока %o,%k је мутилирао %o, +%k reamed %o,TXT_OBITUARY15,,,,%o byl@[ao_cs] proděravěn@[ao_cs] hráčem %k,%k hat %o aufgerieben,Ο/Η %k δέσμισε @[pro2_gr] %o,%k alezis %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 rozwiercił@[ao_pl] %o,%k esquartejou %o,,%k l-a transformat într-un top de hârtie pe %o,%k просверлил игрока %o,%k је наоружао %o, +%k ripped %o a new orifice,TXT_OBITUARY16,,,,%o má novou díru od hráče %k,%k hat %o eine neue Körperöffnung verpasst,Ο/Η άνοιξε μια νέα τρύπα @[pro3_gr] %o,%k ŝiris %o novan truon,%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 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 slaughtered %o,TXT_OBITUARY17,,,,%o byl@[ao_cs] zavražděn@[ao_cs] hráčem %k,%k hat %o geschlachtet,Ο/Η %k έσφαξε @[pro2_gr] %o,%k buĉis %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 zarżn@[irreg_2_pl] %o,%k abateu %o,,%k l-a măcelărit pe %o,%k устроил резню игроку %o,%k је заклао %o, +%k smashed %o,TXT_OBITUARY18,,,,%o byl@[ao_cs] zmlácen@[ao_cs] hráčem %k,%k hat %o zerklatscht,Ο/Η %k τσάκισε @[pro2_gr] %o,%k frakasis %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 stłukł@[ao_pl] %o,%k esmagou %o,,%k l-a spart pe %o,%k размазал игрока %o,%k је поломио %o, +%k sodomized %o,TXT_OBITUARY19,,,,Hráč %k se dopustil sodomie na hráči %o,%k hat %o sodomisiert,Ο/Η %k γάμησε @[pro2_gr] %o,%k sodomizis %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 spenetrował@[ao_pl] %o,%k sodomizou %o,,%k l-a sodomizat pe %o,%k содомировал игрока %o,%k је изјебао %o, +%k splattered %o,TXT_OBITUARY20,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] hráčem %k,%k hat %o zerspritzt,Ο/Η %k έσκασε @[pro2_gr] %o,%k disĵetis %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 rozbryzgał@[ao_pl] %o,%k explodiu %o,,%k l-a împrăștiat pe %o,%k разбрызгал игрока %o,%k је спљоштио %o, +%k squashed %o,TXT_OBITUARY21,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] hráčem %k,%k hat %o zerquetscht,Ο/Η %k πάτησε @[pro2_gr] %o,%k premplatigis %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 zmiażdżył@[ao_pl] %o,%k espatifou %o,,%k l-a strivit pe %o,%k расплющил игрока %o,%k је згњечио %o, +%k throttled %o,TXT_OBITUARY22,,,,%o byl@[ao_cs] zaškrcen@[ao_cs] hráčem %k,%k hat %o erdrosselt,Ο/Η %k κομμάτιασε @[pro2_gr] %o,%k ekbruligis %o,%k aceleró 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 udusił@[ao_pl] %o +",%k estrangulou %o,,%k l-a strâns de gât pe %o,%k задушил игрока %o,%k је угушио %o, +%k wasted %o,TXT_OBITUARY23,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k,%k hat %o verbraucht,Ο/Η %k σκότωσε @[pro2_gr] %o,%k malŝparis %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 roztrwonił@[ao_pl] %o,%k detonou %o,,%k l-a risipit pe %o,%k замочил игрока %o,%k је убио %o, +%k body bagged %o,TXT_OBITUARY24,,,,Hráč %k narval %o@[psn1_cs] tělo do pytle,%k hat %o eingesackt,Ο/Η %k έχωσε @[pro2_gr] %o στη κάσα του/της,%k korpo-ensakigis %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 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 sent %o to Hell,TXT_OBITUARY25,,,,%o byl@[ao_cs] poslán@[ao_cs] do pekla hráčem %k,%k hat %o zur Hölle fahren lassen,Ο/Η %k έστειλε @[pro2_gr] %o στο δίαολο,%k sendis %o al Infero,%k envió 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 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 toasted %o,TXT_OBITUARY26,,,,%o byl@[ao_cs] upečen@[ao_cs] hráčem %k,%k hat %o geröstet,Ο/Η %k έψησε @[pro2_gr] %o,%k tostis %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 stostował@[ao_pl] %o,%k tostou %o,,%k l-a prăjit pe %o,%k поджарил игрока %o,%k је тостирао %o, +%k snuffed %o,TXT_OBITUARY27,,,,%o byl@[ao_cs] rozsápán@[ao_cs] hráčem %k,%k hat %o vernichtet,Ο/Η %k έσβησε @[pro2_gr] %o,%k snufis %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 powąchał@[ao_pl] %o,%k apagou %o,,%k l-a mirosit pe %o,%k прикончил игрока %o,%k је угасио %o, +%k hosed %o,TXT_OBITUARY28,,,,%o byl@[ao_cs] odstříknut@[ao_cs] hráčem %k,%k hat %o eingetütet,Ο/Η %k έονιξε @[pro2_gr] %o σε σφαίρες,%k hosis %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 załatwił@[ao_pl] %o,%k metralhou %o,,%k a pus furtunul pe %o,%k расстрелял игрока %o,%k је упскао %o, +%k sprayed %o,TXT_OBITUARY29,,,,%o byl@[ao_cs] postříkán@[ao_cs] hráčem %k,%k hat %o pulverisiert,Ο/Η %k ψέκασε @[pro2_gr] %o,%k ŝprucigis %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 rozpryskał@[ao_pl] %o,%k pulverizou %o,,%k l-a pulverizat pe %o,%k распылил игрока %o,%k је испрскао %o, +%k made dog meat out of %o,TXT_OBITUARY30,,,,%o byl@[ao_cs] hozen@[ao_cs] psům hráčem %k,%k hat Hundefutter aus %o gemacht,Ο/Η %k γύρισε @[pro2_gr] %o σε κιμά,%k farigis hundan viandon el %o,%k hizo comida para perro 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 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 beat %o like a cur,TXT_OBITUARY31,,,,%o byl@[ao_cs] zmlácen@[ao_cs] jako pes hráčem %k,%k hat %o wie einen Hund geschlagen,Ο/Η %k πλάκοσε @[pro2_gr] %o σαν κοπρίτης,%k batis %o kiel hundaĉon,%k pateó 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 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 is excrement,TXT_SELFOBIT1,,,,%o je exkrement,%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 został@[ao_pl] odpadkami,%o virou escremento,,%o e excrement,%o теперь экскремент,%o је сада измет, +%o is hamburger,TXT_SELFOBIT2,,,,%o je 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 został@[ao_pl] hamburgerem,%o virou hambúrguer,,%o e hamburger,%o теперь гамбургер,%o је сада пљескавица, +%o suffered scrotum separation,TXT_SELFOBIT3,,,,%o prodělal@[ao_cs] separaci šourku,%os Eier wurden gebraten,Οι όρχις @[pro4_gr] %o βγήκανε,%o suferis skrotan disigon,%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 doznał@[ao_pl] oddzielenia moszny,%o sofreu separação escrotal,,%o a suferit o separație de șcrot,%o страдает от потери тестикул,%o му је исечена патка, +%o volunteered for population control,TXT_SELFOBIT4,,,,%o se zúčastnil@[ao_cs] čistky obyvatelstva,%o hat sich freiwillig zur Bevölkerungskontrolle gemeldet,@[art_gr] %o εθελώντησε για έλεγχο του πληθυσμού,%o volontulis por loĝantara regado,%o fue 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 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 has suicided,TXT_SELFOBIT5,,,,%o spáchal@[ao_cs] sebevraždu,%o hat Selbstmord begangen,@[art_gr] %o έχει αυτοκτονήση,%o sin mortigis,%o se ha suicidado,,%o on tehnyt itsemurhan,%o s'est suicidé,%o öngyilkos lett,%o si è suicidato,%o は勝手にくたばった。,%o 은(는) 한심하게 자살했다.,%o heeft zelfmoord gepleegd,%o popełnił@[ao_pl] samobójstwo,%o se suicidou,%o suicidou-se,%o s-a sinucis,Игрок %o самоубился,%o је убио самог себе, +%o received the Darwin Award,TXT_SELFOBIT6,,,,%o dostal@[ao_cs] Darwinovu cenu,%o hat den Darwinpreis erhalten,@[art_gr] %o κέρδισε το Darwin βραβείο,%o ricevis la Darwin-Premion,%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 otrzymał@[ao_pl] Nagrodę Darwina,%o ganhou o Prêmio Darwin,,%o a primit Premiul Darwin,Игрок %o получил премию Дарвина,%o је добио Дарвиново признање, +,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í,Alle Optionen,,Plena agordo-menuo,,,Täysi asetusvalikko,Menu options complet,Teljes beállításmenü,,全オプション欄,,Alle opties tonen,Pełne Menu Opcji,Menu de opções completo,,Meniu Setări Complet,, -Simple options menu,OPTMNU_SIMPLEON,,,,Zjednodušená nastavení,Einfaches Optionsmenü,,Simpla agordo-menuo,,,Yksinkertainen asetusvalikko,Menu options simplifié,Egyszerű beállításmenü,,必要なオプションのみ,,Eenvoudig optiemenu,Uproszczone Menu Opcji,Menu de opções simples,,Meniu Setări Simplificat,, -Swap mouse buttons,MOUSEMNU_SWAPBUTTONS,,,,Prohodit tlačítka myši,Maustasten vertauschen,,Permuti musbutonojn,,,,,Egérgombok felcserélése,,マウスボタンを反転,,,Zamień Przyciski Myszki,Trocar botões do mouse,,Schimbă Butoanele Mouse-ului între Ele,, -,,,,,,,,,,,,,,,,,,,,,,, -Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,Lichteffekt auf Spiegeln,,Medimapo sur speguloj,Mapa de entorno en espejos,,Ympäristökartta peileissä,Mappage environment sur les miroirs,Környezettérkép a tükrökön,Ambiente mappa sugli specchi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Efecte suplimentare pentru oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима -OpenGL ES,OPTVAL_OPENGLES,Rendering backend,,,,,,,,,,,,,,,,,OpenGL ES,,,, -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ě.",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.,Presiona una tecla o da 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 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.,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 dă click oriunde în fereastră pentru a ieși.,"Нажмите любую клавишу или кликните по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете. -Only modified,OPTVAL_ONLYMODIFIED,,,,Pouze upravené,Nur modfizierte,,Sole modifita,Solo modificados,,Vain muunneltu,Modifié seulement,Csak módosított,Solo modificato,モディファイのみ,수정된 것만,Alleen gewijzigd,Tylko zmodyfikowane,Somente modificado,,Numai modificat,Только в модификациях,Само модификовано -Line alpha,AUTOMAPMNU_LINEALPHA,,,,,Alpha für Linien,,,,,,,,,,,,,,,,, -Line thickness,AUTOMAPMNU_LINETHICKNESS,,,,,Dicke der Linien,,,,,,,,,,,,,,,,, \ No newline at end of file +",ĄĆĘŁŃÓŚŹŻ,ÁÉÍÓÚÀÃÕÂÊÔÇ,,ĂÎȚÂȘ,АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ,АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ, +Full options menu,OPTMNU_FULLOPTIONS,,,,Úplná nastavení,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,Pełne Menu Opcji,Menu de opções completo,,Meniu Setări Complet,Полное меню настроек,, +Simple options menu,OPTMNU_SIMPLEON,,,,Zjednodušená nastavení,Einfaches Optionsmenü,Απλό μενού ρυθμίσεον,Simpla agordo-menuo,Menú de opciones simple,,Yksinkertainen asetusvalikko,Menu options simplifié,Egyszerű beállításmenü,Opzioni base,必要なオプションのみ,,Eenvoudig optiemenu,Proste Menu Opcji,Menu de opções simples,,Meniu Setări Simplificat,Упрощённое меню настроек,, +Browse Game Config,OPTMNU_OPENCONFIG,,,,Procházet konfigurační soubory,Konfigurationsdatei anzeigen,,Foliumi Agordojn de Ludo,Abrir Carpeta de Configuración de Juego,,,Parcourir configuration,,Apri le Configurazioni di Gioco,ゲームコンフィグ参照,,Door gameconfiguratie bladeren,Przeglądaj Ustawienia Gry,Abrir pasta de configuração de jogo,,Caută Configurația Jocului,Просмотр настроек игры,, +Browse Screenshots,OPTMNU_OPENSCREENSHOTS,,,,Procházet snímky obrazovky,Screenshots anzeigen,,Foliumi Ekrankopiojn,Abrir Carpeta de Capturas de Pantalla,,,Parcourir les captures d'écran,,Apri gli Screenshot,クリーンショット参照,,Door schermafbeeldingen bladeren,Przeglądaj Zrzuty Ekranu,Abrir pasta de capturas de tela,,Caută Capturi de Ecran,Просмотр скриншотов,, +Browse Saved Games,OPTMNU_OPENSAVES,,,,Procházet uložené hry,Spielstände anzeigen,,Foliumi Konservitajn Ludojn,Abrir Carpeta de Partidas Guardadas,,,Parcourir sauvegardes,,Apri i Giochi Salvati,セーブしたゲーム参照,,Door opgeslagen games bladeren,Przeglądaj Zapisy Gry,Abrir pasta de jogos salvos,,Caută Salvări,Просмотр сохранённых игр,, +Swap mouse buttons,MOUSEMNU_SWAPBUTTONS,,,,Prohodit tlačítka myši,Maustasten vertauschen,,Permuti musbutonojn,Alternar botones de ratón,,,Permuter les boutons de la souris,Egérgombok felcserélése,Inverti i comandi del mouse,マウスボタンを反転,,Muisknoppen verwisselen,Zamień Przyciski Myszki,Trocar botões do mouse,,Schimbă Butoanele Mouse-ului între Ele,Поменять местами кнопки мыши,, +,,,,,,,,,,,,,,,,,,,,,,,, +Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,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,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Efecte suplimentare pentru oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима, +OpenGL ES,OPTVAL_OPENGLES,Rendering backend,,,,,,,,,,,,,,,,,,,,,, +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ě.",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.,Presiona una tecla o da 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 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.,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.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете., +Only modified,OPTVAL_ONLYMODIFIED,,,,Pouze upravené,Nur modfizierte,,Sole modifita,Solo modificados,,Vain muunneltu,Modifié seulement,Csak módosított,Solo modificato,モディファイのみ,수정된 것만,Alleen gewijzigd,Tylko zmodyfikowane,Somente modificado,,Numai modificat,Только в модификациях,Само модификовано, +Line alpha,AUTOMAPMNU_LINEALPHA,,,,Průhlednost čar,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,Przezroczystość Linii,Transparência da linha,,Transparență linii,Прозрачность линий,Транслуценција линија, +Line thickness,AUTOMAPMNU_LINETHICKNESS,,,,Tloušťka čar,Dicke der Linien,,Dikeca de linio,Grosor de línea,,Viivan paksuus,Épaisseur des lignes,Vonal vastagság,Spessore delle linee,,,Dikte van lijnen,Grubość Linii,Espessura da linha,,Grosime linii,Толщина линий,Дебљина линија, +Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderqualität,,Kvalito de bildigado,Calidad de Renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество отображения,Квалитет рендовања, +Speed,OPTVAL_SPEED,,,,Rychlost,Geschwindigkeit,Ταχύτητα,Rapido,Velocidad,,Nopeus,Vitesse,Sebesség,Prestazioni,速度寄り,성능,Snelheid,Szybkość,Velocidade,,Viteză,Скорость,Брзина, +Quality,OPTVAL_QUALITY,,,,Kvalita,Qualität,Ποιότητα,Kvalito,Calidad,,Laatu,Qualité,Minőség,Qualità,品質寄り,고품질,Kwaliteit,Jakość,Qualidade,,Calitate,Качество,Квалитет, +Sector light mode,GLPREFMNU_SECLIGHTMODE,,,,Režim osvětlení sektorů,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,Tryb oświetlenia sektorów,Modo de luz de setor,,Mod iluminare sectorială,Режим освещения секторов,Секторско светло мод, +Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Nebelmodus,Λειτουργία ομίχλης,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Effetto nebbia,フォグモード,안개 모드,Mistmodus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод, +Radial,OPTVAL_RADIAL,,,,Radiální,,Ακτινικό,Radiusa,,,Säteittäinen,,Sugaras,Radiale,放射状,방사형,Radiaal,Promieniowe,,,Radială,Радиальный,Радијално, +Standard,OPTVAL_STANDARD,,,,Standardní,,,Norma,Estándar,,Normaali,,Szabvány,Standard,標準,기본,Standaard,Standard,Padrão,,,Стандартный,Стандардно, +Waiting for players. ,TXT_NET_WAITINGFORPLAYERS,,,,Čeká se na hráče.,Warte auf Mitspieler. ,Αναμονή για παίχτες,Atendante ludantojn.,Esperando jugadores.,,,En attendant les joueurs,Várakozás játékosokra.,In attesa di giocatori.,プレイヤーを待っている,,Wachten op spelers.,Oczekiwanie na graczy.,Aguardando jogadores.,,În așteptarea jucătorilor.,Ожидание игроков.,, +Press ESC to abort.,TXT_NET_PRESSESC,,,,Stiskněte ESC pro storno.,Drücke ESC um abzubrechen,Πάτα ESC για να ακυρώσης,Premu ESC por ĉesigi.,Pulsa ESC para abortar.,,,Appuyez sur Esc pour abandonner,Nyomjon ESC-et a megszakításhoz,Premi Esc per annullare.,ESCキーで中断できる。,,Druk op ESC om af te breken.,"Wciśnij ESC, by przerwać.",Aperte ESC para cancelar.,Carrega ESC para cancelar.,Apasă ESC pentru anulare.,Нажмите ESC для отмены.,, +Done waiting.,TXT_NET_DONEWAITING,,,,Čekání dokončeno.,Warten beendet.,,Fininte atendadon.,Espera finalizada.,,,Fini d'attendre,Lejárt az idő.,Attesa conclusa.,待機終了。,,Klaar met wachten.,Oczekiwanie zakończone.,Espera concluída.,,Așteptarea a luat sfârșit.,Дождались.,, +Waiting for other players.,TXT_NET_WAITFOROTHER,,,,Čeká se na ostatní hráče.,Warte auf andere Spieler.,,Atendante aliajn ludantojn.,Esperando a otros jugadores.,,,En attente d'autres joueurs,Várakozás a többi játékosra,In attesa di altri giocatori.,他のプレイヤーを待っている,,Op andere spelers wachten.,Oczekiwanie na resztę graczy.,Esperando por outros jogadores.,,În așteptarea altor jucători.,Ожидание других игроков.,, +Contacting host.,TXT_NET_CONTACTHOST,,,,Kontaktuje se hostitel.,Kontaktiere Host.,,Kontaktante gastiganton.,Contactando huésped.,,,Contacter l'hôte,Kapcsolódás a hoszthoz,Contattando l'host.,ホストに接続中,,Gastheer contacteren.,Łączenie z hostem.,Contatando host.,Contactando host.,Contactare gazdă.,Обращение к серверу.,, +Exchanging game information.,TXT_NET_EXCHANGE,,,,Vyměňují se informace o hře.,Tausche Spielinformationen aus.,,Interŝanĝante ludinformojn.,Intercambiando información de juego.,,,Échange d'informations sur le jeu.,Játék információcsere,Scambio di informazioni di gioco.,ゲーム情報の交信中,,Spelinformatie uitwisselen.,Wymiana informacji gry.,Trocando informações do jogo.,,Schimb de date de joc.,Обмен информацией об игре.,, +Pause game in background,MISCMNU_PAUSEINBACKGROUND,,,,Pozastavit hru na pozadí,Spiel pausieren wenn im Hintergrund,,Paŭzigi ludon fone,Pausar el juego en segundo plano,,,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,Zapauzuj grę w tle,Pausar jogo ao minimizar,,Pauză dacă jocul este minimizat.,Пауза при сворачивании окна,, +Unknown,TXT_UNKNOWN,,,,Neznámé,Unbekannt,Άχνωστο,Nekonata,Desconocido,,,Inconnue,Ismeretlen,Sconosciuto,不明,,Onbekend,Nieznane,Desconhecido,,Necunoscut,Неизвестно,, +HUD,OPTVAL_HUD,,,,,,,,,,,ATH,,,,,,,,,,Интерфейс,, +Automap,OPTVAL_AUTOMAP,,,,Automapa,,,Aŭtomapo,,,,Carte,,Automappa,オートマップ,,,,Automapa,,Hartă Computerizată,Автокарта,, +HUD + Automap,OPTVAL_HUDANDMAP,,,,HUD + Automapa,,,HUD + Aŭtomapo,,,,ATH + Carte,,HUD + Automappa,HUD+オートマップ,,,,HUD + Automapa,,Interfață + Hartă Computerizată,Интерфейс + автокарта,, \ No newline at end of file diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index eb758c6e3..8805aa159 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -1,7 +1,7 @@ default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,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,pl,pt,ptg,ro,ru,sr ,,Miscellaneous,,,,,,,,,,,,,,,,,,,,, -Press a key.,PRESSKEY,,,,Stiskni klávesu.,Drücke eine Taste,Πάτα οποιοδήποτε πλήκτρο.,Premu klavon.,Presiona una tecla.,,Paina jotain näppäintä.,Appuyez sur une touche.,Nyomj meg egy gombot.,Premi un tasto.,何かキーを押せ,키를 누르시오.,Druk op een toets.,Wciśnij dowolny klawisz.,Aperte uma tecla.,Carrega numa tecla qualquer.,Apasă o tastă.,Нажмите любую клавишу.,Притисните било који тастер. -A secret is revealed!,SECRETMESSAGE,,,,Tajemství odhaleno!,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!,Znaleziono sekret!,Segredo revelado!,,Ai găsit un secret!,Обнаружен тайник!,Откривена тајна! +Press a key.,PRESSKEY,,,,Stiskni klávesu.,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.,Wciśnij dowolny klawisz.,Aperte uma tecla.,Carrega numa tecla qualquer.,Apasă o tastă.,Нажмите любую клавишу.,Притисните било који тастер. +A secret is revealed!,SECRETMESSAGE,,,,Nalezl[@ao_cs] jsi skrýš!,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!,Znaleziono sekret!,Segredo revelado!,,Ai găsit un secret!,Обнаружен тайник!,Откривена тајна! "Useless mode ON. ",D_DEVSTR,,,,Zbytečný režim ZAP.,Nutzloser Modus EIN.,Άχρηστη λειτουργία είναι ΑΝΟΙΧΤΗ,Senutila reĝimo ŜALTITA.,"Modo inútil ACTIVADO. ",,Hyödytön tila PÄÄLLÄ.,"Mode inutile ON. @@ -23,7 +23,7 @@ deste excelente jogo?",Ești sigur că vrei să ieși din acest joc grozav?,"Т из этой замечательной игры?",Желиш ли заиста да изађеш из ове чудесне игре? "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.”",,,"Nemůžeš načíst hru, když hraješ síťovou hru! +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! Stiskni libovolnou klávesu.","Du kannst während eines Netzwerkspiels keinen Spielstand laden. @@ -40,7 +40,7 @@ pendant un jeu en réseau! Appuyez sur une touche.","Nem tudsz betölteni miközben net játékban vagy! -Nyomj meg egy gombot.","Non puoi caricare una partita durante un netgame! +Nyomj meg egy gombot.","Non puoi caricare una partita durante una partita in rete! Premi un tasto.","オンラインプレイでは ロードできない! @@ -64,7 +64,7 @@ Apasă orice tastă.","Невозможно загрузить сохранен Притисните тастер." "You can't quickload during a netgame! -Press a key.",QLOADNET,,,,"Nemůžeš rychle načíst hru, když hraješ síťovou hru! +Press a key.",QLOADNET,,,,"Během síťové hry nelze rychle načíst hru! Stiskni libovolnou klávesu.","Du kannst während eines Netzwerkspiels nicht schnellladen. @@ -81,7 +81,7 @@ pendant un jeu en réseau! Appuyez sur une touche.","Nem tudsz gyorstölteni miközben net játékban vagy! -Nyomj meg egy gombot.","Non puoi fare un quickload durante un netgame! +Nyomj meg egy gombot.","Non puoi fare un quickload durante una partita in rete! Premi un tasto.","オンラインプレイでは ロードできない! @@ -105,7 +105,7 @@ Apasă orice tastă.","Невозможно загрузить быстрое с Притисните тастер." "You haven't picked a quicksave slot yet! -Press a key.",QSAVESPOT,,,,"Ještě jsi nevybral slot pro rychlé uložení! +Press a key.",QSAVESPOT,,,,"Ještě nebyl vybrán slot pro rychlé uložení! Stiskni libovolnou klávesu.","Du hast noch keine Schnellspeicherposition gewählt. @@ -138,7 +138,7 @@ 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ă.","Не выбран слот быстрого сохранения! Нажмите любую клавишу.","Нисте још изабрали слот за брзо чување! @@ -146,13 +146,13 @@ Apasă orice tastă.","У Вас не выбран слот быстрого с "You can't start a new game while in a network game. -Press a key.",NEWGAME,,,,"Dokud jsi v síťové hře, nemůžeš začít novou hru. +Press a key.",NEWGAME,,,,"Během síťové hry nelze začít novou hru. Stiskni libovolnou klávesu.",Du kannst während eines Netzwerkspiels kein neues Spiel starten.,"Δέν μπορείς να ξεκινήσεις ένα νέο παιχνίδι ενώ εισαι σε ένα δικτυακό παιχνίδι. Πάτα οποιδήποτε πλήκτρο.","Vi ne povas lanĉi novan ludon dum retludo. -Premu klavon.","No puedes iniciar un nuevo juego mientras estés jugando online. +Premu klavon.","No puedes iniciar una nueva partida mientras estés jugando online. Presiona una tecla.",,"Et voi aloittaa uutta peliä verkkopelin aikana. @@ -324,7 +324,7 @@ Apasă orice tastă.","Это демонстрационная версия Doom Притисните било који тастер." "You can't end a netgame! -Press a key.",NETEND,,,,"Nemůžeš ukončit síťovou hru! +Press a key.",NETEND,,,,"Síťovou hru nelze ukončit! Stiskni libovolnou klávesu.","Du kannst ein Netzwerkspiel nicht beenden. @@ -340,7 +340,7 @@ Paina jotain näppäintä.","Vous ne pouvez pas mettre fin à une partie en rés Appuyez sur une touche.","Nem tudsz befejezni egy netjátékot! -Nyomj meg egy gombot.","Non puoi terminare un netgame! +Nyomj meg egy gombot.","Non puoi terminare una partita in rete! Premi un tasto.","オンラインプレイでは勝手に終了できない! @@ -414,18 +414,18 @@ des démons a buter!","Kérlek ne lépj le, sok démon vár még arra, hogy fela demoni da ammazzare!","離れないでくれ! まだ獲物が残っているんだ!","부디 나가지 말아줘, 아직 죽여야 할 악마들이 남아있단 말이야!","Ga alsjeblieft niet weg, er zijn meer demonen te roosteren!","Proszę, nie odchodź, jest więcej 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!","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!","Пожалуйста, не уходи! Тут ещё много демонов!","Молим те, не одлази! Има још демона да се побије!" "Let's beat it -- this is turning -into a bloodbath!",QUITMSG2,,,,"Doraž to -- začíná +into a bloodbath!",QUITMSG2,,,,"Utečme -- začíná tu téct krev!",Lass es uns beenden - das wird zu einem Blutbad,Πάεμε να φύγουμε -- έχει γίνει σφαγίο εδώ!,"Ni forlasu -- ĉi tio fariĝas sangoverŝadon!","Aceptémoslo, ¡esto se está convirtiendo en un baño de sangre!",,Häivytään -- tämä on muuttumassa verilöylyksi!,"Fichons le camp, ça dégénère en bain de sang!","Tűnjünk innen, ebből vérfürdő lesz!","Ammettiamolo - tutto ciò si sta trasformando in un bagno di sangue!","まだ物足りないだろう? -早く戻って皆殺しにしろ!",그냥 나가자고- 유혈사태가 곧 시작될 것 같으니!,Laten we ervoor gaan - dit wordt een bloedbad!,Zmywajmy się stąd -- robi się tu rzeźnia!,"Vamos embora, isso tá virando +早く戻って皆殺しにしろ!",그냥 나가자고- 유혈사태가 곧 시작될 것 같으니!,Laten we ervoor gaan - dit wordt een bloedbad!,Zmywajmy się stąd -- robi się tu rzeźnia!,"Vamos embora -- isso tá virando 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!","Да, давай, убегай, если эта @@ -446,7 +446,7 @@ DOS jest o wiele gorszy.","Eu não sairia se fosse você. 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 је много досаднији." "You're trying to say you like DOS better than me, right?",QUITMSG4,,,,"Chceš mi říct, že máš @@ -460,7 +460,7 @@ ti piace più di me, vero?","貴方はこちらよりも 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 +decât de mine, așa-i?","Ты хочешь сказать, что командная строка тебе нравится больше, чем я, а?","Више ти допада DOS него ја, је ли?" "Don't leave yet -- there's a @@ -469,8 +469,7 @@ za rohem je démon!","Bitte gehe noch nicht - hinter der Ecke da lauert ein Dämon.","Μη φύγεις ακόμα, είναι ένας δαίμονας πίσω απο αυτή τι γονία!","Ne jam foriru -- estas demono ĉirkaŭ tiu angulo!","No te vayas aún-- ¡hay un demonio cerca de esa esquina!",,Ä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 -- maradt egy -démon annál a saroknál!","Non abbandonare ora - c'è un +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!,"Nie odchodź jeszcze -- demon czai się w tamtym zaułku!","Não vá embora ainda, tem um @@ -479,8 +478,8 @@ demônio ao virar da esquina!",Nu pleca încă -- e un demon după colțul acela притаился ещё один монстр!","Немој да одеш -- иза угла има још један демон!" "Ya know, next time you come in here -I'm gonna toast ya.",QUITMSG6,,,,"Víš, až se vrátíš, -rozmáčknu tě.","Nur damit du es weißt, wenn du +I'm gonna toast ya.",QUITMSG6,,,,"Tak hele, až se vrátíš, +dostanu tě.","Nur damit du es weißt, wenn du wiederkommst, dann bist du erledigt.","Ξέρεις, την επόμενη φορά που θα έρθεις εδώ, θα σε ψήσω.","Sciu, ke kiam vi sekvafoje venos ĉi tien, mi rostos vin.","Ya lo sabes, la próxima vez que vengas voy a freírte.",,"Tiiäthän, että käristän sut, kun seuraavalla kerralla tuut tänne.","Vous savez, la prochaine fois que vous revenez, @@ -489,23 +488,23 @@ szét foglak kenni.","Sai, la prossima volta che verrai qui ti farò a pezzi.","わかったよ。 今度戻ってきたら一杯奢るよ。","있지, 만약 네가 다시 돌아온다면 너를 아예 구워버릴 거다.","Weet je, de volgende keer dat je hier binnenkomt, ga ik je roosteren.","Wiesz, jeżeli jescze raz tu przyjdziesz, stostuje cię.","Na próxima vez que você vier -aqui, eu vou te torrar.","Sabes, da próxima vez que vieres para +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!","Знаешь, по возвращении тебя будут ждать большие неприятности.","Знаш, по повратку ће те чекати велике невоље." -Go ahead and leave. see if I care.,QUITMSG7,,,,"Tak do toho, odejdi, -jako kdyby mě to zajímalo.","Dann geh doch! Interessiert -mich nicht.","Φύγε, δες αν νιάζομαι.",Ja foriru. Mi fajfas pri tio.,"Anda, 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, úgysem érdekel.",Continua ed esci. sai che mi frega.,置いて行っちゃうんだ。勝手にしろ。,그럼 나가버려. 난 신경 안 써.,"Ga maar, eens kijken of het me interesseert.","No dalej, odejdź. Zobaczymy czy +Go ahead and leave. see if I care.,QUITMSG7,,,,"Jen do toho, odejdi; schválně, +jestli mi to bude jedno.","Dann geh doch! Interessiert +mich nicht.","Φύγε, δες αν νιάζομαι.",Ja foriru. Mi fajfas pri tio.,"Anda, 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.","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ă.","Давай, уходи. Мне совершенно всё равно.","Хајде, одлази. Уопште ме није брига." "You want to quit? Then, thou hast lost an eighth!",QUITMSG8,More info here.,,,"Chceš odejít? -Nuže, kletba nať uvalena byla!","Du willst gehen? +Nuže, přišel jsi o přízeň boží!","Du willst gehen? Hast du den Verstand verloren?","Θέλεις να φύγεις ? Τότε, έχασες ένα έκτο!","Vi volas forlasi? Tiuokaze, ci perdis okonon!","¿Quieres salir? Entonces, ¡habrás perdido una octava!",,"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 elment az eszed!","Vuoi uscire? +Akkor beszolgáltatik a Te vagyonod nyolcada!","Vuoi uscire? Allora hai perso il senno!","終了したい?ならば、 汝は8分の1を失うぞ!","나가시겠다? 그럼, 당신은 8번째 조각을 잃었다!",Wil je stoppen? Dan ben je wel helemaal geschift!,Chcesz odejść? Wiele stracisz!,"Você quer sair? Só pode ter perdido a cabeça!","Queres sair? @@ -542,8 +541,8 @@ te așteaptă la promptul DOS!","Не уходи! Тут межпростран to your boring programs.",QUITMSG10,,,,"Vypadni odsud a vrať se ke svým nudným programům.","Dann geh doch zurück zu deinen langweiligen Programmen",Βγές απο'δω και πήγαινε πίσω στα βαρετά προγράματα σου.,"Ekiru el ĉi tie kaj reiru al -viaj enuaj programoj.",Vete de aquí y vuelve a tus aburridos programas.,,Ala laputtaa takaisin tylsien ohjelmiesi pariin.,"Tirez vous de là et retournez -à vos programmes ennuyeux.","Sicc innen és menj vissza az +viaj enuaj programoj.",Lárgate de aquí y vuelve a tus aburridos programas.,,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.","早く出ていって、いつものつまらない プログラムに戻るんだな。",당장 나가버리고 너의 후진 프로그램들이나 만지작거리시지.,Ga hier weg en terug naar je saaie programma's.,"Wynoś się stąd i wracaj do @@ -557,7 +556,7 @@ plictisitoare.","Вот и убирайся отсюда к deathmatch ya in a minute!",QUITMSG11,,,,"Být tvým šéfem, v deathmatchi bych tě zabil do minuty!","Wenn ich dein Boss wäre, würde ich dich im Deathmatch in einer Minute schlagen.","Άμα ήμουν το αφεντικό σου, θα σε προκαλούσα σε ενα deathmatch αυτη τη στιγμή!","Se mi estus via ĉefo, mi -mortmaĉus vin post minuton!","Si yo fuera tu jefe, ¡te retaría a muerte en un minuto!",,"Jos oisin pomosi, lyttäisin sut kuolonottelussa minuutissa!","Si j'étais votre patron, je vous +mortmaĉus vin post minuton!","Si yo fuera tu jefe, ¡te pegaría a muerte en 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!","Gdybym był twoim szefem, @@ -571,7 +570,7 @@ deathmatch!","Будь я твоим боссом, and you forfeit your body count!",QUITMSG12,,,,"Hele, kámo, když teď odejdeš, přijdeš o svoje skóre!","Also, Kumpel, wenn du jetzt abhaust, begehst du Fahnenflucht!","Κοίτα φίλε, άμα φύγεις τώρα ματαιώσες το σκόρ σου!","Rigardu, ulo. Se vi nun forirus, -vi rezignus vian mortig-nombron!","Mira, amig@[ao_esp]. ¡Te vas ahora y vas a perder tu conteo de cuerpos!",,"Kuules, kaveri: Jos menet nyt, niin siinä samassa menee myös ruumislukusi.","Regardez, l'ami. Vous partez maintenant +vi rezignus vian mortig-nombron!","Mira, amig@[ao_esp]. ¡Te vas ahora y pierdes tu número de bajas!",,"Kuules, kaveri: Jos menet nyt, niin siinä samassa menee myös ruumislukusi.","Regardez, l'ami. Vous partez maintenant et vous pouvez oublier votre score!","Nézd, haver. Ha most kilépsz, feladod a pontjaidat!","Senti amico, esci adesso e perdi la tua conta delle vittime!","おいおい待てよ、今やめたら @@ -592,20 +591,19 @@ je vous attendrai avec une batte.","Menj csak. amikor visszajössz várni foglak egy ütővel.","Esci pure. quanto tornerai ti aspetterò con un bastone.","帰ればいいさ、 君が戻ってきたときには、 -私はバットを持って待ってるから",그냥 나가봐. 돌아올 때까지 방망이를 들고 기다릴테니까.,"Ga gewoon weg. Als je terugkomt, wacht ik met een knuppel op je.","Tylko odejdź. Kiedy wrócisz, będę czekał z kijem.","Só sai daqui. Quando você voltar, +私はバットを持って待ってるから",그냥 나가봐. 돌아올 때까지 방망이를 들고 기다릴테니까.,"Ga gewoon weg. Als je terugkomt, wacht ik met een knuppel op je.","Tylko odejdź. Kiedy wrócisz, będę czekał z kijem.","Sai daqui. Quando você voltar, 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ă.","Уходи, уходи... но когда вернёшься, я буду ждать тебя с битой.","Иди, иди... али када се вратиш, чекаћу те са палицом." "You're lucky I don't smack -you for thinking about leaving.",QUITMSG14,,,,"Máš štěstí, že ti nedám pár facek, -že přemýšlíš o odchodu.","Hast du ein Glück, dass ich +you for thinking about leaving.",QUITMSG14,,,,"Máš štěstí, že tě neprofackuju +za to, že přemýšlíš o odchodu.","Hast du ein Glück, dass ich dir keine reinhaue, weil du gehst.",Είσαι τυχερός που δεν σε χτυπάω που σκέφτεσε να φύγεις,"Vi bonŝancas, ke mi ne batas vin pro pensado pri foriro.","Tienes suerte que no pueda darte una paliza por pensar en salirte.",,"Kiitä onneasi, etten läimäytä sinua siitä hyvästä, että mietit lähtemistä.","Vous êtes chanceux que je ne vous en -colle pas une parce que vous pensez partir.","Szerencsés vagy, hogy nem ütlek meg -a kilépéssel való gondolatoddal.","Sei fortunato che non ti picchi +colle pas une parce que vous pensez partir.","Mákod van, hogy nem kapsz egy fülest amiért ki akartál lépni.","Sei fortunato che non ti picchi per aver pensato di andartene.","やめることについて考えたのに、 私に殴られないなんて、 君はラッキーだな",나간다는 이유로 싸대기를 날리지 않는 게 다행인 줄 알아.,Je hebt geluk dat ik je niet sla alleen al omdat je eraan denkt te vertrekken.,"Masz szczęście, że cię nie zdzielę @@ -639,7 +637,7 @@ Kia inciteto!","Masacre interruptus... ¡Menudo timo!",,"Verilöyly interruptus... Mikä kiusoitus!","Carnage interruptus... Tout un programme!","Carnage interruptus... -Mily kötekedő!","Macellus interruptus... +Micsoda fenyegetés!","Macellus interruptus... Che presa in giro!","大虐殺は寸止めされた... 何という意地悪なやつだ!",학살중절이라... 놀리는구먼!,De slachting geïnterrumpeerd... Wat flauw!,"Rzeź przeszkadza... Co za złośliwość!","Massacre interrompido... @@ -653,7 +651,7 @@ Ce mai tachinare!","Резня прекращается... -- Mia sola ŝanco!!","Pero tú eres la esperanza... ¡¡Mi única oportunidad!!",,"Mutta sinä olet toivo -- ainoa mahdollisuuteni!!","Mais vous êtes l'espoir, -notre unique chance!","De te vagy a remény +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!!,"Ale ty jesteś nadzieją @@ -667,7 +665,7 @@ Nobody walks out on Blackbird.,QUITMSG18,,,,Nikdo se neobrací zády ke Strace., I thought you were different...,QUITMSG19,,,,"Myslela jsem, že jsi jin@[adj_cs]...","Ich dachte, du wärst anders...",Νόμιζα οτι είσουν διαφορετικός...,"Mi pensis, ke vi estas malsama...",Pensé 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....,"Myślałam, że jesteś inny...",Eu achei que você era diferente...,Eu achei que eras diferente...,Am crezut că tu ești diferit...,Я думала о тебе иначе...,О теби сам мислила другачије... Fine! just kill and run!,QUITMSG20,,,,Fajn! Prostě zab a uteč!,"Na toll! Töten und dann wegrennen.",Καλά! Απλώς σκότοσε και φύγε!,Bone! Nur mortigu kaj kuru!,¡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!",Dobra! Zabijaj i biegaj!,Ótimo! Mate e fuja!,Pronto! Mata e foge!,Fie! Doar omoară și fugi!,Отлично! Пострелял и смылся!,Добро! Само убијај и бежи! +et barrez-vous comme ça!",Oké! Csak ölj és fuss!,Ma bravo! Uccidi e scappi!,いいぞ! ゲリラ戦の時間だ!,그래그래 알았다! 그럼 그냥 뛰고 죽이기나 해!,"Goed hoor, schieten en meteen wegrennen!",Dobra! Zabijaj i biegaj!,Ótimo! Mate e fuja!,Pronto! Mata e foge!,Fie! Doar omoară și fugi!,Отлично! Пострелял и смылся!,Добро! Само убијај и бежи! "You can quit... but you can't hide...",QUITMSG21,,,,"Můžeš odejít... ale nemůžeš se skrýt...","Du kannst gehen... @@ -694,7 +692,7 @@ Hat Mami zum Abendessen gerufen?","Οοοοο, τι είναι το πρόβλη Ĉu panjo diris, ke tempas vespermanĝi?","¿Queeeeeé, qué sucede? ¿Mami te llama a cenar?",,"Häää, mikä vikana? Äiti huutaa syömään?","Bah, il est où est le problème? -Maman a dit « à table! »?","Naaaa, mi a baj? +Maman a dit « à table! »?","Naaa, mi a baj? Anyuci szólt, hogy kész a vacsora?","Eehi, che problema c'è? La mamma ha detto che è ora di cena?","はあぁ、どうしたんだい? ママに晩飯へ呼ばれたのかよ?","헤에에, 무슨 일이야? 엄마가 저녁 먹으레?","Hee, wat is er aan de hand? Zegt mama dat het etenstijd is?","Cooo, o co chodzi? @@ -708,8 +706,8 @@ Mami zice că e timpul pentru cină?","Ха! В чём дело? flemoids on the loose!",QUITMSG23,,,,"Teď neodcházej, stále tu pobíhají slizouni!","Bitte gehe nicht, es laufen noch mehr Flemoiden herum","Μή παραιτηθέις, υπάρχουνε ακόμα φλέμοιντς τα οπία έχουν αποδράσει!","Ne nun forlasu, ankoraŭ -estas mukuloj vagantaj!","No te vayas ahora, -¡Aún hay flemoides sueltos!",,Älä lopeta nyt; limatuksia on vielä vapaalla!,"N'abandonnez pas maintenant, les flémoides sont toujours à l'assaut!","Ne lépj ki, még sok slejmoid maradt hátra!","Non uscire ora, ci sono ancora +estas mukuloj amoke!","No te vayas ahora, +¡Aún hay flemoides sueltos!",,Älä lopeta nyt; limatuksia on vielä vapaalla!,"N'abandonnez pas maintenant, les flémoides sont toujours à l'assaut!","Ne lépj ki, még sok slejmoid van szabadon!","Non uscire ora, ci sono ancora flemoidi a piede libero!","まだやめないでくれ、 にげだしたフレモイドたちが のこっているんだから!","부디 종료하지 말아 주세요, 플레모이드들이 아직도 널려있단 말입니다!","Niet stoppen nu, er lopen nog steeds vlezerijen op vrije voeten!","Nie wychodź teraz, są tu wciąż flemoidy na wolności!","Não saia agora! @@ -722,8 +720,8 @@ get the upper hand!",QUITMSG24,,,,"Teď to nevzdávej - slizouni budou mít výhodu!","Gib nicht auf - die Flemoiden gewinnen sonst.",Μή παραιτηθέις -- τα φλέμοιντς θα νικήσουνε!,"Ne rezignu -- La mukuloj atingus la avantaĝon!","No te rindas... -¡Los flemoides tendrán la ventaja!",,Älä luovuta -- limatukset pääsevät voitolle!,"Ne partez pas, ou les -Flémoïdes vont nous battre!",Ne add fel -- a slejmoidok kerülnek fölénybe!,"Non arrenderti -- i flemoidi +¡Los flemoides tendrán ventaja!",,Älä luovuta -- limatukset pääsevät voitolle!,"Ne partez pas, ou les +Flémoïdes vont nous battre!",Ne add fel -- máskülönben slejmoidok győznek!,"Non arrenderti -- i flemoidi ci sopraffaranno!","あきらめてはダメだ、 フレモイドたちの しょうりに なってしまうぞ!",부디 포기하지 마시길- 플레모이드들이 그 순간 우세할 것입니다!,Geef niet op - de vlezerijen krijgen de overhand!,Nie poddawaj się -- flemoidy będą miały przewagę!,"Não desista — os flemoides @@ -739,7 +737,7 @@ Wir brauchen deine Hilfe.","Μή φύγεις τώρα. Ni bezonas vian helpon!","No te vayas ahora. ¡Necesitamos tu ayuda!",,"Älä lähde nyt. Tarvitsemme apuasi!","S'il vous plaît, ne quittez pas, nous -avons besoin de votre aide!","Ne menj most! +avons besoin de votre aide!","Még ne menj! Szükségünk van a segítségedre!","Non andartene ora. Ci serve il tuo aiuto!","まだかえらないでくれ。 われわれには きみのたすけが @@ -755,7 +753,7 @@ break for Chex(R) party mix.",QUITMSG26,,,,"Doufám, že si jen dáváš pauzu na Chex(R) Party Mix.","Ich hoffe mal, dass du nur eine Pause für Chex(R) Party Mix machst.",Ελπίζω οτι απλώς κάνεις ενα διάλειμμα για ένα Chex (R) μέιγμα.,"Mi esperas, ke vi nur paŭzas por manĝi Chex(R)-festmikson.","Espero que solo estés tomando un descanso -para la fiesta de mix Chex(R).",,Toivottavasti pidät taukoa vain Chex(R) Party Mixiä varten.,"J'espère que tu prends une pause +para la fiesta de mezcladitos Chex(R).",,Toivottavasti pidät taukoa vain Chex(R) Party Mixiä varten.,"J'espère que tu prends une pause pour un bol de Chex(R) Party Mix.","Remélem, hogy csak egy szünetet tartasz a Chex(R) parti mixhez.","Spero tu stia solo facendo una pausa per prendere un Chex(R) party mix.","チェックス(R)パーティミックスを @@ -791,7 +789,7 @@ federaci cereálií!","Bitte lasse die Intergalaktische Föderation der Cerealien nicht im Stich!",Μήν εγκαταλήψεις την Διαγαλαξιακή Ομοσπονδία των Δημητριακών!,"Ne forlasu la Intergalaksian Federacion de Cerealaĵoj!",¡No abandones a la Federación Intergaláctica de Cereales!,,Älä hylkää intergalaktista muroliittoa!,"N'abandonnez pas la Fédération Intergalactique des Céréales!","Ne hagyd cserben az -Intergalaktikus Müzliszövetséget!","Non abbandonare la +Intergalaktikus Müzli Szövetséget!","Non abbandonare la Federazione Intergalattica dei Cereali!","ぎんがシリアルれんぽう を みすてないでくれ!",은하연합시리얼국을 위해서라도 부디 떠나지 말아 주시길 바랍니다!,Laat de Intergalactische Federatie van Granen niet in de steek!,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!,"Не оставляй @@ -808,31 +806,31 @@ non si arrenderebbe così in fretta!","しんのチェックス(R)せんしは そんなにすぐあきらめはしないぞ!",진정한 첵스(R)전사는 그렇게 빨리 포기하지 않을 것입니다!,De echte Chex(R) Krijger zou niet zo snel opgeven!,"Prawdziwy Wojownik Chex(R) 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) +de ușor!","Настоящий воин Chex(R) не сдастся так быстро!","Прави Чекс ратници не би одустали тако лако!" ,,Pickups,,,,,,,,,,,,,,,,,,,,, You got a pickup,TXT_DEFAULTPICKUPMSG,,,,Dostal@[ao_cs] jsi věc,Du hast etwas aufgesammelt,Πήρες ένα πράγμα.,Vi akiris aĵon,Obtuviste un objeto.,,Sait jotakin,Quelque chose récupéré.,Felvettél egy tárgyat.,Hai raccolto qualcosa ,何か拾った,무언가를 집어냈다,Je hebt iets opgepakt...,Zebrano przedmiot,Você pegou um item,Apanhaste um item,Ai ridicat un obiect.,Что-то получено,Покупили сте нешто ,,Locks,,,,,,,,,,,,,,,,,,,,, -Any key will open this door,PD_ANY,,,,Jakýkoliv klíč otevře tyto dveře,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,Dowolny klucz otworzy te drzwi,Qualquer chave abre essa porta,Qualquer chave pode abrir esta porta,Orice cheie va deschide ușa aceasta.,Для открытия нужен любой ключ,За отварање потребан је било који кључ -Any key will activate this object,PD_ANYOBJ,,,,Jakýkoliv klíč aktivuje tento 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 az objektumot.,Una chiave qualunque attiverà questo oggetto,いずれかのキーで起動させることができる。,어느 열쇠든 이 물체를 작동 시킬 것입니다,Elke sleutel zal dit object activeren,Dowolny klucz aktywuje ten przedmiot,Qualquer chave ativa esse objeto,Qualquer chave pode ativar este objeto,Orice cheie va activa obiectul acesta.,Для активации нужен любой ключ,За активирање потребан је било који кључ -You need all three keys to open this door,PD_ALL3,,,,Všechny tři klíče jsou potřeba k otevření těchto dveří,"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,"Potrzebujesz wszystkich trzech kluczy, aby otworzyć te drzwi",Você precisa de todas as três chaves para abrir essa porta,Precisas de todas as três chaves para abrir esta porta,"Ai nevoie de toate cele trei chei pentru a deschide +Any key will open this door,PD_ANY,,,,Tyto dveře otevře jakýkoliv klíč,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,Dowolny klucz otworzy te drzwi,Qualquer chave abre esta porta,Qualquer chave pode abrir esta porta,Orice cheie va deschide ușa aceasta.,Для открытия нужен любой ключ,За отварање потребан је било који кључ +Any key will activate this object,PD_ANYOBJ,,,,Tento objekt aktivuje jakýkoliv klíč,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,Dowolny klucz aktywuje ten przedmiot,Qualquer chave ativa este objeto,Qualquer chave pode ativar este objeto,Orice cheie va activa obiectul acesta.,Для активации нужен любой ключ,За активирање потребан је било који кључ +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 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,"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.",Для открытия требуются все три ключа,За отварање потребна су сва три кључа -You need all three keys to activate this object,PD_ALL3O,,,,Všechny tři klíče jsou potřeba k aktivaci tohoto objektu,"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 az objektumot.,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,"Potrzebujesz wszystkich trzech kluczy, aby aktywować ten przedmiot",Você precisa de todas as três chaves para ativar esse objeto,Precisas de todas as três chaves para ativar este objeto,"Ai nevoie de toate cele trei chei pentru a activa +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 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,"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.",Для активации требуются все три ключа,За активирање потребна су сва три кључа -You need all six keys to open this door,PD_ALL6,,,,Všech šest klíčů je potřeba k otevření těchto dveří,"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,"Potrzebujesz wszystkich sześciu kluczy, aby otworzyć te drzwi",Você precisa de todas as seis chaves para abrir essa porta,Precisas de todas as seis chaves para abrir esta porta,"Ai nevoie de toate cele sase chei pentru a deschide +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 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,"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.",Для открытия требуются все шесть ключей,За отварање потребна су свих шест кључева -You need all six keys to activate this object,PD_ALL6O,,,,Všech šest klíčů je potřeba k aktivaci tohoto objektu,"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,"Potrzebujesz wszystkich sześciu kluczy, aby aktywować ten przedmiot",Você precisa de todas as seis chaves para ativar esse objeto,Precisas de todas as seis chaves para ativar este objeto,"Ai nevoie de toate cele șase chei pentru a activa +You need all six keys to activate this object,PD_ALL6O,,,,K aktivaci tohoto objektu je potřeba všech šest klíčů,"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,"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.",Для активации требуются все шесть ключей,За активирање потребна су свих шест кључева -You need all the keys,PD_ALLKEYS,,,,Potřebuješ všechny klíče.,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ég van.,Ti servono tutte le chiavi,全てのキーが必要だ。,모든 열쇠가 필요합니다,Je hebt alle sleutels nodig,Potrzebujesz wszystkich kluczy,Você precisa de todas as chaves,Precisas de todas as chaves,Ai nevoie de toate cheile.,Требуются все ключи,Потребни су сви кључеви +You need all the keys,PD_ALLKEYS,,,,Potřebuješ všechny klíče,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,Potrzebujesz wszystkich kluczy,Você precisa de todas as chaves,Precisas de todas as chaves,Ai nevoie de toate cheile.,Требуются все ключи,Потребни су сви кључеви ,,Chat,,,,,,,,,,,,,,,,,,,,, [Message unsent],HUSTR_MSGU,,,,[Zpráva neposlána],[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],[Wiadomość niewysłana],[Mensagem não enviada],,[Mesaj netrimis],[Сообщение не отправлено],[Порука непослата] -You mumble to yourself,HUSTR_TALKTOSELF1,,,,Něco si zamumláš pro sebe.,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,Mamroczesz do siebie,Você resmunga para si...,Tu resmungas contigo própri@[ao_ptb]...,Bolborosești în sine,Неразборчивое бормотание,Промумљате себи -Who's there?,HUSTR_TALKTOSELF2,,,,Kdo je tam?,Wer ist da?,Πιός είναι εκεί?,Kiu estas tie?,¿Quién está ahí?,,Kuka siellä?,Qui est là?,Ki van ott?,Chi c'è lì?,誰かいるか?,거기 누구 있나?,Wie is daar?,Kto tam?,Quem tá aí?,,Cine-i acolo?,Кто там?,Ко је то? +You mumble to yourself,HUSTR_TALKTOSELF1,,,,Něco si zamumláš pro sebe.,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,Mamroczesz do siebie,Você resmunga para si mesm@[ao_ptb]...,Tu resmungas contigo própri@[ao_ptb]...,Bolborosești în sine,Неразборчивое бормотание,Промумљате себи +Who's there?,HUSTR_TALKTOSELF2,,,,Kdo je tam?,Wer ist da?,Πιός είναι εκεί?,Kiu estas tie?,¿Quién está ahí?,,Kuka siellä?,Qui est là?,Ki van ott?,Chi c'è lì?,誰かいるか?,거기 누구 있나?,Wie is daar?,Kto tam?,Quem está aí?,,Cine-i acolo?,Кто там?,Ко је то? You scare yourself,HUSTR_TALKTOSELF3,,,,Vystrašíš se.,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,Przestraszyłeś się,Você se assusta,Assustas-te a ti propri@[ao_ptb],Te speri pe tine însuți,Что это было?,Плашите самог себе You start to rave,HUSTR_TALKTOSELF4,,,,Začneš pařit.,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,Zaczynasz wariować,Você começa a delirar,Começas a delirar,Începi să aiurezi,Вы бредите.,Брбљате -You've lost it...,HUSTR_TALKTOSELF5,,,,Kleplo ti...,Du verlierst den Verstand...,Το έχασες,Vi freneziĝis...,Perdiste la cabeza...,,Olet seonnut...,Vous avez perdu les pédales...,Neked annyi...,Sei andato...,我を失った...,미치기 시작했다...,Je bent het kwijt,Oszalałeś...,Você enlouqueceu...,Enlouqueceste,Ai luat-o pe ulei...,Какая досада...,Лудите... +You've lost it...,HUSTR_TALKTOSELF5,,,,Kleplo ti...,Du verlierst den Verstand...,Το έχασες,Vi freneziĝis...,Perdiste la cabeza...,,Olet seonnut...,Vous avez perdu les pédales...,Eldobod az agyad...,Sei andato...,我を失った...,미치기 시작했다...,Je bent het kwijt,Oszalałeś...,Você enlouqueceu...,Enlouqueceste,Ai luat-o pe ulei...,Какая досада...,Лудите... [Message Sent],HUSTR_MESSAGESENT,,,,[Zpráva odeslána],[Nachricht gesendet],[Στάλθηκε],[Mesaĝo Sendita],[Mensaje enviado],,[Viesti lähetetty],[Message Envoyé],[Üzenet elküldve],[Messaggio Inviato],[メッセージ送信],[메시지가 전달됨],[Bericht verzonden],[Wiadomość wysłana],[Mensagem enviada],,[Mesaj Trimis],[Сообщение отправлено],[Порука послата] ,,Cheats,,,,,,,,,,,,,,,,,,,,, Music Change,STSTR_MUS,,,,Změna hudby,Musikwechsel,Άλλαξε μουσική,Muzikŝanĝo,Cambio de música,,Musiikin vaihtaminen,Changement de Musique,Zene Váltás,Cambio di musica,music変更,음악 전환,Muziek veranderen,Zmieniono muzykę,Trocando música,Mudar a música,Schimbare muzică...,Смена музыки,Промена музике @@ -846,15 +844,16 @@ Ammo (no keys) Added,STSTR_FAADDED,,,,Munice (bez klíčú) přidána,Munition ( No Clipping Mode ON,STSTR_NCON,,,,Bezkolizní režim ZAP,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,Tryb no-clip WŁĄCZONY,Modo sem colisão ATIVADO,,Modul fără coliziune ACTIVAT,Прохождение сквозь стены ВКЛЮЧЕНО,Пролажење кроз зидове УКЉУЧЕНО No Clipping Mode OFF,STSTR_NCOFF,,,,Bezkolizní režim VYP,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,Tryb no-clip WYŁĄCZONY,Modo sem colisão DESATIVADO,,Modul fără coliziune DEZACTIVAT,Прохождение сквозь стены ОТКЛЮЧЕНО,Пролажење кроз зидове ИСКЉУЧЕНО No Clipping Mode 2 ON,STSTR_NC2ON,,,,Bezkolizní režim 2 ZAP,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,Drugi tryb no-clip WŁĄCZONY,Modo sem colisão 2 ATIVADO,,Modul fără coliziune 2 ACTIVAT,Полёт сквозь стены ВКЛЮЧЁН,Секундарни режим пролажења кроз зидове УКЉУЧЕНО +No Clipping Mode 2 OFF,STSTR_NC2OFF,,,,Bezkolizní režim 2 VYP,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,Drugy tryb no-clip WYŁĄCZONY,Modo sem colisão 2 DESATIVADO,,Modul fără coliziune 2 DEZACTIVAT,Полёт сквозь стены ОТКЛЮЧЁН,Секундарни режим пролажења кроз зидове ИСКЉУЧЕНО "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, nevId, Rad, mApa nebo světLo","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","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 +“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, 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","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,Verbesserung umgeschaltet!,,Plifortigaĵo Baskuligita,Poder alternado,,Tehostin kytketty,Amélioration Activée!,Képesség hozzáadva,Power-up concesso/tolto,パワーアップ 適用,파워-업 전환됨,Versterking ingeschakeld,Wzmocnienie aktywowane,Potencializador ativado,,Putere Activată,Усиление включено,Супер моћи заглављене -... doesn't suck - GM,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,... není cucák - GM,... gar nicht übel - GM,... δέν είναι χάλια - GW,... ne malbona - GM,... no apesta - GM,,... ei ole syvältä - GM,... C'est pas de la merde. - GM,... nem rossz - GM,... non fa cacare - GM,...わるかぁねえぞ --gm,... 후진 건 아니지만 - GM,.... is niet slecht - GM,... nie ssie - GM,... nada mau — GM,,... nu e jalnic - GM,... неплохо — г.м.,... није лоша - GM +... doesn't suck - GM,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,... není cucák - 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,... nie ssie - GM,... não tá ruim — GM,,... nu e jalnic - GM,... неплохо — г.м.,... није лоша - GM Changing Level...,STSTR_CLEV,,,,Měním level...,Wechsle Level...,Αλλαγή πίστας...,Ŝanĝante Nivelon...,"Cambiando de nivel... ",,Vaihdetaan tasoa...,Changement de niveau...,Pályaváltás...,"Cambio di livello... ",場所を変更...,레벨 변경 중...,Level veranderen...,Zmienianie poziomu...,Trocando de fase...,"A mudar de nível... @@ -871,27 +870,27 @@ All keys,TXT_CHEATKEYS,,,,Všechny klíče,Alle Schlüssel,Όλα τα κλει Sound debug on,TXT_CHEATSOUNDON,,,,Debug zvuku ZAP,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,Debugowanie dźwięku włączone,Depuração de som ativada,,Debug sunet activat,Отладка звука ВКЛЮЧЕНА,Дебаговање звука УКЉУЧЕНО Sound debug off,TXT_CHEATSOUNDOFF,,,,Debug zvuku VYP,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,Debugowanie dźwięku wyłączone,Depuração de som desativada,,Debug sunet dezactivat,Отладка звука ОТКЛЮЧЕНА,Дебаговање звука ИСКЉУЧЕНО "Trying to cheat, eh? Now you die!",TXT_CHEATIDDQD,,,,"Pokoušíš se cheatovat, co? Teď zemřeš!","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óbujesz oszukiwać, co? Teraz giń!","Tentando trapacear, né? Morra!","A fazer batota, é? Morre!","Încerci să trișezi, ei? Acum mori!","Жульничаешь, э? Умрёшь!","Покушаваш да вараш, ех? Сада умиреш!" -Cheater - you don't deserve weapons,TXT_CHEATIDKFA,,,,Podvodníku - nezasloužíš si zbraně,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.,Oszust - nie zasługujesz na bronie,Trapaceiros não merecem armas,Batoteir@[ao_ptb] - Não mereces armamento,Trișor - Nu meriți arme,Обманщик — ты не заслуживаешь оружия,Варалице - ти не заслужујеш оружје +Cheater - you don't deserve weapons,TXT_CHEATIDKFA,,,,Podvodníku - nezasloužíš si zbraně,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.,Oszust - nie zasługujesz na bronie,Trapaceiros não merecem armas,Batoteir@[ao_ptb] - Não mereces armamento,Trișor - Nu meriți arme,Жулик — ты не заслуживаешь оружия,Варалице - ти не заслужујеш оружје Ticker on,TXT_CHEATTICKERON,,,,Počítadlo ZAP,Zähler AN,Χρονόμετρο ενεργοποιημένο,Nombrilo ŝaltita,Contador activado,,Laskuri päällä,Compteur allumé,Számláló BE,Ticker attivato,ティッカー オン,프레임 속도 표시 켬,Ticker aan,Wskaźnik włączony,Contador ativado,,Ticăitoare activată,Счётчик включён,Бројач укључен Ticker off,TXT_CHEATTICKEROFF,,,,Počítadlo VYP,Zähler AUS,Χρονόμετρο άπενεργοποιημένο,Nombrilo malŝaltita,Contador desactivado,,Laskuri pois päältä,Compteur éteint,Számláló KI,Ticker disattivato,ティッカー オフ,프레임 속도 표시 끔,Ticker uit,Wskaźnik wyłączony,Contador desativado,,Ticăitoare dezactivată,Счётчик отключён,Бројач искључен -You got it,TXT_CHEATARTIFACTS3,,,,Máš to mít,Du hast es,Το πήρες,Vi havas ĝin,Lo tienes,,Saamasi pitää,C'est à vous!,Megkaptad,Concesso,それを渡そう。,얻었다,Je hebt het,Udało ci się,Concedido,,Ai ce-ți trebuie,Вы получили это,Уреду -"You got the Midas Touch, baby",TXT_MIDASTOUCH,,,,"Máš Midasův dotek, zlato",Dagobert Duck lässt grüßen!,"Έχεις το αγγιγμα το Μίδα, μωρό.","Vi havas la Tuŝon de Midas, kara","Tienes el toque de Midas, muchach@[ao_esp]",,"Kulta, sinulla on Midaksen kosketus",,Dagobert bácsi üdvözöl!,"Hai avuto il Tocco di Mida, baby",ミダス王の様だな、ベイビー,넌 미다스의 손을 얻었어 베이베!,"Je hebt de Midas Touch, schatje","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","Ты превращаешь всё в золото, детка!","Имаш златке руке, душо" -You got the stuff!,TXT_GOTSTUFF,,,,Dostal jsi věci!,Du hast den Kram erhalten,Πήρες τηατ πράγματα !,Vi havas la aĵojn!,¡Tienes el material!,¡Tienes muchas cosas!,Sait kamppeet!,Voilà ton équipement!,Megkaptad a cuccot!,Hai avuto il materiale!,スタッフを手に入れた!,무언가를 얻었다!,Je hebt het spul!,Zdobył@[irreg_3_pl] parę rzeczy!,Você ganhou muitas coisas!,ganhaste muitas coisas!,Ai tot ce-ți trebuie!,Получены предметы!,Покупили сте ствари! +You got it,TXT_CHEATARTIFACTS3,,,,Máš to mít,Du hast es,Το πήρες,Vi akiris ĝin,Lo tienes,,Saamasi pitää,C'est à vous!,Megkaptad,Concesso,それを渡そう。,얻었다,Je hebt het,Udało ci się,Concedido,,Ai ce-ți trebuie,Вы получили это,Уреду +"You got the Midas Touch, baby",TXT_MIDASTOUCH,,,,"Máš Midasův dotek, zlato",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","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","Ты превращаешь всё в золото, детка!","Имаш златке руке, душо" +You got the stuff!,TXT_GOTSTUFF,,,,Dostal jsi věci!,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!,Zdobył@[irreg_3_pl] parę rzeczy!,Você ganhou muitas coisas!,ganhaste muitas coisas!,Ai tot ce-ți trebuie!,Получены предметы!,Покупили сте ствари! Freeze mode on,TXT_FREEZEON,,,,Režim zamrznutí ZAP,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,Tryb zamrożenia włączony,Modo congelado ativado,,Modul înghețat activat,Режим заморозки включён,Мод замрзавања УКЉУЧЕН -Freeze mode off,TXT_FREEZEOFF,,,,Režim zamrznutí VYP,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,Tryb zamrożenia wyłączony,Modo congelado desativado,,Modul înghețat dezactivat,Режим заморозки отключен,Мод замрзавања ИСКЉУЧЕН +Freeze mode off,TXT_FREEZEOFF,,,,Režim zamrznutí VYP,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,Tryb zamrożenia wyłączony,Modo congelado desativado,,Modul înghețat dezactivat,Режим заморозки отключён,Мод замрзавања ИСКЉУЧЕН You feel strange...,TXT_STRANGE,,,,Cítíš se divně...,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...,Dziwnie się czujesz...,Você está com uma sensação estranha...,Tu sentes-te estranh@[ao_ptb].,Te simți ciudat...,Вы чувствуете себя странно...,Осећате се чудно... -You feel even stranger.,TXT_STRANGER,,,,Cítíš se ještě divněji...,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.,Czujesz się jeszcze dziwniej.,Você está com uma sensação mais estranha ainda.,Tu sentes-te ainda mais estranh@[ao_ptb].,Te simți si mai ciudat.,Вы чувствуете себя очень странно.,Осећате се врло чудно. -You feel like yourself again.,TXT_NOTSTRANGE,,,,Cítíš se opět jako ty.,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.,"Úgy érzed, magadnál vagy.",Ti senti di nuovo te stesso.,自分自身の様に感じている。,자기 자신처럼 생각하게 됐다.,Je voelt je weer als jezelf.,Znów czujesz się sobą.,Você se sente normal novamente.,Tu sentes-te normal novamente.,Ți-ai revenit în simțiri.,Вы снова чувствуете себя собой.,Поново се осећате као ви. +You feel even stranger.,TXT_STRANGER,,,,Cítíš se ještě divněji...,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.,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.,Вы чувствуете себя очень странно.,Осећате се врло чудно. +You feel like yourself again.,TXT_NOTSTRANGE,,,,Cítíš se opět jako ty.,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.,Znów czujesz się sobą.,Você se sente normal novamente.,Tu sentes-te normal novamente.,Ți-ai revenit în simțiri.,Вы снова чувствуете себя собой.,Поново се осећате као ви. Lead boots on,TXT_LEADBOOTSON,,,,Olověné boty ZAP,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,Ołowiane buty włączone,Botas de chumbo ativadas,,Bocanci de plumb activați,Свинцовые сапоги надеты,Оловне чизме УКЉУЧЕНЕ Lead boots off,TXT_LEADBOOTSOFF,,,,Olověné boty VYP,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,Ołowiane buty wyłączone,Botas de chumbo desativadas,,Bocanci de plumb dezactivați,Свинцовые сапоги сняты,Оловне чизме ИСКЉУЧЕНЕ You feel lighter,TXT_LIGHTER,,,,Cítíš se lehčí,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,Czujesz się lżejsz@[adj_pl],Você se sente mais leve,Tu sentes-te mais leve,Te simți mai ușor,Вы чувствуете лёгкость.,Осећате лакоћу. -Gravity weighs you down,TXT_GRAVITY,,,,Gravitace tě táhne dolů,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...,Grawitacja znów cię przyciąga,A gravidade volta a funcionar normalmente,A gravidade voltou ao normal,Gravitația te trage în jos,Гравитация тянет Вас вниз.,Гравитација Вас вуче надоле. +Gravity weighs you down,TXT_GRAVITY,,,,Gravitace tě táhne dolů,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...,Grawitacja znów cię przyciąga,A gravidade volta a funcionar normalmente,A gravidade voltou ao normal,Gravitația te trage în jos,Гравитация тянет вас вниз.,Гравитација Вас вуче надоле. No Target ON,TXT_NOTARGET_ON,,,,Neútočící příšery ZAP,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,Głuche i Ślepe Potwory WŁĄCZONE,Sem alvos ATIVADO,,Modul Inamici fără Țintă ACTIVAT,Незаметность включена,Нема мете УКЉУЧЕНО No Target OFF,TXT_NOTARGET_OFF,,,,Neútočící příšery VYP,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,Głuche i Ślepe Potwory WYŁĄCZONE,Sem alvos DESATIVADO,,Modul Inamici fără Țintă DEZACTIVAT,Незаметность отключена,Нема мете ИСКЉУЧЕНО """Quake with fear!""",TXT_ANUBIS_ON,,,,„Třeste se strachy!“,"""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!“,"""Trzęś się ze strachu""","""Trema de medo!""","""Trema com medo!""","""Tremură de Frică!""",«Дрожите от страха!»,„Дрхтите у страху!“ -No more Ogre Armor,TXT_ANUBIS_OFF,,,,Už žádné zlobří brnění,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,Nigdy więcej Pancerza Ogrów,Chega de Armadura de Ogro,Chega de Armadura de Ogre,Gata cu Armura de Căpcăun,Броня Огра снята,Нема више бауков оклоп -chasecam ON,TXT_CHASECAM_ON,,,,Pohled z třetí osoby ZAP,chasecam AN,Κάμερα τρίτου πρωσώπου ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao ŜALTITA,Cámara de seguimiento ACTIVADA,,Seurantakamera PÄÄLLÄ,,követő kamera BE,Modalità camera da inseguimento ATTIVATA,チェイスカメラ オン,3인칭 카메라 켬,Chasecam AAN,kamera śledzenia WŁĄCZONA,Câmera em perceira pessoa ATIVADA,Câmara em Terceira Pessoa ATIVADA,Perspectivă la Persoana a 3-a ACTIVATĂ,Вид от третьего лица активирован,Чејс-кам УКЉУЧЕН -chasecam OFF,TXT_CHASECAM_OFF,,,,Pohled z třetí osoby VYP,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,kamera śledzenia WYŁĄCZONA,Câmera em perceira pessoa DESATIVADA,Câmara em Terceira Pessoa DESATIVADA,Perspectivă la Persoana a 3-a DEZACTIVATĂ,Вид от третьего лица деактивирован,Чејс-кам ИСКЉУЧЕН +No more Ogre Armor,TXT_ANUBIS_OFF,,,,Už žádné zlobří brnění,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,Nigdy więcej Pancerza Ogrów,Chega de Armadura de Ogro,Chega de Armadura de Ogre,Gata cu Armura de Căpcăun,Броня огра снята,Нема више бауков оклоп +chasecam ON,TXT_CHASECAM_ON,,,,Pohled z třetí osoby ZAP,chasecam AN,Κάμερα τρίτου πρωσώπου ΕΝΕΡΓΟΠΟΙΗΜΈΝΗ,Ĉaskamerao ŜALTITA,Cámara de seguimiento ACTIVADA,,Seurantakamera PÄÄLLÄ,,követő kamera BE,Modalità camera da inseguimento ATTIVATA,チェイスカメラ オン,3인칭 카메라 켬,Chasecam AAN,kamera śledzenia WŁĄCZONA,Câmera em terceira pessoa ATIVADA,Câmara em Terceira Pessoa ATIVADA,Perspectivă la Persoana a 3-a ACTIVATĂ,Вид от третьего лица активирован,Чејс-кам УКЉУЧЕН +chasecam OFF,TXT_CHASECAM_OFF,,,,Pohled z třetí osoby VYP,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,kamera śledzenia WYŁĄCZONA,Câmera em terceira pessoa DESATIVADA,Câmara em Terceira Pessoa DESATIVADA,Perspectivă la Persoana a 3-a DEZACTIVATĂ,Вид от третьего лица деактивирован,Чејс-кам ИСКЉУЧЕН 1 baddie killed,TXT_BADDIE_KILLED,,,,1 zloun zabit,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 zabity przeciwnik,1 inimigo morto,,1 slab ucis,1 плохиш убит,Један зликовац убијен %d baddies killed,TXT_BADDIES_KILLED,,,,%d zlounů zabito,%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 zabitych przeciwników,%d inimigos mortos,,%d slabi uciși,Плохишей убито: %d,%d зликовца убијено 1 monster killed,TXT_MONSTER_KILLED,,,,1 příšera zabita,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 zabity potwór,1 monstro morto,,1 monstru ucis,1 монстр убит,Једно чудовиште убијено @@ -900,20 +899,20 @@ Unable to resurrect. Player is no longer connected to its body.,TXT_NO_RESURRECT 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.,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.,Воскрешение невозможно. Игрок больше не соединён с трупом.,Немогуће оживети. Играч није више повезан са својим телом. All Artifacts!,TXT_ALL_ARTIFACTS,,,All Artefacts!,Všechny artefakty!,Alle Artefakte!,Όλα τα τεχνουργίματα!,Ĉiuj Artefaktoj!,¡Todos los Artefactos!,,Kaikki artefaktit!,Tous les artéfacts!,Összes értéktárgy!,Tutti gli Artefatti!,全アーティファクト!,모든 유물들!,Alle artefacten!,Wszystkie Artefakty!,Todos os artefatos!,,Toate Artefactele!,Все артефакты!,Сви артифакти! -What do you want to kill outside of a game?,TXT_WHAT_KILL,,,,"Co chceš zabít, když nejsi ve hře?",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 ölnél meg játékon kívül?,Cosa vorresti uccidere fuori dal gioco?,ゲーム外で何を殺す気だ?,게임 밖에서 무엇을 죽이고 싶습니까?,Wat wil je buiten een spel om doden?,Co ty chcesz zabić poza grą?,O que você gostaria de matar fora de um jogo?,,Ce vrei să ucizi în afara unui joc?,Что вы хотите убить вне игры?,Шта желите да убијете ван игре? +What do you want to kill outside of a game?,TXT_WHAT_KILL,,,,"Co chceš zabít, když nejsi ve hře?",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?,Co ty chcesz zabić poza grą?,O que você gostaria de matar fora de um jogo?,,Ce vrei să ucizi în afara unui joc?,Что вы хотите убить вне игры?,Шта желите да убијете ван игре? Frozen player properties turned off,TXT_NOT_FROZEN,,,,Vlastnosti držící hráče na místě vypnuty,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,Właściwości zamrożonego gracza wyłączone,Propriedades de jogador congelado desativadas,,Proprietăți jucători înghețați DEZACTIVATE,Свойства замороженного игрока отключены,Смрзнути играчи искључени ,,Automap,,,,,,,,,,,,,,,,,,,,, Follow Mode OFF,AMSTR_FOLLOWOFF,,,,Režim sledování VYP,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,Tryb śledzenia WYŁĄCZONY,Modo de seguimento DESATIVADO,,Mod Urmărire DEZACTIVAT,Привязка к игроку ОТКЛЮЧЕНА,Праћење ИСКЉУЧЕНО Follow Mode ON,AMSTR_FOLLOWON,,,,Režim sledování ZAP,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,Tryb śledzenia WŁĄCZONY,Modo de seguimento ATIVADO,,Mod Urmărire ACTIVAT,Привязка к игроку ВКЛЮЧЕНА,Праћење УКЉУЧЕНО Grid ON,AMSTR_GRIDON,,,,Mřížka ZAP,Gitter AN,Πλέχμα ΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado ŜALTITA,Cuadrícula ACTIVADA,Rejilla ACTIVADA,Ruudukko PÄÄLLÄ,Quadrillage ON,Rács BE,Griglia ATTIVATA,グリッド: オン,격자 켬,Raster AAN,Siatka WŁĄCZONA,Grade ATIVADA,Grelha ATIVADA,Grilă ACTIVATĂ,Сетка ВКЛЮЧЕНА,Мрежа УКЉУЧЕНА Grid OFF,AMSTR_GRIDOFF,,,,Mrizka VYP,Gitter AUS,Πλέχμα ΆΠΕΝΕΡΓΟΠΟΙΜΈΝΟ,Krado MALŜALTITA,Cuadrícula DESACTIVADA,Rejilla DESACTIVADA,Ruudukko POIS PÄÄLTÄ,Quadrillage OFF,Rács KI,Griglia DISATTIVATA,グリッド: オフ,격자 끔,Raster UIT,Siatka WYŁĄCZONA,Grade DESATIVADA,Grelha DESATIVADA,Grilă DEZACTIVATĂ,Сетка ОТКЛЮЧЕНА,Мрежа ИСКЉУЧЕНА -Texture Mode ON,AMSTR_TEXON,,,,Texturovaný režim ZAP,Texturmodus AN,Γραφικός χάρτης ΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo ŜALTITA,Modo de texturas ACTIVADO,,Pintakuviointitila PÄÄLLÄ,Mode Texturé ON,Textúrák BE,Modalità Texture ATTIVATA,テクスチャーモード: オン,텍스쳐 모드 켬,Textuurmodus AAN,Tekstury WŁĄCZONE,Modo de textura ATIVADO,,Mod Texturat ACTIVAT,Текстурный режим ВКЛЮЧЁН,Текстуре УКЉУЧЕНЕ -Texture Mode OFF,AMSTR_TEXOFF,,,,Texturovaný režim VYP,Texturmodus AUS,Γραφικός χάρτης ΑΠΕΝΕΡΓΟΠΟΙΜΈΝΟΣ,Tekstura Reĝimo MALŜALTITA,Modo de texturas DESACTIVADO,,Pintakuviointitila POIS PÄÄLTÄ,Mode Texturé OFF,Textúrák KI,Modalità Texture DISATTIVATA,テクスチャーモード: オフ,텍스쳐 모드 끔,Textuurmodus UIT,Tekstury WYŁĄCZONE,Modo de textura DESATIVADO,,Mod Netexturat DEZACTIVAT,Текстурный режим ОТКЛЮЧЕН,Текстуре ИСКЉУЧЕНЕ +Texture Mode ON,AMSTR_TEXON,,,,Texturovaný režim ZAP,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,Tekstury WŁĄCZONE,Modo de textura ATIVADO,,Mod Texturat ACTIVAT,Текстурный режим ВКЛЮЧЁН,Текстуре УКЉУЧЕНЕ +Texture Mode OFF,AMSTR_TEXOFF,,,,Texturovaný režim VYP,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,Tekstury WYŁĄCZONE,Modo de textura DESATIVADO,,Mod Netexturat DEZACTIVAT,Текстурный режим ОТКЛЮЧЁН,Текстуре ИСКЉУЧЕНЕ Marked Spot,AMSTR_MARKEDSPOT,,,,Značka,Punkt markiert,Μαρκαρησμένη τοποθεσεία,Loko Markita,Punto marcado,,Merkitty paikka,Repère marqué.,Megjelölt hely,Posizione segnata,目標をマークした,지점 추가,Gemarkeerde plek,Oznaczono miejsce,Posição marcada,,Loc Marcat,Отметка,Означено место All Marks Cleared,AMSTR_MARKSCLEARED,,,,Všechny značky smazány,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,Wszystkie miejsca wyczyszczone,Todas as marcas removidas,,Toate Marcările Șterse,Отметки очищены,Ознаке избрисане ,,Multiplayer,,,,,,,,,,,,,,,,,,,,, -Fraglimit hit.,TXT_FRAGLIMIT,,,,Fraglimit dosáhnut.,Fraglimit erreicht,Το όριο κοματιασμόν έχει φτάσει.,Ludmurdo-limo trafita.,Límite de bajas alcanzado.,,Frägiraja saavutettu.,Limite de frags atteinte.,Találatlimit elérve.,Fraglimit raggiunto.,フラグリミット!,킬제한에 도달했습니다.,Fraglimiet bereikt.,Limit fragów wyczerpany.,Limite de frags atingido.,,Limita de ucideri atinsă.,Достигнут лимит фрагов.,Фраг-лимит достигнут. -Timelimit hit.,TXT_TIMELIMIT,,,,Časový limit dosáhnut.,Zeitlimit erreicht,Το χρονικό όριο έχει φτάσει.,Tempolimo trafita.,Límite de tiempo alcanzado.,,Aikaraja saavutettu.,Limite de temps atteinte.,Időlimit elérve.,Timelimit raggiunto.,ゲームセット!,시간제한에 도달했습니다.,Tijdslimiet bereikt.,Limit czasowy wyczerpany.,Limite de tempo atingido.,,Limita de timp atinsă.,Достигнут лимит времени.,Временско ограничење достигнуто. +Fraglimit hit.,TXT_FRAGLIMIT,,,,Fraglimit dosáhnut.,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.,Limit fragów wyczerpany.,Limite de frags atingido.,,Limita de ucideri atinsă.,Достигнут лимит фрагов.,Фраг-лимит достигнут. +Timelimit hit.,TXT_TIMELIMIT,,,,Časový limit dosáhnut.,Zeitlimit erreicht,Το χρονικό όριο έχει φτάσει.,Tempolimo trafita.,Límite de tiempo alcanzado.,,Aikaraja saavutettu.,Limite de temps atteinte.,Időhatár elérve.,Timelimit raggiunto.,ゲームセット!,시간제한에 도달했습니다.,Tijdslimiet bereikt.,Limit czasowy wyczerpany.,Limite de tempo atingido.,,Limita de timp atinsă.,Достигнут лимит времени.,Временско ограничење достигнуто. %o was looking good until %g killed %hself!,SPREEKILLSELF,,,,%o vypadal@[ao_cs] dobře dokud se @[self_cs] nezabil@[ao_cs]!,"%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 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 killing spree was ended by %k,SPREEOVER,,,,%o@[psn1_cs] vraždící řádění ukončil hráč %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.,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 %k is on a killing spree!,SPREE5,,,,%k začal@[ao_cs] řádit!,%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 popełnia serię morderstw!,%k está cometendo uma matança!,,%k are chef de ucis!,Игрок %k совершил череду убийств!,%k је серијални убица! @@ -921,28 +920,28 @@ Timelimit hit.,TXT_TIMELIMIT,,,,Časový limit dosáhnut.,Zeitlimit erreicht,Τ %k is dominating!,SPREE15,,,,%k dominuje!,%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 dominuje!,%k está dominando!,,%k domină!,%k доминирует!,%k доминира! %k is unstoppable!,SPREE20,,,,%k je nezastaviteln@[adj_cs]!,%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 jest niepowstrzymany!,%k é implacável!,,%k e de neoprit!,Игрок %k неостановим!,Играч %k је незаустављив! %k is Godlike!,SPREE25,,,,%k je boží!,%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 jest Bogem!,%k é um deus da matança!,,%k e precum un Zeu!,Игрок %k богоподобен!,Играч %k је божанствен! -Double kill!,MULTI2,,,,Dvoj-zabití!,Doppel-Kill!,Δυπλός Θάνατος!,Duobla mortigo!,¡Dos menos!,,Tuplatappo!,Double meurtre!,Dupla gyilok!,Doppia uccisione!,ダブルキル!,더블 킬!,Dubbele kill!,Podwójne zabójstwo!,Lá se foram dois!,,Dublă ucidere!,Двойное убийство!,Дупло убиство! -Multi kill!,MULTI3,,,,Multi-zabití!,Multi-Kill!,Πολυθάνατος!,Pluraj mortigoj!,¡Multidestrucción!,,Multitappo!,Multi meurtre!,Multi gyilok!,Tripla uccisione!,マルチキル!,멀티 킬!,,Multi-zabójstwo!,Lá se foram três!,,Ucidere multiplă!,Массовое убийство!,Вишеструко убиство! +Double kill!,MULTI2,,,,Dvoj-zabití!,Doppel-Kill!,Δυπλός Θάνατος!,Duobla mortigo!,¡Dos menos!,,Tuplatappo!,Double meurtre!,Dupla gyilok!,Doppia uccisione!,ダブルキル!,더블 킬!,Dubbele kill!,Podwójne zabójstwo!,Morte dupla!,,Dublă ucidere!,Двойное убийство!,Дупло убиство! +Multi kill!,MULTI3,,,,Multi-zabití!,Multi-Kill!,Πολυθάνατος!,Pluraj mortigoj!,¡Multidestrucción!,,Multitappo!,Multi meurtre!,Multi gyilok!,Tripla uccisione!,マルチキル!,멀티 킬!,,Multi-zabójstwo!,Morte tripla!,,Ucidere multiplă!,Массовое убийство!,Вишеструко убиство! Ultra kill!,MULTI4,,,,Ultra-zabití!,Ultra-Kill!,Υπερθάνατος!,Ekstremaj mortigoj!,¡¡HIPERDESTRUCCIÓN!!,,Ultratappo!,Ultra meurtre!,Ultra gyilok!,Ultra uccisione!,ウルトラキル!,울트라 킬!,,Ultra-zabójstwo!,Ultra matança!,,Ultra ucidere!,Ультра-убийство!,Ултра убиство! Monster kill!,MULTI5,,,,Monstr-zabití!,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!,モンスターキル!,몬스터 킬!,,Potworne zabójstwo!,Matança monstro!,Matança monstruosa!,Ucidere monstruoasă!,Чудовищное убийство!,Монструозно убиство! ,,Scoreboard,,,,,,,,,,,,,,,,,,,,, Items,SCORE_ITEMS,,,,Předměty,Gegenstände,Αντεικείμενα,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,획득한 아이템,Items,Przedmioty,Itens,,Obiecte,Предметы,Предмети Bonus,SCORE_BONUS,,,,,Bonus,Bonus,Bonuso,Bonificaciones,,Lisäedut,,Bónusz,Bonus,ボーナス,보너스,Bonus,Bonusy,Bônus,,Bonus,Бонус,Бонус Color,SCORE_COLOR,,,Colour,Barva,Farbe,Χρώμα,Koloro,,,Väri,Couleur,Szín,Colore ,色,색상,Kleur,Kolor,Cor,,Culoare,Цвет,Боја -Secret,SCORE_SECRET,,,,Tajemství,Geheimnis,Μυστικό,Sekreto,Secreto,,Salat,,Titok,Segreto,シークレット,밝혀낸 비밀,Geheim,Sekret,Segredo,,Secret,Тайники,Тајна -Name,SCORE_NAME,,,,Jméno,Name,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Nazwa,Nome,,Nume,Имя,Име +Secret,SCORE_SECRET,,,,Skrýše,Geheimnis,Μυστικό,Sekreto,Secreto,,Salat,,Titok,Segreto,シークレット,밝혀낸 비밀,Geheim,Sekret,Segredo,,Secret,Тайники,Тајна +Name,SCORE_NAME,,,,Jméno,Name,Όνομα,Nomo,Nombre,,Nimi,Nom,Név,Nome,名前,이름,Naam,Nazwa,Nome,,Nume,Игрок,Име Delay (ms),SCORE_DELAY,,,,Zpoždění (ms),Verzögerung (ms),Kαθυστέρηση (μδ),Prokrasto (ms),Retraso (ms),,Viive (ms),Délai (ms),Késleltetés (ms),Ritardo (ms) ,ping,핑 (밀리초당),Vertraging (ms),Opóźnienie (ms),Atraso (ms),,Întârziere (ms),Задержка (мс),Кашњење (мс) Kills,SCORE_KILLS,,,,Zabití,,Σκοτομοί,Mortigoj,Asesinatos,,Tapot,Victimes,Áldozatok,Uccisioni,キル,킬수,Dood,Zabici,Vítimas,,Ucideri,Убийства,Убиства Frags,SCORE_FRAGS,,,,Fragy,,Κοματιασμοί,Ludmurdoj,Bajas,,Frägit,,Frag-ek,Frags,フラグ,플레이어 킬수,Frags,Fragi,Frags,,Victime,Фраги,Фрагови Deaths,SCORE_DEATHS,,,,Smrti,Tode,Θάνατοι,Mortoj,Muertes,,Kuolemat,Morts,Halálok,Morti,デス,사망한 횟수,Sterfgevallen,Śmierci,Mortes,,Decese,Смерти,Смрти -Other,SCORE_OTHER,,,,,,,Alia,,,Muu,,Egyéb,,その他,,Anders,Inne,Outro,,Altele,, +Other,SCORE_OTHER,,,,Ostatní,,,Alia,Demás,,Muu,,Egyéb,Altro,その他,,Anders,Inne,Outro,,Altele,Прочее, Missed,SCORE_MISSED,,,,Minuto,Verfehlt,Ξεχάστηκαν,Mankita,Pérdidas,,Hudit,Ratés,Kihagyva,Mancati ,ミス,놓친 수,Gemist,Ominięte,Perdido,,Ratate,Пропущено,Пропуштено Total,SCORE_TOTAL,,,,Celkem,Gesamt,Συνολικό,Tuto,,,Yhteensä,Total,Összesen,Totale,合計,총점,Totaal,Totalne,Total,,Total,Всего,Укупно Level Time,SCORE_LVLTIME,,,,Čas v levelu,Levelzeit,Χρόνος Πίστας,Daŭro de Nivelo,Tiempo de nivel,,Tasoaika,Temps niveau,Pályaidő,Tempo Livello ,時間,레벨 시간,Leveltijd,Czas,Tempo de fase,Tempo do Nível,Timp Petrecut,Время уровня,Време нивоа ,,Level Summary,,,,,,,,,,,,,,,,,,,,, Kills,TXT_IMKILLS,,,,Zabití,,Σκοτομοί,Mortigoj,Muertes,,Tapot,Morts,Áldozatok,Uccisioni,キル,킬수,Dood,Zabici,Vítimas,,Ucideri,Враги,Непријатељи Items,TXT_IMITEMS,,,,Předměty,Gegenstände,Αντεικείμενα,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,획득한 아이템,Items,Przedmioty,Itens,,Obiecte,Предметы,Ставке -Secrets,TXT_IMSECRETS,,,,Tajemství,Geheimnisse,Μυστικά,Sekretoj,Secretos,,Salat,,Titkok,Segreti,シークレット,밝혀낸 비밀,Geheimen,Sekrety,Segredos,,Secrete,Тайники,Тајне +Secrets,TXT_IMSECRETS,,,,Skrýše,Geheimnisse,Μυστικά,Sekretoj,Secretos,,Salat,,Titkok,Segreti,シークレット,밝혀낸 비밀,Geheimen,Sekrety,Segredos,,Secrete,Тайники,Тајне Time,TXT_IMTIME,,,,Čas,Zeit,Χρόνος,Daŭro,Tiempo,,Aika,Temps,Idő,Tempo,経過時間,소모한 시간,Tijd,Czas,Tempo,,Timp,Время,Време Par,TXT_IMPAR,,,,,,Μέσος Όρος,Alparo,,,,,Átlag,Media,最速時間,기준 시간,,Par,Média,,Record,Рекорд,Рекорд Finished,WI_FINISHED,,,,Dokončeno,Abgeschlossen,Ολοκληρώθηκε,Finita,Completado,,Suoritettu,Terminé,Teljesítve,Finito,攻略,완료,Klaar,Ukończono,Finalizado,,Terminat,Уровень завершён,Ниво завршен @@ -950,7 +949,7 @@ Entering,WI_ENTERING,,,,Vstupuješ do,Betrete,Είσοδος,Enirante,Entrando a Now entering:,WI_ENTERING,,heretic hexen,,Nyní vstupuješ do:,Betrete:,Τώρα εισέρχεσε στο:,Nun enirante:,Ahora entrando a:,,Seuraava kohde:,Vous entrez dans:,Következik:,Entrando adesso in:,突入中:,입장합니다:,Volgende:,Teraz wchodzisz do:,Entrando em:,A entrar em:,Acum începe:,Следующий уровень:,Следећи ниво: ,,HUD,,,,,,,,,,,,,,,,,,,,, Monsters:,AM_MONSTERS,,,,Příšery:,Monster:,Τέρατα,Monstroj:,Monstruos:,,Hirviöt:,Monstres:,Szörnyek:,Mostri,奴等:,죽인 적들:,Monsters:,Potwory:,Monstros:,,Monștri:,Монстры:,Чудовишта: -Secrets:,AM_SECRETS,,,,Tajemství:,Geheimnisse:,Μυστικά,Sekretoj:,Secretos:,,Salat:,,Titkos helyek:,Segreti,隠場:,찾은 비밀:,Geheimen:,Sekrety:,Segredos:,,Secrete:,Тайники:,Тајне: +Secrets:,AM_SECRETS,,,,Skrýše:,Geheimnisse:,Μυστικά,Sekretoj:,Secretos:,,Salat:,,Titkos helyek:,Segreti,隠場:,찾은 비밀:,Geheimen:,Sekrety:,Segredos:,,Secrete:,Тайники:,Тајне: Items:,AM_ITEMS,,,,Věci:,Gegenstände:,Αντεικείμενα,Objektoj:,Objetos:,,Esineet:,Objets:,Tárgyak:,Oggetti,物資:,얻은 아이템:,Items:,Przedmioty:,Itens:,,Obiecte:,Предметы:,Предмети: ,,Obituaries,,,,,,,,,,,,,,,,,,,,, %o suicides.,OB_SUICIDE,,,,%o spáchal@[ao_cs] sebevraždu.,%o begeht Selbstmord.,@[art_gr] %o αυτοκτόνησε,%o sinmortigas.,%o se suicidó.,,%o teki itsemurhan.,%o se suicide.,%o öngyilkos lett.,%o si è suicidato.,%o は自殺した。,%o 은(는) 자살했다.,%o pleegt zelfmoord.,%o popełnił@[ao_pl] samobójstwo.,%o se suicidou.,,%o se sinucide.,%o покончил@[ao_rus] с собой.,%o самоубиства. @@ -962,29 +961,29 @@ Items:,AM_ITEMS,,,,Věci:,Gegenstände:,Αντεικείμενα,Objektoj:,Objet %o melted.,OB_LAVA,,,,%o se rozpustil@[ao_cs].,%o schmolz.,@[art_gr] %o έλειοσε,%o fandiĝis.,%o se ha fundido.,,%o suli.,%o a fondu.,%o megolvadt.,%o si è sciolto.,%o は溶かされた。,%o 은(는) 녹아버렸다.,%o smolt.,%o stopił@[ao_pl] się.,%o derreteu.,%o derreteu-se.,%o s-a topit.,%o расплавил@[refl_rus].,%o је отопљен@[adj_1_sr]. %o went boom.,OB_BARREL,,,,%o udělal@[ao_cs] bum.,%o explodierte.,@[art_gr] %o έσκασε,%o eksplodis.,%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 zrobił@[ao_pl] bum.,%o explodiu.,,%o a explodat.,%o взорвал@[refl_rus].,%o је отиш@[ao_2_sr] бум. %o stood in the wrong spot.,OB_SPLASH,,,,%o stál@[ao_cs] na špatném místě.,%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 stan@[irreg_2_pl] w złym miejscu.,%o ficou no lugar errado.,,%o a stat în locul nepotrivit.,%o стоял@[ao_rus] в неверной точке.,%o је стаја@[ao_1_sr] на погрешно место. -%o should have stood back.,OB_R_SPLASH,,,,%o měl@[ao_cs] stát o trochu dál.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debió haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o hátrébb mehetett volna.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 좀 더 떨어져야만 했다.,%o had afstand moeten houden.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,%o не отступил@[ao_rus] в сторону.,Играчу %o је требало да стоји назад. -%o should have stood back.,OB_ROCKET,,,,%o měl@[ao_cs] stát o trochu dál.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debió haberse apartado.,,%o oli liian likellä.,%o aurait dû garder ses distances.,%o hátrébb mehetett volna.,%o si sarebbe dovuto allontanare.,%o は後ろへ引くべきだった。,%o 은(는) 더 멀리 떨어져야만 했다.,%o had afstand moeten houden.,%o nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,%o не отступил@[ao_rus] в сторону.,Играчу %o је требало да стоји назад. +%o should have stood back.,OB_R_SPLASH,,,,%o měl@[ao_cs] stát o trochu dál.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debió 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 nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,%o не отступил@[ao_rus] в сторону.,Играчу %o је требало да стоји назад. +%o should have stood back.,OB_ROCKET,,,,%o měl@[ao_cs] stát o trochu dál.,%o hätte Abstand halten sollen.,@[art_gr] %o έπρεπε να είχε κάτσι πίσω,%o devintus forstarinta.,%o debió 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 nie ustąpił@[ao_pl] na bok.,%o deveria ter se afastado.,,%o ar fi trebuit să stea deoparte.,%o не отступил@[ao_rus] в сторону.,Играчу %o је требало да стоји назад. %o killed %hself.,OB_KILLEDSELF,,,,%o se zabil@[ao_cs].,%o tötete sich selbst.,@[art_gr] %o αυτοκτόνησε,%o mortigis sin.,%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 zabił@[ao_pl] się.,%o se matou.,%o matou-se,%o s-a sinucis.,%o покончил@[ao_rus] с собой.,%o је уби@[ao_1_sr] себе. %o was killed by the power of voodoo.,OB_VOODOO,,,,%o byl@[ao_cs] zabit@[ao_cs] sílou voodoo.,%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 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 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 was telefragged by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] telefraggnut %kem.,%o stand %k im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς απο τον/την %k,%o estis teleportumita de %k.,%o ha sido 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 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.,Игрок %k телефрагнул игрока %o.,%o је телефрагован@[adj_1_sr] од стране %k. -%o was telefragged.,OB_MONTELEFRAG,,,,%o byl@[ao_cs] telefraggnut@[ao_cs].,%o stand jemandem im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς,%o estis teleportumita.,%o ha sido 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 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 was telefragged by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] telefraggnut %kem.,%o stand %k im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς απο τον/την %k,%o estis teleportumita de %k.,%o ha sido 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 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.,Игрок %k убивает телепортом игрока %o.,%o је телефрагован@[adj_1_sr] од стране %k. +%o was telefragged.,OB_MONTELEFRAG,,,,%o byl@[ao_cs] telefraggnut@[ao_cs].,%o stand jemandem im Wege.,@[art_gr] %o κοματιάστηκε μέσω τηλεμεταφοράς,%o estis teleportumita.,%o ha sido 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 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 died.,OB_DEFAULT,,,,"%o zemřel@[ao_cs]. ",%o ist gestorben.,@[art_gr] %o πέθανε,%o mortis.,%o ha muerto.,,%o kuoli.,%o est mort@[e_fr].,%o meghalt.,%o è morto.,%o は死亡した。,%o 은(는) 죽었다.,%o ging dood.,%o umarł@[ao_pl].,%o morreu.,,%o a murit.,Игрок %o погиб.,%o је умр@[ao_1_sr]. %o was killed by %k.,OB_MPDEFAULT,,,,%o byl@[ao_cs] zabit@[ao_cs] hráčem %k.,%o wurde von %k getötet.,@[art_gr] %o στοτώθηκε απο τον/την %k,%o estis mortigita de %k.,%o ha sido 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 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. %k mows down a teammate.,OB_FRIENDLY1,,,,%o rozsekal@[ao_cs] spoluhráče.,%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 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 seems to need glasses.,OB_FRIENDLY2,English was changed to remove problematic pronoun referencing the killer,,,%k potřebuje brýle.,%k sollte eine Brille benutzen.,Ο/Η %k φαίνεται να χρειάζετε γυαλία,%o ŝajnas bezoni okulvitrojn.,%k parece necesitar gafas.,,%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 wydaje się potrzebować okularów.,%k parece que precisa de óculos.,,%k pare să aibă nevoie de ochelari.,Игроку %k следует проверить свои очки.,Играчу %k би приличиле наочаре. +%k seems to need glasses.,OB_FRIENDLY2,English was changed to remove problematic pronoun referencing the killer,,,%k nejspíš potřebuje brýle.,%k sollte eine Brille benutzen.,Ο/Η %k φαίνεται να χρειάζετε γυαλία,%o ŝajnas bezoni okulvitrojn.,%k parece necesitar gafas.,,%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 wydaje się potrzebować okularów.,%k parece que precisa de óculos.,,%k pare să aibă nevoie de ochelari.,Игроку %k следует проверить свои очки.,Играчу %k би приличиле наочаре. %k gets a frag for the other team.,OB_FRIENDLY3,,,,%k dostal@[ao_cs] frag pro další tým.,%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 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 loses another friend.,OB_FRIENDLY4,,,,%k ztratil@[ao_cs] dalšího přítele.,%k hat wieder einen Freund verloren.,Ο/Η %k χάνει ακόμα έναν αλλο φίλο,%k perdas pluan 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 tracil kolejnego przyjaciela.,%k perde mais um amigo.,,%k mai pierde un prieten.,Игрок %k потерял ещё одного друга.,%k је изгуби@[ao_1_sr] још једног пријатеља. ,,Pickup,,,,,,,,,,,,,,,,,,,,, Picked up the armor.,GOTARMOR,,,Picked up the armour.,Sebráno brnění.,Panzer genommen.,Πήρες την πανοπλία.,Prenis la kirason.,Recogiste la armadura.,,Poimit panssarin.,Armure récupérée.,Felvettél egy páncélt.,Raccolto un'armatura.,アーマーを身に着けた。,방호구를 얻었다.,Je hebt het harnas opgepakt.,Zebrano zbroję.,Pegou uma armadura.,Apanhaste uma armadura.,Ai ridicat o armură.,Получена броня.,Покупили сте панцир. -Picked up the MegaArmor!,GOTMEGA,,,Picked up the MegaArmour!,Sebráno Megabrnění.,MegaPanzer genommen!,Πήρες την μέγα πανοπλία!,Prenis la Mega-Kirason!,¡Recogiste la Mega-Armadura!,,Poimit megapanssarin!,Méga-Armure récupérée!,Felvettél egy MegaPáncélt!,Raccolto una MegaArmatura!,メガアーマーを身に着けた!,메가아머를 얻었다!,Je hebt het megaharnas opgepakt!,Zebrano megazbroję!,Pegou uma Mega-armadura!,Apanhaste uma MegaArmadura.,Ai ridicat o MegaArmură!,Получена мегаброня!,Покупили сте мегапанцир! +Picked up the MegaArmor!,GOTMEGA,,,Picked up the MegaArmour!,Sebráno MegaBrnění!,MegaPanzer genommen!,Πήρες την μέγα πανοπλία!,Prenis la Mega-Kirason!,¡Recogiste la Mega-Armadura!,,Poimit megapanssarin!,Méga-Armure récupérée!,Felvettél egy MegaPáncélt!,Raccolto una MegaArmatura!,メガアーマーを身に着けた!,메가아머를 얻었다!,Je hebt het megaharnas opgepakt!,Zebrano megazbroję!,Pegou uma Mega-Armadura!,Apanhaste uma MegaArmadura.,Ai ridicat o MegaArmură!,Получена мегаброня!,Покупили сте мегапанцир! Picked up a health bonus.,GOTHTHBONUS,,,,Sebráno bonusové zdraví.,Gesundheitsbonus genommen.,Πήρες ένα bonus υγείας.,Prenis sano-bonuson.,Recogiste 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.,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.,Получен бонус к здоровью.,Покупили сте бонус здравља. Picked up an armor bonus.,GOTARMBONUS,,,Picked up an armour bonus.,Sebráno bonusové brnění.,Panzerbonus genommen.,Πήρες ένα bonus πανο.πλίας.,Prenis kiraso-bonuson.,Recogiste 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.,Zebrano bonus do zbroi.,Pegou um bônus de armadura.,Apanhaste um bônus de armadura.,Ai ridicat un bonus de armură.,Получен бонус к броне.,Покупили сте бонус панцира. -Picked up a stimpack.,GOTSTIM,,,,Sebrán stimulant.,Stimpack genommen.,Πήρες ένα μικρό πακέτο υγείας.,Prenis stimulilo-pakon.,Recogiste un estimulante.,,Poimit piristeruiskeen.,Stimpack récupéré.,Felvettél egy stimpacket.,Raccolto uno stimpack.,スティムパックを拾った。,스팀팩을 사용했다.,Je hebt een opwekpakket opgepakt.,Zebrano stimpacka.,Pegou um stimpack.,Apanhaste um kit de primeiros socorros.,Ai ridicat un kit de prim-ajutor mic.,Получен стимулятор.,Покупили сте стимпак. -Picked up a medikit that you REALLY need!,GOTMEDINEED,,,,"Sebrána lékárnička, kterou jsi FAKT potřeboval@[ao_cs].","Medikit genommen, das du WIRKLICH brauchst!",Πήρες πρώτες βοήθειες που χρειαζόσουνα ΠΆΡΑ ΠΟΛΥ!,"Prenis sukurkeston, kiun vi VERE bezonas!",¡Recogiste 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!,Hai raccolto un kit medico di cui avevi PROPRIO bisogno!,本当に必要なメディキットを手に入れた!,메디킷을 필요한 순간에 사용했다!,"Je hebt een verbandsdoos, die je ECHT nodig had, opgepakt!",Zebrano apteczkę której NAPRAWDĘ potrzebujesz!,"Pegou um kit médico -que você REALMENTE precisa!","Apanhaste um kit médico +Picked up a stimpack.,GOTSTIM,,,,Sebrán stimulant.,Stimpack genommen.,Πήρες ένα μικρό πακέτο υγείας.,Prenis stimulilo-pakon.,Recogiste un estimulante.,,Poimit piristeruiskeen.,Stimpack récupéré.,Felvettél egy szurit.,Raccolto uno stimpack.,スティムパックを拾った。,스팀팩을 사용했다.,Je hebt een opwekpakket opgepakt.,Zebrano stimpacka.,Pegou um stimpack.,Apanhaste um kit de primeiros socorros.,Ai ridicat un kit de prim-ajutor mic.,Получен стимулятор.,Покупили сте стимпак. +Picked up a medikit that you REALLY need!,GOTMEDINEED,,,,"Sebrána lékárnička, kterou jsi FAKT potřeboval@[ao_cs].","Medikit genommen, das du WIRKLICH brauchst!",Πήρες πρώτες βοήθειες που χρειαζόσουνα ΠΆΡΑ ΠΟΛΥ!,"Prenis sukurkeston, kiun vi VERE bezonas!",¡Recogiste 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!",Zebrano apteczkę której NAPRAWDĘ potrzebujesz!,"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!",Получена крайне необходимая аптечка!,Покупили сте медикит који вам је СТВАРНО потребан! +nevoie!",Получена КРАЙНЕ необходимая аптечка!,Покупили сте медикит који вам је СТВАРНО потребан! Picked up a medikit.,GOTMEDIKIT,,,,Sebrána lékárnička.,Medikit genommen.,Πήρες πρώτες βοήθειες.,Prenis sukurkeston.,Recogiste 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.,Zebrano apteczkę.,Pegou um kit médico.,Apanhaste um kit médico.,Ai ridicat un kit de prim-ajutor.,Получена аптечка.,Покупили сте медикит. Supercharge!,GOTSUPER,,,,Superzdraví!,Super-Ladung!,Υπερφόρτοση!,Superŝargo!,¡Supercarga!,,Supervaraus!,,Szupertöltés!,Sfera dell'Anima!,スーパーチャージ!,슈퍼차지!,,Supernaładowanie!,Supercarga!,,Superîncărcătură!,Сверхзаряд!,Супернабој! Picked up a blue keycard.,GOTBLUECARD,,,,Sebrána modrá karta.,Blaue Schlüsselkarte genommen.,Πήρες ένα μπλε κλειδί.,Prenis bluan ŝlosilkarton.,Recogiste 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.,Zebrano niebieską kartę klucz.,Pegou um cartão de acesso azul.,Apanhaste um cartão de acesso azul.,Ai ridicat un card cheie albastru.,Получена синяя ключ-карта.,Покупили сте плаву кључну карту. @@ -994,13 +993,13 @@ Picked up a blue skull key.,GOTBLUESKUL,,,,Sebrána modrá lebka.,Blauen Schäde Picked up a yellow skull key.,GOTYELWSKUL,,,,Sebrána žlutá lebka.,Geben Schädel-Schlüssel genommen.,Πήρες ένα κύτρινο κρανίο.,Prenis flavan kraniŝlosilon.,Recogiste una llave de calavera amarilla,Recogiste una llave de cráneo 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.,Zebrano żółtą czaszkę.,Pegou uma chave-crânio amarela.,Apanhaste uma chave crânio amarela.,Ai ridicat o cheie craniu galbenă.,Получен жёлтый ключ-череп.,Покупили сте жути кључ лобање. Picked up a red skull key.,GOTREDSKUL,,,,Sebrána červená lebka.,Roten Schädel-Schlüssel genommen.,Πήρες ένα κοκινο κρανίο.,Prenis ruĝan kraniŝlosilon.,Recogiste una llave de calavera roja.,Recogiste una llave de cráneo 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.,Zebrano czerwoną czaszkę.,Pegou uma chave-crânio vermelha.,Apanhaste uma chave crânio vermelha.,Ai ridicat o cheie craniu roșie.,Получен красный ключ-череп.,Покупили сте црвени кључ лобање. Invulnerability!,GOTINVUL,,,,Nezranitelnost!,Unverwundbarkeit!,Αθανασία!,Nevundebleco!,¡Invulnerabilidad!,,Haavoittumattomuus!,Invulnérabilité!,Sérthetetlenség!,Invulnerabilità!,不死身だ!,무적!,Onkwetsbaarheid!,Niezniszczalność!,Invulnerabilidade!,,Invincibilitate!,Неуязвимость!,Нерањивост! -Berserk!,GOTBERSERK,,,,,,Μανία!,Furiozigaĵo!,¡Berserker!,,Raivo!,,Dühös mód!,,バーサーク!,광전사!,,Szał!,Frenesi!,,Forță amplificată!,Берсерк!,Берсерк! +Berserk!,GOTBERSERK,,,,,,Μανία!,Furiozigaĵo!,¡Berserker!,,Raivo!,,Dühödt mód!,,バーサーク!,광전사!,,Szał!,Frenesi!,,Forță amplificată!,Берсерк!,Берсерк! Partial Invisibility,GOTINVIS,,,,Částečná neviditelnost,Teilweise Unsichtbarkeit,Ημη-αoρατότητα,Parta Nevidebleco,Invisibilidad Parcial,,Osittainen näkymättömyys,Invisibilité Partielle,Részleges láthatatlanság,Invisibilità parziale,半透明化スフィア,일시적 투명 효과!,Gedeeltelijke onzichtbaarheid,Częściowa niewidzialność,Invisibilidade parcial,,Invizibilitate parțială,Частичная невидимость.,Делимична невидљивост Radiation Shielding Suit,GOTSUIT,,,,Ochranný oblek proti radioaktivitě,Strahlenschutzanzug.,Προστατευτηκή Στολή,Radiado-Ŝildanta Kostumo,Traje Anti-Radiación,,Säteilysuojapuku,Combinaison Hazmat,Védőruha,Tuta anti-radiazioni,放射線防護服 ,방사능 보호복,Stralingsbeschermingspak,Kombinezon przeciwradiacyjny,Traje anti-radiação,Fato anti-radiação,Costum de protecție împotriva radiaților,Костюм радиационной защиты.,Одело против радијације -Computer Area Map,GOTMAP,,,,Počítačová mapa,Computerkarte.,Τοπικός Χάρτης,Komputila Area Mapo,Mapa Ordenador del Área,Mapa Computadora del Área,Alueen tietokonekartta,Carte Informatique,Térkép,Mappa Completata,コンピューターエリアマップ,구역 지도 컴퓨터,Computerkaart,Komputerowa mapa obszaru,Mapa completo,,Hartă completă,Компьютерная карта уровня.,Компјутерска мапа нивоа +Computer Area Map,GOTMAP,,,,Počítačová mapa,Computerkarte.,Τοπικός Χάρτης,Komputila Mapo de Areo,Mapa Ordenador del Área,Mapa Computadora del Área,Alueen tietokonekartta,Carte Informatique,Térkép,Mappa Completata,コンピューターエリアマップ,구역 지도 컴퓨터,Computerkaart,Komputerowa mapa obszaru,Mapa completo,,Hartă completă,Компьютерная карта уровня.,Компјутерска мапа нивоа Light Amplification Visor,GOTVISOR,,,,Noktovizor,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,Gogle noktowizyjne,Visor de amplificação de luz,Visor de amplificação luminosa,Vedere amplificată,Очки ночного видения.,Ноћни визир -MegaSphere!,GOTMSPHERE,,,,MegaSféra!,MegaSphäre!,Μεγασφαίρα!,MegaSfero!,¡MegaEsfera!,,Megakuula!,Mégasphère!,MegaGömb!,MegaSfera!,メガスフィアー!,메가스피어!,,Megasfera!,MegaEsfera!,,Megasferă!,Мегасфера!,Мегасфера! +MegaSphere!,GOTMSPHERE,,,,MegaSféra!,MegaSphäre!,Μεγασφαίρα!,MegaSfero!,¡MegaEsfera!,,Megakuula!,Mégasphère!,MegaGömb!,MegaSfera!,メガスフィアー!,메가스피어!,,Megasfera!,Mega-Esfera!,,Megasferă!,Мегасфера!,Мегасфера! Picked up a clip.,GOTCLIP,,,,Sebrán zásobník.,Magazin genommen.,Πήρες ένα κουτάκι σφαιρών.,Prenis municio-klipon.,Recogiste un cargador.,,Poimit lippaan.,Chargeur récupéré.,Felvettél egy töltényt.,Raccolto un caricatore.,弾倉を拾った。,탄창을 얻었다.,Je hebt een patroon opgepakt.,Zebrano magazynek.,Pegou um carregador.,Apanhaste um carregador,Ai ridicat un cartuș.,Получен магазин.,Покупили сте оквир. Picked up a box of bullets.,GOTCLIPBOX,,,,Sebrána krabice s kulkami.,Kiste mit Pistolenkugeln genommen.,Πήρες ένα κουτί με σφαίρες.,Prenis skatolon da kugloj.,Recogiste 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.,Zebrano pudełko z nabojami.,Pegou uma caixa de balas.,Apanhaste uma caixa de balas,Ai ridicat o cutie cu gloanțe.,Получена коробка патронов.,Покупили сте кутију метака. Picked up a rocket.,GOTROCKET,,,,Sebrána raketa.,Rakete genommen,Πήρες ένα πύραυλο.,Prenis raketon.,Recogiste un cohete.,,Poimit raketin.,Roquette récupérée.,Felvettél egy rakétát.,Raccolto un razzo.,ロケットを拾った。,로켓을 얻었다.,Je hebt een raket opgepakt.,Zebrano rakietę.,Pegou um foguete.,Apanhaste um míssil,Ai ridicat o rachetă.,Получена ракета.,Покупили сте ракету. @@ -1010,98 +1009,98 @@ Picked up an energy cell pack.,GOTCELLBOX,,,,Sebrán svazek energetických člá Picked up 4 shotgun shells.,GOTSHELLS,,,,Sebrány 4 broky.,4 Schrotflintenpatronen genommen,Πήρες τέσσερεις σφάιρες ντουγεκιόυ.,Prenis 4 kartoĉojn.,Recogiste 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.,Zebrano 4 loftki do strzelby.,Pegou 4 cartuchos de espingarda.,Apanhaste 4 cartuchos de espingarda.,Ai ridicat 4 proiectile pentru pușcă.,Получено 4 патрона для дробовика.,Покупили сте 4 патроне од пумпарице. Picked up a box of shotgun shells.,GOTSHELLBOX,,,,Sebrána krabice s broky.,Kiste mit Schrotflintenpatronen genommen.,Πήρες ένα κουτί με σφάιρες ντουγεκιόυ.,Prenis skatolon da kartoĉoj.,Recogiste 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.,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ă.,Получена коробка патронов для дробовика.,Покупили сте кутију патрона од пумпарице. Picked up a backpack full of ammo!,GOTBACKPACK,,,,Sebrán batoh s haldou munice!,Rucksack mit Munition genommen.,Πήρες μια τσάντα γεμάτη με πυρομαχικά!,Prenis tornistron plenan de municioj!,¡Recogiste 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!,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!,"Получен рюкзак, полный патронов!",Покупили сте ранац с патронама! -"You got the BFG9000! Oh, yes.",GOTBFG9000,,,,"Sebráno BFG9000! Ó, ano!","Das BFG9000! Oh, ja!","Πήρες το BFG9000! ο, ΝΑΊ.","Vi ricevis la BFG9000! Ho, jes.","¡Obtuviste la BFG9000! Oh, sí.",,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.,"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! О, да." -You got the chaingun!,GOTCHAINGUN,,,,Sebrán kulomet.,Maschinengewehr genommen.,Πήρες το πολυβόλο.,Vi ricevis la maŝinpafilon!,¡Obtuviste la ametralladora!,,Sait Gatling-konekiväärin!,Une MITRAILLEUSE!,Felvetted a golyószórót!,Hai trovato un mitragliatore!,チェーンガンを手に入れた!,당신은 체인건을 습득했다!,Je hebt het machinegeweer!,Zebrano karabin maszynowy!,Você pegou a metralhadora!,Apanhaste a metrelhadora!,Ai pus mâna pe mitraliera rotativă!,Получен пулемёт!,Покупили сте митраљез! -A chainsaw! Find some meat!,GOTCHAINSAW,,,,Motorová pila! Najdi maso!,Eine Kettensäge. Such mir etwas Fleisch!,Ένα αλυσοπρίονο! Βρες κρέας!,Ĉensegilo! Trovu ian karnon!,¡Una motosierra! ¡Encuentra 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!,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!,Бензопила! Найди немного мяса!,Тестера! Нађи месо! -You got the rocket launcher!,GOTLAUNCHER,,,,Sebrán raketomet.,Raketenwerfer genommen.,Πήρες το πυραβλοβόλο.,Vi ricevis la raketlanĉilon!,¡Obtuviste el lanzacohetes!,,Sait singon!,Un LANCE-ROQUETTES!,Felvetted a rakétavetőt!,Hai trovato un lanciarazzi!,ロケットランチャーを手に入れた!,당신은 로켓 런쳐를 습득했다!,Je hebt de raketwerper!,Zebrano wyrzutnię rakiet!,Você pegou um lança-foguetes.,Apanhaste um lança-mísseis!,Ai pus mâna pe lansatorul de rachete!,Получена ракетница!,Покупили сте ракетни бацач! -You got the plasma gun!,GOTPLASMA,,,,Sebrána plazmová puška.,Plasma-Gewehr genommen.,Πήρες το όπλο πλάσματος!,Vi ricevis la plasmo-pafilon!,¡Obtuviste el fusil de plasma!,,Sait plasmapyssyn!,Un FUSIL A PLASMA!,Felvetted a plazmafegyvert!,Hai trovato un fucile al plasma!,プラズマライフルを手に入れた!,당신은 플라즈마 건을 습득했다!,Je hebt het plasmageweer!,Zebrano karabin plazmowy!,Você pegou o fuzil de plasma!,Apanhaste uma pistola de plasma!,Ai pus mâna pe arma cu plasmă!,Получен плазмомет!,Покупили сте плазма оружје! -You got the shotgun!,GOTSHOTGUN,,,,Sebrána brokovnice.,Schrotflinte genommen.,Πήρες το ντουφέκι!,Vi ricevis la ĉaspafilon!,¡Obtuviste la escopeta!,,Sait haulikon!,Un FUSIL A POMPE!,Felvetted a puskát!,Hai trovato un fucile!,ショットガンを手に入れた!,당신은 샷건을 습득했다!,Je hebt het jachtgeweer!,Zebrano strzelbę!,Você pegou a espingarda!,Apanhaste uma espingarda.,Ai pus mâna pe pușcă!,Получен дробовик!,Покупили сте пумпарицу! -You got the super shotgun!,GOTSHOTGUN2,,,,Sebrána superbrokovnice.,Super-Schrotflinte genommen.,Πήρες το διπλό ντουφέκι!,Vi ricevis la superan ĉaspafilon!,¡Obtuviste la súper escopeta!,,Sait superhaulikon!,Un SUPER FUSIL DE CHASSE!,Felvetted a Szuper puskát!,Hai trovato una doppietta!,スーパーショットガンを手に入れた!,당신은 슈퍼 샷건을 습득했다!,Je hebt het superjachtgeweer!,Zebrano super strzelbę!,Você pegou uma espingarda de cano duplo!,Apanhaste uma espingarda de cano duplo!,Ai pus mâna pe super pușcă!,Получен супер-дробовик!,Покупили сте двоцевку! +"You got the BFG9000! Oh, yes.",GOTBFG9000,,,,"Sebráno BFG9000! Ó, ano!","Das BFG9000! Oh, ja!","Πήρες το BFG9000! ο, ΝΑΊ.","Vi akiris la BFG9000! Ho, jes.","¡Obtuviste la BFG9000! Oh, sí.",,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.,"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! О, да." +You got the chaingun!,GOTCHAINGUN,,,,Sebrán kulomet.,Maschinengewehr genommen.,Πήρες το πολυβόλο.,Vi akiris la maŝinpafilon!,¡Obtuviste la ametralladora!,,Sait Gatling-konekiväärin!,Une MITRAILLEUSE!,Felvetted a golyószórót!,Hai trovato un mitragliatore!,チェーンガンを手に入れた!,당신은 체인건을 습득했다!,Je hebt het machinegeweer!,Zebrano karabin maszynowy!,Você pegou a metralhadora!,Apanhaste a metrelhadora!,Ai pus mâna pe mitraliera rotativă!,Получен пулемёт!,Покупили сте митраљез! +A chainsaw! Find some meat!,GOTCHAINSAW,,,,Motorová pila! Najdi maso!,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!,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!,Бензопила! Найди немного мяса!,Тестера! Нађи месо! +You got the rocket launcher!,GOTLAUNCHER,,,,Sebrán raketomet.,Raketenwerfer genommen.,Πήρες το πυραβλοβόλο.,Vi akiris la raketlanĉilon!,¡Obtuviste el lanzacohetes!,,Sait singon!,Un LANCE-ROQUETTES!,Felvetted a rakétavetőt!,Hai trovato un lanciarazzi!,ロケットランチャーを手に入れた!,당신은 로켓 런쳐를 습득했다!,Je hebt de raketwerper!,Zebrano wyrzutnię rakiet!,Você pegou um lança-foguetes.,Apanhaste um lança-mísseis!,Ai pus mâna pe lansatorul de rachete!,Получена ракетница!,Покупили сте ракетни бацач! +You got the plasma gun!,GOTPLASMA,,,,Sebrána plazmová puška.,Plasma-Gewehr genommen.,Πήρες το όπλο πλάσματος!,Vi akiris la plasmo-pafilon!,¡Obtuviste el fusil de plasma!,,Sait plasmapyssyn!,Un FUSIL A PLASMA!,Felvetted a plazmafegyvert!,Hai trovato un fucile al plasma!,プラズマライフルを手に入れた!,당신은 플라즈마 건을 습득했다!,Je hebt het plasmageweer!,Zebrano karabin plazmowy!,Você pegou o fuzil de plasma!,Apanhaste uma pistola de plasma!,Ai pus mâna pe arma cu plasmă!,Получен плазмомёт!,Покупили сте плазма оружје! +You got the shotgun!,GOTSHOTGUN,,,,Sebrána brokovnice.,Schrotflinte genommen.,Πήρες το ντουφέκι!,Vi akiris la ĉaspafilon!,¡Obtuviste la escopeta!,,Sait haulikon!,Un FUSIL A POMPE!,Felvetted a puskát!,Hai trovato un fucile!,ショットガンを手に入れた!,당신은 샷건을 습득했다!,Je hebt het jachtgeweer!,Zebrano strzelbę!,Você pegou a espingarda!,Apanhaste uma espingarda.,Ai pus mâna pe pușcă!,Получен дробовик!,Покупили сте пумпарицу! +You got the super shotgun!,GOTSHOTGUN2,,,,Sebrána superbrokovnice.,Super-Schrotflinte genommen.,Πήρες το διπλό ντουφέκι!,Vi akiris la superan ĉaspafilon!,¡Obtuviste la súper escopeta!,,Sait superhaulikon!,Un SUPER FUSIL DE CHASSE!,Felvetted a Szuper puskát!,Hai trovato una doppietta!,スーパーショットガンを手に入れた!,당신은 슈퍼 샷건을 습득했다!,Je hebt het superjachtgeweer!,Zebrano super strzelbę!,Você pegou uma espingarda de cano duplo!,Apanhaste uma espingarda de cano duplo!,Ai pus mâna pe super pușcă!,Получен супердробовик!,Покупили сте двоцевку! Picked up a pistol.,PICKUP_PISTOL_DROPPED,,,,Sebrána pistole.,Pistole genommen.,Πήρες ενα πιστόλι.,Prenis pistolon.,Recogiste una pistola.,,Poimit pistoolin.,Un PISTOLET.,Felvettél egy pisztolyt.,Raccolta una pistola.,ピストルを拾った。,권총을 주웠다.,Je hebt het pistool opgepakt.,Zebrano pistolet.,Pegou uma pistola.,Apanhaste uma pistola.,Ai ridicat un pistol.,Получен пистолет.,Покупили сте пиштољ. You pick up a demonic dagger.,BETA_BONUS1,,,,Sebrána démonická dýka.,Dämonischen Dolch genommen.,Πήρες ένα δαιμονικό μαχαίρι.,Vi prenas demonan ponardon.,Recogiste 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.,Zebrano demoniczny sztylet.,Você pegou uma adaga demoníaca.,Apanhaste uma navalha demoníaca.,Ai ridicat un pumnal demonic.,Вы подобрали демонический кинжал.,Купите демонски бодеж. You pick up a skullchest.,BETA_BONUS2,,,,Sebrána lebkotruhla.,Schädelkiste genommen.,Πήρες ένα κρανομπαούλο.,Vi prenas kraniokeston.,Recogiste un cofre de calaveras.,Recogiste un cofre de cráneos.,Poimit kalloarkun.,Coffre-crâne récupéré.,Felvettél egy skullchest-et.,Hai raccolto un cofanetto del teschio.,スカルチェストを拾った。,당신은 해골상자를 얻었다.,Je hebt een schedelborst opgepakt.,Zebrano skrzynię czaszki.,Você pegou um cofre-caveira.,Apanhaste um cofre caveira.,Ai ridicat o cutie cu craniu.,Вы подобрали сундук с черепом.,Купите ковчег с лобањом. You pick up an evil sceptre.,BETA_BONUS3,,,,Sebráno zlé žezlo.,Teuflisches Zepter genommen.,Πήρες το μοχθηρό σκήπτρο.,Vi prenas malbonan sceptron.,Recogiste 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.,Zebrano złe berło.,Você pegou um cetro maligno.,Apanhaste um cetro maligno,Ai ridicat un sceptru malefic.,Вы подобрали скипетр зла.,Купите зли скиптар. -You pick up an unholy bible.,BETA_BONUS4,,,,Sebrána bezbožná bible.,Unheilige Bibel genommen,Πήρες τήν ανίερη βίβλο.,Vi prenas malsanktan biblion.,Recogiste 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.,Zebrano nieświętą biblię.,Você pegou uma bíblia profana.,Apanhaste uma bíblia profana.,Ai ridicat o biblie nesfântă.,Вы подобрали порочную Библию.,Купите несвету библију. +You pick up an unholy bible.,BETA_BONUS4,,,,Sebrána bezbožná bible.,Unheilige Bibel genommen,Πήρες τήν ανίερη βίβλο.,Vi prenas malsanktan biblion.,Recogiste 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.,Zebrano nieświętą biblię.,Você pegou uma bíblia profana.,Apanhaste uma bíblia profana.,Ai ridicat o biblie nesfântă.,Вы подобрали порочную библию.,Купите несвету библију. ,,Locks,,,,,,,,,,,,,,,,,,,,, -You need a blue key to activate this object,PD_BLUEO,,,,Pro aktivaci tohoto objektu potřebuješ modrý klíč.,"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.,"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 +You need a blue key to activate this object,PD_BLUEO,,,,K aktivaci tohoto objektu potřebuješ modrý klíč.,"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.,"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",Для активации нужен синий ключ,Треба вам плави кључ да би активирали овај предмет -You need a red key to activate this object,PD_REDO,,,,Pro aktivaci tohoto objektu potřebuješ červený klíč.,"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 az objektumot.",Ti serve una chiave rossa per attivare questo oggetto,この装置には レッドキーが必要だ。,이 물체를 작동시키기 위해선 적색 열쇠가 필요합니다,Je hebt een rode sleutel nodig om dit object te activeren.,"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 +You need a red key to activate this object,PD_REDO,,,,K aktivaci tohoto objektu potřebuješ červený klíč.,"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.,"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",Для активации нужен красный ключ,Треба вам црвени кључ да би активирали овај предмет -You need a yellow key to activate this object,PD_YELLOWO,,,,Pro aktivaci tohoto objektu potřebuješ žlutý klíč.,"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 az objektum,Ti serve una chiave gialla per attivare questo oggetto,この装置にはイエローキーが必要だ。,이 물체를 작동시키기 위해선 황색 열쇠가 필요합니다,Je hebt een gele sleutel nodig om dit object te activeren.,"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 +You need a yellow key to activate this object,PD_YELLOWO,,,,K aktivaci tohoto objektu potřebuješ žlutý klíč.,"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.,"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",Для активации нужен жёлтый ключ,Треба вам жути кључ да би активирали овај предмет -You need a blue key to open this door,PD_BLUEK,,,,Pro otevření těchto dveří potřebuješ modrý klíč.,"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 a kék kulcs nyitja.,Ti serve una chiave blu per aprire questa porta,このドアには ブルーキーが必要だ。,이 문을 열기 위해선 청색 열쇠가 필요합니다,Je hebt een blauwe sleutel nodig om deze deur te openen.,"Potrzebujesz niebieskiego klucza, aby otworzyć te drzwi",Você precisa de uma chave azul para abrir essa porta,Precisas de uma chave azul para abrir esta porta,"Ai nevoie de o cheie albastră pentru a deschide +You need a blue key to open this door,PD_BLUEK,,,,K otevření těchto dveří potřebuješ modrý klíč.,"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.,"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",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата -You need a red key to open this door,PD_REDK,,,,Pro otevření těchto dveří potřebuješ červený klíč.,"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.,"Potrzebujesz czerwonego klucza, aby otworzyć te drzwi",Você precisa de uma chave vermelha para abrir essa porta,Precisas de uma chave vermelha para abrir esta porta,"Ai nevoie de o cheie roșie pentru a deschide ușa +You need a red key to open this door,PD_REDK,,,,K otevření těchto dveří potřebuješ červený klíč.,"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.,"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",Для открытия нужен красный ключ,Треба вам црвени кључ да би отворили ова врата -You need a yellow key to open this door,PD_YELLOWK,,,,Pro otevření těchto dveří potřebuješ žlutý klíč.,"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.,"Potrzebujesz żółtego klucza, aby otworzyć te drzwi",Você precisa de uma chave amarela para abrir essa porta,Precisas de uma chave amarela para abrir esta porta,"Ai nevoie de o cheie galbena pentru a deschide ușa +You need a yellow key to open this door,PD_YELLOWK,,,,K otevření těchto dveří potřebuješ žlutý klíč.,"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.,"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",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата -You need a blue card to activate this object,PD_BLUECO,,,,Pro aktivaci tohoto objektu potřebuješ modrou kartu.,"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 az objektumot aktiválhasd",Ti serve una card d'accesso blu per attivare questo oggetto ,この装置には ブルーカード が必要だ。,이 물체를 작동시키기 위해선 청색 키카드가 필요합니다,Je hebt een blauwe sleutelkaart nodig om dit voorwerp te activeren.,"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 +You need a blue card to activate this object,PD_BLUECO,,,,K aktivaci tohoto objektu potřebuješ modrou kartu.,"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.,"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",Для активации нужен синий ключ,Треба вам плава карта да би активирали овај предмет -You need a red card to activate this object,PD_REDCO,,,,Pro aktivaci tohoto objektu potřebuješ červenou kartu.,"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 az objektum,Ti serve una card d'accesso rossa per attivare questo oggetto ,この装置には レッドカード が必要だ。,이 물체를 작동시키기 위해선 적색 키카드가 필요합니다,Je hebt een rode sleutelkaart nodig om dit voorwerp te activeren.,"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 +You need a red card to activate this object,PD_REDCO,,,,K aktivaci tohoto objektu potřebuješ červenou kartu.,"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.,"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",Для активации нужен красный ключ,Треба вам црвена карта да би активирали овај предмет -You need a yellow card to activate this object,PD_YELLOWCO,,,,Pro aktivaci tohoto objektu potřebuješ žlutou kartu.,"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 az objektumot.,ti serve una card d'accesso gialla per attivare questo oggetto ,この装置には イエローカード が必要だ。,이 물체를 작동시키기 위해선 황색 키카드가 필요합니다,Je hebt een gele sleutelkaart nodig om dit voorwerp te activeren.,"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 +You need a yellow card to activate this object,PD_YELLOWCO,,,,K aktivaci tohoto objektu potřebuješ žlutou kartu.,"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.,"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",Для активации нужен жёлтый ключ,Треба вам жута карта да би активирали овај предмет -You need a blue skull to activate this object,PD_BLUESO,,,,Pro aktivaci tohoto objektu potřebuješ modrou lebku.,"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 az objektumot.,ti serve una chiave-teschio blu per attivare questo oggetto ,この装置には ブルースカル が必要だ。,이 물체를 작동시키기 위해선 청색 해골이 필요합니다,Je hebt een blauwe schedel nodig om dit voorwerp te activeren.,"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 +You need a blue skull to activate this object,PD_BLUESO,,,,K aktivaci tohoto objektu potřebuješ modrou lebku.,"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.,"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",Для активации нужен синий череп,Треба вам плава лобања да би активирали овај предмет -You need a red skull to activate this object,PD_REDSO,,,,Pro aktivaci tohoto objektu potřebuješ červenou lebku.,"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 az objektumot.,ti serve una chiave-teschio rossa per attivare questo oggetto ,この装置には レッドスカル が必要だ。,이 물체를 작동시키기 위해선 적색 해골이 필요합니다,Je hebt een rode schedel nodig om dit voorwerp te activeren.,"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 +You need a red skull to activate this object,PD_REDSO,,,,K aktivaci tohoto objektu potřebuješ červenou lebku.,"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.,"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",Для активации нужен красный череп,Треба вам црвена лобања да би активирали овај предмет -You need a yellow skull to activate this object,PD_YELLOWSO,,,,Pro aktivaci tohoto objektu potřebuješ žlutou lebku.,"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 az objektumot.,ti serve una chiave-teschio gialla per attivare questo oggetto ,この装置には イエロースカル が必要だ。,이 물체를 작동시키기 위해선 황색 해골이 필요합니다,Je hebt een gele schedel nodig om dit voorwerp te activeren.,"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 +You need a yellow skull to activate this object,PD_YELLOWSO,,,,K aktivaci tohoto objektu potřebuješ žlutou lebku.,"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.,"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",Для активации нужен жёлтый череп,Треба вам жута лобања да би активирали овај предмет -You need a blue card to open this door,PD_BLUEC,,,,Pro otevření těchto dveří potřebuješ modrou kartu.,"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.,"Egy kék kártya kell, hogy kinyisd ezt az ajtót.",Ti serve una card d'accesso blu per aprire questa porta,このドアには ブルーカード が必要だ。,이 문을 열기 위해선 청색 키카드가 필요합니다,Je hebt een blauwe sleutelkaart nodig om deze deur te openen.,"Potrzebujesz niebieskiej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso azul para abrir essa porta,Precisas de um cartão de acesso azul para abrir esta porta,"Ai nevoie de un card albastru pentru a activa +You need a blue card to open this door,PD_BLUEC,,,,K otevření těchto dveří potřebuješ modrou kartu.,"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.,"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ă",Для активации нужна синяя карта,Треба вам плава карта да би отворили ова врата -You need a red card to open this door,PD_REDC,,,,Pro otevření těchto dveří potřebuješ červenou kartu.,"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.,Piros kártya nyitja ezt az ajtót.,Ti serve una card d'accesso rossa per aprire questa porta,このドアには レッドカード が必要だ。,이 문을 열기 위해선 적색 키카드가 필요합니다,Je hebt een rode sleutelkaart nodig om deze deur te openen.,"Potrzebujesz czerwonej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso vermelho para abrir essa porta,Precisas de um cartão de acesso vermelho para abrir esta porta,"Ai nevoie de un card galben pentru a activa +You need a red card to open this door,PD_REDC,,,,K otevření těchto dveří potřebuješ červenou kartu.,"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.,"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șă",Для активации нужна красная карта,Треба вам црвена карта да би отворили ова врата -You need a yellow card to open this door,PD_YELLOWC,,,,Pro otevření těchto dveří potřebuješ žlutou kartu.,"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ó a 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.,"Potrzebujesz żółtej karty, aby otworzyć te drzwi",Você precisa de um cartão de acesso amarelo para abrir essa porta,Precisas de um cartão de acesso amarelo para abrir esta porta,"Ai nevoie de un card galben pentru a activa -această ușă",Для активации нужна желтая карта,Треба вам жута карта да би отворили ова врата -You need a blue skull to open this door,PD_BLUES,,,,Pro otevření těchto dveří potřebuješ modrou lebku.,"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.,Kék koponya nyitja ezt az ajtót.,Ti serve una chiave-teschio blu per aprire questa porta,このドアには ブルースカル が必要だ。,이 문을 열기 위해선 청색 해골이 필요합니다,Je hebt een blauwe schedel nodig om deze deur te openen.,"Potrzebujesz niebieskiej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio azul para abrir essa porta,Precisas de uma chave crânio azul para abrir esta porta,"Ai nevoie de un craniu albastru pentru a activa +You need a yellow card to open this door,PD_YELLOWC,,,,K otevření těchto dveří potřebuješ žlutou kartu.,"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.,"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șă",Для активации нужна жёлтая карта,Треба вам жута карта да би отворили ова врата +You need a blue skull to open this door,PD_BLUES,,,,K otevření těchto dveří potřebuješ modrou lebku.,"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.,"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șă",Для активации нужен синий череп,Треба вам плава лобања да би отворили ова врата -You need a red skull to open this door,PD_REDS,,,,Pro otevření těchto dveří potřebuješ červenou lebku.,"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.,"Egy piros koponya szükséges, hogy kinyisd ezt az ajtót.",Ti serve una chiave-teschio rossa per aprire questa porta,このドアには レッドスカル が必要だ。,이 문을 열기 위해선 적색 해골이 필요합니다,Je hebt een rode schedel nodig om deze deur te openen.,"Potrzebujesz czerwonej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio vermelha para abrir essa porta,Precsias de uma chave crânio vermelha para abrir esta porta,"Ai nevoie de un craniu roșu pentru a activa +You need a red skull to open this door,PD_REDS,,,,K otevření těchto dveří potřebuješ červenou lebku.,"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.,"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șă",Для активации нужен красный череп,Треба вам црвена лобања да би отворили ова врата -You need a yellow skull to open this door,PD_YELLOWS,,,,Pro otevření těchto dveří potřebuješ žlutou lebku.,"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.,Ezt az ajtót egy sárga koponya nyitja.,Ti serve una chiave-teschio gialla per aprire questa porta,このドアには イエロースカル が必要だ。,이 문을 열기 위해선 황색 해골이 필요합니다,Je hebt een gele schedel nodig om deze deur te openen.,"Potrzebujesz żółtej czaszki, aby otworzyć te drzwi",Você precisa de uma chave-crânio amarela para abrir essa porta,Precisas de uma chave crânio amarela para abrir esta porta,"Ai nevoie de un craniu galben pentru a activa +You need a yellow skull to open this door,PD_YELLOWS,,,,K otevření těchto dveří potřebuješ žlutou lebku.,"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.,"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șă",Для активации нужен жёлтый череп,Треба вам жута лобања да би отворили ова врата ,,Cast call names,,,,,,,,,,,,,,,,,,,,, -Zombieman,CC_ZOMBIE,,,,Zombík,Zombie,Ζόμπι,Zombiviro,Zombi,,Zombimies,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби +Zombieman,CC_ZOMBIE,,,,Zombie,Zombie,Ζόμπι,Zombiviro,Zombi,,Zombimies,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби Shotgun Guy,CC_SHOTGUN,a.k.a. (former human) sergeant,,,Seržant,Schütze,Τύπος με ντουφέκι,Ĉaspafilulo,Tipo de Escopeta,Tipo de la escopeta,Haulikkohemmo,Type au Fusil,Őrmester,Zombie Sergente,ショットガンゾンビ,샷건 가이,Jachtgeweerkerel,Zombie-sierżant,Sargento Possuído,Tipo de Espingarda,Pușcaș,Зомби-сержант,Пумпераш -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,Gépágyús pasas,Zombie Commando,ヘビーウェポンゾンビ,헤비 웨폰 듀드,Zwarewapenskerel,Ciężkozbrojny Zombie,Comando Possuído,Gajo das Armas Pesadas,Mitralior,Пулемётчик,Митраљезац -Imp,CC_IMP,,,,Čertík,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Kobold,Imp,インプ,임프,,Chochlik,Diabrete,,Drac,Имп,Враг -Demon,CC_DEMON,,,,Démon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Demone,デーモン,데몬,Demoon,Demon,Demônio,,Demon,Демон,Демон +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,Ciężkozbrojny Zombie,Comando Possuído,Gajo das Armas Pesadas,Mitralior,Пулемётчик,Митраљезац +Imp,CC_IMP,,,,Čert,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Tűzkobold,Imp,インプ,임프,,Chochlik,Diabrete,,Drac,Имп,Враг +Demon,CC_DEMON,,,,Démon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Pinky,デーモン,데몬,Demoon,Demon,Demônio,,Demon,Демон,Демон Lost Soul,CC_LOST,,,,Ztracená duše,Verlorene Seele,Χαμένη Ξυχή,Perdita Animo,Alma Errante,,Kadonnut sielu,Ame Perdue,Kóbor lélek,Anima Errante,ロストソウル,로스트 소울,Verloren ziel,Zagubiona Dusza,Alma Perdida,Alma Penada,Suflet Pierdut,Потерянная душа,Изгубљена душа Cacodemon,CC_CACO,,,,Kakodémon,Cacodämon,Κακοδαίμονας,Kakodemono,Cacodemonio,,Kakodemoni,Cacodémon,Kakodémon,Cacodemone,カコデーモン,카코데몬,Cacodemoon,Kakodemon,Cacodemônio,,Cacodemon,Какодемон,Какодемон Hell Knight,CC_HELL,,,,Pekelný rytíř,Höllenritter,Ιππότης της Κόλασης,Inferkavaliro,Caballero del Infierno,,Hornanritari,Chevalier Infernal,Pokollovag,Cavaliere Infernale,ヘルナイト,헬 나이트,Helleridder,Rycerz Piekła,Guarda Infernal,Cavaleiro Infernal,Cavaler al Infernului,Рыцарь Ада,Витез пакла Baron of Hell,CC_BARON,,,,Baron pekel,Höllenbaron,Βαρώνος της Κολασης,Barono de Infero,Barón del Infierno,,Hornanparoni,Baron des Enfers,Pokolbáró,Barone Infernale,バロンオブヘル,바론 오브 헬,Baron des Hels,Baron Piekła,Barão do Inferno,,Baron al Infernului,Барон Ада,Барон пакла -Arachnotron,CC_ARACH,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,Arachnotron,,Arachnotron,アラクノトロン,아라크노트론,,Arachnotron,Aracnotron,,Aracnotron,Арахнотрон,Паукотрон -Pain Elemental,CC_PAIN,,,,Elementál bolesti,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње +Arachnotron,CC_ARACH,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,Arachnotron,Póktron,Arachnotron,アラクノトロン,아라크노트론,,Arachnotron,Aracnotron,,Aracnotron,Арахнотрон,Паукотрон +Pain Elemental,CC_PAIN,,,,Živel trýzně,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње Revenant,CC_REVEN,,,,Umrlec,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,Revenant,Kísértet,Revenant,レバナント,레버넌트,Wreker,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник Mancubus,CC_MANCU,,,,Mankubus,,Χοντρός,Mankubo,,,Mankubus,Mancube,Mankubusz,Mancubus,マンキュバス,맨큐버스,,Mankubus,,,,Манкубус,Манкубус -Arch-Vile,CC_ARCH,,,,Veleběs,Scheusal,Νεκρομάντις,Ĉef-Fiulo,,,Arkkihirvitys,Arche-vile,Ősálnok,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Arcy-Podlec,Arquivil,,Abject,Арчвайл,Арчвајл -The Spider Mastermind,CC_SPIDER,,,,Pavoučí velevůdce,Der Spinnenmeister,Το Αραχνό Ιθύνων Νους,La Elektraraneo-Mastro,La Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,A Pókvezér,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Het Spinnenmeesterbrein,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац +Arch-Vile,CC_ARCH,,,,Veleběs,Scheusal,Νεκρομάντις,Ĉef-Fiulo,,,Arkkihirvitys,Arche-vile,Ősármány,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Arcy-Podlec,Arquivil,,Abject,Архвиль,Арчвајл +The Spider Mastermind,CC_SPIDER,,,,Pavoučí velevůdce,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,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац The Cyberdemon,CC_CYBER,,,,Kyberdémon,Der Cyberdämon,Ο Cyber-δαίμονας,La Ciberdemono,El Ciberdemonio,,Kyberdemoni,Le Cyberdémon,A Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Het Cyberdemoon,Cyberdemon,O Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон Our Hero,CC_HERO,,,,Náš hrdina,Unser Held,Ο ήρωας μας,Nia Heroo,Nuestro Héroe,,Sankarimme,Notre Héros,Hősünk,Il Nostro eroe,我らのヒーロー,우리들의 영웅,Onze held,Nasz bohater,Nosso herói,O Nosso Herói,Eroul Nostru,Наш герой,Наш херој ,,Actor tag names,,,,,,,,,,,,,,,,,,,,, Zombieman,FN_ZOMBIE,,,,Zombie,Zombie,Ζόμπι,Zombiviro,Zombi,,Zombi,Zombie,Zombi,Zombie Marine,ゾンビ兵,좀비맨,Zombie,Zombie,Zumbi,Homem Zombie,Zombi,Зомби,Зомби Sergeant,FN_SHOTGUN,,,,Seržant,Schütze,Λοχίας,Serĝento,Sargento,,Kersantti,Type au Fusil,Őrmester,Zombie Sergente,ゾンビ軍曹,샷건 가이,Sergeant,Zombie-sierżant,Sargento Possuído,Sargento,Sergent,Сержант,Водник -Chaingunner,FN_HEAVY,,,,Kulometčík,MG-Schütze,Πολυβόλο Ζόμπι,Maŝinpafilisto,Ametrallador,,Konekiväärimies,Type au Gros Flingue,Gépágyús,Zombie Commando,チェーンガンゾンビ,체인거너,Machinegeweerman,Ciężkozbrojny Zombie,Comando Possuído,Metrelhador,Mitralior,Пулемётчик,Митраљезац -Imp,FN_IMP,,,,Čert,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Kobold,Imp,インプ,임프,,Chochlik,Diabrete,,Drac,Имп,Враг -Demon,FN_DEMON,,,,Démon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Demone,デーモン,데몬,Demoon,Demon,Demônio,,Demon,Демон,Демон -Spectre,FN_SPECTRE,,,,Přízrak,Schemen,Φάντασμα,Fantomo,Espectro,,Haamu,,Fantom,Spettro,スペクトル,스펙터,Spook,Widmo,Espectro,,Spectru,Спектр,Авет +Chaingunner,FN_HEAVY,,,,Kulometčík,MG-Schütze,Πολυβόλο Ζόμπι,Maŝinpafilisto,Ametrallador,,Konekiväärimies,Type au Gros Flingue,Kommandós,Zombie Commando,チェーンガンゾンビ,체인거너,Machinegeweerman,Ciężkozbrojny Zombie,Comando Possuído,Metrelhador,Mitralior,Пулемётчик,Митраљезац +Imp,FN_IMP,,,,Čert,Kobold,Διάβολος,Diableto,,,Piru,Diablotin,Tűzkobold,Imp,インプ,임프,,Chochlik,Diabrete,,Drac,Имп,Враг +Demon,FN_DEMON,,,,Démon,Dämon,Δαίμονας,Demono,Demonio,,Demoni,Démon,Démon,Pinky,デーモン,데몬,Demoon,Demon,Demônio,,Demon,Демон,Демон +Spectre,FN_SPECTRE,,,,Přízrak,Schemen,Φάντασμα,Fantomo,Espectro,,Haamu,,Lidérc,Spettro,スペクトル,스펙터,Spook,Widmo,Espectro,,Spectru,Призрак,Авет Lost Soul,FN_LOST,,,,Ztracená duše,Verlorene Seele,Χαμένη Ξυχή,Perdita Animo,Alma Errante,,Kadonnut sielu,Ame Perdue,Kóbor lélek,Anima Errante,ロストソウル,로스트 소울,Verloren Ziel,Zagubiona Dusza,Alma Perdida,Alma Penada,Suflet Pierdut,Потерянная душа,Изгубљена душа Cacodemon,FN_CACO,,,,Kakodémon,Cacodämon,Κακοδαίμονας,Kakodemono,Cacodemonio,,Kakodemoni,Cacodémon,Kakodémon,Cacodemone,カコデーモン,카코 데몬,Cacodemoon,Kakodemon,Cacodemônio,,Cacodemon,Какодемон,Какодемон Hell Knight,FN_HELL,,,,Pekelný rytíř,Höllenritter,Ιππότης της Κόλασης,Inferkavaliro,Caballero del Infierno,,Hornanritari,Chevalier Infernal,Pokollovag,Cavaliere Infernale,ヘルナイト,헬 나이트,Helleridder,Rycerz Piekła,Guarda Infernal,Cavaleiro Infernal,Cavaler al Infernului,Рыцарь Ада,Витез пакла Baron of Hell,FN_BARON,,,,Baron pekel,Höllenbaron,Βαρώνος της Κολασης,Barono de Infero,Barón del Infierno,,Hornanparoni,Baron des Enfers,Pokolbáró,Barone Infernale,バロンオブヘル,바론 오브 헬,Baron des Hels,Baron Piekła,Barão do Inferno,,Baron al Infernului,Барон Ада,Барон пакла -Arachnotron,FN_ARACH,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,,,Arachnotron,アラクノトロン,아라크노트론,,,,,Aracnotron,Арахнотрон,Паукотрон +Arachnotron,FN_ARACH,,,,,,Αράχνοτρον,Elektraraneo,Aracnotrón,,Araknotroni,,Póktron,Arachnotron,アラクノトロン,아라크노트론,,,,,Aracnotron,Арахнотрон,Паукотрон Pain Elemental,FN_PAIN,,,,Živel trýzně,Elementarschmerz,Στοιχείομα του Πόνου,Doloro-Elementulo,Elemental del Dolor,,Kivun henki,Elémentaire de Douleur,Elemi Kín,Elementale del Dolore,ペインエレメンタル,페인 엘리멘탈,Smartelementaal,Żywiołak Bólu,Elemental da Dor,,Elemental al Durerii,Элементаль боли,Елементал патње -Revenant,FN_REVEN,,,,Umrlec,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,,kísértet,Revenant,レバナント,레버넌트,Wreker,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник -Mancubus,FN_MANCU,,,,Mankubus,,Χοντρός,Mankubo,,,Mankubus,Mancube,,Mancubus,マンキュバス,맨큐버스,,Mankubus,,,,Манкубус,Манкубус -Arch-vile,FN_ARCH,,,,Veleběs,Scheusal,Νεκρομάντις,Ĉef-fiulo,,,Arkkihirvitys,Arche-vile,Ősálnok,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Arcy-Podlec,Arquivil,,Abject,Арчвайл,Арчвајл -Spider Mastermind,FN_SPIDER,,,,Pavoučí velevůdce,Spinnenmeister,Αραχνό Ιθύνων Νους,Elektraraneo-Mastro,Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókvezér,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Spinnenmeesterbrein,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац +Revenant,FN_REVEN,,,,Umrlec,Wiederauferstandener,Εκδικητής,Renaskitulo,,,Henkiinpalannut,,Kísértet,Revenant,レバナント,레버넌트,Wreker,Zjawa,Insepulto,Renascido,Nemort,Ревенант,Повратник +Mancubus,FN_MANCU,,,,Mankubus,,Χοντρός,Mankubo,,,Mankubus,Mancube,Mankubusz,Mancubus,マンキュバス,맨큐버스,,Mankubus,,,,Манкубус,Манкубус +Arch-vile,FN_ARCH,,,,Veleběs,Scheusal,Νεκρομάντις,Ĉef-fiulo,,,Arkkihirvitys,Arche-vile,Ősármány,Arch-vile,アーチバイル,아크-바일,Aartsgedrocht,Arcy-Podlec,Arquivil,,Abject,Архвиль,Арчвајл +Spider Mastermind,FN_SPIDER,,,,Pavoučí velevůdce,Spinnenmeister,Αραχνό Ιθύνων Νους,Elektraraneo-Mastro,Mente-Maestra Arácnida,,Hämähäkkiaivot,L'Araignée Commandante,Pókelme,L'Aracnomente Suprema,スパイダーマスターマインド,스파이더 마스터마인드,Spinnenmeesterbrein,Pajęczy Mistrz,A Aranha-Mestra,,Păianjen Maestru,Паук-предводитель,Паук-руководилац Cyberdemon,FN_CYBER,,,,Kyberdémon,Cyberdämon,Cyber-δαίμονας,Ciberdemono,Ciberdemonio,,Kyberdemoni,Le Cyberdémon,Kiberdémon,Il Cyberdemonio,サイバーデーモン,사이버데몬,Cyberdemoon,Cyberdemon,O Ciberdemônio,,Ciberdemon,Кибердемон,Сајбердемон Nazi,FN_WOLFSS,,,,Nácek,,Ναζιστής,Nazio,,,Natsi,,Náci,Nazista,ナチ兵,나치,,Nazista,Nazista,Nazi,Nazist,Нацист,Нациста Dog,FN_DOG,,,,Pes,Hund,Σκύλος,Hundo,Perro,,Koira,Chien,Kutya,Cane,犬,개,Hond,Pies,Cão,,Câine,Собака,Пас -Brass Knuckles,TAG_FIST,,,,Boxer,Schlagringe,Γροθιά,Pugningo,Nudillos de bronce,,Nyrkkirauta,Poing Américain,Bokszer,Tirapugni ,ナックルダスター,너클,Boksbeugels,Kastety,Soco Inglês,Soqueira,Rozetă,Кулаки,Боксер +Brass Knuckles,TAG_FIST,,,,Boxer,Schlagringe,Γροθιά,Pugningo,Puño Americano,,Nyrkkirauta,Poing Américain,Bokszer,Tirapugni ,ナックルダスター,너클,Boksbeugels,Kastety,Soco Inglês,Soqueira,Rozetă,Кулаки,Боксер Chainsaw,TAG_CHAINSAW,,,,Motorová pila,Kettensäge,Αλλησοπρίονο,Ĉensegilo,Motosierra,,Moottorisaha,Tronçonneuse,Láncfűrész,Motosega,チェーンソウ,전기톱,Kettingzaag,Piła łańcuchowa,Motosserra,,Drujbă,Бензопила,Моторна тестера Pistol,TAG_PISTOL,,,,Pistole,Pistole,Πιστόλι,Pafileto,Pistola,,Pistooli,Pistolet,Pisztoly,Pistola,ピストル,권총,Pistool,Pistolet,Pistola,,Pistol,Пистолет,Пиштољ -Shotgun,TAG_SHOTGUN,,,,Brokovnice,Schrotflinte,Ντουφέκι,Ĉaspafilo,Escopeta,,Haulikko,Fusil à pompe,Sörétes puska,Fucile,ショットガン,샷건,Jachtgeweer,Strzelba,Espingarda,,Pușcă,Дробовик,Пумпарица -Super Shotgun,TAG_SUPERSHOTGUN,,,,Superbrokovnice,Super-Schrotflinte,Διπλό Ντουφέκι,Supera Ĉaspafilo,Súper Escopeta,,Superhaulikko,Super Fusil de chasse,Szuper sörétes puska,Fucile a doppia canna ,スーパーショットガン,슈퍼 샷건,Superjachtgeweer,Super strzelba,Espingarda de cano duplo,,Super Pușcă,Супер-дробовик,Двоцевка +Shotgun,TAG_SHOTGUN,,,,Brokovnice,Schrotflinte,Ντουφέκι,Ĉaspafilo,Escopeta,,Haulikko,Fusil à pompe,Sörétes Puska,Fucile,ショットガン,샷건,Jachtgeweer,Strzelba,Espingarda,,Pușcă,Дробовик,Пумпарица +Super Shotgun,TAG_SUPERSHOTGUN,,,,Superbrokovnice,Super-Schrotflinte,Διπλό Ντουφέκι,Supera Ĉaspafilo,Súper Escopeta,,Superhaulikko,Super Fusil de chasse,Szuper Sörétes,Fucile a doppia canna ,スーパーショットガン,슈퍼 샷건,Superjachtgeweer,Super strzelba,Espingarda de cano duplo,,Super Pușcă,Супердробовик,Двоцевка Chaingun,TAG_CHAINGUN,,,,Kulomet,Maschinengewehr,Πολυβόλο,Maŝinpafilo,Ametralladora,,Gatling-kk,Mitrailleuse,Golyószóró,Mitragliatore a canne rotanti ,チェーンガン,체인건,Machinegeweer,Karabin maszynowy,Metralhadora,,Mitralieră rotativă,Пулемёт,Митраљез Rocket Launcher,TAG_ROCKETLAUNCHER,,,,Raketomet,Raketenwerfer,Πυραυλοβόλο,Raketlanĉilo,Lanzacohetes,,Sinko,Lance-Roquettes,Rakétavető,Lanciamissili,ロケットランチャー,로켓 런쳐,Raketwerper,Wyrzutnia rakiet,Lança-foguetes,Lança-Mísseis,Lansator de Rachete,Ракетница,Бацач ракета Plasma Rifle,TAG_PLASMARIFLE,,,,Plazmová puška,Plasmagewehr,Πλάσμα Όπλο,Plasmo-Pafilo,Rifle de Plasma,,Plasmapyssy,Fusil à Plasma,Plazmafegyver,Fucile al Plasma ,プラズマライフル,플라즈마 라이플,Plasmageweer,Karabin plazmowy,Fuzil de Plasma,Pistola de Plasma,Pușcă cu Plasmă,Плазменная пушка,Плазма оружје @@ -1109,55 +1108,55 @@ BFG 9000,TAG_BFG9000,,,,,,,,,,,,,,,,,,,,,,ВЈП 9000 Bullets,AMMO_CLIP,,,,Kulky,Patronen,Σφαίρες,Kugloj,Balas,,Luodit,Balles,Töltények,Proiettili,銃弾,권총 탄약,Kogels,Naboje,Balas,,Gloanțe,Пули,Меци Shotgun Shells,AMMO_SHELLS,,,,Broky,Schrotpatronen,Σφαίρες Ντουφεκιού,Kartoĉoj,Cartuchos de escopeta,,Haulikon patruunat,Cartouches,Sörétek,Cartucce per fucile,散弾シェル,샷건 탄약,Jachtgeweerkogels,Loftki,Cartuchos de Espingarda,,Proiectile pentru Pușcă,Патроны для дробовика,Патроне за пумпарицу Rockets,AMMO_ROCKETS,,,,Rakety,Raketen,Πύραυλοι,Raketoj,Cohetes,,Raketit,Roquettes,Rakéták,Razzi,ロケット弾,로켓,Raketten,Rakiety,Foguetes,Mísseis,Rachete,Ракеты,Ракете -Energy Cells,AMMO_CELLS,,,,Energetické články,Energiezellen,Κύτταρα Ενέργιας,Energiĉeloj,Célula de energía,,Energia-akut,Cellules,Energiacellák,Batterie,エネルギーセル,에너지 셀,Energiecellen,Ogniwa energetyczne,Células de Energia,,Celule cu Energie,Энергетические ячейки,Енергетске ћелије +Energy Cells,AMMO_CELLS,,,,Energetické články,Energiezellen,Κύτταρα Ενέργιας,Energiĉeloj,Célula de energía,,Energia-akut,Cellules,Energiacellák,Batterie,エネルギーセル,에너지 셀,Energiecellen,Ogniwa energetyczne,Células de Energia,,Celule cu Energie,Энергобатареи,Енергетске ћелије ,,Obituaries,,,,,,,,,,,,,,,,,,,,, -%o thought %g saw an arachnotron.,OB_STEALTHBABY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] arachnotrona.","%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 arachnotront.",a %o sembrava di aver visto un arachnotron.,%o がアラクノトロンを見た気がした。,%o 은(는) 아라크노트론을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een arachnotron zag.,%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 краем глаза заметил@[ao_rus] арахнотрона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] паукотрона. -%o thought %g saw an archvile.,OB_STEALTHVILE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] velezrůdu.","%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álnokot.",a %o sembrava di aver visto un Arch-Vile.,%o がアーチバイルを見た気がした。,%o 은(는) 아크-바일을 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een aartsvijand zag.,%o kątem oka zauważył@[ao_pl] arcy-bestię.,%o achou que viu um arquivil.,,%o a crezut că %g a văzut un abject.,%o краем глаза заметил@[ao_rus] арчвайла.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] једног арчвајла. +%o thought %g saw an arachnotron.,OB_STEALTHBABY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] arachnotrona.","%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 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 краем глаза заметил@[ao_rus] арахнотрона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] паукотрона. +%o thought %g saw an archvile.,OB_STEALTHVILE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] veleběsa.","%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 kątem oka zauważył@[ao_pl] arcy-bestię.,%o achou que viu um arquivil.,,%o a crezut că %g a văzut un abject.,%o краем глаза заметил@[ao_rus] архвиля.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] једног арчвајла. %o thought %g saw a Baron of Hell.,OB_STEALTHBARON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] barona pekel.","%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 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 краем глаза заметил@[ao_rus] барона Ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] барона пакла. %o thought %g saw a cacodemon.,OB_STEALTHCACO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kakodémona.","%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 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 краем глаза заметил@[ao_rus] какодемона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] какодемона. -%o thought %g saw a chaingunner.,OB_STEALTHCHAINGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kulometčíka.","%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 gépágyúst.",a %o sembrava di aver visto uno zombie commando.,%o がチェインガンナーを見た気がした。,%o 은(는) 체인거너를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een zware wapens kerel zag.,%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 краем глаза заметил@[ao_rus] пулемётчика.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] митраљезца. +%o thought %g saw a chaingunner.,OB_STEALTHCHAINGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] kulometčíka.","%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 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 краем глаза заметил@[ao_rus] пулемётчика.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] митраљезца. %o thought %g saw a demon.,OB_STEALTHDEMON,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] démona.","%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 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 краем глаза заметил@[ao_rus] демона.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] демона. %o thought %g saw a Hell Knight.,OB_STEALTHKNIGHT,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] rytíře pekel.","%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 kątem oka zauważył@[ao_pl] Rycerza Piekła.,%o achou que viu um guarda infernal.,%o achou que viu um cavaleiro infernal.,%o a crezut că %g a văzut un Cavaler al Infernului.,%o краем глаза заметил@[ao_rus] рыцаря Ада.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] витеза пакла. -%o thought %g saw an imp.,OB_STEALTHIMP,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] čertíka.","%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 koboldot.",a %o sembrava di aver visto un imp.,%o がインプを見た気がした。,%o 은(는) 임프를 봤다고 생각했다.,%o dacht dat @[hij_ze_nl] een imp zag.,%o kątem oka zauważył@[ao_pl] chochlika.,%o achou que viu um diabrete.,,%o a crezut că %g a văzut un drac.,%o краем глаза заметил@[ao_rus] импа.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] врага. -%o thought %g saw a mancubus.,OB_STEALTHFATSO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] menkuba.","%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 kątem oka zauważył@[ao_pl] mankubusa.,%o achou que viu um mancubus.,,%o a crezut că %g a văzut un mancubus.,%o краем глаза заметил@[ao_rus] манкубуса.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] манкубуса. +%o thought %g saw an imp.,OB_STEALTHIMP,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] čerta.","%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 kątem oka zauważył@[ao_pl] chochlika.,%o achou que viu um diabrete.,,%o a crezut că %g a văzut un drac.,%o краем глаза заметил@[ao_rus] импа.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] врага. +%o thought %g saw a mancubus.,OB_STEALTHFATSO,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] mankuba.","%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 kątem oka zauważył@[ao_pl] mankubusa.,%o achou que viu um mancubus.,,%o a crezut că %g a văzut un mancubus.,%o краем глаза заметил@[ao_rus] манкубуса.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] манкубуса. %o thought %g saw a revenant.,OB_STEALTHUNDEAD,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] umrlce.","%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 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 краем глаза заметил@[ao_rus] ревенанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] повратника. %o thought %g saw a sergeant.,OB_STEALTHSHOTGUNGUY,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] seržanta.","%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 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 краем глаза заметил@[ao_rus] сержанта.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] водника. %o thought %g saw a zombieman.,OB_STEALTHZOMBIE,,,,"%o si myslel@[ao_cs], že viděl@[ao_cs] zombíka.","%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 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 краем глаза заметил@[ao_rus] зомби.,%o мисли@[ao_1_sr] да је виде@[ao_1_sr] зомбија. %o was punched by a revenant.,OB_UNDEADHIT,,,,%o byl@[ao_cs] udeřen@[ao_cs] umrlcem.,%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 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 was slashed by an imp.,OB_IMPHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] čertíkem.,%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 kobold.,%o è stato squarciato da un imp.,%o はインプに切り裂かれた。,%o 은(는) 임프에게 찢겨 죽었다.,%o werd gesneden door een imp.,%o został@[ao_pl] rozcięt@[adj_pl] przez chochlika.,%o foi dilacerad@[ao_ptb] por um diabrete.,,%o a fost zgâriat de un drac.,Игрока %o расцарапал имп.,Играча %o је пресеко враг. +%o was slashed by an imp.,OB_IMPHIT,,,,%o byl@[ao_cs] rozsápán@[ao_cs] čertem.,%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 został@[ao_pl] rozcięt@[adj_pl] przez chochlika.,%o foi dilacerad@[ao_ptb] por um diabrete.,,%o a fost zgâriat de un drac.,Игрока %o расцарапал имп.,Играча %o је пресеко враг. %o got too close to a cacodemon.,OB_CACOHIT,,,,%o se dostal@[ao_cs] moc blízko ke kakodémonovi.,%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 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 слишком сблизил@[refl_rus] с какодемоном.,%o се превише приближи@[ao_1_sr] какодемону. %o was bit by a demon.,OB_DEMONHIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] démonem.,%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 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 was eaten by a spectre.,OB_SPECTREHIT,,,,%o byl@[ao_cs] sežrán@[ao_cs] přízrakem.,%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 fantom.,%o è stato divorato da uno spettro.,%o はスペクトルに喰われた。,%o 은(는) 스펙터에게 잡아먹혔다.,%o werd opgegeten door een spook.,%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 was eaten by a spectre.,OB_SPECTREHIT,,,,%o byl@[ao_cs] sežrán@[ao_cs] přízrakem.,%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 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 was ripped open by a Baron of Hell.,OB_BARONHIT,,,,%o byl@[ao_cs] rozčtvrcen@[ao_cs] baronem pekel.,%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 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 was gutted by a Hell Knight.,OB_KNIGHTHIT,,,,%o byl@[ao_cs] vykuchán@[ao_cs] rytířem pekel.,%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 został@[ao_pl] wypatroszon@[adj_pl] przez Rycerza Piekła.,%o foi estripad@[ao_ptb] por um Guarda Infernal.,%o foi estripad@[ao_ptb] por um Cavaleiro Infernal.,%o a fost măcelărit de un Cavaler al Infernului.,Игрока %o распотрошил рыцарь Ада.,Играча %o је унаказио витез пакла. %o was killed by a zombieman.,OB_ZOMBIE,,,,%o byl@[ao_cs] zabit@[ao_cs] zombíkem.,%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 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 was shot by a sergeant.,OB_SHOTGUY,,,,%o byl@[ao_cs] zastřelen@[ao_cs] seržantem.,%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 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 was incinerated by an archvile.,OB_VILE,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] velezrůdou.,%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álnok.,%o è stato incenerito da un arch-vile.,%o はアーチバイルに焼き尽くされた。,%o 은(는) 아크-바일에 의해 소각되었다.,%o werd verbrand door een aartsvijand.,%o został@[ao_pl] spalon@[adj_pl] przez arcy-podlca.,%o foi incinerad@[ao_ptb] pelo arquivil.,,%o a fost incinerat de un abject.,Игрока %o кремировал арчвайл.,Играча %o је запалио арчвајл. +%o was incinerated by an archvile.,OB_VILE,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] veleběsem.,%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 został@[ao_pl] spalon@[adj_pl] przez arcy-podlca.,%o foi incinerad@[ao_ptb] pelo arquivil.,,%o a fost incinerat de un abject.,Игрока %o кремировал архвиль.,Играча %o је запалио арчвајл. %o couldn't evade a revenant's fireball.,OB_UNDEAD,,,,%o se nevyhnul@[ao_cs] umrlčí ohnivé kouli.,%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 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 не успел@[ao_rus] увернуться от снаряда ревенанта.,%o није мог@[ao_2_sr] да избегне повратникову пламену куглу. -%o was squashed by a mancubus.,OB_FATSO,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] mankubusem.,%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 został@[ao_pl] zmiażdżon@[adj_pl] przez mankubusa.,%o foi esmagad@[ao_ptb] por um mancubus.,,%o a fost strivit de un mancubus.,Игрока %o раздавил манкубус.,Играча %o је изгњечио манкубус. -%o was perforated by a chaingunner.,OB_CHAINGUY,,,,%o byl@[ao_cs] prostřelen@[ao_cs] kulometčikém.,%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 gépágyús.,%o è stato perforato da uno zombie commando.,%o はチェインガンナーに蜂の巣にされた。,%o 은(는) 체인거너에 의해 벌집이 됐다.,%o werd geperforeerd door een zware wapens kerel.,%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 was squashed by a mancubus.,OB_FATSO,,,,%o byl@[ao_cs] rozmačkán@[ao_cs] mankubem.,%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 został@[ao_pl] zmiażdżon@[adj_pl] przez mankubusa.,%o foi esmagad@[ao_ptb] por um mancubus.,,%o a fost strivit de un mancubus.,Игрока %o раздавил манкубус.,Играча %o је изгњечио манкубус. +%o was perforated by a chaingunner.,OB_CHAINGUY,,,,%o byl@[ao_cs] prostřelen@[ao_cs] kulometčíkem.,%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 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 was spooked by a lost soul.,OB_SKULL,,,,%o se lekl@[ao_cs] ztracené duše.,%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 został@[ao_pl] przestraszon@[adj_pl] przez zagubioną duszę.,%o se assustou com uma alma perdida.,%o se assustou com uma alma penada.,%o a fost speriat de un suflet pierdut.,%o испугал@[refl_rus] потерянной души.,%o је уплашен@[adj_1_sr] од изгубљене душе. -%o was burned by an imp.,OB_IMP,,,,%o byl@[ao_cs] spálen@[ao_cs] čertem.,%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 kobold.,%o è stato bruciato da un imp.,%o はインプに焼かれた。,%o 은(는) 임프에게 불태워졌다.,%o werd verbrand door een imp.,%o został@[ao_pl] spalon@[adj_pl] przez chochlika.,%o foi queimad@[ao_ptb] por um diabrete.,,%o a fost ars de un demon.,Игрока %o сжёг имп.,%o је изгорен@[adj_1_sr] од стране врага. +%o was burned by an imp.,OB_IMP,,,,%o byl@[ao_cs] spálen@[ao_cs] čertem.,%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 został@[ao_pl] spalon@[adj_pl] przez chochlika.,%o foi queimad@[ao_ptb] por um diabrete.,,%o a fost ars de un demon.,Игрока %o сжёг имп.,%o је изгорен@[adj_1_sr] од стране врага. %o was smitten by a cacodemon.,OB_CACO,,,,%o byl@[ao_cs] udeřen@[ao_cs] kakodémonem.,%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 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 was bruised by a Baron of Hell.,OB_BARON,,,,%o byl@[ao_cs] pomačkán@[ao_cs] baronem pekel.,%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 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 получил@[ao_rus] синяк от барона Ада.,%o је мод@[adj_3_sr] због барона пакла. %o was splayed by a Hell Knight.,OB_KNIGHT,,,,%o byl@[ao_cs] rozpůlen@[ao_cs] rytířem pekel.,%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.,%o został@[ao_pl] rozcapierzon@[adj_pl] przez Rycerza Piekła.,%o foi espalmad@[ao_ptb] por um Guarda 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 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 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ókvezértől.,%o è stato soggiogato dal Ragno demoniaco.,%o はスパイダーデーモンに恐れをなした。,%o 은(는) 거미악마의 무자비함을 느꼈다.,%o stond in ontzag voor de spindemon.,%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 стоял@[ao_rus] в восторге перед пауком-предводителем.,%o се смрзну@[ao_1_sr] у очарању паук-руководилаца. -%o let an arachnotron get %h.,OB_BABY,,,,%o se nechal@[ao_cs] dostat arachnotronem.,%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 arachnotron.",%o ha permesso che un arachnotron l'uccidesse.,%o が アラクノトロンに討ち取られた。,%o 은(는) 아라크노트론이 %o를(을) 죽이도록 놔두었다.,%o werd gedood door een 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 дал@[ao_rus] арахнотрону себя убить.,%o је допусти@[ao_1_sr] да паукотрон дође до %h. +%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 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 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 стоял@[ao_rus] в восторге перед пауком-предводителем.,%o се смрзну@[ao_1_sr] у очарању паук-руководилаца. +%o let an arachnotron get %h.,OB_BABY,,,,%o se nechal@[ao_cs] dostat arachnotronem.,%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 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 дал@[ao_rus] арахнотрону себя убить.,%o је допусти@[ao_1_sr] да паукотрон дође до %h. %o was splattered by a cyberdemon.,OB_CYBORG,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši kyberdémonem.,%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 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 met a Nazi.,OB_WOLFSS,,,,%o potkal@[ao_cs] nácka.,%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.,%o spotkał@[ao_pl] nazistę.,%o encontrou um Nazista.,%o encontrou um Nazi.,%o a întâlnit un Nazist.,%o встретил@[ao_rus] нациста.,%o је упозна@[ao_1_sr] нацисту. -%o was mauled by a dog.,OB_DOG,,,,%o byl@[ao_cs] roztrhán@[ao_cs] psem.,%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 megmarta egy kutya.,%o è stato sbranato da un cane.,%o は犬に引き裂かれた。,%o 은(는) 개한테 으스러졌다.,%o werd verminkt door een hond.,%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 chewed on %k's fist.,OB_MPFIST,,,,%o ochutnal@[ao_cs] pěst hráče %k.,%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 przygryza pięść %k.,%o foi espancad@[ao_ptb] até a morte por %k,,%o a mestecat pumnul lui %k.,Игрок %o отведал кулака игрока %k.,Играча %o је сажвакао песницу играча %k. -%o was mowed over by %k's chainsaw.,OB_MPCHAINSAW,,,,%o byl@[ao_cs] zkácen@[ao_cs] motorovkou hráče %k.,%o wurde von %ks Kettensäge zerteilt.,@[art_gr] %o κόπηκε απο το αλλησοπρίονο του/της %k.,%o estis buĉita de la ĉensagilo 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 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 was mauled by a dog.,OB_DOG,,,,%o byl@[ao_cs] roztrhán@[ao_cs] psem.,%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 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 chewed on %k's fist.,OB_MPFIST,,,,%o si pochutnal@[ao_cs] na pěsti hráče %k.,%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 przygryza pięść %k.,%o foi espancad@[ao_ptb] até a morte por %k,,%o a mestecat pumnul lui %k.,Игрок %o отведал кулака игрока %k.,Играча %o је сажвакао песницу играча %k. +%o was mowed over by %k's chainsaw.,OB_MPCHAINSAW,,,,%o byl@[ao_cs] zkácen@[ao_cs] motorovkou hráče %k.,%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 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 was tickled by %k's pea shooter.,OB_MPPISTOL,,,,%o byl@[ao_cs] polechtán@[ao_cs] pistolkou hráče %k.,%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 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 chewed on %k's boomstick.,OB_MPSHOTGUN,,,,%o si pochutnal@[ao_cs] na brokádě hráče %k.,%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 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 was splattered by %k's super shotgun.,OB_MPSSHOTGUN,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši superbrokovnicí hráče %k.,%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 szuperpuskája.,%o è stato smembrato dalla doppietta di %k.,%o は %k のスーパーショットガンでバラバラにされた。,%o 은(는) %k 의 슈퍼 샷건에 의해 터졌다.,%o werd gespat door %k's super jachtgeweer.,%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 was splattered by %k's super shotgun.,OB_MPSSHOTGUN,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] na kaši superbrokovnicí hráče %k.,%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 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 was mowed down by %k's chaingun.,OB_MPCHAINGUN,,,,%o byl@[ao_cs] prostřílen@[ao_cs] kulometem hráče %k.,%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 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 rode %k's rocket.,OB_MPROCKET,,,,%o se projel@[ao_cs] na raketě hráče %k.,%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 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 almost dodged %k's rocket.,OB_MPR_SPLASH,,,,%o se skoro vyhnul@[ao_cs] raketě hráče %k.,"%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 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 was melted by %k's plasma gun.,OB_MPPLASMARIFLE,,,,%o se roztekl@[ao_cs] plazmapuškou hráče %k.,%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 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 was splintered by %k's BFG.,OB_MPBFG_BOOM,,,,%o byl@[ao_cs] rozštěpen@[ao_cs] BFGčkem hráče %k.,%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 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 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 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 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 was railed by %k.,OB_RAILGUN,,,,%o byl@[ao_cs] napíchnut@[ao_cs] hráčem %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.,%k lemészárolta %o-t.,%o è stato bucherellato dal railgun di %k.,%o は %k のレールガンで死亡した。,%o 은(는) %k 의 레일건에 관통당했다.,%o werd gespaakt door %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 was railed by %k.,OB_RAILGUN,,,,%o byl@[ao_cs] napíchnut@[ao_cs] hráčem %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 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 was burned by %k's BFG.,OB_MPBFG_MBF,,,,%o shořel@[ao_cs] BFGčkem hráče %k.,%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 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. ,,Heretic,,,,,,,,,,,,,,,,,,,,, ,,Pickup ,,,,,,,,,,,,,,,,,,,,, @@ -1165,23 +1164,23 @@ Blue Key,TXT_GOTBLUEKEY,,,,Modrý klíč,Blauer Schlüssel,Μπλέ Κλειδί Yellow Key,TXT_GOTYELLOWKEY,,,,Žlutý klíč,Gelber Schlüssel,Κύτρινο Κλειδί,Flava Ŝlosilo,Llave Amarilla,,Keltainen avain,Clé Jaune,Sárga kulcs,Chiave gialla,黄の鍵,황색 열쇠,Gele sleutel,Żółty klucz,Chave Amarela,,Cheie Galbenă,Жёлтый ключ,Жути кључ Green Key,TXT_GOTGREENKEY,,,,Zelený klíč,Grüner Schlüssel,Πράσινο Κλειδί,Verda Ŝlosilo,Llave Verde,,Vihreä avain,Clé Verte,Zöld kulcs,Chiave verde,緑の鍵,녹색 열쇠,Groene sleutel,Zielony klucz,Chave Verde,,Cheie Verde,Зелёный ключ,Зелени кључ Quartz Flask,TXT_ARTIHEALTH,,,,Blyštivá baňka,Quarzflasche,Φλάσκα Χαλαζίας,Kvarca Flakono,Frasco de Cuarzo,,Kvartsipullo,Flasque en Quartz,Kvarc flaska,Ampolla di quarzo,石英フラスコ,석영 플라스크,Kwartskolf,Kwarcowa Butelka,Frasco de Quartzo,,Flacon de Quartz,Кварцевый флакон,Кварцна боца -Wings of Wrath,TXT_ARTIFLY,,,,Křídla hněvu,Flügel des Zorns,Φτερά της Οργής,Flugiloj de Kolero,Alas de Ira,,Kiihtymyksen siivet,Ailes du Courroux,A harag szárnyai,Ali iraconde,レイスの翼,분노의 날개,Vleugels der Toorn,Skrzydła Gniewu,Asas da Ira,,Aripile Furiei,Крылья гнева,Крила гнева -Ring of Invincibility,TXT_ARTIINVULNERABILITY,,,,Prsten nesmrtelnosti,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,Pierścień Niewrażliwości,Anel da Invencibilidade,,Inelul Invincibilității,Кольцо неуязвимости,Прстен непобедивости -Tome of Power,TXT_ARTITOMEOFPOWER,,,,Kniha moci,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,Tom Mocy,Livro do Poder,Livro do Poder,Cartea Puterii,Том могущества,Том моћи -Shadowsphere,TXT_ARTIINVISIBILITY,,,,Šerosféra,Schattensphäre,Σκιόσφαιρα,Ombrosfero,Esfera de Sombra,,Varjokehrä,Sphère des Ombres,Sötétgömb,Sfera dell'ombra,闇の球体,그림자 구체,Schaduwbol,Sfera Cieni,Esfera das Sombras,,Sfera Umbrei,Теневая сфера,Сфера сенки +Wings of Wrath,TXT_ARTIFLY,,,,Křídla hněvu,Flügel des Zorns,Φτερά της Οργής,Flugiloj de Kolero,Alas de Ira,,Kiihtymyksen siivet,Ailes du Courroux,A Harag Szárnyai,Ali iraconde,レイスの翼,분노의 날개,Vleugels der Toorn,Skrzydła Gniewu,Asas da Ira,,Aripile Furiei,Крылья гнева,Крила гнева +Ring of Invincibility,TXT_ARTIINVULNERABILITY,,,,Prsten nesmrtelnosti,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,Pierścień Niewrażliwości,Anel da Invencibilidade,,Inelul Invincibilității,Кольцо неуязвимости,Прстен непобедивости +Tome of Power,TXT_ARTITOMEOFPOWER,,,,Kniha moci,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,Tom Mocy,Livro do Poder,Livro do Poder,Cartea Puterii,Том могущества,Том моћи +Shadowsphere,TXT_ARTIINVISIBILITY,,,,Šerosféra,Schattensphäre,Σκιόσφαιρα,Ombrosfero,Esfera de Sombra,,Varjokehrä,Sphère des Ombres,Árnygömb,Sfera dell'ombra,闇の球体,그림자 구체,Schaduwbol,Sfera Cieni,Esfera das Sombras,,Sfera Umbrei,Теневая сфера,Сфера сенки 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,Яйцо превращения,Преображавајуће јајашце Mystic Urn,TXT_ARTISUPERHEALTH,,,,Tajemná urna,Mystische Urne,Μυστικό Δοχείο,Mistika Urno,Urna Mística,,Mystinen uurna,Urne Mystique,Misztikus urna,Urna mistica,神秘の骨壷,신비한 항아리,Mystieke Urn,Mistyczna Urna,Urna Mística,,Urnă Mistică,Мистическая урна,Мистериозна урна Torch,TXT_ARTITORCH,,,,Pochodeň,Fackel,Πυρσός,Torĉo,Antorcha,,Soihtu,Torche,Fáklya,Torcia,松明,횃불,Fakkel,Pochodnia,Tocha,,Torță,Факел,Бакља -Time Bomb of the Ancients,TXT_ARTIFIREBOMB,,,,Časovaná bomba starověku,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,Starożytna Bomba Czasu,Bomba-Relógio dos Antigos,,Bomba cu Ceas a Anticilor,Часовая бомба древних,Временска бомба древних +Time Bomb of the Ancients,TXT_ARTIFIREBOMB,,,,Časovaná bomba starověku,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,Starożytna Bomba Czasu,Bomba-Relógio dos Antigos,,Bomba cu Ceas a Anticilor,Часовая бомба древних,Временска бомба древних Chaos Device,TXT_ARTITELEPORT,,,,Zmatkostroj,Chaosgerät,Συσκευή του Χάος,Ĥaos-Aparato,Dispositivo del Caos,,Kaaoskoje,Outil du Chaos,Káoszszerkezet,"Dispositivo del Caos ",カオスデバイス,혼돈의 장치,Chaosapparaat,Urządzenie Chaosu,Dispositivo do Caos,,Dispozitiv al Haosolui,Эмблема Хаоса,Уређај хаоса Crystal Vial,TXT_ITEMHEALTH,,,,Křišťálový flakón,Kristallfläschchen,Κρυσταλλικό Φιάλιδο,Fiolo de Kristalo,Tubo de Cristal,,Kristallipullo,Fiole de Cristal,Kristályampulla,Fiala di cristallo,水晶瓶,수정 약병,Kristallen Flesje,Kryształowa Fiolka,Ampola de Cristal,,Fiolă de Cristal,Кристальный флакон,Кристална бочица -Bag of Holding,TXT_ITEMBAGOFHOLDING,,,,Tlumok,Rucksack,Τσάντα Κρατησης,Taŝo de Tenado,Bolso sin Fondo,,Säilön laukku,Sac sans Fond,A birtoklás batyuja,Borsa Portaoggetti,持ち物袋,보관용 가방,Rugzak,Plecak,Bolsa de Utensílios,,Poșetă,Носильный кошель,Торба носивости -Silver Shield,TXT_ITEMSHIELD1,,,,Stříbrný štít,Silberner Schild,Ασημένια Ασπίδα,Arĝenta Ŝildo,Escudo Plateado,,Hopeakilpi,Bouclier d'Argent,Ezüst pajzs,Scudo d'argento,銀の盾,은 방패,Zilveren Schild,Srebrna Tarcza,Escudo de Prata,,Scut de Argint,Серебряный щит,Сребрни штит -Enchanted Shield,TXT_ITEMSHIELD2,,,,Kouzelný štít,Verzauberter Schild,,Sorĉita Ŝildo,Escudo Encantado,,Lumottu kilpi,Bouclier Enchanté,Bűvös pajzs,Scudo incantato,魔法の盾,마력 강화 방패,Betoverd schild,Zaklęta Tarcza,Escudo Encantado,,Scut Mistificat,Зачарованный щит,Зачарани штит -Map Scroll,TXT_ITEMSUPERMAP,,,,Mapa,Kartenrolle,,Map-volvolibro,Mapa en Pergamino,,Karttakäärö,Rouleau du Cartographe,Térkép tekercs,Pergamena della Mappa,地図の巻物,두루마리 지도,Kaartrol,Zwój Mapy,Pergaminho do Mapa,,Hartă Pergament,Свиток карты,Мапа +Bag of Holding,TXT_ITEMBAGOFHOLDING,,,,Tlumok,Rucksack,Τσάντα Κρατησης,Taŝo de Tenado,Bolso sin Fondo,,Säilön laukku,Sac sans Fond,A Birtoklás Batyuja,Borsa Portaoggetti,持ち物袋,보관용 가방,Rugzak,Plecak,Bolsa de Utensílios,,Poșetă,Носильный кошель,Торба носивости +Silver Shield,TXT_ITEMSHIELD1,,,,Stříbrný štít,Silberner Schild,Ασημένια Ασπίδα,Arĝenta Ŝildo,Escudo Plateado,,Hopeakilpi,Bouclier d'Argent,Ezüst Pajzs,Scudo d'argento,銀の盾,은 방패,Zilveren Schild,Srebrna Tarcza,Escudo de Prata,,Scut de Argint,Серебряный щит,Сребрни штит +Enchanted Shield,TXT_ITEMSHIELD2,,,,Kouzelný štít,Verzauberter Schild,,Sorĉita Ŝildo,Escudo Encantado,,Lumottu kilpi,Bouclier Enchanté,Bűvös Pajzs,Scudo incantato,魔法の盾,마력 강화 방패,Betoverd schild,Zaklęta Tarcza,Escudo Encantado,,Scut Mistificat,Зачарованный щит,Зачарани штит +Map Scroll,TXT_ITEMSUPERMAP,,,,Mapa,Kartenrolle,,Map-volvolibro,Mapa en Pergamino,,Karttakäärö,Rouleau du Cartographe,Térkép Tekercs,Pergamena della Mappa,地図の巻物,두루마리 지도,Kaartrol,Zwój Mapy,Pergaminho do Mapa,,Hartă Pergament,Свиток карты,Мапа Wand Crystal,TXT_AMMOGOLDWAND1,,,,Zlaté krystaly,Zauberstabkristall,,Kristalo de Sorĉbastono,Cristal para Vara,,Sauvakristalli,Cristal Elfique,Kristálypor,Bacchetta di cristallo,ワンドクリスタル,지팡이 결정,Toverstok van Kristal,Kryształ do Różdżki,Cristal para o Cetro,,Cristal pentru Toiag,Кристалл для эльфийского жезла,Кристали за штап -Crystal Geode,TXT_AMMOGOLDWAND2,,,,Shluk krystalů,Kristallklumpen,,Kristalgeodo,Geoda de Cristal,,Kristalligeoidi,Géode de Cristal,Kristály geoda,Geode di cristallo,晶洞石,결정 원석,Kristal Geode,Kryształowa Geoda,Geodo de Cristal,,Geodă de Cristal,Жеода кристалла,Кристални камен +Crystal Geode,TXT_AMMOGOLDWAND2,,,,Shluk krystalů,Kristallklumpen,,Kristalgeodo,Geoda de Cristal,,Kristalligeoidi,Géode de Cristal,Kristály Geoda,Geode di cristallo,晶洞石,결정 원석,Kristal Geode,Kryształowa Geoda,Geodo de Cristal,,Geodă de Cristal,Жеода кристалла,Кристални камен Mace Spheres,TXT_AMMOMACE1,,,,Žezlometné koule,Keulenkugeln,,Klabsferoj,Esferas de Maza,,Nuijakuulia,Sphère de Masse,Jogargömbök,Sfere per la mazza,メイス球弾,철퇴 포탄,Strijdknotsen,Kule do Buzdyganu,Esferas para Clava,,Sfere pentru Buzdugan,Сферы для булавы,Сфере за буздован Pile of Mace Spheres,TXT_AMMOMACE2,,,,Hromada žezlometných koulí,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,Sterta Kul do Buzdyganu,Pilha de Esferas para Clava,,Grămadă de Sfere pentru Buzdugan,Груда сфер для булавы,Гомила сфера за буздован Ethereal Arrows,TXT_AMMOCROSSBOW1,,,,Éterické šípy,Ätherische Pfeile,,Eteraj Sagoj,Flechas Etéreas,,Eetterinuolia,Carreaux Ethériques,Éteri nyílvesszők,Frecce eteree,イセリアルの矢,유체 화살,Etherische Pijlen,Eteryczne Strzały,Flechas Etéreas,,Săgeți Celeste,Эфирные стрелы,Етеричне стреле @@ -1197,27 +1196,27 @@ Firemace,TXT_WPNMACE,,,,Žezlomet,Feuerkeule,,Fajroklabo,Maza de Fuego,,Tulinuij ",ファイアメイス,투사철퇴,Vuurfoelie,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован Ethereal Crossbow,TXT_WPNCROSSBOW,,,,Éterická kuše,Ätherische Armbrust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Ethérique,Éteri számszeríj,Balestra eterea,イセリアルクロスボウ,유체 쇠뇌,Etherische kruisboog,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел Dragon Claw,TXT_WPNBLASTER,,,,Drakospár,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del drago,ドラゴンクロー,용발톱,Drakenklauw,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Коготь дракона,Змајева канџа -Hellstaff,TXT_WPNSKULLROD,,,,Peklopal,Höllenrute,,Inferbastono,Bastón Infernal,,Hornansauva,Bâton Infernal,Pokolpálca,Staffa infernale,ヘルスタッフ,지옥지팡이,Hellestaf,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох ада,Паклени штап -Phoenix Rod,TXT_WPNPHOENIXROD,,,,Fénixova hůl,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix rúd,Asta della fenice,フェニックスロッド,불사조 지팡이,Feniksstaf,Różdżka Feniksa,Bastão da Fênix,,Joarda Phoenix,Жезл феникса,Шипка феникса -Gauntlets of the Necromancer,TXT_WPNGAUNTLETS,,,,Nekromancerovy rukavice,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,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова +Hellstaff,TXT_WPNSKULLROD,,,,Peklopal,Höllenrute,,Inferbastono,Bastón Infernal,,Hornansauva,Bâton Infernal,Pokolpálca,Staffa infernale,ヘルスタッフ,지옥지팡이,Hellestaf,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох Ада,Паклени штап +Phoenix Rod,TXT_WPNPHOENIXROD,,,,Fénixova hůl,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix Rúd,Asta della fenice,フェニックスロッド,불사조 지팡이,Feniksstaf,Różdżka Feniksa,Bastão da Fênix,,Joarda Phoenix,Жезл феникса,Шипка феникса +Gauntlets of the Necromancer,TXT_WPNGAUNTLETS,,,,Nekromancerovy rukavice,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,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова ,,Locks,,,,,,,,,,,,,,,,,,,,, -You need a blue key to open this door,TXT_NEEDBLUEKEY,,,,Potřebuješ modrý klíč pro otevření těchto dveří,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 a kék kulcsra,"Ti serve una chiave blu per aprire questa porta -",開くには 青の鍵が必要だ,이 문을 열기 위해선 청색 열쇠가 필요하다,Je hebt een blauwe sleutel nodig om deze deur te openen,"Potrzebujesz niebieskiego klucza, by otworzyć te drzwi.",Você precisa da chave azul para abrir essa porta,Precisas da chave azul para abrir esta porta,"Ai nevoie de o cheie albastră pentru a deschide +You need a blue key to open this door,TXT_NEEDBLUEKEY,,,,K otevření těchto dveří potřebuješ modrý klíč,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,"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șă",Для открытия нужен синий ключ,Треба вам плави кључ да би отворили ова врата -You need a green key to open this door,TXT_NEEDGREENKEY,,,,Potřebuješ červený klíč pro otevření těchto dveří,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 a zöld kulcsra,"Ti serve una chiave verde per aprire questa porta -",開くには 緑の鍵が必要だ,이 문을 열기 위해선 녹색 열쇠가 필요하다,Je hebt een groene sleutel nodig om deze deur te openen,"Potrzebujesz zielonego klucza, by otworzyć te drzwi.",Você precisa da chave verde para abrir essa porta,Precisas da chave verde para abrir esta porta,"Ai nevoie de o cheie verde pentru a deschide +You need a green key to open this door,TXT_NEEDGREENKEY,,,,K otevření těchto dveří potřebuješ červený klíč,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,"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șă",Для открытия нужен зелёный ключ,Треба вам зелени кључ да би отворили ова врата -You need a yellow key to open this door,TXT_NEEDYELLOWKEY,,,,Potřebuješ žlutý klíč pro otevření těchto dveří,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 a sárga kulcsra,Ti serve una chiave gialla per aprire questa porta,開くには 黄の鍵が必要だ,이 문을 열기 위해선 황색 열쇠가 필요하다,Je hebt een gele sleutel nodig om deze deur te openen,"Potrzebujesz żółtego klucza, by otworzyć te drzwi.",Você precisa da chave amarela para abrir essa porta,Precisas da chave amarela para abrir esta porta,"Ai nevoie de o cheie galbenă pentru a deschide +You need a yellow key to open this door,TXT_NEEDYELLOWKEY,,,,K otevření těchto dveří potřebuješ žlutý klíč.,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,"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șă",Для открытия нужен жёлтый ключ,Треба вам жути кључ да би отворили ова врата ,,Actor tag names,,,,,,,,,,,,,,,,,,,,, Chicken,FN_CHICKEN,,,,Slepice,Huhn,Κότα,Koko,Pollo,,Kana,Poulet,Csirke,Pollo,鶏,닭,Kip,Kurczak,Galinha,,Găină,Цыплёнок,Кокошка Weredragon,FN_BEAST,,,,Vlkodrak,Werdrache,Θηρίο,Lupdrako,Bestia dragón,,Ihmislohikäärme,Dragon-garou,Vérsárkány,Drago Mannaro,ウェア ドラゴン,웨어드래곤,Weerdraak,Smokołak,Homem-dragão,,Vârcodragon,Дракон-оборотень,Змајодлак Sabreclaw,FN_CLINK,,,,Šavlozub,Säbelklaue,,Sabrokrifo,Garra de sable,,Sapelikynsi,Sabregriffe,Szablyakarom,Lamartiglio,サーベルクロー,세이버클로,Sabelklauw,Szabloszpon,Unhas-de-sabre,,Gheară de Sabie,Саблекоготь,Тигар -D'Sparil,FN_DSPARIL,,,,D'Sparil,,,,,,,D'Sparil,,D'Sparil,デ'スパリル,드'스파릴,D'Sparil,D'Sparil,,,D'Sparil,Д'Спарил,Д'Спарил +D'Sparil,FN_DSPARIL,,,,,,,,,,,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,Горгулья,Камена утвара Ironlich,FN_IRONLICH,,,,Železný kostěj,Eiserne Leiche,,Ferliĉo,Liche de hierro,,Rautakalmo,Liche de Fer,Ezüst lich,Lich di Ferro,アイアンリッチ,아이언 리치,IJzeren Lijk,Żelazny Lisz,Lich de Ferro,,Cadavru de Fier,Железный лич,Челични лич -Undead Warrior,FN_BONEKNIGHT,,,,Nemrtvý válečník,Untoter Krieger,Αθάνατος Πολεμιστής,Malviva Batalisto,Guerrero no-muerto,,Epäkuollut soturi,Guerrier Mort-Vivant,Élőhalott harcos,Guerriero Non Morto,アンデット兵,언데드 전사,Ondode Krijger,Nieumarły wojownik,Guerreiro Morto-vivo,,Războinic Nemort,Воин-нежить,Немртви ратник -Maulotaur,FN_MINOTAUR,,,,Mínotaurus,Minotaurus,Μινόταυρος,Bategtaŭro,Mazotauro,,Maulotauri,Massetaure,,Maulotauro,マウロタウロス,몰로타우어,Maulotaurus,Młototaur,Marretauro,,,Молотавр,Минотаур +Undead Warrior,FN_BONEKNIGHT,,,,Nemrtvý válečník,Untoter Krieger,Αθάνατος Πολεμιστής,Malviva Batalisto,Guerrero no-muerto,,Epäkuollut soturi,Guerrier Mort-Vivant,Élőhalott harcos,Guerriero Non Morto,アンデット兵,언데드 전사,Ondode Krijger,Nieumarły wojownik,Guerreiro Morto-vivo,,Războinic Nemort,Воин нежити,Немртви ратник +Maulotaur,FN_MINOTAUR,,,,Minotaurus,Minotaurus,Μινόταυρος,Bategtaŭro,Mazotauro,,Maulotauri,Massetaure,,Maulotauro,マウロタウロス,몰로타우어,Maulotaurus,Młototaur,Marretauro,,,Молотавр,Минотаур Golem,FN_MUMMY,,,,Golém,,,Golemo,,,,Golem,Gólem,Golem,ゴーレム,골렘,,Golem,,,,Голем,Голем Nitrogolem,FN_MUMMYLEADER,,,,Střelgolém,,,Azotgolemo,,,,Nitrogolem,Nitrógólem,Nitrogolem,ニトロゴーレム,니트로 골렘,,Nitrogolem,,,,Нитроголем,Нитро голем Ophidian,FN_SNAKE,,,,Šupinatec,,,Ofidio,Ofidio,,Käärmeolio,Ophidien,Ofidián,Ophidian,オフィディアン,오피디안,Ophidiaan,Wężowaty,Ofídio,,Ofidian,Офидиан,Змија @@ -1230,7 +1229,7 @@ Hellstaff Runes,AMMO_SKULLROD,,,,Peklopalné runy,Höllenrutenrunen,,Inferbaston Flame Orbs,AMMO_PHOENIXROD,,,,Plamenné náboje,Flammenkugeln,,Flamorboj,Orbes de llama,Orbes de flama,Liekkikehriä,Orbes de Feu,Tűzgolyók,Sfere di fuoco,フレイム オーブ,화염 구슬,Vuurballen,Kule Ognia,Orbes de Chamas,,Globuri de Foc,Пламенный шар,Ватрена сфера Staff,TAG_STAFF,,,,Hole,Stab,Ράβδος,Bastono,Bastón,,Sauva,Bâton,Bot,Staffa,杖,지팡이,Staf,Kostur,Bastão,,Baston,Посох,Штап Gauntlets of the Necromancer,TAG_GAUNTLETS,,,,Nekromancerovy rukavice,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,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице призивача духова -Elven Wand,TAG_GOLDWAND,,,,Elfská hůl,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf pálca,Scettro Elfico,エルフのワンド,엘프 지팡이,Elvenstokje,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић +Elven Wand,TAG_GOLDWAND,,,,Elfí hůlka,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf pálca,Scettro Elfico,エルフのワンド,엘프 지팡이,Elvenstokje,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић Ethereal Crossbow,TAG_CROSSBOW,,,,Éterická kuše,Ätherische Armbrust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Etherique,Éteri nyílpuska,Balestra Eterea ,イセリアルクロスボウ,유체 쇠뇌,Etherische Kruisboog,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел Dragon Claw,TAG_BLASTER,,,,Drakospár,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del Drago ,ドラゴンの鉤爪,용발톱,Drakenklauw,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Драконий коготь,Змајева канџа Hellstaff,TAG_SKULLROD,,,,Peklopal,Höllenrute,,Inferbastono,Bastón infernal,,Hornansauva,Bâton Infernal,Pokolbot,Staffa Infernale ,ヘルスタッフ,지옥지팡이,Hellestaf,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох ада,Паклени штап @@ -1238,10 +1237,10 @@ Phoenix Rod,TAG_PHOENIXROD,,,,Fénixova hůl,Phönixstab,,Feniksvergo,Báculo de Firemace,TAG_MACE,,,,Žezlomet,Feuerkeule,,Fajroklabo,Maza de Fuego,,Tulinuija,Masse de Feu,Tűzbuzogány,Mazza del Fuoco ,ファイアメイス,투사철퇴,Vuurknots,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован Staff,TAG_STAFFP,,,,Hůl,Stab,Ράβδος,Bastono,Bastón,,Sauva,Bâton,Jogar,Staffa ,杖,마법부가 지팡이,Staf,Kostur,Bastão,,Baston,Посох,Штап Gauntlets of the Necromancer,TAG_GAUNTLETSP,,,,Nekromancerovy rukavice,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,Rękawice Nekromanty,Manoplas do Necromante,,Mănușile Necromantului,Перчатки некроманта,Рукавице некроманцера -Elven Wand,TAG_GOLDWANDP,,,,Elfská hůlka,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf jogar,Scettro Elfico,エルフのワンド,마법부가 엘프 지팡이,Elvenstokje,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић +Elven Wand,TAG_GOLDWANDP,,,,Elfí hůlka,Elfenstab,,Elfa Sorĉbastono,Vara de Elfo,,Haltiasauva,Baguette Elfique,Elf jogar,Scettro Elfico,エルフのワンド,마법부가 엘프 지팡이,Elvenstokje,Elfia Różdżka,Cetro Élfico,,Toiag,Эльфийский жезл,Вилењачки штапић Ethereal Crossbow,TAG_CROSSBOWP,,,,Éterická kuše,Ätherische Armbust,,Etera Arbalesto,Ballesta Etérea,,Eetterivarsijousi,Arbalète Etherique,Éteri nyílpuska,Balestra Eterea ,イセリアルクロスボウ,마법부가 유체 쇠뇌,Etherische Kruisboog,Eteryczna Kusza,Besta Etérea,,Arbaletă Celestă,Эфирный арбалет,Етерични самострел Dragon Claw,TAG_BLASTERP,,,,Drakospár,Drachenklaue,,Drakokrifo,Garra de Dragón,,Lohikäärmeenkynsi,Griffe Draconique,Sárkány karom,Artiglio del Drago ,ドラゴンの鉤爪,마법부가 용발톱,Drakenklauw,Smoczy Pazur,Garra de Dragão,,Gheara Dragonului,Коготь дракона,Змајева канџа -Hellstaff,TAG_SKULLRODP,,,,Peklopal,Höllenrute,,Inferbastono,Bastón infernal,,Hornansauva,Bâton Infernal,Pokolbot,Staffa Infernale ,ヘルスタッフ,마법부가 지옥지팡이,Hellestaf,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох ада,Мотка пакла +Hellstaff,TAG_SKULLRODP,,,,Peklopal,Höllenrute,,Inferbastono,Bastón infernal,,Hornansauva,Bâton Infernal,Pokolbot,Staffa Infernale ,ヘルスタッフ,마법부가 지옥지팡이,Hellestaf,Piekielny Kostur,Cajado Infernal,,Baston Infernal,Посох Ада,Мотка пакла Phoenix Rod,TAG_PHOENIXRODP,,,,Fénixova hůl,Phönixstab,,Feniksvergo,Báculo del Fénix,,Feenikssauva,Bâton du Phénix,Főnix rúd,Bastone della Fenice,フェニックスロッド,마법부가 불사조 지팡이,Feniksstaf,Różdżka Feniksa,Bastão da Fênix,,Joardă Phoenix,Жезл феникса,Фениксов прут Firemace,TAG_MACEP,,,,Žezlomet,Feuerkeule,,Fajrklabo,Maza de Fuego,,Tulinuija,Masse de Feu,Tűzbuzogány,Mazza del Fuoco ,ファイアメイス,마법부가 투사철퇴,Vuurknots,Buzdygan Ognia,Clava de Fogo,,Buzdugan de Foc,Огненная булава,Ватрени буздован Morph Ovum,TAG_ARTIEGG,,,,Měnivejce,Transformations-Ei,,Ovo de Transformado,Huevo de Transformación,,Muodonmuutoksen muna,Ovule de Métamorphose,Átváltoztató gömb,Morph Ovum,変貌の卵子,변신 알,Morfose-Ei,Jajko Morfujące,Ovo da Metamorfose,,Oul Metamorfozei,Яйцо превращения,Преображајyће јајашце @@ -1262,18 +1261,18 @@ Torch,TAG_ARTITORCH,,,,Pochodeň,Fackel,Πύρσος,Torĉo,Antorcha,,Soihtu,Tor %o was chewed up by D'Sparil's serpent.,OB_DSPARIL1HIT,,,,%o byl@[ao_cs] rozkousán@[ao_cs] ořem D'Sparila.,%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 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 was no match for D'Sparil.,OB_DSPARIL2,,,,%o nebyl@[ao_cs] pro D'Sparila žádná výzva.,%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 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 был@[ao_rus] не ровня Д'Спарилу.,%o није ни до колена Д'Спарилу. %o was smacked down by D'Sparil.,OB_DSPARIL2HIT,,,,%o byl@[ao_cs] sražen@[ao_cs] D'Sparilem.,%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 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 was scarred by a gargoyle.,OB_HERETICIMP,,,,%o byl@[ao_cs] upálen@[ao_cs] chrličem.,%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 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 was hacked by a gargoyle.,OB_HERETICIMPHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] chrličem.,%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 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 was devastated by an ironlich.,OB_IRONLICH,,,,%o byl@[ao_cs] zničen@[ao_cs] železným kostějem.,%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 Vastetem miatt.,%o è stato devastato da un ironlich.,%o はアイアンリッチに吹き飛ばされた。,%o 은(는) 아이언 리치에게 붕괴 당했다.,%o werd verwoest door een ijzeren lijk.,%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 got up-close and personal with an ironlich.,OB_IRONLICHHIT,,,,%o se dostal@[ao_cs] moc blízko k železnému kostěji.,%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 Vastetemmel szemben.,%o è andato troppo vicino a un ironlich.,%o はアイアンリッチと密接に関わった。,%o 은(는) 사적인 이유로 아이언 리치에게 다가왔다.,%o werd door een ijzeren lijk onheus bejegend.,%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 +%o was scarred by a gargoyle.,OB_HERETICIMP,,,,%o byl@[ao_cs] upálen@[ao_cs] chrličem.,%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 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 was hacked by a gargoyle.,OB_HERETICIMPHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] chrličem.,%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 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 was devastated by an ironlich.,OB_IRONLICH,,,,%o byl@[ao_cs] zničen@[ao_cs] železným kostějem.,%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 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 got up-close and personal with an ironlich.,OB_IRONLICHHIT,,,,%o se dostal@[ao_cs] moc blízko k železnému kostěji.,%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 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 сближал@[refl_rus] с железным личем.,%o се лично приближи@[ao_1_sr] челичном личу. -%o was axed by an undead warrior.,OB_BONEKNIGHT,,,,%o dostal@[ao_cs] sekyrou od nemrtvého válečníka.,%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 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 was slain by an undead warrior.,OB_BONEKNIGHTHIT,,,,%o byl@[ao_cs] zabit@[ao_cs] nemrtvým válečníkem.,%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 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 was blasted into cinders by a Maulotaur.,OB_MINOTAUR,,,,%o byl@[ao_cs] rozmetán@[ao_cs] na popel Mínotaurem.,%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 Maulotaur. ,%o はマウロタウロスに燃やされ炭化した。,%o 은(는) 몰로타우어에게 잿더미가 되도록 파괴당했다.,%o werd door een Maulotaurus tot sintels geblazen.,%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 was pulped by a Maulotaur.,OB_MINOTAURHIT,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] Mínotaurem.,%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 Maulotaur. ,%o はマウロタウロスにグシャグシャにされた。,%o 은(는) 몰로타우어에 의해 내동댕이쳐졌다.,%o werd verpulverd door een Maulotaurus.,%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 was smashed by a golem.,OB_MUMMY,,,,%o byl@[ao_cs] umlácen@[ao_cs] golémem.,%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 una mummia.,%o はゴーレムに叩きのめされた。,%o 은(는) 골렘에게 두들겨 맞았다.,%o werd verbrijzeld door een 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 was shrieked to death by a nitrogolem.,OB_MUMMYLEADER,,,,%o byl@[ao_cs] ukřičen@[ao_cs] k smrti střelgolémem.,%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 una mummia.,%o はニトロゴーレムに脅かされた。,%o 은(는) 니트로 골렘에 의해 비명횡사 당했다.,%o werd doodgekrijst door een 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 was rattled by an ophidian.,OB_SNAKE,,,,%o byl@[ao_cs] zachřestěn@[ao_cs] šupinatcem.,%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 Kígyószerű által.,%o è stato stritolato da un serpente.,%o はオフィディアンに動揺した。,%o 은(는) 오피디안에게 흔들렸다.,%o werd gerammeld door een ophidiaan.,%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 was axed by an undead warrior.,OB_BONEKNIGHT,,,,%o dostal@[ao_cs] sekyrou od nemrtvého válečníka.,%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 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 was slain by an undead warrior.,OB_BONEKNIGHTHIT,,,,%o byl@[ao_cs] zabit@[ao_cs] nemrtvým válečníkem.,%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 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 was blasted into cinders by a Maulotaur.,OB_MINOTAUR,,,,%o byl@[ao_cs] rozmetán@[ao_cs] na popel Minotaurem.,%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 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 was pulped by a Maulotaur.,OB_MINOTAURHIT,,,,%o byl@[ao_cs] rozmáčknut@[ao_cs] Minotaurem.,%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 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 was smashed by a golem.,OB_MUMMY,,,,%o byl@[ao_cs] umlácen@[ao_cs] golémem.,%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 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 was shrieked to death by a nitrogolem.,OB_MUMMYLEADER,,,,%o byl@[ao_cs] ukřičen@[ao_cs] k smrti střelgolémem.,%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 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 was rattled by an ophidian.,OB_SNAKE,,,,%o byl@[ao_cs] zachřestěn@[ao_cs] šupinatcem.,%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 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 was cursed by a wizard.,OB_WIZARD,,,,%o byl@[ao_cs] zaklet@[ao_cs] čarodějem.,%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 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 was palpated by a wizard.,OB_WIZARDHIT,,,,%o byl@[ao_cs] prozkoumán@[ao_cs] čarodějem.,%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 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 got staffed by %k.,OB_MPSTAFF,,,,%o dostal@[ao_cs] holí od hráče %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 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. @@ -1281,25 +1280,25 @@ cadavru de fier.",%o сближал@[refl_rus] с железным личем.,% %o waved goodbye to %k's elven wand.,OB_MPGOLDWAND,,,,%o zamával@[ao_cs] elfské hůlce hráče %k.,%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 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 was pegged by %k's ethereal crossbow.,OB_MPCROSSBOW,,,,%o byl@[ao_cs] prostřelen@[ao_cs] éterickou kuší hráče %k.,%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 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 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 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 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 got sent down under by %k's hellstaff.,OB_MPSKULLROD,,,,Pod hráčem %o se propadla zem peklopalem hráče %k.,%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 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 got sent down under by %k's hellstaff.,OB_MPSKULLROD,,,,Pod hráčem %o se propadla zem peklopalem hráče %k.,%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 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 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 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 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 was bounced by %k's firemace.,OB_MPMACE,,,,%o byl@[ao_cs] odpálen@[ao_cs] žezlometem hráče %k.,%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 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 got clapped by %k's charged staff.,OB_MPPSTAFF,,,,%o byl@[ao_cs] profackován@[ao_cs] nabitou holí hráče %k.,%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 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 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 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.,%o elvérzett %k Páncélöklei által.,Il sangue di %o è stato prosciugato dai guanti di %k.,%o は %k の篭手で血を絞り取られた。,%o 은(는) %k 의 마법부가 건틀릿에 의해 바싹 말랐다.,%o werd leeggebloed door %k's handschoenen.,%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 +%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 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 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 was assaulted by %k's elven wand.,OB_MPPGOLDWAND,,,,%o byl@[ao_cs] napaden@[ao_cs] elfskou hůlkou hráče %k.,%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.,%o meg lett bántva %k Elf Botjának köszönhetően.,%o è stato assalito dallo Scettro Elfico di %k.,%o は %k のエルフのワンドで襲われた。,%o 은(는) %k 의 마법부가 엘프 지팡이에 의해 사냥당했다.,%o werd aangevallen door %k's elvenstaf.,%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 was assaulted by %k's elven wand.,OB_MPPGOLDWAND,,,,%o byl@[ao_cs] napaden@[ao_cs] elfskou hůlkou hráče %k.,%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 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 was shafted by %k's ethereal crossbow.,OB_MPPCROSSBOW,,,,%o byl@[ao_cs] proděravěn@[ao_cs] éterickou kuší hráče %k.,%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 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 was ripped apart by %k's dragon claw.,OB_MPPBLASTER,,,,%o byl@[ao_cs] roztrhnut@[ao_cs] naskrz drakospárem hráče %k.,%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 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 de dragon a lui %k.,Игрок %o разорван драконьим когтем %k.,%o је поцепан@[adj_1_sr] змајевим канџама играча %k. -%k poured the hellstaff on %o.,OB_MPPSKULLROD,,,,Hráč %k vylil svůj peklopal na hráče %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.,%k ráfröcsögte a Pokolbotját %o felé.,%k ha fatto sgorgare la sua Staffa Infernale su %o.,%o は %k にヘルスタッフを %p 注ぎ込まれた。,%k의 마법부가 지옥지팡이가 쏟아붓는 비를 %o 이(가) 맞았다.,%k liet de helregen los op %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 poured the hellstaff on %o.,OB_MPPSKULLROD,,,,Hráč %k vylil svůj peklopal na hráče %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 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 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 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 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 phoenix a lui %k.,Игрок %o сожжён жезлом феникса %k.,%o је изгоре@[ao_1_sr] шипком феникса играча %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 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 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 gigantic al buzduganului lui %k.",Игрок %o раздавлен огромной сферой из огненной булавы %k.,%o је смрвљен@[adj_1_sr] од стане огромном сферско буздована играча %k. ,,Hexen,,,,,,,,,,,,,,,,,,,,, ,,Pickup,,,,,,,,,,,,,,,,,,,,, Blue Mana,TXT_MANA_1,,,,Modrá mana,Blaues Mana,,Blua Manao,Maná Azul,Mana Azul,Sininen mana,Mana Bleu,Kék Mana,Mana blu,青マナ,청색 마나,Blauwe Mana,Niebieska Mana,Mana Azul,,Mană Albastră,Синяя мана,Плава мана -Green Mana,TXT_MANA_2,,,,Zelená mana,Grünes Mana,,Verda Manao,Maná Verde,Mana Verde,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,緑マナ,녹색 마나,Groene Mana,Zielona Mana,Mana Verde,,Mană Verde,Зеленая мана,Зелена мана +Green Mana,TXT_MANA_2,,,,Zelená mana,Grünes Mana,,Verda Manao,Maná Verde,Mana Verde,Vihreä mana,Mana Vert,Zöld Mana,Mana verde,緑マナ,녹색 마나,Groene Mana,Zielona Mana,Mana Verde,,Mană Verde,Зелёная мана,Зелена мана Combined Mana,TXT_MANA_BOTH,,,,Smíšená mana,Kombiniertes Mana,,Kuna Manao,Maná Combinado,Mana Combinado,Yhdistetty mana,Mana Combiné,Kombinált Mana,Mana misto,複合マナ,윰합된 마나,Gecombineerde Mana,Połączona Mana,Mana Combinado,,Mană Mixtă,Комбинированная мана,Комбинована мана Steel Key,TXT_KEY_STEEL,,,,Ocelový klíč,Stahlschlüssel,Ατσάλινο Κλειδί,Ŝtala Ŝlosilo,Llave de Acero,,Teräsavain,Clé d'Acier,Acél Kulcs,Chiave d'acciaio,鋼の鍵,강철 열쇠,Stalen Sleutel,Stalowy Klucz,Chave de Aço,,Cheia din Oțel,Стальной ключ,Челични кључ Cave Key,TXT_KEY_CAVE,,,,Klíč od jeskyně,Höhlenschlüssel,,Kavern-Ŝlosilo,Llave de la Caverna,,Luola-avain,Clé de la Cave,Barlang Kulcs,Chiave della caverna,洞窟の鍵,동굴 열쇠,Grotsleutel,Klucz do Jaskini,Chave da Caverna,,Cheia Peșterii,Пещерный ключ,Пећински кључ @@ -1313,8 +1312,8 @@ Horn Key,TXT_KEY_HORN,,,,Parožní klíč,Hornschlüssel,,Hup-Ŝlosilo,Llave de Swamp Key,TXT_KEY_SWAMP,,,,Klíč od bažiny,Sumpfschlüssel,,Marĉo-Ŝlosilo,Llave del Pantano,,Suoavain,Clé des Marécages,Mocsár Kulcs,Chiave della palude,沼の鍵,늪지대 열쇠,Moerassleutel,Bagienny Klucz,Chave do Pântano,,Cheia Mlaștinii,Болотный ключ,Мочварни кључ Castle Key,TXT_KEY_CASTLE,,,,Klíč od hradu,Burgschlüssel,,Kastel-Ŝlosilo,Llave del Castillo,,Linnan avain,Clé du Château,Kastély Kulcs,Chiave del castello,城の鍵,성 열쇠,Kasteelsleutel,Klucz do Zamku,Chave do Castelo,,Cheia Castelului,Ключ от замка,Кључ од замка Icon of the Defender,TXT_ARTIINVULNERABILITY2,,,,Obráncova ikona,Ikone des Verteidigers,,Ikono de la Defendanto,Ícono del Defensor,Ícono del Defensor,Puolustajan ikoni,Icône du Défenseur,Védelmező Ikonja,Icona del difensore,守護者の像,수호의 성상,Symbool van de Verdediger,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Символ защитника,Симбол браниоца -Dark Servant,TXT_ARTISUMMON,,,,Temný služebník,Dunkler Diener,,Malluma Servanto,Sirviente Oscuro,,Pimeä palvelija,Serviteur Noir,Sötét Szolga,Servitore oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга -Porkalator,TXT_ARTIEGG2,,,,Vepřovitel,,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Porkolátor,Porchificatore,ポークレイター,돈육기,,Schabowator,Porquificador,,Porcolator,Свиноморфер,Свињатор +Dark Servant,TXT_ARTISUMMON,,,,Temný služebník,Dunkler Diener,,Malluma Servanto,Sirviente Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servitore oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга +Porkalator,TXT_ARTIEGG2,,,,Vepřovitel,,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,Schabowator,Porquificador,,Porcolator,Свиноморфер,Свињатор Flechette,TXT_ARTIPOISONBAG,,,,Střelka,,,Flakono,Flechette,,,Fléchette,Flakon,Fiaschetta,フレチェット,플레셰트,,Flaszka,,,Flacon,Зелье,Бочица Banishment Device,TXT_ARTITELEPORTOTHER,,,,Vyhošťovač,Verbannungsgerät,,Forpelilo,Dispositivo de Desvanecimiento,,Häivytyskoje,Outil de Banissement,Száműző,Artifatto dell'esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Эмблема изгнания,Амблем прогањања Boots of Speed,TXT_ARTISPEED,,,,Běhuté boty,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipője,Stivali della velocità,素早さの靴,속도의 신발,Snelheidslaarzen,Buty Szybkości,Botas da Velocidade,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме @@ -1329,30 +1328,30 @@ Emerald Planet,TXT_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta,Smaragdplanet,,Smera Emerald Planet,TXT_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta,Smaragdplanet,,Smeralda Planedo,Planeta Esmeralda,,Smaragdiplaneetta,Planète de Saphir,Smaragd Bolygó,Pianeta di smeraldo,エメラルドの宝石,에메랄드 행성석 (2),Smaragdgroene Planeet,Szmaragdowa Planeta,Planeta Esmeralda,,Planetă din Smarald,Изумрудная планета,Смарагдна планета Sapphire Planet,TXT_ARTIPUZZGEMBLUE1,,,,Safírová planeta,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (1),Saffierblauwe Planeet,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета Sapphire Planet,TXT_ARTIPUZZGEMBLUE2,,,,Safírová planeta,Saphirplanet,,Safira Planedo,Planeta Zafiro,,Safiiriplaneetta,Planète de Saphir,Zafír Bolygó,Pianeta di zaffiro,サファイアの宝石,사파이어 행성석 (2),Saffierblauwe Planeet,Szafirowa Planeta,Planeta Safira,,Planetă din Safir,Сапфировая планета,Сафирна планета -Daemon Codex,TXT_ARTIPUZZBOOK1,,,,,,,Kodekso de Demono,Códice del Demonio,,,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс +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,Flammenmaske,,Flamomasko,Mascara de Llamas,Mascara de Flamas,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle fiamme,炎の仮面,화염의 가면,Vuurmasker,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена -Glaive Seal,TXT_ARTIPUZZFWEAPON,,,,Glévská pečeť,Schwetsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Kard Pecsét,Sigillo della brando,グレイブシール,밀폐된 칼날,Lanszegel,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат +Glaive Seal,TXT_ARTIPUZZFWEAPON,,,,Glévská pečeť,Schwetsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo della brando,グレイブシール,밀폐된 칼날,Lanszegel,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат Holy Relic,TXT_ARTIPUZZCWEAPON,,,,Svatá relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia sacra,聖遺物,신성한 유물,Heilige Relikwie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија Sigil of the Magus,TXT_ARTIPUZZMWEAPON,,,,Mágovo sigilium,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,Emblemat Maga,Sigilo do Mago,,Sigiliul Magului,Символ мага,Чаробњаков симбол Clock Gear,TXT_ARTIPUZZGEAR,,,,Ozubené kolečko,Zahnrad,,Dentrado de Horloĝo,Engranaje de reloj,,Kellonratas,Rouage d'Horloge,Óra Szerkezet,Ingranaggio d'orologio,時計の歯車,시계 톱니바퀴,Kloktandwiel,Mechanizm Zegara,Engrenagem de Relógio,,Mecanism Ceas,Часовая шестерня,Сатни зупчаник -You Cannot Use This Here,TXT_USEPUZZLEFAILED,,,,Zde se tento předmět použít nedá,Das kannst du hier nicht benutzen,,Vi ne eblas uzi tion ĉi tie.,No puedes usar esto aquí,,Et voi käyttää tätä tässä,Vous ne pouvez pas utiliser cela ici.,Nem Használhatod Ezt Itt,Non puoi usare questo oggetto qui,ここでは使用できない,이것은 여기에 사용할 수 없다,Dat kan je hier niet gebruiken,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,Здесь это невозможно использовать,Ово се не може користити овде +You Cannot Use This Here,TXT_USEPUZZLEFAILED,,,,Zde se tento předmět použít nedá,Das kannst du hier nicht benutzen,,Vi ne eblas uzi 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,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,Здесь это невозможно использовать,Ово се не може користити овде 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,Kolczuga,Armadura de Malha,,Armură din Zale,Кольчуга,Верижњача Falcon Shield,TXT_ARMOR2,,,,Sokolí štít,Falkenschild,,Falko-Ŝildo,Escudo de Halcón,,Haukkakilpi,Bouclier du Faucon,Sólyom Pajzs,Scudo del falco,鷹の盾,팔콘 방패,Valkenschild,Sokola Tarcza,Escudo do Falcão,,Scut Șoim,Соколиный щит,Соколов штит -Platinum Helmet,TXT_ARMOR3,,,,Platinová helma,Platinhelm,,Platena Kasko,Casco de Platino,,Platinakypärä,Casque de Platine,Platinum Sisak,Elmo di platino,白金の兜,백금 투구,Platina Helm,Platynowy Hełm,Capacete de Platina,,Coif de Platină,Платиновый шлем,Шлем од платине -Amulet of Warding,TXT_ARMOR4,,,,Amulet uhýbání,Wachamulett,,Amuleto de Gardado,Amuleto de Guarda,,Suojelusamuletti,Amulette de Protection,Védekezés Amulettje,Amuleto di protezione,回避の護符,수호의 부적,Amulet van Bescherming,Amulet Ochrony,Amuleto da Proteção,,Amuleta Protecției,Амулет стража,Амулет страже +Platinum Helmet,TXT_ARMOR3,,,,Platinová helma,Platinhelm,,Platena Kasko,Casco de Platino,,Platinakypärä,Casque de Platine,Platina Sisak,Elmo di platino,白金の兜,백금 투구,Platina Helm,Platynowy Hełm,Capacete de Platina,,Coif de Platină,Платиновый шлем,Шлем од платине +Amulet of Warding,TXT_ARMOR4,,,,Amulet uhýbání,Wachamulett,,Amuleto de Gardado,Amuleto de Guarda,,Suojelusamuletti,Amulette de Protection,Oltalom Amulettje,Amuleto di protezione,回避の護符,수호의 부적,Amulet van Bescherming,Amulet Ochrony,Amuleto da Proteção,,Amuleta Protecției,Амулет стража,Амулет страже Timon's Axe,TXT_WEAPON_F2,,,,Timonova sekera,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира -Hammer of Retribution,TXT_WEAPON_F3,,,,Kladivo odplaty,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Büntetés Kalapácsa,Martello del castigo,報復の金槌,징벌의 망치,Hamer der Vergelding,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде +Hammer of Retribution,TXT_WEAPON_F3,,,,Kladivo odplaty,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,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде Quietus Assembled,TXT_WEAPON_F4,,,,Složený Tišitel,Erlöser komplettiert,,Kvietus' Muntita,Quietus Ensamblado,,Quietus koottuna,Quietus Assemblée,Némusz Összerakva,Quietus assemblato,組み立てた 死滅の剣,완성된 종언의 검,Quietus in elkaar gezet,Złożony Uciszacz,Quietus Montada,,Argument Final Asamblat,Последний довод собран воедино,Самрт је сабрана Serpent Staff,TXT_WEAPON_C2,,,,Hadí hůl,Schlangenstab,,Serpentbastono,Vara de Serpiente,,Käärmesauva,Sceptre du Serpent,Kígyó Bot,Bastone del serpente,蛇の杖,뱀 지팡이,Slangenstaf,Laska Węży,Cetro da Serpente,,Bastonul Șarpelui,Змеиный посох,Змијски штап Firestorm,TXT_WEAPON_C3,,,,Ohnivá bouře,Feuersturm,,Fajroŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di fuoco,ファイアストーム,화염폭풍,Vuurstorm,Burza Ognia,Tempestade-de-Fogo,,Furtună de Foc,Огненный шторм,Огњена олуја -Wraithverge Assembled,TXT_WEAPON_C4,,,,Složený Zjevitel,Geisterbringer komplettiert,,Fantomkruc' Muntita,Báculo Fantasmal Ensamblado,Vara Fantasmal Ensamblada,Haamusauva koottuna,Verge Phantasmale Assemblée,Lélekvég Összerakva,Verga Sconfinaspettri assemblata,組み立てた レイスバージ,완성된 사령의 십자가,Schimroede in elkaar gezet,Złożony Widmoskraj,Cajado Fantasma Montado,,Toiag Stafie Asamblat,Жезл духов собран воедино,Жезло утвара је сабрано +Wraithverge Assembled,TXT_WEAPON_C4,,,,Složený Zjevitel,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,Złożony Widmoskraj,Cajado Fantasma Montado,,Toiag Stafie Asamblat,Жезл духов собран воедино,Жезло утвара је сабрано Frost Shards,TXT_WEAPON_M2,,,,Ledové střepy,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Frantumi gelati,フロスト シャード,얼음 파편,Vorstscherven,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Ледяные осколки,Ледене крхотине -Arc of Death,TXT_WEAPON_M3,,,,Jiskry smrti,Todesblitz,,Arko de Morto,Arcos de la Muerte,,Kuolonkaari,Foudre Mortelle,Halál Körívja,Arco della morte,死の円弧,죽음의 번갯불,Doodsboog,Łuk Śmierci,Arcos da Morte,,Izvorul Morții,Дуга смерти,Лук смрти +Arc of Death,TXT_WEAPON_M3,,,,Jiskry smrti,Todesblitz,,Arko de Morto,Arcos de la Muerte,,Kuolonkaari,Foudre Mortelle,Halál Boltíve,Arco della morte,死の円弧,죽음의 번갯불,Doodsboog,Łuk Śmierci,Arcos da Morte,,Izvorul Morții,Дуга смерти,Лук смрти Bloodscourge Assembled,TXT_WEAPON_M4,,,,Složený Krvehrom,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,Złożona Krwioplaga,Flagelo de Sangue Montado,,Flagel Sângeros Asamblat,Кровавый бич собран воедино,Крвави бич је сабран -A weapon piece! This is your lucky day!,TXT_WEAPONPIECE,,,,Část zbraně! Dnes je tvůj šťastný den!,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!,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ă!,Часть оружия! Сегодня Ваш счастливый день!,Део оружја! Данас Вам је срећан дан! +A weapon piece! This is your lucky day!,TXT_WEAPONPIECE,,,,Část zbraně! Dnes je tvůj šťastný den!,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!,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ă!,Часть оружия! Сегодня ваш счастливый день!,Део оружја! Данас Вам је срећан дан! Segment of Quietus,TXT_QUIETUS_PIECE,,,,Část Tišitele,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,Fragment Uciszacza,Segmento de Quietus,,Fragment din Argumentul Final,Часть последнего довода,Део Самрти -Segment of Wraithverge,TXT_WRAITHVERGE_PIECE,,,,Část Zjevitele,Segment des Geisterbringers,,Segmento de Fantomkruc',Segmento del Báculo Fantasmal,,Haamusauvan osa,Segment de la Verge Phantasmale,Darab a Fantomperemből,Parte della Verga Sconfinaspettri,レイスバージの切片,사령의 십자가 조각,Segment van Schimroede,Fragment Widmoskraju,Segmento do Cajado Fantasma,,Fragment din Toiagul Stafie,Часть жезла духов,Део Жезла утвара +Segment of Wraithverge,TXT_WRAITHVERGE_PIECE,,,,Část Zjevitele,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,Fragment Widmoskraju,Segmento do Cajado Fantasma,,Fragment din Toiagul Stafie,Часть жезла духов,Део Жезла утвара Segment of Bloodscourge,TXT_BLOODSCOURGE_PIECE,,,,Část Krvehromu,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,Fragment Krwioplagi,Segmento do Flagelo de Sangue,,Fragment din Flagelul Sângeros,Часть кровавого бича,Део Крвавог бича ,,Locks,,,,,,,,,,,,,,,,,,,,, You need the Steel Key,TXT_NEED_KEY_STEEL,,,,Potřebuješ ocelový klíč,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.,Potrzebujesz Stalowego Klucza,Você precisa da Chave de Aço,Precisas da Chave de Aço,Ai nevoie de Cheia din Oțel,Для открытия нужен стальной ключ,За отварање је потребан челични кључ @@ -1371,12 +1370,12 @@ Afrit,FN_FIREDEMON,,,,,,,Afrito,,,,,,Afrit,アフリート,아프리트,Afriet,A Serpent,FN_DEMON1,,,,Zlohad,Chaos-Schlange,,Serpento,Serpiente,,Käärme,,Kígyó,Serpente del Caos,サーペント,서펜트,Slang,Wąż,Serpente,,Șarpe,Серпент,Серпент Ettin,FN_ETTIN,,,,Skřet,,,Gigantaĉo,,,,,,Ettin,エティン,에틴,,Ettin,,,Etin,Эттин,Етин Centaur,FN_CENTAUR,,,,Kentaur,Zentaur,,Centaŭro,Centauro,,Kentauri,Centaure,Kentaur,Centauro,ケンタウロス,켄타우로스,Centaurus,Centaur,Centauro,,Centaur,Кентавр,Кентаур -Slaughtaur,FN_SLAUGHTAUR,,,,Ničitaur,Schlachtaur,,Buĉataŭro,Masacratauro,,Teurastauri,Sangtaure,Gyilkos kentaur,Sventrauro,スロアタウル,슬로터로스,Slachttaurus,Rzeziotaur,Chacinotauro,,Centaur Violent,Старший кентавр,Кентаур старешина +Slaughtaur,FN_SLAUGHTAUR,,,,Ničitaur,Schlachtaur,,Buĉataŭro,Masacratauro,,Teurastauri,Sangtaure,Vágtaur,Sventrauro,スロアタウル,슬로터로스,Slachttaurus,Rzeziotaur,Chacinotauro,,Centaur Violent,Старший кентавр,Кентаур старешина Bishop,FN_BISHOP,,,,Biskup,Bischof,,Episkopo,Obispo,,Piispa,Evèque,Érsek,Vescovo,ビショップ,비숍,Bisschop,Biskup,Bispo,,Episcop,Епископ,Епископ Wendigo,FN_ICEGUY,,,,,,,Vendiko,,,,,,Wendigo,ウェンディゴ,윈디고,,Wendigo,,,Vendigo,Вендиго,Вендиго -Stalker,FN_SERPENT,,,,Slídil,Wasserjäger,,Gvatanto,Acechador,,Vaanija,Chasseur,Cserkész,Cacciatore,ストーカー,스토커,,Prześladowca,Caçador,,Vânător,Сталкер,Вребач -Reiver,FN_WRAITH,,,,Přízrak,Phantom,,Fantomo,Saqueador,,Ryöväri,,Orvvadász,Incursore,レイバー,리버,Rover,Rozbójnik,Fantasma,,Pungaș,Грабитель,Грабљивац -Death Wyvern,FN_DRAGON,,,,Smrtidrak,Todesdrache,,Mortviverno,Wyvern de la muerte,Guiverno de la muerte,Kuolontraakki,Vouivre de la Mort,A Halál sárkánya,Viverna Mortale,デス ワイバーン,데스 와이번,Doodsdraak,Wiwerna Śmierci,Serpe da Morte,,Balaur al Morții,Виверна смерти,Змајак смрти +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ș,Грабитель,Грабљивац +Death Wyvern,FN_DRAGON,,,,Smrtidrak,Todesdrache,,Mortviverno,Wyvern de la muerte,Guiverno de la muerte,Kuolontraakki,Vouivre de la Mort,A Halál Sárkánya,Viverna Mortale,デス ワイバーン,데스 와이번,Doodsdraak,Wiwerna Śmierci,Serpe da Morte,,Balaur al Morții,Виверна смерти,Змајак смрти Korax,FN_KORAX,,,,,,,Korax,,,Kooraks,,,Korax,唯一神コラックス,코락스,,Korax,Korax,,,Коракс,Коракс Zedek,FN_FBOSS,,,,,,,Zedeko,,,Sedek,,,Zedek,ゼデク,제닥,,Zedek,Zedek,,,Зедек,Зедек Menelkir,FN_MBOSS,,,,,,,Menelkiro,,,Menelkir,,,Menelkir,メネルキル,메넬키어,,Menelkir,Menelkir,,,Менелкир,Менелкир @@ -1389,26 +1388,26 @@ Serpent Staff,TAG_CWEAPSTAFF,,,,Hadí hůl,Schlangenstab,,Serpentbastono,Bastón Firestorm,TAG_CWEAPFLAME,,,,Ohnivá bouře,Feuersturm,,Fajrŝtormo,Tormenta de Fuego,,Tulimyrsky,Tempête de Feu,Tűzvihar,Tempesta di Fuoco ,ファイアストーム,화염폭풍,Vuurstorm,Burza Ognia,Tempestade-de-fogo,,Furtună de Foc,Огненный шторм,Огњена олуја Wraithverge,TAG_CWEAPWRAITHVERGE,,,,Zjevitel,Geisterbringer,,Fantomkruc',Báculo Fantasmal,,Haamusauva,Verge Phantasmale,Lidércvég,Verga SconfinaSpettri,レイスバージ,사령의 십자가,Schimroede,Widmoskraj,Cajado Fantasma,,Toiag Stafie,Жезл духов,Жезло утвара Spiked Gauntlets,TAG_FWEAPFIST,,,,Ohrocené rukavice,Stachelhandschuhe,,Pintaj Fergantoj,Guanteletes Puntiagudos,,Piikkirautakintaat,Gantelets à Pointes,Tűskés Páncélkesztyűk,Guantoni Spinati,スパイク ガントレット,가시 장갑,Spijkerhandschoenen,Kolczaste Rękawice,Manoplas Espinhadas,,Mănuși cu Țepi,Шипастые перчатки,Бодљикаве рукавице -Timon's Axe,TAG_FWEAPAXE,,,,Timonova sekera,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di Timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор тимона,Тимонова секира -Hammer of Retribution,TAG_FWEAPHAMMER,,,,Kladivo odplaty,Hammer der Rache,,Martelo de Repago,Martillo de Retribución,,Koston vasara,Marteau de la Rétribution,Büntetés Kalapácsa,Martello del Castigo,報復の金槌,징벌의 망치,Hamer van Vergelding,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде +Timon's Axe,TAG_FWEAPAXE,,,,Timonova sekera,Timons Axt,,Hakilo de Timon,Hacha de Timón,,Timonin kirves,Hache de Timon,Timon Baltája,Ascia di Timon,タイモンの斧,티몬의 도끼,Timon's Bijl,Topór Timona,Machado de Timon,,Toporul lui Timon,Топор Тимона,Тимонова секира +Hammer of Retribution,TAG_FWEAPHAMMER,,,,Kladivo odplaty,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,Młot Odkupienia,Martelo da Retribuição,,Ciocanul Salvării,Молот возмездия,Чекић одмазде Quietus,TAG_FWEAPQUIETUS,,,,Tišitel,Erlöser,,Kvietus',,,,Quietus,Némusz,Quietus,死滅の剣,종언의 검,,Uciszacz,Quietus,,Argument Final,Последний довод,Самрт Sapphire Wand,TAG_MWEAPWAND,,,,Safírová hůl,Saphirstab,,Safirsorĉbastono,Varita de Zafiro,,Safiirisauva,Baguette de Saphir,Zafír Pálca,Scettro di Zaffiro ,サファイア ワンド,사파이어 지팡이,Saffieren Toverstok,Szafirowa Różdżka,Cetro de Safira,,Toiag cu Safir,Сапфировая волшебная палочка,Сафирни штап Frost Shards,TAG_MWEAPFROST,,,,Ledové střepy,Frostsplitter,,Frostfragmentoj,Fragmentos de Escarcha,,Pakkassirpaleet,Eclats de Givre,Fagyos Szilánkok,Schegge di Ghiaccio ,フロスト シャード,얼음 파편,Vorstscherven,Lodowe Odłamki,Fragmentos de Geada,,Cioburi de Gheață,Замораживающие осколки,Ледене крхотине -Arcs of Death,TAG_MWEAPLIGHTNING,,,,Jiskry smrti,Todesblitz,,Arkoj de Morto,Arcos de la Muerte,,Kuolonkaaret,Foudre Mortelle,Halál Körívei,Archi della Morte ,死の円弧,죽음의 번갯불,Doodsboog,Łuki Śmierci,Arcos da Morte,,Izvoarele Morții,Дуга смерти,Лук смрти +Arcs of Death,TAG_MWEAPLIGHTNING,,,,Jiskry smrti,Todesblitz,,Arkoj de Morto,Arcos de la Muerte,,Kuolonkaaret,Foudre Mortelle,Halál Boltíve,Archi della Morte ,死の円弧,죽음의 번갯불,Doodsboog,Łuki Śmierci,Arcos da Morte,,Izvoarele Morții,Дуга смерти,Лук смрти Bloodscourge,TAG_MWEAPBLOODSCOURGE,,,,Krvehrom,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í,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaszorítás Lemeze,Disco della Repulsione ,反発の円盤,방탄의 원반,Schijf van Afstoting,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања +Disc of Repulsion,TAG_ARTIBLASTRADIUS,,,,Kotouč odpuzení,Rückstoßscheibe,,Disko de Repelado,Disco de Repulsión,,Karkotuskiekko,Disque de Répulsion,Visszaverő Pajzs,Disco della Repulsione ,反発の円盤,방탄의 원반,Schijf van Afstoting,Dysk Odpychania,Disco da Repulsão,,Disc al Repulsiei,Диск отторжения,Диск одбијања Dragonskin Bracers,TAG_ARTIBOOSTARMOR,,,,Dračí nátepníky,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,Karwasze ze Smoczej Skóry,Braçadeiras de Pele de Dragão,,Brățări din Piele de Dragon,Наручи драконьей кожи,Наруквице од змајеве коже Krater of Might,TAG_ARTIBOOSTMANA,,,,Kalich síly,Kelch der Macht,,Kratero de Potenco,Crátera de Poder,,Mahtikrateeri,Cratère de Pouvoir,Hatalom Kráterje,Calice della Forza,魔力の盃,힘의 향로,Beker van Macht,Czara mocy,Cálice do Poder,,Pocal al Puterii,Кубок могущества,Чаша силе -Flechette,TAG_ARTIPOISONBAG,,,,Střelka,,,Flakono,,,,Fléchette,Nyíl,Fiaschetta ,フレシェット,플레셰트,,Flaszka,,,Flacon,Флешетта,Бочица -Poison Cloud Flechette,TAG_ARTIPOISONBAG1,,,,Otrávená střelka,Flechette (Giftwolke),,Venennub-Flakono,Flechette de Nube Venenosa,,Myrkkypilviflechette,Fléchette - Nuage Toxique,Méregfelhő nyíl,Fiaschetta Velenosa,毒ガス フレシェット,독구름 플레셰트,Flechette (giftige wolk),Flaszka Trującej Chmury,Flechette de Nuvem Venenosa,,Flacon cu Otravă,Флешетта ядовитого облака,Бочица отровног облака -Timebomb Flechette,TAG_ARTIPOISONBAG2,,,,Časovaná střelka,Flechette (Zeitbombe),,Horloĝbomb-Flakono ,Bomba de Tiempo Flechette,,Aikapommiflechette,Fléchette - Bombe a Retardement,Időbomba nyíl,Fiaschetta a Tempo ,時限爆弾フレシェット,시한폭탄 플레셰트,Flechette (tijdbom),Flaszka-Bomba Zegarowa,Flechette Bomba-Relógio,,Bombă cu Ceas,Флешетта часовой бомбы,Бочица временске бомбе -Grenade Flechette,TAG_ARTIPOISONBAG3,,,,Granátová střelka,Flechettre (Granate),,Grenad-Flakono,Granada Flechette,,Kranaattiflechette,Fléchette - Grenade,Robbanó nyíl,Fiaschetta da Lancio,グレネードフレシェット,폭발성 플레셰트,Flechette (granaat),Flaszka-Granat,Flechette Granada,,Flacon-Grenadă,Флешетта граната,Бочица граната +Flechette,TAG_ARTIPOISONBAG,,,,Střelka,,,Flakono,,,,Fléchette,Nyílhegy,Fiaschetta ,フレシェット,플레셰트,,Flaszka,,,Flacon,Флешетта,Бочица +Poison Cloud Flechette,TAG_ARTIPOISONBAG1,,,,Otrávená střelka,Flechette (Giftwolke),,Venennub-Flakono,Flechette de Nube Venenosa,,Myrkkypilviflechette,Fléchette - Nuage Toxique,Méregfelhő hegy,Fiaschetta Velenosa,毒ガス フレシェット,독구름 플레셰트,Flechette (giftige wolk),Flaszka Trującej Chmury,Flechette de Nuvem Venenosa,,Flacon cu Otravă,Флешетта ядовитого облака,Бочица отровног облака +Timebomb Flechette,TAG_ARTIPOISONBAG2,,,,Časovaná střelka,Flechette (Zeitbombe),,Horloĝbomb-Flakono ,Bomba de Tiempo Flechette,,Aikapommiflechette,Fléchette - Bombe a Retardement,Időbomba hegy,Fiaschetta a Tempo ,時限爆弾フレシェット,시한폭탄 플레셰트,Flechette (tijdbom),Flaszka-Bomba Zegarowa,Flechette Bomba-Relógio,,Bombă cu Ceas,Флешетта часовой бомбы,Бочица временске бомбе +Grenade Flechette,TAG_ARTIPOISONBAG3,,,,Granátová střelka,Flechettre (Granate),,Grenad-Flakono,Granada Flechette,,Kranaattiflechette,Fléchette - Grenade,Robbanó hegy,Fiaschetta da Lancio,グレネードフレシェット,폭발성 플레셰트,Flechette (granaat),Flaszka-Granat,Flechette Granada,,Flacon-Grenadă,Флешетта граната,Бочица граната 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,Мистический зачарованный свиток,Чаролија магичног јединства Icon of the Defender,TAG_ARTIDEFENDER,,,,Obráncova ikona,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 ,守護者の像,수호의 성상,,Ikona Obrońcy,Ícone do Defensor,,Imaginea Apărătorului,Икона защитника,Симбол браниоца -Porkalator,TAG_ARTIPORK,,,,Vepřovitel,Porkalator,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Malacátor,Porchificatore,ポークレイター,돈육기,,Schabowator,Porquificador,,Porcolator,Хрякинатор,Свињатор +Porkalator,TAG_ARTIPORK,,,,Vepřovitel,Porkalator,,Porkigilo,Porcinador,,Sikaannuttaja,Porcificateur,Ártányátok,Porchificatore,ポークレイター,돈육기,,Schabowator,Porquificador,,Porcolator,Хрякинатор,Свињатор Boots of Speed,TAG_ARTISPEED,,,,Běhuté boty,Turbo-Stiefel,,Botoj de Rapideco,Botas de Velocidad,,Ripeyssaappaat,Bottes de Célérité,Sebesség Cipői,Stivali della Fretta,素早さの靴,속도의 부츠,Snelheidslaarzen,Buty Szybkości,Botas da Rapidez,,Bocancii Vitezei,Сапоги-скороходы,Брзинске чизме -Dark Servant,TAG_ARTISUMMON,,,,Temný služebník,Dunkler Diener,,Malluma Servanto,Servidor Oscuro,,Pimeä palvelija,Serviteur Noir,Sötét Szolga,Servo Oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга -Banishment Device,TAG_ARTITELEPORTOTHER,,,,Vyhošťovač,Verbannungsgerät,,Forpelilo,Dispositivo de Destierro,,Häivytyskoje,Outil de Banissement,Számüzető Készülék,Congegno dell'Esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Механизм изгнания,Амблем прогањања +Dark Servant,TAG_ARTISUMMON,,,,Temný služebník,Dunkler Diener,,Malluma Servanto,Servidor Oscuro,,Pimeä palvelija,Serviteur Noir,Árny Szolga,Servo Oscuro,闇の従者,어둠의 하인,Donkere Dienaar,Mroczny Sługa,Servo Negro,,Servitor Întunecat,Тёмный слуга,Мрачни слуга +Banishment Device,TAG_ARTITELEPORTOTHER,,,,Vyhošťovač,Verbannungsgerät,,Forpelilo,Dispositivo de Destierro,,Häivytyskoje,Outil de Banissement,Számüzető Szerkentyű,Congegno dell'Esilio,追放のデバイス,소멸 장치,Verbanningsapparaat,Urządzenie Wygnania ,Dispositivo do Banimento,,Dispozitiv al Alungării,Механизм изгнания,Амблем прогањања Yorick's Skull,TAG_ARTIPUZZSKULL,,,,Jorikova lebka,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,Czaszka Yoricka,Crânio de Yorick,,Craniul lui Yorick,Череп Йорика,Јорикова лобања Heart of D'Sparil,TAG_ARTIPUZZGEMBIG,,,,Srdce D'Sparila,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,Serce D'Sparila,Coração de D'Sparil,,Inima lui D'Sparil,Сердце Д'Спарила,Д'Спарилово срце Ruby Planet,TAG_ARTIPUZZGEMRED,,,,Rubínová planeta,Rubinplanet,,Rubena Planedo,Planeta Rubí,,Rubiiniplaneetta,Planète en rubis,Rubin Bolygó,Pianeta di Rubino,ルビーの宝石,루비 행성석,Robijnrode Planeet,Rubinowa Planeta,Planeta Rubi,,Planetă din Rubin,Рубиновая планета,Планета рубина @@ -1416,41 +1415,41 @@ Emerald Planet (1),TAG_ARTIPUZZGEMGREEN1,,,,Smaragdová planeta (1),Smaragdplane Emerald Planet (2),TAG_ARTIPUZZGEMGREEN2,,,,Smaragdová planeta (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),Szmaragdowa Planeta (2),Planeta Esmeralda (2),,Planetă din Smarald (2),Изумрудная планета (2),Смарагдна планета (2) Sapphire Planet (1),TAG_ARTIPUZZGEMBLUE1,,,,Safírová planeta (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),Szafirowa Planeta (1),Planeta Safira (1),,Planetă din Safir (1),Сапфировая планета (1),Сафирна планета (1) Sapphire Planet (2),TAG_ARTIPUZZGEMBLUE2,,,,Safírová planeta (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),Szafirowa Planeta (2),Planeta Safira (2),,Planetă din Safir (2),Сапфировая планета (2),Сафирна планета (2) -Daemon Codex,TAG_ARTIPUZZBOOK1,,,,,,,Kodekso de Demono,Códice del Demonio,,,Codex Démoniaque,Démon Kódex,Codice Demoniaco ,デーモンの写本,악마의 고문서,,Demoniczny Kodeks,Códice Demoníaco,,Codexul Demonilor,Демонический кодекс,Демонски кодекс +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,Flammenmaske,,Fajrmasko,Mascara de Llamas,Mascara de Flamas,Liekkinaamio,Masque de Flammes,Láng Maszk,Maschera delle Fiamme ,炎の仮面,화염의 가면,Vuurmasker,Maska Płomieni,Máscara das Chamas,,Mască de Foc,Маска пламени,Маска пламена -Glaive Seal,TAG_ARTIPUZZFWEAPON,,,,Glévská pečeť,Schwertsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Kard Pecsét,Sigillo del Brando,グレイブシール,밀폐된 칼날,Lanszegel,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат +Glaive Seal,TAG_ARTIPUZZFWEAPON,,,,Glévská pečeť,Schwertsiegel,,Sigelo de Glavo,Sello de Espada,,Miekkasinetti,Sceau du Glaive,Pallos Pecsét,Sigillo del Brando,グレイブシール,밀폐된 칼날,Lanszegel,Pieczęć Glewii,Selo do Gládio,,Sigiliu Spadă,Печать воителя,Војников печат Holy Relic,TAG_ARTIPUZZCWEAPON,,,,Svatá relikvie,Heiliges Relikt,,Sankta Relikvo,Santa Reliquia,,Pyhä reliikki,Relique Sacrée,Szent Ereklye,Reliquia Sacra,聖遺物,신성한 유물,Heilige Relikwie,Święta Relikwia,Relíquia Sagrada,,Relicvă Sfântă,Святая реликвия,Света реликвија Sigil of the Magus,TAG_ARTIPUZZMWEAPON,,,,Mágovo sigilium,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,Emblemat Maga,Sígilo do Mago,,Sigiliul Magului,Символ мага,Чаробњаков симбол Iron gear,TAG_ARTIPUZZGEAR1,,,,Železné kolečko,Eisenzahnrad,,Fera Dentrado,Engranaje de Hierro,,Rautaratas,Engrenage en Fer,Vas Felszerelés,Ingranaggio di Ferro,鉄の歯車,양철 톱니바퀴,IJzeren uitrusting,Żelazna Zębatka,Engrenagem de ferro,,Mecanism din fier,Железная шестерня,Гвожђени зупчаник -Brass gear,TAG_ARTIPUZZGEAR2,,,,Mosazné kolečko,Messingzahnrad,,Latuna Dentrado,Engranaje de Bronce,,Messinkiratas,Engrenage en Bronze,Sárgaréz Felszerelés,Ingranaggio di Ottone ,真鍮のギア,황동 톱니바퀴,Messing uitrusting,Mosiężna Zębatka,Engrenagem de latão,,Mecanism din alamă,Латунная шестерня,Месингани зупчаник -Brass and iron gear,TAG_ARTIPUZZGEAR3,,,,Mosazo-železné kolečko,Messing-und-Eisen-Zahnrad,,Latuna Fera Dentrado,Engranaje de Bronce y Hierro,,Messinki- ja rautaratas,Engrenage en Fer et Bronze,Vas és Sárgaréz Felszerelés,Ingranaggio di Ferro e Ottone ,鉄と真鍮のギア,황동과 양철 톱니바퀴,Messing en ijzeren uitrusting,Zębatka z mosiądzu i żelaza,Engrenagem de ferro e latão,,Mecanism din alamă și fier,Латунно-железная шестерня,Месинганoгвожђени зупчаник -Silver and brass gear,TAG_ARTIPUZZGEAR4,,,,Střibro-mosazné kolečko,Silber-und-Messing-Zahnrad,,Arĝenta Latuna Dentrado,Engranaje de Plata y Bronce,,Hopea- ja messinkiratas,Engrenage en Argent et Bronze,Ezüst és Sárgaréz Felszerelés,Ingranaggio di Ottone e Argento ,銀と真鍮のギア,은과 황동 톱니바퀴,Zilveren en messing uitrusting,Zębatka ze srebra i mosiądzu,Engrenagem de prata e latão,,Mecanism din argint și alamă,Серебряно-латунная шестерня,Сребрномесигани зупчаник +Brass gear,TAG_ARTIPUZZGEAR2,,,,Mosazné kolečko,Messingzahnrad,,Latuna Dentrado,Engranaje de Bronce,,Messinkiratas,Engrenage en Bronze,Réz Felszerelés,Ingranaggio di Ottone ,真鍮のギア,황동 톱니바퀴,Messing uitrusting,Mosiężna Zębatka,Engrenagem de latão,,Mecanism din alamă,Латунная шестерня,Месингани зупчаник +Brass and iron gear,TAG_ARTIPUZZGEAR3,,,,Mosazno-železné kolečko,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,Zębatka z mosiądzu i żelaza,Engrenagem de ferro e latão,,Mecanism din alamă și fier,Латунно-железная шестерня,Месинганoгвожђени зупчаник +Silver and brass gear,TAG_ARTIPUZZGEAR4,,,,Stříbro-mosazné kolečko,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,Zębatka ze srebra i mosiądzu,Engrenagem de prata e latão,,Mecanism din argint și alamă,Серебряно-латунная шестерня,Сребрномесигани зупчаник ,,Obituaries,,,,,,,,,,,,,,,,,,,,, -%o tasted an Afrit's fire.,OB_FIREDEMON,,,,%o ochutnal@[ao_cs] Afritův oheň.,%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 parázsát.,%o ha assaggiato il fuoco di un Afrit. ,%o はアフリートの炎を味わった。,%o 은(는) 아프리트의 화염을 맛봤다.,%o proefde het vuur van een Afriet.,%o spróbował@[ao_pl] ognia Afrita.,%o provou o fogo de um Afrit.,,%o a gustat flacăra Demonului de Foc.,%o отведал@[ao_rus] огня Африта.,%o је окуси@[ao_1_sr] Афритов огањ. -%o was scalded by a Serpent.,OB_DEMON1,,,,%o byl@[ao_cs] spálen@[ao_cs] Zlohadem.,%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 został@[ao_pl] poparzon@[adj_pl] przez Węża.,Uma Serpente escaldou %o.,,%o a fost opărit de un Șarpe.,Игрока %o спалил Серпент.,Играча %o је спалио Серпент. -%o was poisoned by a Serpent.,OB_DEMON2,,,,%o byl@[ao_cs] otráven@[ao_cs] Zlohadem.,%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 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 was mashed by an Ettin.,OB_ETTIN,,,,%o byl@[ao_cs] umlácen@[ao_cs] Ettinem.,%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 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 was cut up by a Centaur.,OB_CENTAUR,,,,%o byl@[ao_cs] rozsekán@[ao_cs] Kentaurem.,%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 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 was cut up by a Slaughtaur.,OB_SLAUGHTAURHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] Ničitaurem.,%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ágtaúr is a játékost,%o è stato affettato da uno Sventrauro. ,%o はスロアタウルに切り刻まれた。,%o 은(는) 슬로터로스에 의해 심하게 절단됐다.,%o werd versneden door een Slachtaurus.,%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 was struck down by a Slaughtaur's fireball.,OB_SLAUGHTAUR,,,,%o byl@[ao_cs] zabit@[ao_cs] Ničitaurovou ohnivou koulí.,%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 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 succumbed to a Bishop's dark power.,OB_BISHOP,,,,%o podlehl@[ao_cs] Biskupově temné moci.,%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 uległ@[ao_pl] mrocznej mocy Biskupa.,%o sucumbiu ao poder negro de um Bispo.,,%o a cedat puterii întunecate a Episcopului.,%o поддал@[refl_rus] чёрным силам Епископа.,%o је подлег@[ao_2_sr] Епископовим црним силама. -%o was frozen solid by a Wendigo.,OB_ICEGUY,,,,%o byl@[ao_cs] zamrznut@[ao_cs] Wendigem.,%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 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 was mauled by a Stalker.,OB_SERPENTHIT,,,,%o byl@[ao_cs] umlácen@[ao_cs] Slídilem.,%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 Orvvadász által.,%o è stato malmenato da un Cacciatore. ,%o はストーカーに引っ掻かれた。,%o 은(는) 스토커에게 발렸다.,%o werd verminkt door een 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 was melted by a Stalker.,OB_SERPENT,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] Slídilem.,%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 Orvvadász,%o è stato squagliato da un Cacciatore. ,%o はストーカーに溶かされた。,%o 은(는) 스토커에 의해 녹았다.,%o werd gesmolten door een 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 was charred by a Reiver.,OB_WRAITH,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] Přízrakem.,%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 Fosztogató elszenesítette.,%o è stato carbonizzato da un Incursore. ,%o はレイバーに黒焦げにされた。,%o 은(는) 리버에 의해 그슬렸다.,%o werd verbrand door een Rover.,%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 had %p life stolen by a Reiver.,OB_WRAITHHIT,,,,%o si nechal@[ao_cs] ukradnout život Přízrakem.,%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 Fosztogató,%o ha permesso che un Incursore prosciugasse la sua vita ,%o はレイバーに命を %p盗まれた。,%o 은(는) 리버에게 영혼을 도둑맞았다.,%o had @[zijn_haar_nl] leven gestolen door een Rover.,"Ż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 was incinerated by the Death Wyvern.,OB_DRAGON,,,,%o byl@[ao_cs] upálen@[ao_cs] Smrtidrakem.,%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 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 was swept from the board by Korax.,OB_KORAX,,,,%o byl@[ao_cs] odebrán@[ao_cs] ze šachovnice Koraxem.,%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 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 tasted an Afrit's fire.,OB_FIREDEMON,,,,%o okusil@[ao_cs] afritův oheň.,%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 spróbował@[ao_pl] ognia Afrita.,%o provou o fogo de um Afrit.,,%o a gustat flacăra Demonului de Foc.,%o отведал@[ao_rus] огня африта.,%o је окуси@[ao_1_sr] Афритов огањ. +%o was scalded by a Serpent.,OB_DEMON1,,,,%o byl@[ao_cs] upálen@[ao_cs] zlohadem.,%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 został@[ao_pl] poparzon@[adj_pl] przez Węża.,Uma Serpente escaldou %o.,,%o a fost opărit de un Șarpe.,Игрока %o спалил серпент.,Играча %o је спалио Серпент. +%o was poisoned by a Serpent.,OB_DEMON2,,,,%o byl@[ao_cs] otráven@[ao_cs] zlohadem.,%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 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 was mashed by an Ettin.,OB_ETTIN,,,,%o byl@[ao_cs] umlácen@[ao_cs] skřetem.,%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 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 was cut up by a Centaur.,OB_CENTAUR,,,,%o byl@[ao_cs] rozsekán@[ao_cs] kentaurem.,%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 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 was cut up by a Slaughtaur.,OB_SLAUGHTAURHIT,,,,%o byl@[ao_cs] rozsekán@[ao_cs] ničitaurem.,%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 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 was struck down by a Slaughtaur's fireball.,OB_SLAUGHTAUR,,,,%o byl@[ao_cs] zabit@[ao_cs] ničitaurovou ohnivou koulí.,%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 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 succumbed to a Bishop's dark power.,OB_BISHOP,,,,%o podlehl@[ao_cs] biskupově temné moci.,%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 uległ@[ao_pl] mrocznej mocy Biskupa.,%o sucumbiu ao poder negro de um Bispo.,,%o a cedat puterii întunecate a Episcopului.,%o поддал@[refl_rus] чёрным силам епископа.,%o је подлег@[ao_2_sr] Епископовим црним силама. +%o was frozen solid by a Wendigo.,OB_ICEGUY,,,,%o byl@[ao_cs] zamrznut@[ao_cs] wendigem.,%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 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 was mauled by a Stalker.,OB_SERPENTHIT,,,,%o byl@[ao_cs] umlácen@[ao_cs] slídilem.,%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 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 was melted by a Stalker.,OB_SERPENT,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] slídilem.,%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 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 was charred by a Reiver.,OB_WRAITH,,,,%o byl@[ao_cs] zpopelněn@[ao_cs] přízrakem.,%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 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 had %p life stolen by a Reiver.,OB_WRAITHHIT,,,,%o si nechal@[ao_cs] ukradnout život přízrakem.,%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.,"Ż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 was incinerated by the Death Wyvern.,OB_DRAGON,,,,%o byl@[ao_cs] upálen@[ao_cs] smrtidrakem.,%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 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 was swept from the board by Korax.,OB_KORAX,,,,%o byl@[ao_cs] odhozen@[ao_cs] ze šachovnice Koraxem.,%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 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 was slain by Zedek.,OB_FBOSS,,,,%o byl@[ao_cs] zabit@[ao_cs] Zedekem.,%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 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 couldn't absorb Menelkir's Mana.,OB_MBOSS,,,,%o nemohl@[ao_cs] pojmout Menelkirovu manu.,%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 nie m@[irreg_4_pl] wchłonąć Many Menelkira.,%o não conseguiu absorver a Mana de Menelkir.,,%o nu a reușit să absoarbă mana lui Menelkir.,%o не смог@[irreg_2_rus] бороться с маной Менелкира.,%o се није узмог@[ao_2_sr] носити с Менелкировом маном. %o was baptized by Traductus.,OB_CBOSS,,,,%o byl@[ao_cs] posvěcen@[ao_cs] Traduktem.,%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 został@[ao_pl] ochrzczon@[adj_pl] przez Traductusa.,%o foi batizad@[ao_ptb] por Traductus.,,%o a fost botezat de Traductus.,Игрока %o крестил Традуктус.,Играча %o је крстио Традуктус. %o had %p bones rolled by the Heresiarch.,OB_HERESIARCH,,,,%o si nechal@[ao_cs] rozmetat kosti Arcikacířem.,%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.,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 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 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 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 got the axe from %k.,OB_MPFWEAPAXE,,,,%o dostal@[ao_cs] sekerou od hráče %k.,%o sah %ks Axt.,,%o akiris 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 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 had %p head caved in by %k's hammer.,OB_MPFWEAPHAMMERM,,,,%o ztratil@[ao_cs] hlavu kladivem hráče %k.,%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.,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 got the axe from %k.,OB_MPFWEAPAXE,,,,%o dostal@[ao_cs] sekerou od hráče %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 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 had %p head caved in by %k's hammer.,OB_MPFWEAPHAMMERM,,,,%o dostal@[ao_cs] po hlavě kladivem hráče %k.,%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.,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's soul was forged anew by %k's hammer.,OB_MPFWEAPHAMMERR,,,,%o@[psf1_cs] duše byla obrozena kladivem hráče %k.,%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.,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 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 wurde durck %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 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. @@ -1458,11 +1457,11 @@ lui %k.",Игрок %o утихомирен легендарным Послед %o was bitten by %k's serpent staff.,OB_MPCWEAPSTAFFM,,,,%o byl@[ao_cs] kousnut@[ao_cs] hadí holí hráče %k.,%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 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 choked on %k's serpent staff.,OB_MPCWEAPSTAFFR,,,,%o se zadusil@[ao_cs] hadí holí hráče %k.,%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 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 was lit up by %k's flames.,OB_MPCWEAPFLAME,,,,%o vzplanul@[ao_cs] plameny hráče %k.,%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 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 was cleansed by %k's Wraithverge.,OB_MPCWEAPWRAITHVERGE,,,,%o byl@[ao_cs] očištěn@[ao_cs] Zjevitelem hráče %k.,%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 Lélekvégje által.,%o è stato purificato dalla Verga SconfinaSpettri di %k.,%o は %k のレイスバージによって浄化された。,%o 은(는) %k 의 사령의 지팡이에 의해 정화되었다.,%o werd gereinigd door %k's Schimroede.,%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 took one too many sapphire beams from %k.,OB_MPMWEAPWAND,,,,%o koupil@[ao_cs] moc safírových ran od hráče %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 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 was cleansed by %k's Wraithverge.,OB_MPCWEAPWRAITHVERGE,,,,%o byl@[ao_cs] očištěn@[ao_cs] Zjevitelem hráče %k.,%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 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 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 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 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 was turned into a frosty fellow by %k.,OB_MPMWEAPFROST,,,,%o byl@[ao_cs] zchlazen@[ao_cs] hráčem %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 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 received a shocking revelation from %k.,OB_MPMWEAPLIGHTNING,,,,%o zjistil@[ao_cs] šokující odhalení hráče %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 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 was wiped off the face of the universe by %k's Bloodscourge.,OB_MPMWEAPBLOODSCOURGE,,,,%o byl@[ao_cs] smazán@[ao_cs] z tváře vesmíru Krvehromem hráče %k.,%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.,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 +%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 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.,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. ,,Strife,,,,,,,,,,,,,,,,,,,,, ,,Pickups,,,,,,,,,,,,,,,,,,,,, @@ -1472,15 +1471,15 @@ You picked up the Med patch.,TXT_MEDPATCH,,,,Sebral@[ao_cs] jsi obvaz.,Du hast d You picked up the Medical kit.,TXT_MEDICALKIT,,,,Sebral@[ao_cs] jsi lékárničku.,Du hast den Verbandskasten genommen.,,Vi prenis la Medicinilaron.,Recogiste un Kit Médico.,,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.,Podniosł@[irreg_3_pl] Apteczkę.,Você pegou o Kit Médico.,Apanhaste o Kit Médico.,Ai ridicat Kitul de Prim-Ajutor.,Получена аптечка.,Покупио си медицински комплет You picked up the Surgery Kit.,TXT_SURGERYKIT,,,,Sebral@[ao_cs] jsi chirurgickou soupravu.,Du hast den Erste-Hilfe-Kasten genommen.,,Vi prenis la Kirurgirilaron.,Recogiste 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.,Podniosł@[irreg_3_pl] Zestaw Chirurga.,Você pegou o Kit de Cirurgia.,Apanhaste o Kit de Cirugia.,Ai ridicat Kitul pentru Operații.,Получен медкомплект.,Покупио си хируршки комплет You picked up the map.,TXT_STRIFEMAP,,,,Sebral@[ao_cs] jsi mapu.,Du hast die Karte genommen.,Πήρες το χάρτη.,Vi prenis la mapon.,Recogiste el mapa.,,Poimit kartan.,Vous avez pris la carte,Felvetted a térképet.,Hai raccolto la Mappa.,マップ 取得。,지도를 획득했다.,Je hebt de kaart opgepakt.,Podniosł@[irreg_3_pl] mapę.,Você pegou o mapa.,Apanhaste o mapa.,Ai ridicat harta.,Получена карта.,Покупио си мапу. -You picked up the ring.,TXT_BELDINSRING,,,,Sebral@[ao_cs] jsi prsten.,Du hast den Ring genommen.,Πήρες το Δακτύλιο.,Vi prenis la ringon.,Recogiste un anillo.,,Poimit sormuksen.,Vous avez pris l'anneau.,Felvetted a gyűrűt.,Hai raccolto l'Anello.,指輪 取得。,반지를 획득했다.,Je hebt de ring opgepakt.,Podniosł@[irreg_3_pl] pierścień.,Você pegou o anel.,Apanhaste o anel.,Ai ridicat inelul.,Получено кольцо.,Покупио си прстен. +You picked up the ring.,TXT_BELDINSRING,,,,Sebral@[ao_cs] jsi prsten.,Du hast den Ring genommen.,Πήρες το Δακτύλιο.,Vi prenis la ringon.,Recogiste un anillo.,,Poimit sormuksen.,Vous avez pris l'anneau.,Felvetted a Gyűrűt.,Hai raccolto l'Anello.,指輪 取得。,반지를 획득했다.,Je hebt de ring opgepakt.,Podniosł@[irreg_3_pl] pierścień.,Você pegou o anel.,Apanhaste o anel.,Ai ridicat inelul.,Получено кольцо.,Покупио си прстен. You picked up the Offering Chalice.,TXT_OFFERINGCHALICE,,,,Sebral@[ao_cs] jsi obětní kalich.,Du hast den Opferkelch genommen.,,Vi prenis la Ofertkilkon.,Recogiste 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.,Podniosł@[irreg_3_pl] Kielich Ofiarny.,Você pegou o Cálice de Oferenda.,Apanhaste o Cálice de Oferenda.,Ai ridicat Potirul pentru Ofrande.,Получена чаша для подношений.,Покупио си Жртвени пехар. -You picked up the ear.,TXT_EAR,,,,Sebral@[ao_cs] jsi ucho.,Du hast das Ohr gernommen.,Πήρες το αυτί.,Vi prenis la orelon.,Recogiste la oreja.,,Poimit korvan.,Vous avez pris l'oreille.,Felvetted a fület.,Hai raccolto l'Orecchio.,耳 取得。,잘린 귀를 주웠다.,Je hebt het oor opgepakt.,Podniosł@[irreg_3_pl] ucho.,Você pegou a orelha.,Apanhaste a orelha.,Ai ridicat urechea.,Получено ухо.,Покупио си уво. +You picked up the ear.,TXT_EAR,,,,Sebral@[ao_cs] jsi ucho.,Du hast das Ohr gernommen.,Πήρες το αυτί.,Vi prenis la orelon.,Recogiste la oreja.,,Poimit korvan.,Vous avez pris l'oreille.,Felvetted a Fület.,Hai raccolto l'Orecchio.,耳 取得。,잘린 귀를 주웠다.,Je hebt het oor opgepakt.,Podniosł@[irreg_3_pl] ucho.,Você pegou a orelha.,Apanhaste a orelha.,Ai ridicat urechea.,Получено ухо.,Покупио си уво. You picked up the broken power coupling.,TXT_BROKENCOUPLING,,,,Sebral@[ao_cs] jsi rozbitou spojku.,Du hast den defekten Stromabnehmer genommen.,,Vi prenis la rompan povkuplilon.,Recogiste 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.,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.,Получена повреждённая муфта.,Покупио си неисправну спојницу напајања. You picked up the Shadow armor.,TXT_SHADOWARMOR,,,You picked up the Shadow armour.,Sebral@[ao_cs] jsi krycí brnění.,Du hast die Schattenrüstung genommen.,,Vi prenis la Ombrokirason.,Recogiste 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.,Podniosł@[irreg_3_pl] Cienisty Pancerz.,Você pegou a armadura das sombras.,Apanhaste a armadura das sombras.,Ai ridicat Armura Umbrei.,Получена теневая броня.,Покупио си оклоп сенки. You picked up the Environmental Suit.,TXT_ENVSUIT,,,,Sebral@[ao_cs] jsi ochranný oděv,Du hast den Schutzanzug genommen.,,Vi prenis la Mediveston,Recogiste un Traje 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.,Podniosł@[irreg_3_pl] Skafander Ochronny.,Você pegou o Traje de Proteção.,Apanhaste o Fato Protetor.,Ai ridicat Costumul de Protecție.,Получен защитный костюм.,Покупио си заштитно одело. You picked up the Guard Uniform.,TXT_GUARDUNIFORM,,,,Sebral@[ao_cs] jsi hlídačovu uniformu.,Du hast die Wächteruniform genommen.,,Vi prenis la Gardistan Uniformon.,Recogiste 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.,Podniosł@[irreg_3_pl] Mundur Strażnika.,Você pegou o Uniforme de Guarda.,Apanhaste o Uniforme de Guarda.,Ai ridicat Uniforma de Paznic.,Получена униформа стражника.,Покупио си стражарску униформу You picked up the Officer's Uniform.,TXT_OFFICERSUNIFORM,,,,Sebral@[ao_cs] jsi důstojníkovu uniformu.,Du hast die Offiziersuniform genommen.,,Vi prenis la Oficiran Uniformon.,Recogiste el Uniforme de un 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.,Podniosł@[irreg_3_pl] Mundur Oficera.,Você pegou o Uniforme de Oficial.,Apanhaste o Uniforme de Oficial.,Ai ridicat Uniforma Ofițerului.,Получена униформа офицера.,Покупио си официрску униформу -You picked up the flame thrower parts.,TXT_FTHROWERPARTS,,,,Sebral@[ao_cs] jsi součástky plamenometu.,Du hast die Flammenwerferteile genommen.,,Vi prenis la partojn de la flamĵetilo.,Recogiste las partes del 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.,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.,Получены детали для огнемёта.,Покупио си делове за бацач пламена. +You picked up the flame thrower parts.,TXT_FTHROWERPARTS,,,,Sebral@[ao_cs] jsi součásti plamenometu.,Du hast die Flammenwerferteile genommen.,,Vi prenis la partojn de la flamĵetilo.,Recogiste las partes del 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.,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.,Получены детали для огнемёта.,Покупио си делове за бацач пламена. You picked up the report.,TXT_REPORT,,,,Sebral@[ao_cs] jsi hlášení.,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.,Podniosł@[irreg_3_pl] raport.,Você pegou o relatório.,Apanhaste o relatório.,Ai ridicat raportul.,Получен отчёт.,Покупио си извештај. You picked up the info.,TXT_INFO,,,,Sebral@[ao_cs] jsi informace.,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.,Podniosł@[irreg_3_pl] informacje.,Você pegou a informação.,Apanhaste a informação.,Ai recepționat informația.,Получена сводка.,Покупио си инфо. You picked up the Targeter.,TXT_TARGETER,,,,Sebral@[ao_cs] jsi zaměřovač.,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.,Podniosł@[irreg_3_pl] Namierzacz.,Você pegou a Mira.,Apanhaste a Mira.,Ai ridicat Țintitorul.,Получен целеуказатель.,Покупио си нишанитеља. @@ -1495,26 +1494,26 @@ You picked up the scanner.,TXT_SCANNER,,,,Sebral@[ao_cs] jsi skener.,Du hast den ",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!,Skaner nie zadziała bez mapy!,"O scanner não funciona sem um mapa! ",,Scannerul nu poate funcționa fără o hartă!,"Сканер не будет работать без карты! ",Скенер неће радити без мапе! -You picked up the Prison pass.,TXT_PRISONPASS,,,,Sebral@[ao_cs] jsi vězeňskou propustku.,Du hast den Gefängnispass genommen.,,Vi prenis la Malliberejan pasaĵon.,Recogiste el pase de 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.,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.,Получен пропуск в тюрьму.,Покупио си затворску пропусницу. +You picked up the Prison pass.,TXT_PRISONPASS,,,,Sebral@[ao_cs] jsi propustku do vězení.,Du hast den Gefängnispass genommen.,,Vi prenis la Malliberejan pasaĵon.,Recogiste el pase de 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.,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.,Получен пропуск в тюрьму.,Покупио си затворску пропусницу. You picked up the crossbow.,TXT_STRIFECROSSBOW,,,,Sebral@[ao_cs] jsi kuši.,Du hast die Armbrust genommen.,Πήρες το τόξο,Vi prenis la arbaleston.,Recogiste la ballesta.,,Poimit jousipyssyn.,Vous avez pris l'arbalète.,Felvetted a számszeríjat.,Hai raccolto la Balestra.,クロスボウ 入手。,석궁을 획득했다.,Je hebt de kruisboog opgepakt.,Podniosł@[irreg_3_pl] kuszę.,Você pegou a besta.,Apanhaste uma besta.,Ai ridicat arbaleta.,Получен арбалет.,Покупио си самострел. You picked up the assault gun.,TXT_ASSAULTGUN,,,,Sebral@[ao_cs] jsi pušku.,Du hast das Sturmgewehr genommen.,Πήρες το πολυβόλο.,Vi prenis la atakan pafilon.,Recogiste el 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.,Podniosł@[irreg_3_pl] karabin szturmowy.,Você pegou o fuzil de assalto.,Apanhaste a arma de assalto.,Ai ridicat pușca de asalt.,Получена штурмовая винтовка.,Покупио си аутоматску пушку. You picked up the mini missile launcher.,TXT_MMLAUNCHER,,,,Sebral@[ao_cs] jsi miniraketomet.,Du hast den Miniraketenwerfer genommen.,Πήρες το μίνι πυραυλοβόλο.,Vi prenis la misilĵetetilon.,Recogiste el mini lanzacohetes.,,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.,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.,Получена мини-ракетница.,Покупио си мини ручни бацач. You picked up the flame thrower.,TXT_FLAMER,,,,Sebral@[ao_cs] jsi plamenomet.,Du hast den Flammenwerfer genommen.,Πήρες το φλογοβόλο.,Vi prenis la flamĵetilon.,Recogiste el lanzallamas.,,Poimit liekinheittimen.,Vous avez pris le lance-flames.,Felvetted a lángszórót.,Hai raccolto il Lanciafiamme.,火炎放射器 入手。,완성된 화염방사기를 얻었다.,Je hebt de vlammenwerper opgepakt.,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.,Получен огнемёт.,Покупио си бацач пламена. -You picked up the mauler.,TXT_MAULER,,,,Sebral@[ao_cs] jsi trhač.,Du hast den Vernichter genommen.,,Vi prenis la vundegilon.,Recogiste el triturador.,,Poimit moukarin.,Vous avez pris le Broyeur.,Felvetted a sorvasztót.,Hai raccolto il Pestatore.,マウラー 入手。,마울러를 획득했다.,Je hebt de toetakelaar opgepakt.,Podniosł@[irreg_3_pl] miażdżyciel.,Você pegou o desintegrador.,Apanhaste o desintegrador.,Ai ridicat sfâșietorul.,Получен истязатель.,Покупио си маулер. +You picked up the mauler.,TXT_MAULER,,,,Sebral@[ao_cs] jsi trhač.,Du hast den Vernichter genommen.,,Vi prenis la vundegilon.,Recogiste el triturador.,,Poimit moukarin.,Vous avez pris le Broyeur.,Felvetted a marcangolót.,Hai raccolto il Pestatore.,マウラー 入手。,마울러를 획득했다.,Je hebt de toetakelaar opgepakt.,Podniosł@[irreg_3_pl] miażdżyciel.,Você pegou o desintegrador.,Apanhaste o desintegrador.,Ai ridicat sfâșietorul.,Получен истязатель.,Покупио си маулер. You picked up the Grenade launcher.,TXT_GLAUNCHER,,,,Sebral@[ao_cs] jsi granátomet.,Du hast den Granatwerfer genommen.,Πήρες το εκτοξευτη χειροβομβίδων.,Vi prenis la Gernadĵetilon.,Recogiste el lanzagranadas.,,Poimit kranaatinheittimen.,Vous avez pris le lance-grenades,Felvetted a gránátvetőt.,Hai raccolto il Lanciagranate.,グレネードランチャー 入手。,유탄발사기를 획득했다.,Je hebt de granaatwerper opgepakt.,Podniosł@[irreg_3_pl] wyrzutnię granatów.,Você pegou o lança-granadas.,Apanhaste o lança-granadas.,Ai ridicat Lansatorul de rachete.,Получен гранатомёт.,Покупио си бацач граната. You picked up the SIGIL.,TXT_SIGIL,,,,Sebral@[ao_cs] jsi Pečeť.,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.,Podniosł@[irreg_3_pl] PIECZĘĆ.,Você pegou o SIGILO.,Apanhaste o SIGILO,Ai ridicat SIGILIUL.,Получен СИГИЛ.,Покупио си СИГИЛ. You picked up the Base Key.,TXT_BASEKEY,,,,Sebral@[ao_cs] jsi klíč od základny.,Du hast den Basisschlüssel genommen.,,Vi prenis la Ŝliosilon de la Bazejo.,Recogiste 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.,Podniosł@[irreg_3_pl] Klucz do Bazy.,Você pegou a Chave da Base.,Apanhaste a Chave da Base.,Ai ridicat Cheia Bazei.,Получен ключ от базы.,Покупио си кључ базе. You picked up the Govs Key.,TXT_GOVSKEY,,,,Sebral@[ao_cs] jsi klíč ke guvernérovi.,Du hast den Gouverneursschlüssel genommen.,,Vi prenis la Ŝliosilon de la Registaro.,Recogiste 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.,Podniosł@[irreg_3_pl] Klucz Gubernatora.,Você pegou a Chave do Governador.,Apanhaste a Chave do Governador.,Ai ridicat Cheia Guvernatorului.,Получен ключ губернатора.,Покупио си клуч гувернанте. -You picked up the Passcard.,TXT_PASSCARD,,,,Sebral@[ao_cs] jsi průkaz.,Du hast die Zugangskarte genommen.,,Vi prenis la Paskarton.,Recogiste el Pase de Acceso.,,Poimit avainkortin.,Vous avez pris le passe.,Felvetted a Belépőkártyát.,Hai raccolto la Tessera Lasciapassare.,パスカード 取得。,통행 카드를 획득했다.,Je hebt de doorgangskaart opgepakt.,Podniosł@[irreg_3_pl] Kartę Dostępu.,Você pegou o Cartão de Acesso.,Apanhaste o Cartão de Acesso.,Ai ridicat Legitimația.,Получен пропуск.,Покупио си пасош. +You picked up the Passcard.,TXT_PASSCARD,,,,Sebral@[ao_cs] jsi průkazku.,Du hast die Zugangskarte genommen.,,Vi prenis la Paskarton.,Recogiste el Pase de Acceso.,,Poimit avainkortin.,Vous avez pris le passe.,Felvetted a Belépőkártyát.,Hai raccolto la Tessera Lasciapassare.,パスカード 取得。,통행 카드를 획득했다.,Je hebt de doorgangskaart opgepakt.,Podniosł@[irreg_3_pl] Kartę Dostępu.,Você pegou o Cartão de Acesso.,Apanhaste o Cartão de Acesso.,Ai ridicat Legitimația.,Получен пропуск.,Покупио си пасош. You picked up the ID Badge.,TXT_IDBADGE,,,,Sebral@[ao_cs] jsi identifikační odznak.,Du hast die Identitätskarte genommen.,,Vi prenis la Identigo-insignon.,Recogiste la insignia de Identificació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.,Podniosł@[irreg_3_pl] Odznakę Identyfikacyjną.,Você pegou o Crachá de Identificação.,Apanhaste o Crachá de Identificação,Ai ridicat Ecusonul de Identificare.,Получена личная карта.,Покупио си личну карту. You picked up the Prison Key.,TXT_PRISONKEY,,,,Sebral@[ao_cs] jsi klič k vězení.,Du hast den Gefängnisschlüssel genommen.,,Vi prenis la Ŝlosilon de la Malliberejo.,Recogiste 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.,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.,Получен ключ от тюрьмы.,Покупио си затворски кључ You picked up the Severed Hand.,TXT_SEVEREDHAND,,,,Sebral@[ao_cs] jsi useknutou ruku.,Du hast die abgetrennte Hand genommen.,,Vi prenis la Apartan Manon.,Recogiste la Mano Cercenada.,,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.,Podniosł@[irreg_3_pl] Odciętą Rękę.,Você pegou a Mão Decepada.,Apanhaste a Mão Desmenbrada.,Ai ridicat Mâna Retezată.,Получена отрезанная рука.,Покупио си шаку -You picked up the Power1 Key.,TXT_POWER1KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 1.,Du hast den Kraftwerksschlüssel 1 genommen,,Vi prenis Povŝlosilon1.,Recogiste la Llave de Energía 1.,,Poimit voimalan 1-avaimen.,Vous avez pris la clé Power1.,Felvetted az Áram1 kulcsot.,Hai raccolto la chiave della Centrale n.1,パワー1キー 取得。,발전소 1호 키를 획득했다.,Je hebt de 1e Machtsleutel opgepakt.,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.,Покупио си први кључ од електране. -You picked up the Power2 Key.,TXT_POWER2KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 2.,Du hast den Kraftwerksschlüssel 2 genommen,,Vi prenis Povŝlosilon2.,Recogiste la Llave de Energía 2.,,Poimit voimalan 2-avaimen.,Vous avez pris la clé Power2.,Felvetted az Áram2 kulcsot.,Hai raccolto la chiave della Centrale n.2,パワー2キー 取得。,발전소 2호 키를 획득했다.,Je hebt de 2e Machtsleutel opgepakt.,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.,Покупио си други кључ од електране. -You picked up the Power3 Key.,TXT_POWER3KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 3.,Du hast den Kraftwerksschlüssel 3 genommen,,Vi prenis Povŝlosilon3.,Recogiste la Llave de Energía 3.,,Poimit voimalan 3-avaimen.,Vous avez pris la clé Power3.,Felvetted az Áram3 kulcsot.,Hai raccolto la chiave della Centrale n.3,パワー3キー 取得。,발전소 3호 키를 획득했다.,Je hebt de 3e Machtsleutel opgepakt.,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.,Покупио си трећи кључ од електране. +You picked up the Power1 Key.,TXT_POWER1KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 1.,Du hast den Kraftwerksschlüssel 1 genommen,,Vi prenis Povŝlosilon1.,Recogiste la Llave de Energía 1.,,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.,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.,Покупио си први кључ од електране. +You picked up the Power2 Key.,TXT_POWER2KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 2.,Du hast den Kraftwerksschlüssel 2 genommen,,Vi prenis Povŝlosilon2.,Recogiste la Llave de Energía 2.,,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.,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.,Покупио си други кључ од електране. +You picked up the Power3 Key.,TXT_POWER3KEY,,,,Sebral@[ao_cs] jsi klíč k elektrárně 3.,Du hast den Kraftwerksschlüssel 3 genommen,,Vi prenis Povŝlosilon3.,Recogiste la Llave de Energía 3.,,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.,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.,Покупио си трећи кључ од електране. You picked up the Gold Key.,TXT_GOLDKEY,,,,Sebral@[ao_cs] jsi zlatý klíč.,Du hast den Goldschlüssel genommen.,,Vi prenis la Orkoloran Ŝlosilon.,Recogiste la Llave de Oro.,,Poimit kulta-avaimen.,Vous avez pris la clé d'or.,Felvetted az Aranykulcsot.,Hai raccolto la chiave dorata,ゴールドキー 取得。,황금 키를 획득했다.,Je hebt de gouden sleutel opgepakt.,Podniosł@[irreg_3_pl] Złoty Klucz.,Você pegou a Chave de Ouro.,Apanhaste a Chave de Ouro,Ai ridicat Cheia de Aur.,Получен золотой ключ.,Покупио си златни кључ. You picked up the ID Card.,TXT_IDCARD,,,,Sebral@[ao_cs] jsi ID kartu.,Du hast den Ausweis genommen.,,Vi prenis la Identigo-karton.,Recogiste la Tarjeta de Identificación.,,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.,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.,Получено удостоверение.,Покупио си идентификациону картицу. -You picked up the Silver Key.,TXT_SILVERKEY,,,,Sebral@[ao_cs] jsi stříbrný klíč.,Du hast den Silberschlüssel genommen.,,Vi prenis la Arĝentkoloran Ŝlosilon.,Recogiste la 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.,Podniosł@[irreg_3_pl] Srebrny Klucz.,Você pegou a Chave de Prata.,Apanhaste a Chave de Prata,Ai ridicat Cheia de Argint.,Получен серебряный ключ.,Покупио си сребрни кључ. +You picked up the Silver Key.,TXT_SILVERKEY,,,,Sebral@[ao_cs] jsi stříbrný klíč.,Du hast den Silberschlüssel genommen.,,Vi prenis la Arĝentkoloran Ŝlosilon.,Recogiste la 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.,Podniosł@[irreg_3_pl] Srebrny Klucz.,Você pegou a Chave de Prata.,Apanhaste a Chave de Prata,Ai ridicat Cheia de Argint.,Получен серебряный ключ.,Покупио си сребрни кључ. You picked up the Oracle Key.,TXT_ORACLEKEY,,,,Sebral@[ao_cs] jsi věštcův klíč.,Du hast den Orakelschlüssel genommen.,,Vi prenis la Ŝlosilo de la Oraklo,Recogiste la 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.,Podniosł@[irreg_3_pl] Klucz do Wyroczni.,Você pegou a Chave do Oráculo.,Apanhaste a Chave do Oráculo.,Ai ridicat Cheia Oracol.,Получен ключ Оракула.,Покупио си кључ пророка You picked up the Military ID.,TXT_MILITARYID,,,,Sebral@[ao_cs] jsi vojenské ID.,Du hast den Militärausweis genommen.,,Vi prenis la Militan Identigon.,Recogiste la 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.,Podniosł@[irreg_3_pl] Wojskowy Identyfikator.,Você pegou a Identificação Militar.,Apanhaste a Identificação Militar.,Ai ridicat Legitimația Militară.,Получено военное удостоверение.,Покупио си војну идентификацију You picked up the Order Key.,TXT_ORDERKEY,,,,Sebral@[ao_cs] jsi klíč Řádu.,Du hast den Ordensschlüssel genommen.,,Vi prenis la Ŝlosilon de la Ordeno.,Recogiste 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.,Podniosł@[irreg_3_pl] Klucz Zakonu.,Você pegou a Chave da Ordem.,Apanhaste a Chave da Ordem.,Ai ridicat Cheia Ordinului.,Получен ключ Ордена.,Покупио си кључ одреда @@ -1526,37 +1525,37 @@ You picked up the Chapel Key.,TXT_CHAPELKEY,,,,Sebral@[ao_cs] jsi klíč ke kapl You picked up the Catacomb Key.,TXT_CATACOMBKEY,,,,Sebral@[ao_cs] jsi klíč do katakomb.,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.,Podniosł@[irreg_3_pl] Klucz do Katakumb.,Você pegou a Chave da Catacumba.,Apanhaste a Chave da Catacumba.,Ai ridicat Cheia Catacombei.,Получен ключ от катакомб.,Покупио си кључ катакомбе You picked up the Security Key.,TXT_SECURITYKEY,,,,Sebral@[ao_cs] jsi klíč ochranky.,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.,Podniosł@[irreg_3_pl] Klucz Ochrony.,Você pegou a Chave de Seguranca.,Apanhaste a Chave de Segurança,Ai ridicat Cheia Securității.,Получен ключ охраны.,Покупио си кључ обезбеђења You picked up the Core Key.,TXT_COREKEY,,,,Sebral@[ao_cs] jsi klíč k jádru.,Du hast den Reaktorschlüssel genommen.,,Vi prenis la Ŝlosilon de la Kernejo.,Recogiste 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.,Podniosł@[irreg_3_pl] Klucz do Rdzenia.,Você pegou a Chave do Núcleo.,Apanhaste a Chave do Núcleo.,Ai ridicat Cheia Nucleului.,Получен ключ от реактора.,Покупио си кључ језгра -You picked up the Mauler Key.,TXT_MAULERKEY,,,,Sebral@[ao_cs] jsi klíč k trhačům.,Du hast den Vernichterschlüssel genommen.,,Vi prenis la Ŝlosilon de la Vundegilo.,Recogiste la Llave del Triturador.,,Poimit moukarin avaimen.,Vous avez pris la clé du Broyeur.,Felvetted a sorvasztó kulcsát -- vagy mi ez is majd megnézem,Hai raccolto la chiave del Pestatore.,マウラーキー 取得。,마울러 키를 획득했다.,Je hebt de toetakelaarssleutel opgepakt.,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.,Получен ключ истязателя.,Покупио си кључ Маулера. +You picked up the Mauler Key.,TXT_MAULERKEY,,,,Sebral@[ao_cs] jsi klíč k trhačům.,Du hast den Vernichterschlüssel genommen.,,Vi prenis la Ŝlosilon de la Vundegilo.,Recogiste la Llave del Triturador.,,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.,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.,Получен ключ истязателя.,Покупио си кључ Маулера. You picked up the Factory Key.,TXT_FACTORYKEY,,,,Sebral@[ao_cs] jsi klíč do továrny.,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.,Podniosł@[irreg_3_pl] Klucz do Fabryki.,Você pegou a Chave da Fábrica.,Apanhaste a Chave da Fábrica.,Ai ridicat Cheia Fabricii.,Получен ключ от фабрики.,Покупио си кључ фабрике You picked up the Mine Key.,TXT_MINEKEY,,,,Sebral@[ao_cs] jsi klíč do dolů.,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.,Podniosł@[irreg_3_pl] Klucz do Kopalni.,Você pegou a Chave da Mina.,Apanhaste a Chave da Mina.,Ai ridicat Cheia Minei.,Получен ключ от шахт.,Покупио си кључ рудника -You picked up the New Key5.,TXT_NEWKEY5,,,,Sebral@[ao_cs] jsi nový klíč 5,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.,Podniosł@[irreg_3_pl] Nowy Klucz5,Você pegou a Chave Nova 5.,Apanhaste a Chave Nova 5.,Ai ridicat Cheia Nouă5.,Получен Новый Ключ5.,Покупио си нови кључ5 +You picked up the New Key5.,TXT_NEWKEY5,,,,Sebral@[ao_cs] jsi nový klíč 5.,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.,Podniosł@[irreg_3_pl] Nowy Klucz5,Você pegou a Chave Nova 5.,Apanhaste a Chave Nova 5.,Ai ridicat Cheia Nouă5.,Получен новый ключ 5.,Покупио си нови кључ5 You picked up the Oracle Pass.,TXT_ORACLEPASS,,,,Sebral@[ao_cs] jsi věštcovu propustku.,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.,Podniosł@[irreg_3_pl] Przepustkę Wyroczni.,Você pegou o Passe do Oráculo.,Apanhaste o Passe do Oráculo.,Ai ridicat Legitimația Oracol.,Получен пропуск Оракула.,Покупио си пророкову пропусницу You picked up the HE-Grenade Rounds.,TXT_HEGRENADES,,,,Sebral@[ao_cs] jsi výbušné granáty.,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.,Podniosł@[irreg_3_pl] Wiązkę Granatów.,Você pegou as Granadas Explosivas.,Apanhaste as Granadas Explosivas.,Ai ridicat Grenadele Explozive.,Получена связка гранат.,Покупио си ХЕ-Граната чауре -You picked up the Phosphorus-Grenade Rounds.,TXT_PHGRENADES,,,,Sebral@[ao_cs] jsi fosforečné granáty.,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.,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.,Получена связка фосфорных гранат.,Покупио си шаржер фосфорних граната. -You picked up the clip of bullets.,TXT_CLIPOFBULLETS,,,,Sebral@[ao_cs] jsi zásobník.,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.,Podniosł@[irreg_3_pl] magazynek.,Você pegou o carregador.,Apanhaste o carregador.,Ai ridicat cartușul cu gloanțe.,Получена обойма., -You picked up the box of bullets.,TXT_BOXOFBULLETS,,,,Sebral@[ao_cs] jsi krabici kulek.,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.,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.,Получена коробка патронов.,Покупио си кутију меткова +You picked up the Phosphorus-Grenade Rounds.,TXT_PHGRENADES,,,,Sebral@[ao_cs] jsi fosforové granáty.,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.,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.,Получена связка фосфорных гранат.,Покупио си шаржер фосфорних граната. +You picked up the clip of bullets.,TXT_CLIPOFBULLETS,,,,Sebral@[ao_cs] jsi zásobník s náboji.,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.,Podniosł@[irreg_3_pl] magazynek.,Você pegou o carregador.,Apanhaste o carregador.,Ai ridicat cartușul cu gloanțe.,Получена обойма., +You picked up the box of bullets.,TXT_BOXOFBULLETS,,,,Sebral@[ao_cs] jsi krabici nábojů.,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.,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.,Получена коробка патронов.,Покупио си кутију меткова You picked up the mini missiles.,TXT_MINIMISSILES,,,,Sebral@[ao_cs] jsi minirakety.,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.,Podniosł@[irreg_3_pl] mini pociski.,Você pegou os mini-mísseis.,Apanhaste os mini-mísseis.,Ai ridicat mini proiectilele.,Получены мини-ракеты.,Покупио си мини ракете -You picked up the crate of missiles.,TXT_CRATEOFMISSILES,,,,Sebral@[ao_cs] jsi krabici miniraket.,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.,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.,Получен ящик мини-ракет.,Покупио си кутију ракета +You picked up the crate of missiles.,TXT_CRATEOFMISSILES,,,,Sebral@[ao_cs] jsi bednu miniraket.,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.,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.,Получен ящик мини-ракет.,Покупио си кутију ракета You picked up the energy pod.,TXT_ENERGYPOD,,,,Sebral@[ao_cs] jsi energetický kokón.,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.,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.,Получена энергоячейка.,Покупио си енергетско постоље. You picked up the energy pack.,TXT_ENERGYPACK,,,,Sebral@[ao_cs] jsi energetický svazek.,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.,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.,Получена энергобатарея.,Покупио си пакет енергије -You picked up the poison bolts.,TXT_POISONBOLTS,,,,Sebral@[ao_cs] jsi jedovaté šípy.,Du hase die Giftbolzen genommen.,,Vi prenis la venenajn sagetojn.,Recogiste las saetas 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.,Podniosł@[irreg_3_pl] zatrute bełty.,Você pegou as setas envenenadas.,Apanhaste as setas envenedadas.,Ai ridicat bolțurile cu otravă.,Получены отравленные болты.,Покупио си отровне стреле +You picked up the poison bolts.,TXT_POISONBOLTS,,,,Sebral@[ao_cs] jsi otrávené šípy.,Du hase die Giftbolzen genommen.,,Vi prenis la venenajn sagetojn.,Recogiste las saetas 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.,Podniosł@[irreg_3_pl] zatrute bełty.,Você pegou as setas envenenadas.,Apanhaste as setas envenedadas.,Ai ridicat bolțurile cu otravă.,Получены отравленные болты.,Покупио си отровне стреле You picked up the electric bolts.,TXT_ELECTRICBOLTS,,,,Sebral@[ao_cs] jsi elektrické šípy.,Du hast die elektrischen Bolzen genommen.,,Vi prenis la elektrajn sagetojn.,Recogiste las saetas 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.,Podniosł@[irreg_3_pl] elektryczne bełty.,Você pegou as setas eletricas.,Apanhaste as setas electricas.,Ai ridicat bolțurile cu electricitate.,Получены электрические болты.,Покупио си електричне стреле You picked up the ammo satchel.,TXT_AMMOSATCHEL,,,,Sebral@[ao_cs] jsi brašnu na munici.,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.,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.,Получен ранец для боеприпасов.,Покупио си торбицу муниције 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 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...,"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ă...,"Кажется, этой вещи ещё никто не касался...",Имаш осећај да није требало бити дирано... "Whatever it is, it doesn't belong in this world...",MSG_TALISMANGREEN,,,,"Je jedno, co to je, do tohoto světa to nepatří...","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...","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...","Что бы это ни было, оно не из этого мира...","Шта год да је, не припада овом свету..." It must do something...,MSG_TALISMANBLUE,,,,Něco to dělat musí...,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....,To musi coś robić...,Deveria fazer alguma coisa...,Devia fazer alguma coisa.,Trebuie să facă ceva...,Оно ведь зачем-то нужно?..,Мора урадити нешто... -You have super strength!,MSG_TALISMANPOWER,,,,Dostal@[ao_cs] jsi super sílu!,Du hast Superkräfte,,Vi havas superan forton!,¡Tienes súper fuerza!,,Sinulla on supervoimat!,Vous avez une puissance inégalée!,Szuper erőt birtokolsz!,Hai la super forza!,豪剛なる力を得た!,엄청난 힘이 솟는다!,Je hebt superkracht!,Masz super siłę!,Você tem a super força!,Tu tens super força!,Ai super forță!,Вы получили сверхсилу!,Имаш супер снагу! +You have super strength!,MSG_TALISMANPOWER,,,,Získal@[ao_cs] jsi super sílu!,Du hast Superkräfte,,Vi havas superan forton!,¡Tienes súper fuerza!,,Sinulla on supervoimat!,Vous avez une puissance inégalée!,Tied a Szuper Erő!,Hai la super forza!,豪剛なる力を得た!,엄청난 힘이 솟는다!,Je hebt superkracht!,Masz super siłę!,Você tem a super força!,Tu tens super força!,Ai super forță!,Вы получили сверхсилу!,Имаш супер снагу! ,,Locks,,,,,,,,,,,,,,,,,,,,, -You don't have the key,TXT_NEEDKEY,,,,Nemáš klíč.,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.,Nie masz klucza,Você não possui a chave,Tu não tens a chave,Nu ai cheia,Нужен ключ,Немаш кључ +You don't have the key,TXT_NEEDKEY,,,,Nemáš klíč.,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.,Nie masz klucza,Você não tem a chave,Tu não tens a chave,Nu ai cheia,Нужен ключ,Немаш кључ You need a passcard,TXT_NEED_PASSCARD,,,,Potřebuješ průkaz.,Du brauchst eine Zugangskarte.,,Vi bezonas paskarton.,Necesitas el pase de acceso,,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.,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,Нужен пропуск,Треба ти пропусница -You need a pass card key to open this door,TXT_NEED_PASSCARD_DOOR,,,,Pro otevření dveří potřebuješ průkaz.,"Du brauchst eine Zugangskarte, um diese Tür zu öffnen.",,Vi bezonas paskarton por malfermi tiun pordon.,Necesitas un pase de acceso 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.,Potrzebujesz karty dostępu aby otworzyć te drzwi,Você precisa de um cartão de acesso para abrir essa porta,Precisas de um cartão de acesso para abrir esta porta,"Ai nevoie de un card de acces ca să deschizi ușa +You need a pass card key to open this door,TXT_NEED_PASSCARD_DOOR,,,,Pro otevření dveří potřebuješ průkaz.,"Du brauchst eine Zugangskarte, um diese Tür zu öffnen.",,Vi bezonas paskarton por malfermi tiun pordon.,Necesitas un pase de acceso 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.,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",Для открытия нужен пропуск,Треба ти пасош да отвориш ова врата You need an ID card,TXT_NEED_IDCARD,,,,Potřebuješ identifikační kartu.,Du brauchst einen Ausweis.,,Vi ne bezonas identigo-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.,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,Нужна личная карта,Треба ти идентификациона картица You don't have the key to the prison,TXT_NEED_PRISONKEY,,,,Nemáš klíč do vězení.,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.,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,Нужен ключ от тюрьмы,Треба ти кључ затвора Hand print not on file,TXT_NEED_HANDPRINT,,,,Otisk ruky není v databázi.,Handabdruck nicht gespeichert!,,Manspuro ne sur dosiero,La huella digital no esta en el archivo,,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.,Brak odcisku dłoni w bazie danych,Biometria não autorizada,Impressão digital não autorizada,Amprenta mâinii nerecunoscută,Отпечаток руки не распознан,Отисак длана није у записнику You need the Gold Key,TXT_NEED_GOLDKEY,,,,Potřebuješ zlatý klíč.,Du brauchst den goldenen Schlüssel,,Vi bezonas la Ora Ŝ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.,Potrzebujesz Złotego Klucza,Você precisa da Chave de Ouro,Precisas da Chave de Ouro,Ai nevoie de cheia din Aur,Нужен золотой ключ,Треба ти златни кључ You need an ID Badge,TXT_NEED_IDBADGE,,,,Potřebuješ identifikační odznak.,Du brauchst eine Identitätskarte.,,Vi bezonas identig-insignon.,Necesitas una Insignia de Identificació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.,Potrzebujesz Odznaki Identyfikacyjnej,Você precisa do Crachá de Identificação,Precisas do Crachá de Identificação,Ai nevoie de un ecuson de identificare,Нужна личная карта,Треба ти лична карта -You need an ID Badge to open this door,TXT_NEED_IDBADGE_DOOR,,,,Potřebuješ identifikační odznak pro otevření dveří.,"Du brauchst eine Identitätskarte, um diese Tür zu öffnen.",,Vi bezonas identig-insignon por malfermi tion pordon.,Necesitas una Insignia de Identificació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.,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ă +You need an ID Badge to open this door,TXT_NEED_IDBADGE_DOOR,,,,Pro otevření dveří potřebuješ identifikační odznak.,"Du brauchst eine Identitätskarte, um diese Tür zu öffnen.",,Vi bezonas identig-insignon por malfermi tion pordon.,Necesitas una Insignia de Identificació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.,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",Для открытия нужна личная карта,Треба ти лична карта да отвориш ова врата You need the Silver Key,TXT_NEED_SILVERKEY,,,,Potřebuješ stříbrný klíč.,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.,Potrzebujesz Srebrnego Klucza,Você precisa da Chave de Prata,Precisas da Chavede Prata,Ai nevoie de cheia din Argint,Нужен серебряный ключ,Треба ти сребрни кључ You need the Brass Key,TXT_NEED_BRASSKEY,,,,Potřebuješ mosazný klíč.,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.,Potrzebujesz Mosiężnego Klucza,Você precisa da Chave de Latão,Precisas da Chave de Latão,Ai nevoie de cheia din Alamă,Нужен латунный ключ,Треба ти кључ од месинга @@ -1568,14 +1567,14 @@ That doesn't seem to work,TXT_DOES_NOT_WORK,,,,Takhle to nepůjde.,Das scheint n You need the chalice!,TXT_NEED_CHALICE,,,,Potřebuješ kalich!,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!,Potrzebujesz kielicha!,Você precisa do cálice!,Precisas do cálice!,Ai nevoie de potir!,Нужна чаша!,Треба ти пехар! You need the Oracle Pass!,TXT_NEED_OPASS,,,,Potřebuješ propustku od věštce!,Du brauchst den Orakelpass!,,Vi bezonas la Pason de Oraklo!,¡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!,Potrzebujesz Przepustki Wyroczni!,Você precisa do Passe do Oráculo!,Precisas do Passe do Oráculo!,Ai nevoie de legitimația Oracol!,Нужен пропуск Оракула!,Треба ти Пророкова пропусница! ,,Actor tags,,,,,,,,,,,,,,,,,,,,, -Dagger,TAG_PUNCHDAGGER,,,,Dýka,Dolch,Μαχάιρι,Ponardo,Daga,,Tikari,Dague de Poing,Tör,Pugnale,ダガー,단검,Dolk,Sztylet,Punhal,,Pumnal,Кинжал,Бодеж +Dagger,TAG_PUNCHDAGGER,,,,Dýka,Dolch,Μαχάιρι,Ponardo,Daga,,Tikari,Dague de Poing,Tőr,Pugnale,ダガー,단검,Dolk,Sztylet,Punhal,,Pumnal,Кинжал,Бодеж Crossbow,TAG_STRIFECROSSBOW1,Crossbow with electric bolts,,,Kuše,Armbrust,Τόξο (Δηλητήριο),Arbalesto (Elektraj segetoj),Ballesta,,Jousipyssy,Arbalète Electrique,Nyílpuska,Balestra ,クロスボウ,석궁 (전격),Kruisboog,Kusza,Besta,,Arbaletă,Арбалет,Самострел Crossbow,TAG_STRIFECROSSBOW2,Crossbow with poison bolts,,,Kuše,Armbrust,Τόξο (Ηλεκτρικό),Arbalesto (Venemaj segetoj),Ballesta,,Jousipyssy,Arbalète Empoisonée,Nyílpuska,Balestra ,クロスボウ,석궁 (맹독),Kruisboog,Kusza,Besta,,Arbaletă,Арбалет,Самострел Assault Gun,TAG_ASSAULTGUN,,,,Útočná puška,Sturmgewehr,,Ataka Pafilo,Fusil de Asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'Assalto ,アサルトガン,돌격소총,Aanvalswapen,Karabin Szturmowy,Fuzil de Assalto,Arma de Assalto,Pușcă de Asalt,Винтовка,Аутоматска пушка Mini Missile Launcher,TAG_MMLAUNCHER,,,,Miniraketomet,Miniraketenwerfer,Μίνι-Πυραυλοβόλο,Misiletĵteilo,Mini Lanzamisiles,,Miniohjuslaukaisin,Lanceur de Mini-Missiles,Mini Rakétavető,Mini-Lanciamissili,ミニミサイルランチャー,미니 미사일 런쳐,Miniraketwerper,Wyrzutnia Minipocisków,Mini Lança-mísseis,,Mini Lansator de Proiectile,Мини-ракетница,Мини ракетни бацач Flame Thrower,TAG_FLAMER,,,,Plamenomet,Flammenwerfer,,Flamĵetilo,Lanzallamas,,Liekinheitin,Lance-Flammes,Lángszóró,Lanciafiamme ,火炎放射器,화염방사기,Vlammenwerper,Miotacz Ognia,Lança-chamas,,Aruncător de Flăcări,Огнемёт,Бацеч пламена -Mauler,TAG_MAULER1,,,,Trhač,Vernichter,,Vundegilo,Triturador,,Moukari,Broyeur,Bomlasztó,Pestatore ,マウラー,마울러 (저출력),Toetakelaar,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер -Mauler,TAG_MAULER2,,,,Trhač,Vernichter,,Vundegilo,Triturador,,Moukari,Broyeur,Bomlasztó,Pestatore,マウラー,마울러 (고출력),Toetakelaar,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер +Mauler,TAG_MAULER1,,,,Trhač,Vernichter,,Vundegilo,Triturador,,Moukari,Broyeur,Marcangoló,Pestatore ,マウラー,마울러 (저출력),Toetakelaar,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер +Mauler,TAG_MAULER2,,,,Trhač,Vernichter,,Vundegilo,Triturador,,Moukari,Broyeur,Marcangoló,Pestatore,マウラー,마울러 (고출력),Toetakelaar,Miażdżyciel,Desintegrador,,Sfâșietor,Истязатель,Маулер Grenade Launcher,TAG_GLAUNCHER1,High-explosive grenade launcher,,,Granátomet,Granatwerfer,,Granadĵetilo (PE),Lanzagranadas,,Kranaatinheitin,Lance-Grenades Explosif,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (고폭탄),Granaatwerper,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната Grenade Launcher,TAG_GLAUNCHER2,White phosphorous grenade launcher ,,,Granátomet,Granatwerfer,,Granadĵetilo (Fosfora),Lanzagranadas,,Kranaatinheitin,Lance-Grenades Incendiaire,Gránátvető,Lanciagranate,グレネードランチャー,유탄발사기 (소이탄),Granaatwerper,Wyrzutnia Granatów,Lança-granadas,,Lansator de Grenade,Гранатомёт,Бацач граната Sigil,TAG_SIGIL,,,,Pečeť,,,Sigelo,Emblema,,Sinetti,,Pecsét,Sigillo,シジル,시질,Sigil,Pieczęć,Sigilo,,Sigiliu,Сигил,Сигил @@ -1587,11 +1586,11 @@ Ring,TAG_BELDINSRING,,,,Prsten,,,Ringo,Anillo,,Sormus,Anneau,Gyűrű,Anello ,指 Offering Chalice,TAG_OFFERINGCHALICE,,,,Obětní kalich,Opferkelch,,Ofertkilko,Cáliz de Ofrenda,,Uhrimalja,Calice d'Obole,Áldozati kehely,Calice delle Offerte,寄贈された聖杯,번제 성배,Offerbeker,Kielich Ofiarny,Calice de Oferenda,,Potir pentru Ofrande,Чаша для подношений,Жртвени пехар Ear,TAG_EAR,,,,Ucho,Ohr,,Orelo,Oreja,,Korva,Oreille,Fül,Orecchio,耳,귀,Oor,Ucho,Orelha,,Ureche,Ухо,Уво Broken Power Coupling,TAG_BROKENCOUPLING,,,,Rozbitá spojka,Defekter Stromabnehmer,,Rompa Povkuplilo,Acoplador de Energía Roto,,Rikkinäinen virtaliitin,Coupleur Energétique cassé,Elromlott Tápcsatlakozó,Coppia Energetica Rotta ,壊れたパワーカップリング,망가진 동력선,Gebroken stroomkoppeling,Zepsute Obwody Zasilające,Acoplador de Energia Quebrado,Acoplador de Energia Partido,Cuplaj de Putere Defect,Повреждённая муфта,Неисправна спојница напајања -Shadow Armor,TAG_SHADOWARMOR,,,Shadow Armour,Krycí brnění,Schattenrüstung,,Ombrokiraso,Armadura de Sombra,,Varjohaarniska,Armure de l'Ombre,Sötét Páncél,Armatura Ombra ,シャドウアーマー,그림자 갑옷,Schaduwharnas,Cienisty Pancerz,Armadura das Sombras,,Armura Umbrei,Теневая броня,Оклоп сенки +Shadow Armor,TAG_SHADOWARMOR,,,Shadow Armour,Stínové brnění,Schattenrüstung,,Ombrokiraso,Armadura de Sombra,,Varjohaarniska,Armure de l'Ombre,Sötét Páncél,Armatura Ombra ,シャドウアーマー,그림자 갑옷,Schaduwharnas,Cienisty Pancerz,Armadura das Sombras,,Armura Umbrei,Теневая броня,Оклоп сенки Environmental Suit,TAG_ENVSUIT,,,,Ochranný oblek,Schutzanzug,,Medivesto,Traje Ambiental,,Ympäristösuojapuku,Combinaison Hazmat,Védőöltözet,Tuta Ambientale ,耐環境スーツ,환경 방호복,Beschermend pak,Skafander Ochronny,Traje de Proteção,Fato Protetor,Costum de Protecție,Защитный костюм,Заштитно одело Guard Uniform,TAG_GUARDUNIFORM,,,,Hlídačova uniforma,Wächteruniform,,Gardista Uniformo,Uniforme de Guardia,,Vartijan univormu,Uniforme de Garde,Őr Egyenruha,Uniforme da Guardia,ガードの制服,경비 전투복,Wachtersuniform,Mundur Strażnika,Uniforme de Guarda,,Uniformă de Paznic,Униформа стражника,Стражарска униформа Officer's Uniform,TAG_OFFICERSUNIFORM,,,,Důstojníkova uniforma,Offiziersuniform,,Oficira Uniformo,Uniforme de Oficial,,Upseerin univormu,Uniforme d'Officier,Tiszti Egyenruha,Uniforme da Ufficiale ,士官の制服,장교 전투복,Officiersuniform,Mundur Oficera,Uniforme de Oficial,,Uniformă de Ofițer,Офицерская униформа,Официрска униформа -Flame Thrower Parts,TAG_FTHROWERPARTS,,,,Součásti plamenometu,Flammenwerferteile,,Partoj de Flamjetilo,Partes de Lanzallamas,,Liekinheittimen osat,Pièces de Lance-Flamme,Lángszóró Alkatrészek,Parti di Lanciafiamme ,火炎放射器の部品,화염방사기 부품,Vlammenwerperonderdelen,Części Miotacza Ognia,Partes do lança-chamas,,Bucăți de Aruncător de Flăcări,Детали огнемёта,Делови бацача пламена +Flame Thrower Parts,TAG_FTHROWERPARTS,,,,Díly plamenometu,Flammenwerferteile,,Partoj de Flamjetilo,Partes de Lanzallamas,,Liekinheittimen osat,Pièces de Lance-Flamme,Lángszóró Alkatrészek,Parti di Lanciafiamme ,火炎放射器の部品,화염방사기 부품,Vlammenwerperonderdelen,Części Miotacza Ognia,Partes do lança-chamas,,Bucăți de Aruncător de Flăcări,Детали огнемёта,Делови бацача пламена Report,TAG_REPORT,,,,Hlášení,,,Raporto,Reporte,,Raportti,Compte-rendu,Jelentés,Rapporto ,報告書,보고서,Verslag,Raport,Relatório,,Raport,Отчёт,Извештај Info,TAG_INFO,,,,Informace,,,Informo,Información,,Tiedot,,Információ,Informazioni ,情報,정보,Info,Informacje,Informação,,Informație,Сводка,Инфо Targeter,TAG_TARGETER,,,,Zaměřovač,Zielhilfe,,Celilo,Apuntador,,Tähtäinlaite,Cibleur,Célzó eszköz,Puntatore,照準器,조준기,Richter,Namierzacz,Mira,,Țintitor,Целеуказатель,Нишанџија @@ -1608,15 +1607,15 @@ Teleporter Beacon,TAG_TELEPORTERBEACON,,,,Teleportační maják,Teleportersignal Metal Armor,TAG_METALARMOR,,,Metal Armour,Kovové brnění,Metallrüstung,,Metala Kiraso,Armadura de Metal,,Metallihaarniska,Armure en Métal,Fém Páncél,Armatura di Metallo ,メタルアーマー,강철 갑옷,Metalen harnas,Metalowy Pancerz,Armadura de Metal,,Armură din Metal,Металлическая броня,Метални оклоп Leather Armor,TAG_LEATHER,,,Leather Armour,Kožené brnění,Lederrüstung,,Leda Kiraso,Armadura de Cuero,,Nahkasuojus,Armure en Cuir,Bőr Páncél,Armatura di Cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Skórzany Pancerz,Armadura de Couro,,Armură din Piele,Кожаная броня,Кожни оклоп HE-Grenade Rounds,TAG_HEGRENADES,,,,Výbušné granáty,HE-Granaten,,PV-Gernadmunicioj,Granadas HE,,Räjähdekranaatit,Grenades Explosives,Gránát Lőszer,Granata HE,HEグレネード弾,고폭 유탄,HE-granaten,Wiązka Granatów,Munição - Granadas Explosivas,,Grenade Explozive,Осколочные гранаты,Хе-Граната чауре -Phosphorus-Grenade Rounds,TAG_PHGRENADES,,,,Fosforečné granáty,Phosphorgranaten,,Fosforaj Gernadmunicioj,Granadas de Fósforo,,Fosforikranaatit,Grenades Incendiaires,Foszfor-Gránát Lőszer,Granata al Fosforo ,白リングレネード弾,소이 유탄,Fosforgranaten,Wiązka Fosforowych Granatów,Municão - Granadas de Fósforo,,Grenade cu Fosfor,Фосфорные гранаты,Фосфорне гранате -Clip of Bullets,TAG_CLIPOFBULLETS,,,,Zásobník,Gewehrmunition,,Kuglujo,Cargador de Balas,,Luotilipas,Chargeur d'Assaut,Golyó töltények,Caricatore di Proiettili ,弾丸のクリップ,소총 탄창,Patroon kogels,Magazynek,Carregador de Balas,,Cartuș cu Gloanțe,Обойма,Клип метака -Ammo,TAG_BOXOFBULLETS,,,,Bedna munice,Munitionskiste,,Municio,Caja de Municiones,,Luotilaatikko,Bôite de Munitions,Lőszer,Munizioni ,弾薬箱,탄약,Munitie,Amunicja,Caixa de Balas,,Muniție,Боеприпасы,Муниција +Phosphorus-Grenade Rounds,TAG_PHGRENADES,,,,Fosforové granáty,Phosphorgranaten,,Fosforaj Gernadmunicioj,Granadas de Fósforo,,Fosforikranaatit,Grenades Incendiaires,Foszfor-Gránát Lőszer,Granata al Fosforo ,白リングレネード弾,소이 유탄,Fosforgranaten,Wiązka Fosforowych Granatów,Municão - Granadas de Fósforo,,Grenade cu Fosfor,Фосфорные гранаты,Фосфорне гранате +Clip of Bullets,TAG_CLIPOFBULLETS,,,,Zásobník s náboji,Gewehrmunition,,Kuglujo,Cargador de Balas,,Luotilipas,Chargeur d'Assaut,Golyó töltények,Caricatore di Proiettili ,弾丸のクリップ,소총 탄창,Patroon kogels,Magazynek,Carregador de Balas,,Cartuș cu Gloanțe,Обойма,Клип метака +Ammo,TAG_BOXOFBULLETS,,,,Krabice nábojů,Munitionskiste,,Municio,Caja de Municiones,,Luotilaatikko,Bôite de Munitions,Lőszer,Munizioni ,弾薬箱,탄약,Munitie,Amunicja,Caixa de Balas,,Muniție,Боеприпасы,Муниција Mini Missiles,TAG_MINIMISSILES,,,,Minirakety,Miniraketen,,Misileto,Mini Misiles,,Miniohjukset,Mini-Missiles,Mini Rakéták,Mini-Missili,ミニミサイル,미니 미사일,Mini-raketten,Mini Pociski,Mísseis,,Mini Proiectile,Мини-ракеты,Мини Ракете Crate of Missiles,TAG_CRATEOFMISSILES,,,,Bedna raket,Raketenkiste,,Misilarujo,Caja de Cohetes,,Ohjuslaatikko,Caisse de Mini-Missiles,Ládányi Rakéta,Cassa di Missili,ミサイルの箱,미사일 박스,Krat raketten,Skrzynia z Pociskami,Caixa de Mísseis,,Ladă cu Proiectile,Коробка ракет,Кутија ракета Energy Pod,TAG_ENERGYPOD,,,,Energetický kokón,Energiezelle,,Umon de Energio,Vaina de Energía,,Energia-akku,Cellule Energétique,Energia Lőszer,Nucleo Enegetico ,エネルギーポット,에너지 포드,Energiecel,Kapsuła Energii,Energia (pequeno),,Capsulă cu Energie,Энергоячейка,Енергетска шипка Energy Pack,TAG_ENERGYPACK,,,,Energetický svazek,Energiekiste,,Pako de Energio,Pack de Energía,,Energiapaketti,Pack Energétique,Energia Csomag,Carica Energetica ,エネルギーパック,에너지 팩,Energiepak,Zasobnik Energii,Energia (grande),,Pachet cu Energie,Энергобатарея,Паковање енергије -Poison Bolts,TAG_POISONBOLTS,,,,Otrávené šípy,Giftbolzen,,Venenaj Sagetoj,Saetas Venenosas,,Myrkkynuolet,Carreaux Empoisonnés,Mérgező Nyílak,Dardi Velenosi ,ポイズンボルト,맹독 볼트,Giftige bouten,Zatrute Bełty,Setas Envenenadas,,Bolțuri cu Otravă,Отравленные болты,Отровне стреле -Electric Bolts,TAG_ELECTRICBOLTS,,,,Elektrické šípy,Elektrische Bolzen,,Elektraj Sagetoj,Saetas Eléctricas,,Sähkönuolet,Carreaux Electriques,Elektromos Nyílak,Dardi Elettrici ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektryczne Bełty,Setas Elétricas,,Bolțuri cu Electricitate,Электрические болты,Електричне стреле +Poison Bolts,TAG_POISONBOLTS,,,,Otrávené šípy,Giftbolzen,,Venenaj Sagetoj,Saetas Venenosas,,Myrkkynuolet,Carreaux Empoisonnés,Mérgező hegyek,Dardi Velenosi ,ポイズンボルト,맹독 볼트,Giftige bouten,Zatrute Bełty,Setas Envenenadas,,Bolțuri cu Otravă,Отравленные болты,Отровне стреле +Electric Bolts,TAG_ELECTRICBOLTS,,,,Elektrické šípy,Elektrische Bolzen,,Elektraj Sagetoj,Saetas Eléctricas,,Sähkönuolet,Carreaux Electriques,Elektromos hegyek,Dardi Elettrici ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektryczne Bełty,Setas Elétricas,,Bolțuri cu Electricitate,Электрические болты,Електричне стреле Ammo Satchel,TAG_AMMOSATCHEL,,,,Brašna na munici,Munitionstasche,,Municiingo,Bolsa de Municiones,,Ammuslaukku,Sacoche à munitions,Lőszeres táska,Borsa di Munizioni ,弾薬鞄,탄약 배낭,Munitietassen,Torba z Amunicją,Bolsa de Munição,,Sacoșă cu Muniție,Ранец для боеприпасов,Торбица муниције Base Key,TAG_BASEKEY,,,,Klíč od základny,Basisschlüssel,,Bazŝlosilo,Llave de la Base,,Tukikohdan avain,Clé de la base,Bázis Kulcs,Chiave della Base,,기지 키,Basissleutel,Klucz do Bazy,Chave da Base,,Cheia Bazei,Ключ от базы,Кључ базе Govs Key,TAG_GOVSKEY,,,,Klíč ke guvernérovi,Gouverneursschlüssel,,Ŝlosilo de Reganto,Llave del Gobernador,,Kuvernöörin avain,Clé du Gouverneur,Kormányzó Kulcs,Chiave del Governatore ,,총독의 키,Gouverneursleutel,Klucz Gubernatora,Chave do Governador,,Cheia Guvernatorului,Ключ губернатора,Гувернеров кључ @@ -1631,7 +1630,7 @@ Gold Key,TAG_GOLDKEY,,,,Zlatý klíč,Goldschlüssel,,Ora Klavo,Llave Dorada,,Ku ID Card,TAG_IDCARD,,,,Identifikační karta,Ausweis,,Identigo-karto,Tarjeta de Identificación,,Henkilökortti,Carte d'Identité,Azonosító Kártya,Tessera Identificativa,,신분증,ID-Kaart,Karta Identyfikacyjna,Cartão de Identificação,,Card de Identitate,Удостоверение,Лична карта Silver Key,TAG_SILVERKEY,,,,Stříbrný klíč,Silberschlüssel,,Arĝenta Ŝlosilo,Llave Plateada,,Hopea-avain,Clé en Argent,Ezüst Kulcs,Chiave Argentata,,은 키,Zilveren sleutel,Srebrny Klucz,Chave de Prata,,Cheia din Argint,Серебряный ключ,Сребрни кључ Oracle Key,TAG_ORACLEKEY,,,,Věštcův klíč,Orakelschlüssel,,Orakolo-ŝlosilo,Llave del Oráculo,,Oraakkelin avain,Clé de l'Oracle,Orákulum kulcs,Chiave dell'Oracolo ,,오라클 키,Orakelsleutel,Klucz do Wyroczni,Chave do Oráculo,,Cheia Oracol,Ключ Оракула,Пророков кључ -Military ID,TAG_MILITARYID,,,,Vojenské ID,Militärausweis,,Militidentigilo,Identificación Militar,,Sotilastunnus,Identification Militaire,Katonai Azonosító Kártya,Identificativo Militare,,군용 아이디,Militaire ID,Wojskowy Identyfikator,ID Militar,,Legitimație Militară,Военный ID,Војна идентификација +Military ID,TAG_MILITARYID,,,,Vojenské ID,Militärausweis,,Militidentigilo,Identificación Militar,,Sotilastunnus,Identification Militaire,Katonai Azonosító Kártya,Identificativo Militare,,군용 아이디,Militaire ID,Wojskowy Identyfikator,ID Militar,,Legitimație Militară,Удостовер. военного,Војна идентификација Order Key,TAG_ORDERKEY,,,,Klíč Řádu,Ordensschlüssel,,Ordeno-ŝlosilo,Llave de la Orden,,Veljeskunnan avain,Clé de l'Ordre,Rend Kulcs,Chiave dell'Ordine,,오더의 키,Ordesleutel,Klucz Zakonu,Chave da Ordem,,Cheia Ordinului,Ключ Ордена,Кључ одреда Warehouse Key,TAG_WAREHOUSEKEY,,,,Klíč ke skladu,Lagerhausschlüssel,,Stokejŝlosilo,Llave del Almacén,,Varaston avain,Clé de l'Entrepôt,Raktár Kulcs,Chiave del Magazzino ,,창고 키,Magazijnsleutel,Klucz do Magazynu,Chave do Armazém,,Cheia Depozitului,Ключ от склада,Кључ складишта Brass Key,TAG_BRASSKEY,,,,Mosazný klíč,Messingschlüssel,,Latuna Ŝlosilo,Llave de Latón,,Messinkiavain,Clé en Bronze,Réz Kulcs,Chiave d'Ottone ,,황동 키,Messing sleutel,Mosiężny Klucz,Chave de Latão,,Cheia din Alamă,Латунный ключ,Кључ од месинга @@ -1641,10 +1640,10 @@ Chapel Key,TAG_CHAPELKEY,,,,Klíč od kaple,Kapellenschlüssel,,Kapelŝlosilo,Ll Catacomb Key,TAG_CATACOMBKEY,,,,Klíč do katakomb,Katakombenschlüssel,,Katakombŝlosilo,Llave de la Catacumba,,Katakombin avain,Clé des Catacombes,Katakomba Kulcs,Chiave delle Catacombe ,,고대 묘지 키,Catacombesleutel,Klucz do Katakumb,Chave da Catacumba,,Cheia Catacombei,Ключ от катакомб,Кључ од катакомби Security Key,TAG_SECURITYKEY,,,,Klíč ochranky,Sicherheitsschlüssel,,Gardŝlosilo,Llave de Seguridad,,Turvamiesavain,Clé de la Sécurité,Biztonsági Kulcs,Chiave della Sicurezza ,,보안 키,Beveiligingssleutel,Klucz Ochrony,Chave de Segurança,,Cheia Securității,Ключ охраны,Сигурносни кључ Core Key,TAG_COREKEY,,,,Klíč k jádru,Reaktorschlüssel,,Kernŝlosilo,Llave del Núcleo,,Ytimen avain,Clé du Réacteur,Mag Kulcs,Chiave del Nucleo,,중심부 키,Kernsleutel,Klucz do Rdzenia,Chave do Núcleo,,Cheia Nucleului,Ключ от реактора,Кључ језгра -Mauler Key,TAG_MAULERKEY,,,,Klíč k trhačům,Vernichterschlüssel,,Vundegilo-ŝlosilo,Llave del Triturador,,Moukarin avain,Clé du Broyeur,Szétbomló Kulcs,Chiave del Pestatore ,,마울러 키,Toetakelaarssleutel,Klucz do Magazynu Miażdżycieli,Chave - Mauler,,Cheia Sfâșietorului,Ключ истязателя,Маулер кључ +Mauler Key,TAG_MAULERKEY,,,,Klíč k trhačům,Vernichterschlüssel,,Vundegilo-ŝlosilo,Llave del Triturador,,Moukarin avain,Clé du Broyeur,Marcangoló Kulcs,Chiave del Pestatore ,,마울러 키,Toetakelaarssleutel,Klucz do Magazynu Miażdżycieli,Chave - Mauler,,Cheia Sfâșietorului,Ключ истязателя,Маулер кључ Factory Key,TAG_FACTORYKEY,,,,Klíč do továrny,Fabrikschlüssel,,Fabrikejo-ŝlosilo,Llave de la Fábrica,,Tehtaan avain,Clé de l'Usine,Gyár Kulcs,Chiave della Fabbrica ,,공장 키,Fabriekssleutel,Klucz do Fabryki,Chave da Fábrica,,Cheia Fabricii,Ключ от фабрики,Кључ фабрике Mine Key,TAG_MINEKEY,,,,Klíč od dolů,Minenschlüssel,,Minejŝlosilo,Llave de la Mina,,Kaivoksen avain,Clé de la Mine,Bánya Kulcs,Chiave della Miniera ,,탄광 키,Mijnsleutel,Klucz do Kopalni,Chave da Mina,,Cheia Minei,Ключ от шахт,Кључ рудника -New Key5,TAG_NEWKEY5,,,,Nový klíč 5,Neuer Schlüssel 5,,Nova Ŝlosilo5,Llave Nueva5,,Uusi 5-avain,Clé nouveau 5,5. kulcs,Nuova Chiave 5,,새로운 키5,Nieuwe sleutel 5,Nowy Klucz5,Chave Nova 5,,Noua Cheie5,Новый ключ5,Нови кључ5 +New Key5,TAG_NEWKEY5,,,,Nový klíč 5,Neuer Schlüssel 5,,Nova Ŝlosilo5,Llave Nueva5,,Uusi 5-avain,Clé nouveau 5,5. kulcs,Nuova Chiave 5,,새로운 키5,Nieuwe sleutel 5,Nowy Klucz5,Chave Nova 5,,Noua Cheie5,Новый ключ 5,Нови кључ5 Oracle Pass,TAG_ORACLEPASS,,,,Věštcova propustka,Orakelpass,,Oraklo-pasilo,Pase del Oráculo,,Oraakkelin kulkulupa,Passe de l'Oracle,Orákulum útlevél,Lasciapassare dell'Oracolo ,,오라클의 통행증,Orakelpas,Przepustka Wyroczni,Passe do Oráculo,,Legitimația Oracol,Пропуск Оракула,Пророкова пропусница 10 gold,TAG_10GOLD,,,,10 zlatých,10 Gold,,10 da oro,10 de Oro,,10 kolikkoa,10 Pièces,10 arany,10 pezzi d'oro ,10ゴールド,10 골드,10 goud,10 monet,10 moedas,10 moedas de ouro,10 monezi de aur,10 золотых,10 златника 25 gold,TAG_25GOLD,,,,25 zlatých,25 Gold,,25 da oro,25 de Oro,,25 kolikkoa,25 Pièces,25 arany,25 pezzi d'oro ,25ゴールド,25 골드,25 goud,25 monet,25 moedas,25 moedas de ouro,25 de monezi de aur,25 золотых,25 златника @@ -1653,7 +1652,7 @@ Oracle Pass,TAG_ORACLEPASS,,,,Věštcova propustka,Orakelpass,,Oraklo-pasilo,Pas Person,TXT_PERSON,,,,Osoba,,,Persono,Persona,,Henkilö,Personne,Személy,Persona,一員,민간인,Persoon,Osoba,Pessoa,,Persoană,Горожанин,Особа Acolyte,TAG_ACOLYTE,,,,Akolyta,Ministrant,,Akolito,Acólito,,Akoluutti,,Ministráns,Accolito ,アコライト,아콜라이트,Acoliet,Akolita,Acólito,,Acolit,Служитель,Следбеник Armorer,TAG_ARMORER,,,Armourer,Kovář,Rüster,,Armilisto,Armero,,Asemestari,Armurier,Páncélkovács,Armaiolo ,装甲,병기공,Harnassmid,Płatnerz,Armeiro,,Armurier,Бронник,Ковач -Bar Keep,TAG_BARKEEP,,,,Barman,Wirt,,Trinkejisto,Cantinero,,Baarimikko,Barman,Csapos,Barista,酒屋,바텐더,Barman,Barman,Dono do Bar,,Barman,Хозяин таверны,Конобар +Bar Keep,TAG_BARKEEP,,,,Výčepní,Wirt,,Trinkejisto,Cantinero,,Baarimikko,Barman,Csapos,Barista,酒屋,바텐더,Barman,Barman,Dono do Bar,,Barman,Хозяин таверны,Конобар Beggar,TAG_BEGGAR,,,,Žebrák,Bettler,,Almozulo,Mendigo,,Kerjäläinen,Mendiant,Koldus,Mendicante ,乞食,거지,Bedelaar,Żebrak,Mendigo,,Sărman,Нищий,Просјак Macil,TAG_MACIL1,,,,Macil,,,,,,,,,Macil,マシル,마실,Macil,Macil,Macil,,Macil,Мэйсил,Мејсил Macil,TAG_MACIL2,,,,Macil,,,,,,,,,Macil ,マシル,마실,Macil,Macil,Macil,,Macil,Мэйсил,Мејсил @@ -1668,19 +1667,19 @@ Red Talisman,TAG_TALISMANRED,,,,Červený talisman,Roter Talisman,,Ruĝa Talisma Green Talisman,TAG_TALISMANGREEN,,,,Zelený talisman,Grüner Talisman,,Verda Talismano,Talismán verde,,Vihreä talismaani,Talisman Vert,Zöld Talizmán,Talismano verde,緑の魔除け,녹색 부적,Groene Talisman,Zielony Talizman,Talismã Verde,,Talisman Verde,Зелёный талисман,Зелени талисман Blue Talisman,TAG_TALISMANBLUE,,,,Modrý talisman,Blauer Talisman,,Blua Talismano,Talismán azul,,Sininen talismaani,Talisman Bleu,Kék Talizmán,Talismano blu,青の魔除け,푸른 부적,Blauwe Talisman,Niebieski Talizman,Talismã Azul,,Talisman Albastru,Синий талисман,Плави талисман ,,Obituaries,,,,,,,,,,,,,,,,,,,,, -%o was zealously shot down by an Acolyte.,OB_ACOLYTE,,,,%o byl@[ao_cs] horlivě zastřelen@[ao_cs] akolytou.,%o wurde eifrig von dem Ministranten erschossen.,,%o fervore pafiĝis de Akolito.,%o fue celosamente derribad@[ao_esp] por un Acólito.,,%o joutui kiivailevan akoluutin ampumaksi.,%o a souffert d'une bavure policière.,%o buzgóan 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 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 фанатично убит@[ao_rus] служителем.,%o је ревносно упуцан@[adj_1_sr] од стране секташа. -%o should have never rebelled against Macil.,OB_MACIL,,,,%o se nikdy neměl@[ao_cs] vzbouřit vůči Macilovi.,%o hätte nicht gegen Macil rebellieren sollen.,,%o neniam devintus ribeli kontraŭ Macilo.,%o no debió haberse rebelado contra Macil.,,%o paran ei olisi ikinä pitänyt kapinoida Macilia vastaan.,%o n'aurait jamais du se rebeller contre Macil.,%o egy 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 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 +%o was zealously shot down by an Acolyte.,OB_ACOLYTE,,,,%o byl@[ao_cs] horlivě zastřelen@[ao_cs] akolytou.,%o wurde eifrig von dem Ministranten erschossen.,,%o fervore pafiĝis de Akolito.,%o fue celosamente derribad@[ao_esp] 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 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 фанатично убит@[ao_rus] служителем.,%o је ревносно упуцан@[adj_1_sr] од стране секташа. +%o should have never rebelled against Macil.,OB_MACIL,,,,%o se nikdy neměl@[ao_cs] vzbouřit vůči Macilovi.,%o hätte nicht gegen Macil rebellieren sollen.,,%o neniam devintus ribeli kontraŭ Macilo.,%o no debió haberse rebelado 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 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 was gunned down by a Rebel.,OB_REBEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] rebelem.,%o wurde von einem Rebellen erschossen.,,%o pafegiĝis de ribelanto.,%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 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 was beaten to death by the poor.,OB_BEGGAR,,,,%o byl@[ao_cs] umlácen@[ao_cs] chudými.,%o fiel der Armut zum Opfer.,,%o morte bategiĝis de la malriĉuloj.,%o fue abatid@[ao_esp] hasta la muerte por 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 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 was beaten to death by the poor.,OB_BEGGAR,,,,%o byl@[ao_cs] umlácen@[ao_cs] chudinou.,%o fiel der Armut zum Opfer.,,%o morte bategiĝis de la malriĉuloj.,%o fue abatid@[ao_esp] hasta la muerte por 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 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 should have never picked a fight with a civilian.,OB_PEASANT,,,,%o si neměl@[ao_cs] začínat s civilistou.,%o hätte sich nicht mit einem Zivilisten anlegen sollen.,,%o neniam devintus komenci batalon al civilulo.,%o nunca debió haberse metido en 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 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 was struck down by the Spectre.,OB_ALIENSPECTRE,,,,%o byl@[ao_cs] zničen@[ao_cs] přízrakem.,%o wurde von dem Schemen niedergestreckt.,,%o subite mortiĝis de la Fantomo.,%o fue abatid@[ao_esp] por el Espectro.,,%o joutui haamun kaatamaksi.,%o a été terrassé@[e_fr] par le Spectre.,%o ki lett ütve a Kísértet által.,%o è stato abbattuto dallo Spettro. ,%o はスペクトルに討ち滅ぼされた。,%o 은(는) 스펙터에 의해 무너져 내렸다.,%o werd door de Specter neergeslagen.,%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 was struck down by the Spectre.,OB_ALIENSPECTRE,,,,%o byl@[ao_cs] zničen@[ao_cs] přízrakem.,%o wurde von dem Schemen niedergestreckt.,,%o subite mortiĝis de la Fantomo.,%o fue abatid@[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 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 felt the wrath of The One God.,OB_ENTITY,,,,%o pocítil@[ao_cs] vztek Jediného Boha,%o spürte den Zorn des Einen Gottes.,,%o sentis la koleregon de La Unu Dio.,%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 poczuł@[ao_pl] gniew Jedynego Boga.,%o sentiu a ira do Deus Único.,,%o a simțit furia Zeului.,%o столкнул@[refl_rus] с гневом Единого Бога.,Играча %o је осетио бес Јединог бога. -%o couldn't escape from the Lore Master's grasp.,OB_LOREMASTER,,,,%o nemohl@[ao_cs] utéct Dějepiscově sevření.,%o konnte dem Griff des Wissensmeisters nicht entkommen.,,%o ne povis eskapi el la kapto de le Ĉeffoklorulo.,%o no pudo escapar del agarre 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 Maestro del Sapere. ,%o はロアマスターの手から逃れられなかった。,%o 은(는) 로어마스터의 촉수를 벗어나지 못했다.,%o kon niet ontsnappen aan de greep van de kennismeester.,%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 +%o couldn't escape from the Lore Master's grasp.,OB_LOREMASTER,,,,%o nemohl@[ao_cs] utéct Dějepiscově sevření.,%o konnte dem Griff des Wissensmeisters nicht entkommen.,,%o ne povis eskapi el la kapto de le Ĉeffoklorulo.,%o no pudo escapar del agarre 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 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 не смог@[irreg_2_rus] избежать длани Хранителя мудрости.,%o није успе@[ao_1_sr] побећи из Чувареве мудрости домашаја. %o was deleted by the Programmer.,OB_PROGRAMMER,,,,%o byl@[ao_cs] vymazán@[ao_cs] Programátorem.,%o wurde vom Programmierer gelöscht.,,%o eksiĝis de la Programisto.,%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 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 was blown away by the Bishop.,OB_STFBISHOP,,,,%o byl@[ao_cs] odpálen@[ao_cs] Biskupem.,%o wurde vom Bischof weggeblasen.,,%o forbloviĝis de la Episkopo.,%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 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 foi deletad@[ao_ptb] pelo Programador.,%o foi apagad@[ao_ptb] pelo Programador.,%o a fost șters de Programator.,Игрока %o удалил программист.,Играча %о је обрисао Програмер. +%o was blown away by the Bishop.,OB_STFBISHOP,,,,%o byl@[ao_cs] odpálen@[ao_cs] Biskupem.,%o wurde vom Bischof weggeblasen.,,%o forbloviĝis de la Episkopo.,%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 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 was shot down by a Sentinel.,OB_SENTINEL,,,,%o byl@[ao_cs] odstřelen@[ao_cs] strážným robotem.,%o wurde von dem Wächter niedergeschossen.,,%o pafegiĝis de Gardspektisto.,%o fue derribado 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 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 was swept away by a Crusader.,OB_CRUSADER,,,,%o byl@[ao_cs] odhozen@[ao_cs] křižákem.,%o wurde vom Ordensritter weggeblasen.,,%o rapide svingiĝis de Krucmilitisto.,%o fue barrid@[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 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] с ногу крсташ. @@ -1700,8 +1699,8 @@ Cunoștințelor.",%o не смог@[irreg_2_rus] избежать длани Х %k.",Игрок %o изрешечён штурмовой винтовкой %k.,%o је изрешетан@[adj_1_sr] од стране јуришне пушке играча %k. %o gulped down %k's missile.,OB_MPMINIMISSILELAUNCHER,,,,%o spolknul@[ao_cs] raketu hráče %k.,%o schluckte %ks Rakete herunter.,,%o glutis la misilon 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 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 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 wurde von %ks HE-Granate invertiert.,,%o estis inversigita de la P-E granato 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 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 инвертировался H-E гранатой %k.,%o се преокрену@[ao_1_sr] од стране Х-Е гранате играча %k. -%o took a flame bath in %k's phosphorous pyre.,OB_MPPHOSPHOROUSGRENADE,,,,%o si dal@[ao_cs] ohnivou koupel ve fosforovém požáru hráče %k.,%o nahm ein Flammenbad in %ks Scheiterhaufen.,,%o prenis flaman banon en la fosfora ŝtiparo de %k.,%o tomó un baño de llamas en la hoguera 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 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 was barbecued by %k.,OB_MPFLAMETHROWER,,,,%o byl@[ao_cs] osmažen@[ao_cs] hráčem %k.,%o wurde von %k gegrillt,,%o kradrostiĝis de %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 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 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 nahm ein Flammenbad in %ks Scheiterhaufen.,,%o prenis flaman banon en la fosfora ŝtiparo de %k.,%o tomó un baño de llamas en la hoguera 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 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 was barbecued by %k.,OB_MPFLAMETHROWER,,,,%o byl@[ao_cs] usmažen@[ao_cs] hráčem %k.,%o wurde von %k gegrillt,,%o kradrostiĝis de %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 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 was zapped by %k.,OB_MPMAULER1,,,,%o byl@[ao_cs] zničen@[ao_cs] hráčem %k.,%o wurde von %k geschockt.,,%o elektrokutiĝis de %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 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 was viciously vaporized by %k.,OB_MPMAULER,,,,%o byl@[ao_cs] rozpuštěn@[ao_cs] hráčem %k.,%o wurde von %k vaporisiert.,,%o estis brutale vaporigita de %k.,%o fue viciosamente 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 rozpłyn@[irreg_2_pl] się przez %k.,%o foi vaporizado por %k.,,%o a fost evaporat în mod vicios de %k.,Игрок %k безжалостно распылил игрока %o.,%o је брутално испари@[ao_1_sr] од стране играча %k. %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 kapitulierte vor der Macht von %ks Sigil.,,%o kliniĝis antaŭ la plena potenco de la Sigelo 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 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 @@ -1718,54 +1717,54 @@ You've blown up the Computer,TXT_QUEST_27,,,,Odpálil@[ao_cs] jsi počítač,Du You killed the Bishop!,TXT_KILLED_BISHOP,,,,Zabil@[ao_cs] jsi Biskupa!,Du hast den Bischof getötet.,,Vi mortigis la Episkopon!,¡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!,Zabił@[irreg_3_pl] Biskupa!,Você matou o Bispo!,Mataste o Bispo!,Ai omorât Episcopul!,Епископ убит!,Епископ је мртав! You've killed the Oracle!,TXT_KILLED_ORACLE,,,,Zabil@[ao_cs] jsi Věštce!,Du hast das Orakel getötet,,Vi mortigis la Orakolon!,¡Has matado 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!,Zabił@[irreg_3_pl] Wyrocznię!,Você matou o Oráculo!,Mataste o Oráculo,Ai omorât Oracolul!,Оракул убит!,Пророк је мртав! You killed Macil!,TXT_KILLED_MACIL,,,,Zabil@[ao_cs] jsi Macila!,Du hast Macil getötet.,,Vi mortigis Macil!,¡Mataste a Macil!,¡Has matado a Macil!,Tapoit Macilin!,Vous avez tué Macil!,Megölted Macilt!,Hai ucciso Macil!,マシルを討ち取った!,마실을 처단했다!,Je hebt Macil vermoord!,Zabił@[irreg_3_pl] Macila!,Você matou o Macil!,Mataste Macil!,L-ai omorât pe Macil!,Мэйсил убит!,Мејсил је мртав! -You've killed the Loremaster!,TXT_KILLED_LOREMASTER,,,,Zabil@[ao_cs] jsi Dějepisce!,Du hast den Wissensmeister getötet!,,Vi mortigis la Scimajstro!,¡Has matado al Maestro del Conocimiento!,,Olet tappanut Oppi-Isän!,Vous avez tué le Maitre des traditions!,Megölted a Tudóst!,Hai ucciso il Maestro del Sapere!,ロアマスターを吊り上げた!,로어마스터의 목숨에 종지부를 찍었다!,Je hebt de Kennismeester vermoord!,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!,Хранитель мудрости убит!,Чувара мудрости је мртав! +You've killed the Loremaster!,TXT_KILLED_LOREMASTER,,,,Zabil@[ao_cs] jsi Dějepisce!,Du hast den Wissensmeister getötet!,,Vi mortigis la Scimajstro!,¡Has matado 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!,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!,Хранитель мудрости убит!,Чувара мудрости је мртав! You fool! You've set off the alarm.,TXT_YOUFOOL,,,,Blázne! Spustil@[ao_cs] jsi alarm!,Du Trottel! Du hast den Alarm ausgelöst.,,Vi stultulo! Vi ekigis la alarmon.,¡Insensat@[ao_esp]! Has activado la alarma.,¡Tont@[ao_esp]! Has activado 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.,Głupcze! Włączył@[irreg_3_pl] alarm!,Seu idiota! Você ativou o alarme.,Idiota! Ativaste o alarme.,Nesăbuitule! Ai declanșat alarma!,Глупец. Ты включил сигнализацию!,Будало! Активирао си аларм. You're dead! You set off the alarm.,TXT_YOUREDEAD,,,,Jsi mrtv@[adj_cs]! Spustil@[ao_cs] jsi alarm!,Du bist tot. Du hast den Alarm ausgelöst.,,Vi estas morta! Vi ekigis la alarmon.,¡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.,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!,Ты поднял тревогу! Готовься к смерти!,Активирао си аларм. Спреми се да умреш! -You seem to have enough!,TXT_HAVEENOUGH,,,,Ty už toho máš dostatek!,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!,Sembra ne hai avuto abbastanza!,十分に持ち合わせている!,충분히 가진 것 같은데?,Je lijkt genoeg te hebben!,"Wydaje się, że już ci wystarczy!",Você parece ter o suficiente!,Pareces ter o suficiente!,Pare că ai destule!,"Кажется, тебе хватит!",Изгледа да ти је доста! +You seem to have enough!,TXT_HAVEENOUGH,,,,Ty už máš přece dost!,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!,"Wydaje się, że już ci wystarczy!",Você parece ter o suficiente!,Pareces ter o suficiente!,Pare că ai destule!,"Кажется, тебе хватит!",Изгледа да ти је доста! Go away!,TXT_GOAWAY,,,,Jdi pryč!,Verschwinde!,,Foriru!,¡Lárgate!,,Häivy!,Allez-vous en!,Takarodj!,Vattene via!,逃げ出せ!,저리 가!,Ga weg!,Idź stąd!,Vá embora!,Vai-te embora!,Pleacă!,Уходи!,Одлази! -Incoming Message...,TXT_COMM0,,,,Příchozí zpráva...,Nachricht erhalten...,,Alvenanta Mesaĝo...,Mensaje entrante...,,Vastaantuleva viesti...,Message reçu.,Bejövő Üzenet,Messaggio in arrivo...,メッセージが届いた...,메시지가 옴...,Inkomend bericht....,Nadchodzi wiadomość...,Recebendo Mensagem...,A Receber Mensagem...,Mesaj în intrare...,Входящее сообщение...,Наилази порука... -Incoming Message from BlackBird...,TXT_COMM1,,,,Příchozí zpráva od Straky...,Nachricht von Blackbird erhalten...,,Alvenanta 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....,Nadchodzi wiadomość od BlackBird...,Recebendo Mensagem de BlackBird...,A Receber Mensagem de BlackBird...,Mesaj în intrare de la BlackBird...,Входящее сообщение от Чёрного дрозда...,Наилази порука од Црне птице.... +Incoming Message...,TXT_COMM0,,,,Příchozí zpráva...,Nachricht erhalten...,,Alvenanta Mesaĝo...,Mensaje entrante...,,Vastaantuleva viesti...,Message reçu.,Bejövő Üzenet...,Messaggio in arrivo...,メッセージが届いた...,메시지가 옴...,Inkomend bericht....,Nadchodzi wiadomość...,Recebendo Mensagem...,A Receber Mensagem...,Mesaj în intrare...,Входящее сообщение...,Наилази порука... +Incoming Message from BlackBird...,TXT_COMM1,,,,Příchozí zpráva od Straky...,Nachricht von Blackbird erhalten...,,Alvenanta 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....,Nadchodzi wiadomość od BlackBird...,Recebendo Mensagem de BlackBird...,A Receber Mensagem de BlackBird...,Mesaj în intrare de la BlackBird...,Входящее сообщение от Чёрного дрозда...,Наилази порука од Црне птице.... Find help,TXT_FINDHELP,,,,Najdi pomoc.,Finde Hilfe,,Trovu helpon,Busca ayuda,,Etsi apua,Trouvez de L'aide,Keress segítséget,Trova aiuto,助けを探せ,도움말,Zoek hulp,Znajdź pomoc,Procure ajuda,Procura ajuda,Găsește ajutor,Найди помощь,Нађи помоћ -for %u,TXT_TRADE,As in for %u amount of money.,,,za %u zlatých,für %u,,por %u,por %u,,hintaan %u,pour %u,%u,per %u,%u ゴールド,(가격: %u),voor %u,za %u,por %u,,pentru %u,за %u,за %u +for %u,TXT_TRADE,As in for %u amount of money.,,,za %u zlatých,für %u,,por %u,por %u,,hintaan %u,pour %u,%u számára,per %u,%u ゴールド,(가격: %u),voor %u,za %u,por %u,,pentru %u,за %u,за %u ,,Chex Quest,,,,,,,,,,,,,,,,,,,,, ,,Pickups,,,,,,,,,,,,,,,,,,,,, -Picked up the Chex(R) Armor.,GOTCHEXARMOR,,,Picked up the Chex(R) Armour.,Sebráno Chex(R) brnění.,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.,Zebrano Pancerz Chex(R).,Pegou uma Armadura Chex(R).,Apanhaste uma Armadura Chex(R).,Ai ridicat Armura Chex(R).,Получена Chex(R)-броня.,Покупио си Чех оклоп. -Picked up the Super Chex(R) Armor!,GOTSUPERCHEXARMOR,,,Picked up the Super Chex(R) Armour!,Sebráno Super Chex(R) brnění!,Du hast die Superchex(R)Rüstung genommen!,,Prenis la superan Chex(R)-kirason!,¡Recogiste la armadura Súper 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!,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)-сверхброня!,Покупио си Супер Чех оклоп. +Picked up the Chex(R) Armor.,GOTCHEXARMOR,,,Picked up the Chex(R) Armour.,Sebráno Chex(R) brnění.,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.,Zebrano Pancerz Chex(R).,Pegou uma Armadura Chex(R).,Apanhaste uma Armadura Chex(R).,Ai ridicat Armura Chex(R).,Получена Chex(R)-броня.,Покупио си Чех оклоп. +Picked up the Super Chex(R) Armor!,GOTSUPERCHEXARMOR,,,Picked up the Super Chex(R) Armour!,Sebráno Super Chex(R) brnění!,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!,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)-сверхброня!,Покупио си Супер Чех оклоп. Picked up a glass of water.,GOTWATER,,,,Sebrána sklenice vody.,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.,Zebrano szklankę wody.,Pegou um copo d'água.,Apanhaste um copo de água.,Ai ridicat un pahar cu apă.,Получен стакан воды.,Покупио си чашу воде Picked up slime repellent.,GOTREPELLENT,,,,Sebrán repelent proti slizu.,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.,Zebrano odstraszacz szlamu.,Pegou repelente de gosma.,Apanhaste repelente de gosma.,Ai ridicat respingătorul de mâzga.,Получен репеллент против слизи.,Покупио си одбијаш љигавца. -Supercharge Breakfast!,GOTBREAKFAST,,,,Supervýživná snídaně!,Überladenes Frühstück!,,Ŝargega Matenmanĝon!,¡Desayuno supercargado!,,Superaamiaislatinki!,Petit-déjeuner superchargé!,Szupertöltött Reggeli!,Colazione da supercarica!,ちょうしょく スーパーチャージ!,힘찬 아침식사 섭취!,Overbelast ontbijt!,Supernaładowane Śniadanie!,Super Café da Manhã!,Super Pequeno-Almoço!,Superîncărcătură Mic Dejun!,Супер-завтрак!,Супер-напуњен доручак. +Supercharge Breakfast!,GOTBREAKFAST,,,,Supervýživná snídaně!,Überladenes Frühstück!,,Ŝargega Matenmanĝon!,¡Desayuno supercargado!,,Superaamiaislatinki!,Petit-déjeuner superchargé!,Szupertöltött Reggeli!,Colazione da supercarica!,ちょうしょく スーパーチャージ!,힘찬 아침식사 섭취!,Overbelast ontbijt!,Supernaładowane Śniadanie!,Super Café da Manhã!,Super Pequeno-Almoço!,Superîncărcătură Mic Dejun!,Суперзавтрак!,Супер-напуњен доручак. Picked up a blue key.,GOTCBLUEKEY,,,,Sebrán modrý klíč.,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.,Zebrano niebieski klucz.,Pegou a chave azul.,Apanhaste a chave azul.,Ai ridicat o cheie albastră.,Получен синий ключ.,Покупио си плави кључ. Picked up a yellow key.,GOTCYELLOWKEY,,,,Sebrán žlutý klíč.,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.,Zebrano żółty klucz.,Pegou a chave amarela.,Apanhaste a chave amarela.,Ai ridicat o cheie galbenă.,Получен жёлтый ключ.,Покупио си жути кључ. Picked up a red key.,GOTCREDKEY,,,,Sebrán červený klíč.,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.,Zebrano czerwony klucz.,Pegou a chave vermelha.,Apanhaste a chave vermelha.,Ai ridicat o cheie roșie.,Получен красный ключ.,Покупио си црвени кључ. -Picked up a bowl of fruit.,GOTFRUIT,,,,Sebrána mísa s ovocem.,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.,Zebrano miskę owoców.,Pegou uma tigela de frutas.,Apanhaste uma taça com fruta.,Ai ridicat un bol de fructe.,Полуена тарелка с фруктами.,Покупио си чинију воћа. -Vegetables are REALLY good for you!,GOTVEGETABLESNEED,,,,Zelenina je VELMI zdravá!,Gemüse ist RICHTIG gut für dich!,,Legomoj estas TRE bonaj por vi!,¡Los vegetales son REALMENTE buenos 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!,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!,Овощи ОЧЕНЬ полезны для здоровья!,Поврће је ЈАКО добро за тебе! -Picked up a bowl of vegetables.,GOTVEGETABLES,,,,Sebrána mísa se zeleninou.,Du hast eine Gemüseschale genommen.,,Prenis bovlon de legomoj.,Recogiste un tazón de vegetales.,,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.,Zebrano miskę warzyw.,Pegou uma tigela de vegetais.,Apanhaste uma tigela com vegetais.,Ai ridicat un bol de legume.,Получена тарелка с овощами.,Покупио си чинију поврћа. +Picked up a bowl of fruit.,GOTFRUIT,,,,Sebrána mísa s ovocem.,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.,Zebrano miskę owoców.,Pegou uma tigela de frutas.,Apanhaste uma taça com fruta.,Ai ridicat un bol de fructe.,Получена тарелка с фруктами.,Покупио си чинију воћа. +Vegetables are REALLY good for you!,GOTVEGETABLESNEED,,,,Zelenina je VELMI zdravá!,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!,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!,Овощи ОЧЕНЬ полезны для здоровья!,Поврће је ЈАКО добро за тебе! +Picked up a bowl of vegetables.,GOTVEGETABLES,,,,Sebrána mísa se zeleninou.,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.,Zebrano miskę warzyw.,Pegou uma tigela de vegetais.,Apanhaste uma tigela com vegetais.,Ai ridicat un bol de legume.,Получена тарелка с овощами.,Покупио си чинију поврћа. Found a Slime-Proof Suit,GOTSLIMESUIT,,,,Nalezen slizu odolný oblek.,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.,Znaleziono Szlamoodporny Kombinezon,Achou um Traje Anti-Gosma,Apanhaste um Fato Anti-Gosma.,Ai ridicat un Costum Rezistent la Mâzgă,Получен противослизневый костюм,Нашо си љигаво-отпорано одело. Found a Computer Area Map,GOTCHEXMAP,,,,Nalezena počítačová mapa oblasti.,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.,Znaleziono Komputerową Mapę Obszaru,Achou um Mapa Computadorizado,Apanhaste um Mapa Digital.,Ai ridicat o Hartă Generată pe Calculator a Zonei.,Получена компьютерная карта местности,Нашао компјутерку мапу окружења -Picked up a mini zorch recharge.,GOTZORCHRECHARGE,,,,Sebrán minibzukový náboj.,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.,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.,Получена зарядка для Мини-Зорчера.,Покупио си мини зорч пуњач. -Picked up a mini zorch pack.,GOTMINIZORCHPACK,,,,Sebrán minibzukový balík.,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.,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.,Получена батарея для Мини-Зорчера.,Покупио си мини зорч пакет. -Picked up a zorch propulsor recharge.,GOTPROPULSORRECHARGE,,,,Sebrán náboj pro bzukový propulzor.,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.,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.,Получена зарядка для Ускорителя Зорча.,Покупио си зорч погонски пуњач. -Picked up a zorch propulsor pack.,GOTPROPULSORPACK,,,,Sebrán balík pro bzukový propulzor.,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.,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.,Получена батарея для Ускорителя Зорча.,Покупио си зорч погонски пакет. -Picked up a phasing zorcher recharge,GOTPHASINGZORCHERRECHARGE,,,,Sebrán náboj pro fázovací bzukr.,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.,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,Получена зарядка для Фазерного Зорчера.,Покупио си фазни зорчер пуњач. +Picked up a mini zorch recharge.,GOTZORCHRECHARGE,,,,Sebrán minibzukový náboj.,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.,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.,Получена зарядка для мини-Зорчера.,Покупио си мини зорч пуњач. +Picked up a mini zorch pack.,GOTMINIZORCHPACK,,,,Sebrán minibzukový balík.,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.,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.,Получена батарея для мини-Зорчера.,Покупио си мини зорч пакет. +Picked up a zorch propulsor recharge.,GOTPROPULSORRECHARGE,,,,Sebrán náboj pro bzukový propulzor.,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.,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.,Получена зарядка для ускорителя Зорча.,Покупио си зорч погонски пуњач. +Picked up a zorch propulsor pack.,GOTPROPULSORPACK,,,,Sebrán balík pro bzukový propulzor.,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.,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.,Получена батарея для ускорителя Зорча.,Покупио си зорч погонски пакет. +Picked up a phasing zorcher recharge,GOTPHASINGZORCHERRECHARGE,,,,Sebrán náboj pro fázovací bzukr.,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.,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,Получена зарядка для фазерного Зорчера.,Покупио си фазни зорчер пуњач. Picked up a phasing zorcher pack.,GOTPHASINGZORCHERPACK,,,,Sebrán balík pro fázovací bzukr.,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.,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.",Получена батарея для Фазерного Зорчера.,Покупио си фазни зорчер пакет. -Picked up a large zorcher recharge.,GOTLARGEZORCHERRECHARGE,,,,Sebrán náboj pro velký bzukr.,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.,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.,Получена зарядка для Большого Зорчера.,Покупио си велики зорчер пуњач. -Picked up a large zorcher pack.,GOTLARGEZORCHERPACK,,,,Sebrán balík pro velký bzukr.,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.,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.,Получена батарея для Большого Зорчера.,Покупио си велики зорчер пакет. +zorcher.",Получена батарея для фазерного Зорчера.,Покупио си фазни зорчер пакет. +Picked up a large zorcher recharge.,GOTLARGEZORCHERRECHARGE,,,,Sebrán náboj pro velký bzukr.,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.,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.,Получена зарядка для большого Зорчера.,Покупио си велики зорчер пуњач. +Picked up a large zorcher pack.,GOTLARGEZORCHERPACK,,,,Sebrán balík pro velký bzukr.,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.,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.,Получена батарея для большого Зорчера.,Покупио си велики зорчер пакет. Picked up a Zorchpak!,GOTZORCHPACK,,,,Sebrán Bzukrbatoh!,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.,Zebrano Paczkę Zorch.,Pegou um Zorchpak!,Apanhaste um Zorchpak!,Ai ridicat un Ghiozdan Zorch!,Получен Зорч-рюкзак!,Покупио си зорчпак. -You got the LAZ Device! Woot!,GOTLAZDEVICE,,,,Získal@[ao_cs] jsi velkodosahový bzukr! Cooo?,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!,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!,Получено Устройство Зорчирования Большого Радиуса! Ура!,Добио си ЛАЗ уређај. ВУТ! -You got the Rapid Zorcher!,GOTRAPIDZORCHER,,,,Získal@[ao_cs] jsi rychlobzukr!,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!,Zdobył@[irreg_3_pl] Szybkostrzelny Zorcher!,Você pegou o Zorcher Automático!,Apanhaste o Zorcher Automático!,Ai ridicat un Zorcher cu Foc Rapid!,Получен Скорострельный Зорчер!,Добио си рапидан зорчер! -You got the Super Bootspork!,GOTSUPERBOOTSPORK,,,,Získal@[ao_cs] jsi super botovidličku!,Du hast den Super-Gabelquirl genommen!,,Vi prenis la Superan Ŝargmanĝilaron!,¡Tienes el Súper cubierto!,,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!,Zdobył@[irreg_3_pl] Super Łyżkowidelec!,Você pegou o Super Garfo!,Apanhaste o Super Garfo-Colher!,Ai ridicat o Super Lingură!,Получена Супер Ложковилка!,Добио си супер чизмо-порк! -You got the Zorch Propulsor!,GOTZORCHPROPULSOR,,,,Získal@[ao_cs] jsi bzukový propulsor!,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!,Zdobył@[irreg_3_pl] Pędnik Zorch!,Você pegou o Propulsor de Zorch!,Apanhaste o Propulsor de Zorch!,Ai ridicat un Accelerator Zorch!,Получен Ускоритель Зорча!,Добио си зорч погон! -You got the Phasing Zorcher!,GOTPHASINGZORCHER,,,,Získal@[ao_cs] jsi fázovací bzukr!,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!,Zdobył@[irreg_3_pl] Fazowy Zorcher!,Você pegou o Zorcher Fásico!,Apanhaste o Zorcher Fásico!,Ai ridicat un Zorcher Fazat!,Получен Фазерный Зорчер!,Добио си фазни зорчер! -You got the Large Zorcher!,GOTLARGEZORCHER,,,,Získal@[ao_cs] jsi velký bzukr!,Du hast den großen Zorcher genommen!,,Vi prenis la Grandzorĉilon,¡Tienes el Zorcher largo!,,Sait ison zorcherin!,Vous avez pris le Zorcheur Large!,Felvetted a Nagy Zorkert!,Hai trovato il zorcher grande!,おおがたゾーチャー をてにいれた!,대형 자쳐 습득!,Je hebt de grote Zorcher!,Zdobył@[irreg_3_pl] Duży Zorcher!,Você pegou o Zorcher Grande!,Apanhaste o Zorcher Grande!,Ai ridicat un Zorcher Mare!,Получен Большой Зорчер!,Добио си велики зорчер! -You got the Mega Zorcher!,GOTSUPERLARGEZORCHER,,,,Získal@[ao_cs] jsi megabzukr!,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!,Zdobył@[irreg_3_pl] Mega Zorcher!,Você pegou o Mega Zorcher!,Apanhaste o Mega Zorcher!,Ai ridicat un Mega Zorcher!,Получен Мега-Зорчер!,Добио си мега зорчер! -Picked up a Mini Zorcher.,GOTMINIZORCHER,,,,Sebrán minibzukr.,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.,Zebrano Mini Zorcher.,Você pegou um Mini Zorcher.,Apanhaste um Mini Zorcher.,Ai ridicat un Mini Zorcher.,Получен Мини-Зорчер.,Покупио си мини зорчер! +You got the LAZ Device! Woot!,GOTLAZDEVICE,,,,Získal@[ao_cs] jsi velkodosahový bzukr! Cooo?,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!,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!,Получено устройство Зорчирования большого радиуса! Ура!,Добио си ЛАЗ уређај. ВУТ! +You got the Rapid Zorcher!,GOTRAPIDZORCHER,,,,Získal@[ao_cs] jsi rychlobzukr!,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!,Zdobył@[irreg_3_pl] Szybkostrzelny Zorcher!,Você pegou o Zorcher Automático!,Apanhaste o Zorcher Automático!,Ai ridicat un Zorcher cu Foc Rapid!,Получен скорострельный Зорчер!,Добио си рапидан зорчер! +You got the Super Bootspork!,GOTSUPERBOOTSPORK,,,,Získal@[ao_cs] jsi super botovidličku!,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!,Zdobył@[irreg_3_pl] Super Łyżkowidelec!,Você pegou o Super Garfo!,Apanhaste o Super Garfo-Colher!,Ai ridicat o Super Lingură!,Получена суперложковилка!,Добио си супер чизмо-порк! +You got the Zorch Propulsor!,GOTZORCHPROPULSOR,,,,Získal@[ao_cs] jsi bzukový propulsor!,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!,Zdobył@[irreg_3_pl] Pędnik Zorch!,Você pegou o Propulsor de Zorch!,Apanhaste o Propulsor de Zorch!,Ai ridicat un Accelerator Zorch!,Получен ускоритель Зорча!,Добио си зорч погон! +You got the Phasing Zorcher!,GOTPHASINGZORCHER,,,,Získal@[ao_cs] jsi fázovací bzukr!,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!,Zdobył@[irreg_3_pl] Fazowy Zorcher!,Você pegou o Zorcher Fásico!,Apanhaste o Zorcher Fásico!,Ai ridicat un Zorcher Fazat!,Получен фазерный Зорчер!,Добио си фазни зорчер! +You got the Large Zorcher!,GOTLARGEZORCHER,,,,Získal@[ao_cs] jsi velký bzukr!,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!,Zdobył@[irreg_3_pl] Duży Zorcher!,Você pegou o Zorcher Grande!,Apanhaste o Zorcher Grande!,Ai ridicat un Zorcher Mare!,Получен большой Зорчер!,Добио си велики зорчер! +You got the Mega Zorcher!,GOTSUPERLARGEZORCHER,,,,Získal@[ao_cs] jsi megabzukr!,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!,Zdobył@[irreg_3_pl] Mega Zorcher!,Você pegou o Mega Zorcher!,Apanhaste o Mega Zorcher!,Ai ridicat un Mega Zorcher!,Получен Мегазорчер!,Добио си мега зорчер! +Picked up a Mini Zorcher.,GOTMINIZORCHER,,,,Sebrán minibzukr.,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.,Zebrano Mini Zorcher.,Você pegou um Mini Zorcher.,Apanhaste um Mini Zorcher.,Ai ridicat un Mini Zorcher.,Получен мини-Зорчер.,Покупио си мини зорчер! ,,Actor tags,,,,,,,,,,,,,,,,,,,,, Spoon,TAG_SPOON,,,,Lžíce,Löffel,,Kulero,Cuchara,,Lusikka,Cuillère à Botte,Kanál,Cucchiaio ,スプーン,숟가락,Lepel,Łyżka,Colher,,Lingură,Ложка,Кашика -Super Bootspork,TAG_SPORK,,,,Super botodlička,Supergabel,,Ega Ŝargmanĝilaro,Súper Cubierto,,Superluha,Super Fourchette,Szuper Rotációs Villa,Super Forcucchiaio,スーパーさきわれスプーン,부트스포크,,Super Łyżkowidelec,Super Garfo,Super Garfo-Colher,Super Lingură,Супер Ложковилка,Супер виљушка +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ă,Суперложковилка,Супер виљушка Mini Zorcher,TAG_MINIZORCHER,,,,Minibzukr,Minizorcher,,Zorĉileto,Mini Zorcher,,Minizorcheri,Mini Zorcheur,Mini Zorker,Mini Zorcher,こがたゾーチャー,소형 자쳐,Minizorcher,Mini Zorcher,Mini Zorcher,,Mini Zorcher,Мини-Зорчер,Мини зорчер -Large Zorcher,TAG_LARGEZORCHER,,,,Velký bzukr,Großer Zorcher,,Granda Zorĉilo,Zorcher largo,,Iso zorcheri,Zorcheur Large,Nagy Zorker,Grosso Zorcher ,おおがたゾーチャー,대형 자쳐,Grote Zorcher,Duży Zorcher,Zorcher Grande,,Zorcher Mare,Большой Зорчер,Велики зорчер -Super-Large Zorcher,TAG_SUPERLARGEZORCHER,,,,Supervelký bzukr,Riesenzorcher,,Grandega Zorĉilo,Zorcher Súper Largo,,Superiso zorcheri,Zorcheur Extra-large,Hatalmas Zorker,Zorcher Enorme ,ちょうおおがたゾーチャー,초대형 자쳐,Super grote Zorcher,Większy Zorcher,Super Zorcher Grande,,Zorcher Super-Mare,Мега-Зорчер,Супер-велики зорчер +Large Zorcher,TAG_LARGEZORCHER,,,,Velký bzukr,Großer Zorcher,,Granda Zorĉilo,Zorcher Grande,,Iso zorcheri,Zorcheur Large,Nagy Zorker,Grosso Zorcher ,おおがたゾーチャー,대형 자쳐,Grote Zorcher,Duży Zorcher,Zorcher Grande,,Zorcher Mare,Большой Зорчер,Велики зорчер +Super-Large Zorcher,TAG_SUPERLARGEZORCHER,,,,Supervelký bzukr,Riesenzorcher,,Grandega Zorĉilo,Zorcher Súper Grande,,Superiso zorcheri,Zorcheur Extra-large,Hatalmas Zorker,Zorcher Enorme ,ちょうおおがたゾーチャー,초대형 자쳐,Super grote Zorcher,Większy Zorcher,Super Zorcher Grande,,Zorcher Super-Mare,Мега-Зорчер,Супер-велики зорчер 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,Быстрый Зорчер,Рапидни зорчер 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,Фазерный Зорчер,Фазни зорчер @@ -1780,11 +1779,11 @@ armură.",Игрока %o обслюнявила бронированная дв %o was spoon fed by %k.,OB_MPSPOON,,,,%o byl@[ao_cs] nakrmen@[ao_cs] lžičkou hráče %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 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 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 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 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 was zorched by %k.,OB_MPZORCH,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] hráčem %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 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 was hit by %k's mega-zorcher.,OB_MPMEGAZORCH,,,,%o byl@[ao_cs] trefen@[ao_cs] megabzukrem hráče %k.,%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 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 was rapid zorched by %k.,OB_MPRAPIDZORCH,,,,%o dostal@[ao_cs] rychlobzukrem hráče %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 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 was zorched by %k's propulsor.,OB_MPPROPULSOR,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] propulzorem hráče %k.,%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 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 was hit by %k's propulsor.,OB_MPP_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráčem %k.,%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 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 was phase zorched by %k.,OB_MPPHASEZORCH,,,,%o byl@[ao_cs] bzukr-vyfázován@[ao_cs] hráčem %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 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 was hit by %k's mega-zorcher.,OB_MPMEGAZORCH,,,,%o byl@[ao_cs] trefen@[ao_cs] megabzukrem hráče %k.,%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 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 was rapid zorched by %k.,OB_MPRAPIDZORCH,,,,%o dostal@[ao_cs] rychlobzukrem hráče %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 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 was zorched by %k's propulsor.,OB_MPPROPULSOR,,,,%o byl@[ao_cs] bzukrnut@[ao_cs] propulzorem hráče %k.,%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 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 was hit by %k's propulsor.,OB_MPP_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráčem %k.,%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 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 was phase zorched by %k.,OB_MPPHASEZORCH,,,,%o byl@[ao_cs] bzukr-vyfázován@[ao_cs] hráčem %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 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 fell prey to %k's LAZ device.,OB_MPLAZ_BOOM,,,,%o padl@[ao_cs] velkodosahovému bzukru hráče %k.,%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 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 was lazzed by %k.,OB_MPLAZ_SPLASH,,,,%o byl@[ao_cs] odbzukrován hráčem %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 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. ,,Miscellaneous,,,,,,,,,,,,,,,,,,,,, @@ -1792,7 +1791,7 @@ E1M1: Landing Zone,CHUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landezone,,E1M E1M2: Storage Facility,CHUSTR_E1M2,,,,E1M2: Skladiště,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: Magazyn,E1M2: Depósito,E1M2: Armazém,E1M2: Depozitul,E1M2: Хранилище,Е1М2: Складиште E1M3: Experimental Lab,CHUSTR_E1M3,,,,E1M3: Testovací laboratoř,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: Laboratorium Eksperymentalne,E1M3: Laboratório de Experimentos,E1M3: Laboratório Experimental,E1M2: Laboratorul,E1M3: Лаборатория,Е1М3: Експериментална лабораторија E1M4: Arboretum,CHUSTR_E1M4,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,E1M4: L'Arboretum,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもくえん,E1M4: 수목원,E1M4: Arboretum,E1M4: Arboretum,E1M4: Arvoredo,,E1M4: Arboretum,E1M4: Дендрарий,Е1М4: Ботаничка башта -E1M5: Caverns of Bazoik,CHUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,E1M5: Die Höhlen von Bazoik,,E1M5: Kavernoj de Bazojk,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: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Каверны Базоика,Е1М5: Пећине Базоика +E1M5: Caverns of Bazoik,CHUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,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: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Каверны Базоика,Е1М5: Пећине Базоика "Mission accomplished. Are you prepared for the next mission? @@ -1960,7 +1959,7 @@ Stiskni libovolnou klávesu.","Du kannst während eines Netzwerkspiels keinen Sp Drücke eine Taste",,"Vi ne povas ŝargi dum ret-serĉo! -Premu klavon.","¡No puedes cargar mientras estés en una aventura en línea! +Premu klavon.","¡No puedes cargar mientras estés en una aventura online! Presiona una tecla.",,"Et voi ladata verkkopelin aikana! @@ -1969,7 +1968,7 @@ vous êtes en ligne! Appuyez sur une touche.","Nem tudsz mentést betölteni netes küldetés közben! -Nyomj meg egy gombot.","Non puoi caricare una partita durante una net quest! +Nyomj meg egy gombot.","Non puoi caricare una partita durante una netquest! Premi un tasto.","オンラインモードでは セーブデータをロードできません @@ -1987,7 +1986,7 @@ Aperte alguma tecla.","Não é possível carregar durante uma aventura em rede! Carrega numa tecla qualquer.","Nu poți face o încărcare în timpul unei căutări online! -Apasă orice tastă.","Невозможно загрузить сохранение в сетевом квесте! +Apasă orice tastă.","Невозможно загрузить сохранение в сетевом задании! Нажмите любую клавишу.","Не можете учитати док сте у мрежној потрази! @@ -2050,7 +2049,7 @@ Carrega Y ou N.","Salvare rapidă peste căutarea numită '%s'? -Apasă Y sau N.","Выполнить быстрое сохранение квеста +Apasă Y sau N.","Выполнить быстрое сохранение задания «%s»? @@ -2063,7 +2062,7 @@ Stiskni libovolnou klávesu.","Du kannst während eines Netzwerkspiels nicht sch Drücke eine Taste",,"Vi ne povas rapidŝargi dum ret-serĉo! -Premu klavon.","¡No puedes cargar una partida guardada durante una aventura en línea! +Premu klavon.","¡No puedes cargar una partida guardada durante una aventura online! Presiona una tecla.",,"Et voi pikaladata verkkopelin aikana! @@ -2092,7 +2091,7 @@ Aperte alguma tecla.","Não é possível carregar durante uma aventura em rede! Carrega numa tecla qualquer.","Nu poți faci o încărcare rapidă în timpul unei căutări online! -Apasă orice tastă.","Невозможно загрузить быстрое сохранение в сетевом квесте! +Apasă orice tastă.","Невозможно загрузить быстрое сохранение в сетевом задании! Нажмите любую клавишу.","Не можете брзо-учитати док сте у мрежној потрази! @@ -2155,7 +2154,7 @@ Carrega Y ou N.","Vrei să faci o încărcare rapidă a misiunii '%s'? -Apasă Y sau N.","Загрузить быстрое сохранение квеста +Apasă Y sau N.","Загрузить быстрое сохранение задания «%s»? @@ -2171,7 +2170,7 @@ Stiskni libovolnou klávesu.","Du kannst während eines Netzwerkspiels kein neue Drücke eine Taste",,"Vi ne povas komencigi novan serĉon dum ret-serĉon. -Premu klavon.","No puedes iniciar una nueva aventura mientras estés en una aventura en línea. +Premu klavon.","No puedes iniciar una nueva aventura mientras estés en una aventura online. Presiona una tecla.",,"Et voi aloittaa uutta peliä verkkopelin aikana. @@ -2201,8 +2200,7 @@ Aperte alguma tecla.","Não é possível iniciar uma nova aventura durante uma a Carrega numa tecla qualquer.","Nu poți începe o căutare nouă în timpul unei căutări în rețea! -Apasă orice tastă.","Невозможно начать новый квест -при сетевом квесте! +Apasă orice tastă.","Невозможно начать новое задание при сетевом задании! Нажмите любую клавишу.","Не можете почети нову потрагу док сте у мрежној потрази. @@ -2340,7 +2338,7 @@ Stiskni libovolnou klávesu","Du kannst ein Netzwerkspiel nicht beenden. Drücke eine Taste.",,"Vi ne povas fini ret-serĉon! -Premu klavon.","¡No puedes terminar una aventura en línea! +Premu klavon.","¡No puedes terminar una aventura online! Presiona una tecla.",,"Et voi päättää verkkopeliä! @@ -2366,7 +2364,7 @@ Aperte alguma tecla.","Não podes terminar uma aventura em rede! Carrega numa tecla qualquer.","Nu poți încheia brusc o căutare în rețea! -Apasă orice tastă.","Невозможно прервать сетевой квест! +Apasă orice tastă.","Невозможно прервать сетевое задание! Нажмите любую клавишу.","Не можете завршити мрежну потрагу! @@ -2404,7 +2402,7 @@ Aperte Y ou N.","Tens a certeza que queres terminar esta aventura? Carrega Y ou N.","Ești sigur că vrei să încetezi căutarea? -Apasă Y sau N.","Вы точно хотите завершить квест? +Apasă Y sau N.","Вы точно хотите завершить задание? Нажмите Y или N.","Да ли си сигуран да желиш да завршиш трагање? @@ -2412,31 +2410,31 @@ Apasă Y sau N.","Вы точно хотите завершить квест? Invincible Mode ON,STSTR_DQDON,,chex,,Režim nezranitelnosti ZAP,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,Tryb Niewrażliwości WŁĄCZONY,Modo invencível ATIVADO,,Modul Invincibil ACTIVAT,Режим неуязвимости включён,Неуништив УКЉУЧЕН Invincible Mode OFF,STSTR_DQDOFF,,chex,,Režim nezranitelnosti VYP,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,Tryb Niewrażliwości WYŁĄCZONY,Modo invencível DESATIVADO,,Modul Invincibil DEZACTIVAT,Режим неуязвимости выключен,Неуништив ИСКЉУЧЕН Zorch Added,STSTR_FAADDED,,chex,,Bzukry přidány,Zorch hinzugefügt,,Zorĉo Aldonita,Zorch añadido,,Zorch lisätty,Zorch Ajouté,Szörcs felvéve,Zorch aggiunto,ゾーチ ついか,모든 저치 에너지 추가,Zorch toegevoegd,Zorch dodany,Zorch adicionado,,Zorcher Adăugat,Добавлен Зорч,Зорч додат -Super Zorch Added,STSTR_KFAADDED,,chex,,Superbzukry přidány,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 dodany,Super Zorch adicionado,,Super Lingură Adăugată,Добавлен Супер Зорч,Супер зорч додат +Super Zorch Added,STSTR_KFAADDED,,chex,,Superbzukry přidány,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 dodany,Super Zorch adicionado,,Super Lingură Adăugată,Добавлен Суперзорч,Супер зорч додат ... Eat Chex(R)!,STSTR_CHOPPERS,,chex,,... Jez 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)!,... jedz płatki Chex(R)!,... coma Chex(R)!,,... Mănâncă Chex(R)!,... Ешь Chex(R)!,... Једи Chex(R)! -Mini Zorch Charge,AMMO_CLIP,,chex,,Minibzukrové náboje,Minizorcher-Ladung,,Zorĉileto-Ŝarĝo,Carga de Mini Zorch,,Minizorchvaraus,Charge Zorch,Mini szörcs töltet,Ricarica Mini Zorch,ミニゾーチ ほきゅう,소형 저치 전지,Mini Zorchlading,Mini Ładunek Zorch,Recarga de Mini Zorch,,Mini Încărcătură pentru Zorcher,Заряд Мини-Зорчера,Мини зорч пуњач -Large Zorcher Charge,AMMO_SHELLS,,chex,,Velkobzukrové náboje,Zorcher-Ladung,,Ŝarĝo por Granda Zorĉilo,Carga de Zorcher Largo,,Ison zorcherin varaus,Charge de Zorcheur Large,Nagy szörcs töltet,Ricarica Grande Zorch,ラージゾーチャー ほきゅう,대형 저치 카트리지,Grote Zorchlading,Ładunek do Dużego Zorchera,Recarga de Zorch Grande,,Încărcătură Mare pentru Zorcher,Заряд Большого Зорчера,Велики зорч пуњач -Propulsor Charge,AMMO_ROCKETS,,chex,,Propulzorové náboje,Propeller-Ladung,,Zorĉpropulsilo-ŝarĝo,Carga de Propulsor de Zorcher,,Työntimen varaus,Charge de Propulseur,Hajtómű töltet,Ricarica Propulsore,プロパルサー ほきゅう,저치 추진료,Propulsorlading,Ładunek do Pędnika,Recarga de Propulsor de Zorch,,Încărcătură pentru Accelerator,Заряд Ускорителя,Погонски зорч пуњач -Phasing Zorcher Charge,AMMO_CELLS,,chex,,Fázovací náboje,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,Ładunek do Fazowego Zorchera,Recarga de Zorcher Fásico,,Încărcătură pentru Zorcherul Fazat,Заряд Фазового Зорчера,Фазни зорч пуњач +Mini Zorch Charge,AMMO_CLIP,,chex,,Minibzukrové náboje,Minizorcher-Ladung,,Zorĉileto-Ŝarĝo,Carga de Mini Zorch,,Minizorchvaraus,Charge Zorch,Mini szörcs töltet,Ricarica Mini Zorch,ミニゾーチ ほきゅう,소형 저치 전지,Mini Zorchlading,Mini Ładunek Zorch,Recarga de Mini Zorch,,Mini Încărcătură pentru Zorcher,Заряд мини-Зорчера,Мини зорч пуњач +Large Zorcher Charge,AMMO_SHELLS,,chex,,Velkobzukrové náboje,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,Ładunek do Dużego Zorchera,Recarga de Zorch Grande,,Încărcătură Mare pentru Zorcher,Заряд большого Зорчера,Велики зорч пуњач +Propulsor Charge,AMMO_ROCKETS,,chex,,Propulzorové náboje,Propeller-Ladung,,Zorĉpropulsilo-ŝarĝo,Carga de Propulsor de Zorch ,,Työntimen varaus,Charge de Propulseur,Hajtómű töltet,Ricarica Propulsore,プロパルサー ほきゅう,저치 추진료,Propulsorlading,Ładunek do Pędnika,Recarga de Propulsor de Zorch,,Încărcătură pentru Accelerator,Заряд ускорителя,Погонски зорч пуњач +Phasing Zorcher Charge,AMMO_CELLS,,chex,,Fázovací náboje,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,Ładunek do Fazowego Zorchera,Recarga de Zorcher Fásico,,Încărcătură pentru Zorcherul Fazat,Заряд фазерного Зорчера,Фазни зорч пуњач ,,Menus,,,,,,,,,,,,,,,,,,,,, ,,Main Menus,,,,,,,,,,,,,,,,,,,,, -New Game,MNU_NEWGAME,,,,Nová hra,Neues Spiel,Νέο Παιχνίδι,Nova Ludo,Nueva Partida,,Uusi peli,Nouvelle Partie,Új játék,Nuovo gioco,新規ゲーム,새로운 게임,Nieuw spel,Nowa Gra,Novo Jogo,,Joc Nou,Новая игра,Нова игра +New Game,MNU_NEWGAME,,,,Nová hra,Neues Spiel,Νέο Παιχνίδι,Nova Ludo,Nueva Partida,,Uusi peli,Nouvelle Partie,Új játék,Nuova partita,新規ゲーム,새로운 게임,Nieuw spel,Nowa Gra,Novo jogo,,Joc Nou,Новая игра,Нова игра Options,MNU_OPTIONS,,,,Možnosti,Optionen,Ρυθμίσεις,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Opcje,Opções,,Opțiuni,Настройки,Подешавања -Game Files,MNU_GAMEFILES,,,,Uložené hry,Spieldateien,Αρχεία Παιχνιδιού,Ludo-Dosieroj,Archivos del Juego,,Pelitiedostot,Fichiers de jeu,Játékfájlok,File di gioco,ゲームファイル,게임 파일,Spelbestanden,Pliki Gry,Jogos Salvos,Jogos Gravados,Fișiere Joc,Файлы игры,Фајлови игре -Info,MNU_INFO,,,,Informace,Informationen,Πληροφορίες,Informo,Información,,Tiedot,Info,Információ,Informazioni,情報,정보,Info,Info,Informações,,Info,Информация,Подаци +Game Files,MNU_GAMEFILES,,,,Uložené hry,Spieldateien,Αρχεία Παιχνιδιού,Ludo-Dosieroj,Archivos del Juego,,Pelitiedostot,Fichiers de jeu,Játékfájlok,File di gioco,ゲームファイル,게임 파일,Spelbestanden,Pliki Gry,Jogos salvos,Jogos Gravados,Fișiere Joc,Файлы игры,Фајлови игре +Info,MNU_INFO,,,,Informace,Informationen,Πληροφορίες,Informoj,Información,,Tiedot,Info,Információ,Informazioni,情報,정보,Info,Info,Informações,,Info,Информация,Подаци Quit Game,MNU_QUITGAME,,,,Ukončit hru,Spiel verlassen,Έξοδος,Forlasi Ludon,Salir del juego,,Lopeta peli,Quitter le jeu,Kilépés,Esci dal gioco,終了,게임 종료,Verlaat spel,Wyjdź z Gry,Sair,,Ieșire din Joc,Выход,Заврши игру -Choose Skill Level:,MNU_CHOOSESKILL,This text is extremely space limited!,,,Vyber obtížnost:,Schwierigkeitsgrad:,Επίλεξε ΔυσκολΊα:,Elektu Malfacilecon:,Elige nivel de dificultad:,,Valitse vaikeustaso:,Difficulté:,Nehézségi szint:,Livello di difficoltà:,実力を選べ:,난이도를 고르시오:,Vaardigheidsniveau:,Wybierz Poziom Trudności:,Escolha o Nível de Dificuldade:,,Alege Dificultatea:,Уровень сложности:,Ниво тежине: +Choose Skill Level:,MNU_CHOOSESKILL,This text is extremely space limited!,,,Vyber obtížnost:,Schwierigkeitsgrad:,Επίλεξε ΔυσκολΊα:,Elektu Malfacilecon:,Elige nivel de dificultad:,,Valitse vaikeustaso:,Difficulté:,Nehézségi szint:,Livello di difficoltà:,実力を選べ:,난이도를 고르시오:,Vaardigheidsniveau:,Wybierz Poziom Trudności:,Escolha o nível de dificuldade:,,Alege Dificultatea:,Уровень сложности:,Ниво тежине: I'm too young to die.,SKILL_BABY,,,,Ještě nechci umřít.,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.,Jestem za młody by umierać.,Sou jovem demais para morrer.,Demasiado novo para morrer.,Sunt prea tânăr ca să mor.,Мне рано умирать.,Премлад сам да умрем. "Hey, not too rough.",SKILL_EASY,,,,"Hej, ne tak tvrdě.","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.","Hej, nie tak mocno.","Opa, pega leve aí.","Ei, mais devagar.","Hei, nu foarte dur.","Эй, не так грубо.","Хеј, не претерано грубо." -Hurt me plenty.,SKILL_NORMAL,,,,Pojď do mě.,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.,Dowal mi.,Pode vir quente.,Dá-me com força.,Rănește-mă din plin.,Сделай мне больно.,Повреди ме кол'ко можеш. -Ultra-Violence.,SKILL_HARD,,,,Ultrařežba.,Volle Gewalt.,Ύπερ-Βία,Ekstrema Perforto.,Ultra-Violencia.,,Ultraväkivalta.,Ultra-Violence!,Ultraerőszak!,Ultra-violenza.,ウルトラ バイオレンス,극단적인-폭력.,Ultra Geweld.,Ultra-Przemoc.,Ultra-Violência,,Ultra-Violență.,Ультранасилие.,Ултра-насилно. +Hurt me plenty.,SKILL_NORMAL,,,,Pojď do mě.,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.,Dowal mi.,Vem com tudo.,Dá-me com força.,Rănește-mă din plin.,Сделай мне больно.,Повреди ме кол'ко можеш. +Ultra-Violence.,SKILL_HARD,,,,Ultrařežba.,Volle Gewalt.,Ύπερ-Βία,Ekstrema Perforto.,Ultra-Violencia.,,Ultraväkivalta.,Ultra-Violence!,Ultraerőszak!,Ultra-violenza.,ウルトラ バイオレンス,극단적인-폭력.,Ultra Geweld.,Ultra-Przemoc.,Ultraviolência.,,Ultra-Violență.,Ультранасилие.,Ултра-насилно. Nightmare!,SKILL_NIGHTMARE,,,,Noční můra!,Alptraum!,Εφιάλτης!,Inkubo!,¡Pesadilla!,,Painajainen!,Cauchemar!,Rémálom!,Incubo!,悪夢だ!,악몽!,Nachtmerrie!,Koszmar!,Pesadelo!,,Coșmar!,Кошмар!,Ноћна мора! Easy does it,CSKILL_BABY,,,,Hezky zlehka,Immer sachte,,Kvietiĝu,Así de fácil,,Hiljaa hyvä tulee,On y va Doucement,Csak gyengéden.,Facile no?,やさしくして,살살 하면 좋겠네,Gemakkelijk doet het,Łatwizna,Vamos com calma,,Merge ușor,Потихоньку-полегоньку,Лагано сад Not so sticky,CSKILL_EASY,,,,Ne tak ulepeně,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.,Nie tak lepko,Não tão gosmento,,Nu așa de lipicios,Не особо липко,Не тако лепљиво Gobs of goo,CSKILL_NORMAL,,,,Hafo hlenu,Schleimklumpen,,Buloj de muko,Montón de moco,,Limaklönttejä,Des Tonnes de Gelée,Egy csomó trutymó,Sputi di sostanza,"カッチカチスライム ",적지 않은 질퍽함,brokken slijm,Maziste Gęby,Um montão de meleca,Um montão de ranho,Multă mâzgă,Масса слизи,Лопте љиге -Extreme Ooze,CSKILL_HARD,,,,Extra bláto,Extrem glitschig,,Ekstrema Pusado,Goteo en extremo,,Äärimmäisen mönjäistä,Extrêmement Gluant,Extrém nyúlós,Melma estrema,"かげきなウーズ +Extreme Ooze,CSKILL_HARD,,,,Extra bláto,Extrem glitschig,,Ekstrema Pusado,Goteo Extremo,,Äärimmäisen mönjäistä,Extrêmement Gluant,Extrém nyúlós,Melma estrema,"かげきなウーズ ",엄청난 끈끈함,Uiterst glibberig,Ekstremalny Muł,Gosma ao extremo,,Noroi Extrem,Экстремальная грязь,Екстремно љигаво Super Slimey!,CSKILL_NIGHTMARE,,,,Superslizké!,Super schleimig!,,Tre Ŝlima!,¡Súper Viscoso!,,Superlimaista!,Carrément Crade!,Szupernyálkás!,Super Viscido!,ちょうベトベト!,끈쩍함 천지!,Super slijmerig!,Super Oślizgły!,Super Gosmento!,,Super Mâzgos!,Сверхсклизский!,СУПЕР ЉИГАВО Training,SSKILL_BABY,,,,Trénink,,Eκπαίδευση,Trejnado,Práctica,,Koulutus,Entrâinement,Kiképzés,Allenamento,トレーニング,훈련병,Opleiding,Trening,Treinamento,Treino,În Pregătiri,Разминка,Тренинг @@ -2444,8 +2442,8 @@ Rookie,SSKILL_EASY,,,,Zelenáč,Anfänger,Αρχάριος,Komencanto,Novato,,Al Veteran,SSKILL_NORMAL,,,,Veterán,,,Veterano,Veterano,,Veteraani,Véteran,Veterán,Veterano,ベテラン,고참병,Veteraan,Weteran,Veterano,,Veteran,Ветеран,Ветеран Elite,SSKILL_HARD,,,,Elita,,,Elito,Élite,,Eliitti,,Elit,Elite,エリート,정예병,,Elita,Elite,,Elită,Элита,Елитни Bloodbath,SSKILL_NIGHTMARE,,,,Krveřežba,Blutbad,,Sangoverŝado,Baño de sangre,,Verilöyly,Massacre!,Vérfürdő,Bagno di sangue,ブラッドバス,피의 목욕,Bloedbad,Rozlew krwi,Banho de sangue,,Baie de sânge,Кровавая бойня,Купка крви -Thou needeth a Wet-Nurse,MNU_WETNURSE,,,,Potřěbuješ krmlici,Wo ist die Krankenschwester?,,Vi Nutristinon bezonas,Necesitareis una nodriza,,Tarvitseos imettäjää,Une Nourrice Vous Voulez,Süldőgyermek,Necessiti di un'infermiera per neonati,汝は乳母を欲する,그대에게는 유모가 필요하다,Waar is de verpleegster?,Chyba potrzebujesz Mamki,Tu precisas de uma Ama-de-Leite,Tu precisas de uma Ama-Seca,Doica are Nevoie de Mine,Нянечка надобна мне,Треба ти бабица -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,Tchórze To My,Tu és um Amarelão,Tu és um Cobardolas,Nu Sunt Așa de Curajos,Не столь мужественен я,Ми-смо-жутица +Thou needeth a Wet-Nurse,MNU_WETNURSE,,,,Potřěbuješ krmlici?,Wo ist die Krankenschwester?,,Vi Nutristinon bezonas,Necesitareis una nodriza,,Tarvitseos imettäjää,Une Nourrice Vous Voulez,Süldőgyermek,Necessiti di un'infermiera per neonati,汝は乳母を欲する,그대에게는 유모가 필요하다,Waar is de verpleegster?,Chyba potrzebujesz Mamki,Tu precisas de uma Ama-de-Leite,Tu precisas de uma Ama-Seca,Doica are Nevoie de Mine,Нянечка надобна мне,Треба ти бабица +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,Tchórze To My,Tu és um Amarelão,Tu és um Cobardolas,Nu Sunt Așa de Curajos,Не столь мужественен я,Ми-смо-жутица Bringest Them Oneth,MNU_BRINGEST,,,,Chtějúci se práti?,Her damit,,Al Mi Ilin Kunvenigu,Traédnoslos,,Antaos tullaos,Amenez les moi!,Ide velük hinnye,Portali a me,招かれし者共,혈투를 벌일 준비하라,Geef me dat.,Dawaj Ich,Podeis Virdes,Podeis Virdes,Aduceți-mi,Подайте мне их,Донеси изабраног Thou art a Smite-Meister,MNU_SMITE,,,,Ktož jsú boží bojovníci,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.,Jesteś Mistrzem Walki,Tu és Mestre-de-Massacres,,Lupta mă Ispitește,Искушён я сражениями,Ти си обузети-мајстор Black Plague Possesses Thee,MNU_BLACKPLAGUE,,,,Jsúci Smrtonošem morovým!,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,Czarna Plaga Cię Opętuje,A Peste Negra te Possui,A Peste Negra Possui-te,Ciuma Neagră mă Posedă,Чума овладела мной,Имаш црну кугу @@ -2477,9 +2475,9 @@ The Dome of D'Sparil,MNU_DOME,,,,Báň D'Sparilova,D'Sparils Dom,,La Kupolo de D The Ossuary,MNU_OSSUARY,,,,Kostnice,Das Beinhaus,,La Ostejo,El Osario,,Luuhuone,L'Ossuaire,Csontkamra,L'Ossario,納骨堂,납골당,Het Ossuarium,Kostnica,O Ossuário,O Ossário,Osuarul,Склеп,Костурница The Stagnant Demesne,MNU_DEMESNE,,,,Zatuchlé panství,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,Zapuszczona Posiadłość,O Reino Estagnado,,Tărâmul Stagnării,Застойные владения,Стагнирајући домени ,Gameplay menus,,,,,,,,,,,,,,,,,,,,,, -Teamplay,GMPLYMNU_TEAMPLAY,,,,Týmová hra,Teamspiel,,Teamludado,Juego por equipos,,Joukkuepeli,Jeu en équipe,Csapatjáték,Gioco di squadra,チーム制,팀플레이,Teamplay,Gra Drużynowa,Jogo em Equipe,Jogo em Equipa,Joc în Echipă,Командный режим,Тимска игра +Teamplay,GMPLYMNU_TEAMPLAY,,,,Týmová hra,Teamspiel,,Teamludado,Juego por equipos,,Joukkuepeli,Jeu en équipe,Csapatjáték,Gioco di squadra,チーム制,팀플레이,Teamplay,Gra Drużynowa,Jogo em equipe,Jogo em Equipa,Joc în Echipă,Командный режим,Тимска игра Team damage scalar,GMPLYMNU_TEAMDAMAGE,,,,Faktor týmového poškození,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 Obrażeń Drużyny,Escala de fogo amigo,,Multiplicator daune,Множитель урона по своим,Мултипликатор пријатељске ватре -Smart Autoaim,GMPLYMNU_SMARTAUTOAIM,,,,Chytré automatické zaměřování,Intelligene Zielautomatik,,Inteligenta Celasisto,Autoapuntado inteligente,,Älykäs automaattitähtäys,Autovisée intelligente,Okos automata célzás,Mira automatica intelligente,スマートオートエイム,정확한 자동 조준,Slimme Autoaim,Mądre Autocelowanie,Mira Automática Inteligente,,Asistare inteligentă la țintire,Умное автоприцеливание,Паметни нишан +Smart Autoaim,GMPLYMNU_SMARTAUTOAIM,,,,Chytré automatické zaměřování,Intelligene Zielautomatik,,Inteligenta Celasisto,Autoapuntado inteligente,,Älykäs automaattitähtäys,Autovisée intelligente,Okos automata célzás,Mira automatica intelligente,スマートオートエイム,정확한 자동 조준,Slimme Autoaim,Mądre Autocelowanie,Mira automática inteligente,,Asistare inteligentă la țintire,Умное автоприцеливание,Паметни нишан Falling damage,GMPLYMNU_FALLINGDAMAGE,,,,Zranění pádem,Fallschaden,,Faldamaĝo,Daño por caída,,Putoamisvahinko,Dommages de chute,Eséskor sebzés,Danno da caduta,落下ダメージ,낙하 데미지,Vallende schade,Obrażenia przy upadku,Dano de queda,,Daune la căderi libere,Урон от падения,Штета од пада Drop weapon,GMPLYMNU_DROPWEAPON,,,,Odhazování zbraní,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,Wyrzuć broń,Largar arma,,Aruncare armă,Выбрасывать оружие после смерти,Баци оружје @@ -2487,20 +2485,20 @@ Double ammo,GMPLYMNU_DOUBLEAMMO,,,,Dvojnásobná munice,Doppelte Munition,,Duobl Infinite ammo,GMPLYMNU_INFINITEAMMO,,,,Nekonečná munice,Unendlich Munition,,Infinita municio,Munición infinita,,Loppumattomat ammukset,Munitions infinies,Végtelen muníció,Infinite munizioni,弾無限,무한 탄약,Oneindige munitie,Nieskończona amunicja,Munição infinita,,Muniție infinită,Бесконечные патроны,Бесконачна муниција Infinite inventory,GMPLYMNU_INFINITEINVENTORY,,,,Nekonečný inventář,Unendliche Gegenstände,,Infinita inventorio,Inventario infinito,,Loppumattomat varusteet,Objets infinis,Végtelen felszerelés,Infinito inventario,所持品無限,무한 인벤토리,Oneindige voorraad,Nieskończony ekwipunek,Inventário infinito,,Inventar infinit,Бесконечный инвентарь,Бесконачно складиштење No monsters,GMPLYMNU_NOMONSTERS,,,,Bez příšer,Keine Monster,,Neniuj monstroj,Sin monstruos,,Ei hirviöitä,Pas de monstres,Szörnyek nélkül,Nessun mostro,モンスターを出現させない,적 제거,Geen monsters,Brak potworów,Sem monstros,,Fără monștri,Без монстров,Без чудовишта -No monsters to exit,GMPLYMNU_NOMONSTERSTOEXIT,,,,Ukončení levelu pouze bez příšer,Keine Monster um Level zu beenden,,Neniuj monstroj por eliri,Sin monstruos para salir,,Ei hirviöitä tason lopettamiseksi,Rien à tuer pour sortir,Megölhető szörnyek nélkül,Nessun mostro da uccidere per uscire,モンスター全滅までMAPから脱出不可,탈출을 위한 적 제거,Geen monsters om af te sluiten,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 putea ieși,Убить всех монстров для выхода,Без чудовишта до излаза -Monsters respawn,GMPLYMNU_MONSTERSRESPAWN,,,,Příšery se respawnují,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,Ponowne pojawianie się potworów,Respawn de monstros,,Monștrii reapar,Монстры воскрешаются,Чудовишта се оживљавају -Monsters do not respawn,GMPLYMNU_NORESPAWN,,,,Příšery se nerespawnují,Kein Zurückkehren,,Neniu reekapero,Sin reaparición,,Ei henkiinheräämistä,Pas de réapparition,Szörnyek nem születnek újra,Nessun respawn,プレイヤーの復活禁止,부활 없음,Geen respawn,Brak ponownego pojawienia się,Sem respawn,,Monștrii nu reapar,Отключить воскрешение,Без оживљавања -Items respawn,GMPLYMNU_ITEMSRESPAWN,,,,Předměty se respawnují,Gegenstände erscheinen wieder,,Objektoj reekaperas,Reaparecer objetos,,Esineet syntyvät takaisin,Objets réapparaissent,tárgyak újrateremnek,Respawn oggetti,アイテムを復活,아이템 재생성,Items respawn,Ponowne pojawianie się przedmiotów,Respawn de itens,,Obiectele reapar,Восстановление предметов,Предмети се ресетују -Big powerups respawn,GMPLYMNU_SUPERRESPAWN,,,,Bonusy se respawnují,Große Boni erscheinen wieder,,Grandaj plifortigaĵoj reekaperas,Reaparecer poderes grandes,,Isot tehostimet syntyvät takaisin,Powerups réapparaissent,Nagy powerupok újraszületnek,Respawn grandi potenziamenti,強力なパワーアップアイテムを復活,파워업 재생성,Grote power-ups respawn,Ponowne pojawianie się dużych wzmocnień,Respawn de powerups,,Super bonusurile reapar,Восстановление супер-бонусов,Велики предмети се ресетују +No monsters to exit,GMPLYMNU_NOMONSTERSTOEXIT,,,,Ukončení levelu pouze bez příšer,Keine Monster um Level zu beenden,,Neniuj monstroj 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,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 putea ieși,Убить всех монстров для выхода,Без чудовишта до излаза +Monsters respawn,GMPLYMNU_MONSTERSRESPAWN,,,,Příšery se respawnují,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,Ponowne pojawianie się potworów,Ressurgimento de monstros,,Monștrii reapar,Монстры воскрешаются,Чудовишта се оживљавају +Monsters do not respawn,GMPLYMNU_NORESPAWN,,,,Příšery se nerespawnují,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,Brak ponownego pojawienia się,Sem ressurgimento de monstros,,Monștrii nu reapar,Отключить воскрешение,Без оживљавања +Items respawn,GMPLYMNU_ITEMSRESPAWN,,,,Předměty se respawnují,Gegenstände erscheinen wieder,,Objektoj reekaperas,Reaparecer objetos,,Esineet syntyvät takaisin,Objets réapparaissent,tárgyak újrateremnek,Respawn oggetti,アイテムを復活,아이템 재생성,Items respawn,Ponowne pojawianie się przedmiotów,Ressurgimento de itens,,Obiectele reapar,Восстановление предметов,Предмети се ресетују +Big powerups respawn,GMPLYMNU_SUPERRESPAWN,,,,Bonusy se respawnují,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,Ponowne pojawianie się dużych wzmocnień,Ressurgimento de potencializadores,,Super bonusurile reapar,Восстановление супербонусов,Велики предмети се ресетују Fast monsters,GMPLYMNU_FASTMONSTERS,,,,Rychlé příšery,Schnelle Monster,,Rapidaj monstroj,Monstruos rápidos,,Nopeat hirviöt,Monstres Rapides,Gyors szörnyek,Mostri veloci,モンスター高速化,빠른 적 개체 움직임,Snelle monsters,Szybkie potwory,Monstros rápidos,,Monștri rapizi,Ускоренные монстры,Брза чудовишта -Monsters Nightmare Reflexes,GMPLYMNU_INSTANTREACTION,,,,,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,,敵が悪夢と同じ機敏さ,,,Refleks Potworów z Trybu Koszmar,,,Monștri cu Reflexe de Coșmar,, +Monsters Nightmare Reflexes,GMPLYMNU_INSTANTREACTION,,,,Okamžité reakce příšer (obtížnost Noční můra!),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,,敵が悪夢と同じ機敏さ,,,Refleks Potworów z Trybu Koszmar,Reflexos dos Monstros em Pesadelo,,Monștri cu Reflexe de Coșmar,Кошмарные рефлексы монстров, Degeneration,GMPLYMNU_DEGENERATION,,,,Degenerace,,,Degenero,Degeneración,,Rappeutuva terveys,Dégéneration,Degeneráció,Degrado della salute,プレイヤーの自動体力減少,약화,Degeneratie,Degeneracja,Degeneração,,Degenerare,Уменьшать дополнительное здоровье,Смањење додатног здравља -Allow Autoaim,GMPLYMNU_NOAUTOAIM,,,,Povolit automatické míření,Zielautomatik zulassen,,Permesi Celasiston,Permitir Autoapuntar,,Salli automaattitähtäys,Autoriser Auto-visée,Autocélzás engedélyezése,Mira automatica consentita,オートエイム有効化,자동 조준 허용,Autoaim toestaan,Pozwól na Autocelowanie,Permitir Mira Automática,,Permite asistența pentru țintire,Разрешить автоприцеливание,Дозволи аутоматско циљање -Allow Suicide,GMPLYMNU_ALLOWSUICIDE,,,,Povolit sebevraždu,Selbstmord zulassen,,Permesi Memmortigon,Permitir Suicidio,,Salli itsemurha,Autoriser Suicide,Öngyilkosság engedélyezése,Suicidio consentito,自殺コマンド有効化,자살 허용,Zelfmoord toestaan,Pozwól na Samobójstwo,Permitir suicídio,,Permite sinuciderile,Разрешить суицид,Дозволи самоубиство +Allow Autoaim,GMPLYMNU_NOAUTOAIM,,,,Povolit automatické míření,Zielautomatik zulassen,,Permesi Celasiston,Permitir Autoapuntar,,Salli automaattitähtäys,Autoriser Auto-visée,Autocélzás engedélyezése,Mira automatica consentita,オートエイム有効化,자동 조준 허용,Autoaim toestaan,Pozwól na Autocelowanie,Permitir mira automática,,Permite asistența pentru țintire,Разрешить автоприцеливание,Дозволи аутоматско циљање +Allow Suicide,GMPLYMNU_ALLOWSUICIDE,,,,Povolit sebevraždu,Selbstmord zulassen,,Permesi Memmortigon,Permitir Suicidio,,Salli itsemurha,Autoriser Suicide,Öngyilkosság engedélyezése,Suicidio consentito,自殺コマンド有効化,자살 허용,Zelfmoord toestaan,Pozwól na Samobójstwo,Permitir suicídio,,Permite sinuciderile,Разрешить самоубийство,Дозволи самоубиство Allow jump,GMPLYMNU_ALLOWJUMP,,,,Povolit skákání,Springen zulassen,,Permesi salton,Permitir salto,,Salli hyppiminen,Autoriser Sauts,Ugrás engedélyezése,Salto consentito,ジャンプ有効化,점프 허용,Springen toestaan,Pozwól na skakanie,Permitir pulo,Permitir salto,Permite săriturile,Прыжки,Дозволи скок Allow crouch,GMPLYMNU_ALLOWCROUCH,,,,Povolit klečení,Ducken zulassen,,Permesi kaŭron,Permitir agacharse,,Salli kyyristyminen,Autoriser Acroupissement,Guggolás engedélyezése,Abbassamento consentito,しゃがみ有効化,앉기 허용,Hurken toestaan,Pozwól na kucanie,Permitir agachamento,,Permite ghemuirile,Приседание,Дозволи чучање -Allow freelook,GMPLYMNU_ALLOWFREELOOK,,,,Povolit koukání nahoru/dolů,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,Pozwól na swobodne rozglądanie się,Permitir vista livre,,Permite privirea în jur cu mouse-ul,Обзор мышью,Дозволи слободан поглед -Allow FOV,GMPLYMNU_ALLOWFOV,,,,Povolit změnu 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,Pozwól na Pole Widzenia,Permitir ângulo de visão,,Permite ajustarea câmpului vizual,Разрешить изменение FOV,Дозволи FOV +Allow freelook,GMPLYMNU_ALLOWFREELOOK,,,,Povolit koukání nahoru/dolů,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,Pozwól na swobodne rozglądanie się,Permitir visão livre,,Permite privirea în jur cu mouse-ul,Обзор мышью,Дозволи слободан поглед +Allow FOV,GMPLYMNU_ALLOWFOV,,,,Povolit změnu 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,Pozwól na Pole Widzenia,Permitir campo de visão,,Permite ajustarea câmpului vizual,Разрешить изменение поля видимости,Дозволи FOV Allow BFG aiming,GMPLYMNU_BFGFREEAIM,,,,Povolit míření s BFG,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,Pozwól na celowanie BFG,Permitir mira de BFG,,Permite țintirea cu BFG,Разрешить прицеливание с BFG,Дозволи BFG нишање Allow automap,GMPLYMNU_ALLOWAUTOMAP,,,,Povolit automapu,Automap zulassen,,Permesi aŭtomapon,Permitir automapa,,Salli automaattikartta,Autoriser Carte,Autotérkép engedélyezése,Automap consentito,オートマップ有効化,오토맵 허용,Automap toestaan,Pozwól na mapę,Permitir automapa,,Permite utilizarea hărții computerizate,Разрешить использование автокарты,Дозволи мапу Automap allies,GMPLYMNU_AUTOMAPALLIES,,,,Zobrazit na automapě spojence,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,Sojusznicy na mapie,Permitir aliados no automapa,,Aliați pe harta computerizată,Показывать союзников на автокарте,Савезници на аутомапи @@ -2510,95 +2508,97 @@ Check ammo for weapon switch,GMPLYMNU_DONTCHECKAMMO,,,,Přepnout na zbraň pouze Icon's death kills its spawns,GMPLYMNU_KILLBOSSSPAWNS,,,,Smrt Ikony zabije i její potomky,,,La morto de Icon motrigas 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,Ś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,Убить порождения Иконы при её смерти,Смрт Икона греха убија његова потомства End sector counts for kill %,GMPLYMNU_NOCOUNTENDMONSTER,,,,Započítávat monstra v ukončujících sektorech,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 %,"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,Засчитывать убийства монстров в конечных секторах,Урачунај убиство чудовишта у коначним секторима -Deathmatch Settings,GMPLYMNU_DEATHMATCH,,,,Nastavení deathmatche,Deathmatcheinstellungen,,Mortmaĉo-Agordoj,Configuración modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch beállítások,Impostazioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch instellingen,Ustawienia Deathmatchu,Configurações de Deathmatch,,Setări Deathmatch,Настройки deathmatch,Детмеч подешавања +Deathmatch Settings,GMPLYMNU_DEATHMATCH,,,,Nastavení deathmatche,Deathmatcheinstellungen,,Mortmaĉo-Agordoj,Configuración modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch beállítások,Impostazioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch instellingen,Ustawienia Deathmatchu,Configurações de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања Weapons stay,GMPLYMNU_WEAPONSSTAY,,,,Zbraně zůstávají,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,Bronie zostają,Armas permanecem,,Părăsire arme după selectare,Оставлять оружие после подбора,Оружје се остаје након купљења Allow powerups,GMPLYMNU_ALLOWPOWERUPS,,,,Povolit bonusy,Boni erlauben,,Permesi plifortigaĵojn,Permitir poderes,,Salli tehostimet,Autoriser powerups,Powerupok engedélyezése,Potenziamenti consentiti,パワーアップアイテムを出現させる,파워 업 허용,Power-ups toestaan,Pozwól na wzmocnienia,Permitir powerups,,Permite bonusuri,Разрешить бонусы,Дозволи бонусе Allow health,GMPLYMNU_ALLOWHEALTH,,,,Povolit zdraví,Gesundheit erlauben,,Permesi sanon,Permitir salud,,Salli terveysesineet,Autoriser objets santé,Életerő engedélyezése,Oggetti per la salute consentiti,回復アイテムを出現させる,체력 회복 아이템 허용,Gezondheid toestaan,Pozwól na przedmioty zdrowotne,Permitir itens de saúde,,Permite prim-ajutor,Разрешить бонусы к здоровью,Дозволи бонусе за здравље Allow armor,GMPLYMNU_ALLOWARMOR,,,Allow armour,Povolit brnění,Panzer erlauben,,Permesi kirason,Permitir armadura,,Salli panssariesineet,Autoriser objets armure,Páncél engedélyezése,Armature consentite,アーマーを出現させる,아머 허용,Pantsertoeslag toestaan,Pozwól na pancerz,Permitir itens de armadura,,Permite bonusuri de armură,Разрешить броню,Дозволи оклоп -Spawn farthest,GMPLYMNU_SPAWNFARTHEST,,,,Spawnovat hráče nejdále od sebe,Am weitesten entfernten Punkt erscheinen,,Ekaperi plej fore,Aparecer más lejos,,Herää henkiin kauimpaa,Apparaître au plus loin,Legmesszebb spawnolni a többiektől,Spawn il più lontano possibile,他のプレイヤーから最遠の場所に復活,먼 곳에서 소환,Kuitschieten het verst verwijderd,Pojaw się jak najdalej,Spawn mais longe,,Apariție cât mai departată de ceilalți,Воскрешение подальше от остальных,Оживљавање даље од других +Spawn farthest,GMPLYMNU_SPAWNFARTHEST,,,,Spawnovat hráče co nejdále od sebe,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,Pojaw się jak najdalej,Surgimento mais longe,,Apariție cât mai departată de ceilalți,Воскрешение подальше от остальных,Оживљавање даље од других Same map,GMPLYMNU_SAMEMAP,,,,Stejná mapa,Gleiches Level,,Sama mapo,Mismo mapa,,Sama taso,Même Carte,Ugyanazon pálya,Stessa mappa,同じMAPを繰り返す,같은 맵 플레이,Dezelfde kaart,Ta sama mapa,Mesmo mapa,,Reluare nivel,Зациклить уровень,Понављање нивоа Force respawn,GMPLYMNU_FORCERESPAWN,,,,Vynutit 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,Wymuś ponowne pojawienie się,Forçar reaparecimento,,Reapariție instantă,Моментальное воскрешение,Форсирано оживљавање Allow exit,GMPLYMNU_ALLOWEXIT,,,,Povolit ukončení levelu,Verlassen erlauben,,Permesi eliron,Permitir salir,,Salli tasosta poistuminen,Autoriser Sortie,Kijárat engedélyezése,Uscita consentita,出口の使用を許可,탈출 허용,Uitgang toestaan,Pozwól na wyjście,Permitir saída,,Permite ieșirea,Разрешить выход,Дозволи излазак из нивоа Barrels respawn,GMPLYMNU_BARRELSRESPAWN,,,,Barely se respawnují,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,Beczki pojawiają się ponownie,Barrís reaparecem,,Butoaiele reapar,Восстановление бочек,Бурад се ресетују Respawn protection,GMPLYMNU_RESPAWNPROTECTION,,,,Ochrana po respawnu,Schutzboni kehen zurück,,Protekto de reekapero,Reaparecer protección,,Henkiinheräämissuoja,Protection à la réapparition,Újraszületési védelem,Protezione al respawn,復活したばかりのプレイヤーを保護,부활시 무적,Respawn bescherming,Ochrona przy ponownym pojawieniu się,Proteção de reaparecimento,,Protecție la apariția pe hartă,Кратковременная защита после воскрешения,Ресетује се заштита -Lose frag if fragged,GMPLYMNU_LOSEFRAG,,,,Ztratit frag pokud zabit,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,Strać fraga jeśli jesteś sfragowany,Perder frag ao ser fragado,,Pierdere din victime la deces,Терять фраг при смерти,Изгубити гранату ако опаљена -Keep frags gained,GMPLYMNU_KEEPFRAGS,,,,Ponechávání fragů mezi levely,Frags zwischen Leveln behalten,,Teni ludmurdojn gajnitajn,Mantener bajas ganadas,,Pidä ansaitut frägit,Garder les frags gagnés,,Mantenere i frag vinti,MAP変更後も得点を保持する,맵 변경 시 점수 유지,Houd frags opgedaan,Zachowaj zdobyte fragi,Manter frags ganhos,,Păstrare număr victime,Сохранять фраги между уровнями,Задржати стечене гранате +Lose frag if fragged,GMPLYMNU_LOSEFRAG,,,,"Hráč ztratí frag, pokud je zabit",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,Strać fraga jeśli jesteś sfragowany,Perder frag ao ser fragado,,Pierdere din victime la deces,Терять фраг при смерти,Изгубити гранату ако опаљена +Keep frags gained,GMPLYMNU_KEEPFRAGS,,,,Ponechávat fragy mezi levely,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,Zachowaj zdobyte fragi,Manter frags ganhos,,Păstrare număr victime,Сохранять фраги между уровнями,Задржати стечене гранате No team switching,GMPLYMNU_NOTEAMSWITCH,,,,Uzamknout týmy,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,Zakaz zmieniania drużyn,Desativar troca de time,Desativar troca de equipa,Nu permite schimbarea echipelor,Запретить переход между командами,Нема мешања тимова -Cooperative Settings,GMPLYMNU_COOPERATIVE,,,,Nastavení co-op módu,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,Ustawienia Kooperacji,Configurações de Jogo Cooperativo,,Setări cooperative,Настройки совместного режима,Кооперативне поставке -Spawn multi. weapons,GMPLYMNU_MULTIPLAYERWEAPONS,,,,Spawnovat multiplayerově zbraně,Deathmartch Waffen sind verfügbar,,Ekaperi armilojn por plurdanta reĝimo,Aparecer armas multi.,,Kuolonotteluaseet saatavilla,Spawns d'armes deathmatch,Többjátékos fegyverek engedélyezése,Spawn armi multiplayer,マルチプレイ用の武器を出現させる,멀티플레이어 무기 소환,Spawn multi. wapens,Zezwól na bronie trybu dla wielu graczy,Spawn de armas em multijogador,,Permite apariția armelor din modul online,Появление оружия из мультиплеера,Створити мулти оружја +Cooperative Settings,GMPLYMNU_COOPERATIVE,,,,Nastavení co-op módu,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,Ustawienia Kooperacji,Configurações de jogo cooperativo,,Setări cooperative,Настройки совместного режима,Кооперативне поставке +Spawn multiplayer weapons,GMPLYMNU_MULTIPLAYERWEAPONS,,,,Spawnovat multiplayerově zbraně,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,Zezwól na bronie trybu dla wielu graczy,Surgimento de armas em multijogador,,Permite apariția armelor din modul online,Появление оружия из сетевой игры,Створити мулти оружја Lose entire inventory,GMPLYMNU_LOSEINVENTORY,,,,Ztrácet celý inventář,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,Utrać cały ekwipunek,Perder todo o inventário,,Pierdere inventar,Терять весь инвентарь при смерти,Изгубити цело складиште Keep keys,GMPLYMNU_KEEPKEYS,,,,Ponechat klíče,Schlüssel behalten,,Teni ŝlosiojn,Mantener llaves,,Pidä avaimet,Garder clés,Kulcsok megtartása,Mantenere le chiavi,死亡後もキーを保持する,열쇠들을 소지하고 시작,Sleutels bewaren,Zachowaj klucze,Manter chaves,,Păstrare chei,Сохранять ключи,Задржати кључеве Keep weapons,GMPLYMNU_KEEPWEAPONS,,,,Ponechat zbraně,Waffen behalten,,Teni armilojn,Mantener armas,,Pidä aseet,Garder armes,Fegyverek megtartása,Mantenere le armi,死亡後も武器を保持する,무기들을 소지하고 시작,Wapens bewaren,Zachowaj bronie,Manter armas,,Păstrare arme,Сохранять оружие,Задржати оружје Keep armor,GMPLYMNU_KEEPARMOR,,,Keep armour,Ponechat brnění,Rüstung behalten,,Teni kirason,Mantener armadura,,Pidä panssari,Garder armure,Páncél megtartása,Mantenere l'armatura,死亡後もアーマーを保持する,아머를 소지하고 시작,Pantser bewaren,Zachowaj pancerz,Manter armadura,,Păstrare armură,Сохранять броню,Задржати панцир -Keep powerups,GMPLYMNU_KEEPPOWERUPS,,,,Ponechat bonusy,Behalte Boni,,Teni plifortigaĵojn,Mantener poderes,,Pidä tehostimet,Garder powerups,Powerupok megtartása,Mantenere i potenziamenti,死亡後もパワーアップを保持する,파워업을 소지하고 시작,Power-ups bewaren,Zachowaj wzmocnienia,Manter powerups,,Păstrare bonusuri,Сохранять супер-бонусы,Задржати повећану моћ +Keep powerups,GMPLYMNU_KEEPPOWERUPS,,,,Ponechat bonusy,Behalte Boni,,Teni plifortigaĵojn,Mantener poderes,,Pidä tehostimet,Garder powerups,Powerupok megtartása,Mantenere i potenziamenti,死亡後もパワーアップを保持する,파워업을 소지하고 시작,Power-ups bewaren,Zachowaj wzmocnienia,Manter powerups,,Păstrare bonusuri,Сохранять супербонусы,Задржати повећану моћ Keep ammo,GMPLYMNU_KEEPAMMO,,,,Ponechat munici,Munition behalten,,Teni municion,Mantener munición,,Pidä ammukset,Garder munitions,Muníció megtartása,Mantenere le ammunizioni,死亡後も弾薬を保持する,탄약을 소지하고 시작,Munitie bewaren,Zachowaj amunicję,Manter munição,,Păstrare armură,Сохранять патроны,Задржати муницију Lose half ammo,GMPLYMNU_LOSEHALFAMMO,,,,Ztratit polovinu munice,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,Utrać pół amunicji,Perder metade da munição,,Pierdere jumătate din armură,Терять половину патронов,Изгубити пола муниције -Spawn where died,GMPLYMNU_SPAWNWHEREDIED,,,,Respawn na místě smrti,Neuerscheinen wo gestorben,,Ekaperi 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,Pojaw się znów tam gdzie zginąłeś,Spawn no local de morte,Reaparecer onde morreu,Apariție la locul decesului,Воскрешение на месте смерти,Оживљавање на месту смрти -Always spawn multiplayer objects,GMPLYMNU_ALWAYSSPAWNMULTI,,,,Vždy spawnovat multiplayerové objekty,Mehrspielerobjekte immer erzeugen,,Ĉiam ekaperi plurludantajn objektojn,Siempre hacer aparecer objetos en el modo multijugador,,Aina luo moninpelioliot,,Mindig megjelennek a többjátékos tárgyak,,常にマルチプレイ用の物を出現,,,Pozwól na przedmioty dla trybu wielu graczy,Sempre spawnar objetos multijogador,,Permite apariția obiectelor din multiplayer,, -Compatibility Options,OPTMNU_COMPATIBILITY,,,,Nastavení kompatibility,Kompatibilitätseinstellungen,Ρυθμίσεις Συμβατότητας,Kongruo-Agordoj,Opciones de Compatibilidad,,Yhteensopivuusasetukset,Options de Compatibilité,Kompatibilitási beállítások,Opzioni Compatibilità,互換性 オプション,호환 설정,Compatibiliteitsopties,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Совместимость,Компатибилност -Compatibility Options,CMPTMNU_TITLE,,,,Nastavení kompatibility,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-Agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options Compatibilité,Kompatibilitási beállítások,Opzioni compatibilità,互換性 オプション,호환성 설정,Compatibiliteitsopties,Opcje Zgodności,Opções de Compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилна подешавања +Spawn where died,GMPLYMNU_SPAWNWHEREDIED,,,,Respawn na místě smrti,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,Pojaw się znów tam gdzie zginąłeś,Surgir no local da morte,Reaparecer onde morreu,Apariție la locul decesului,Воскрешение на месте смерти,Оживљавање на месту смрти +Always spawn multiplayer objects,GMPLYMNU_ALWAYSSPAWNMULTI,,,,Vždy spawnovat multiplayerové objekty,Mehrspielerobjekte immer erzeugen,,Ĉiam ekaperi plurludantajn objektojn,Siempre hacer aparecer objetos en el modo multijugador,,Aina luo moninpelioliot,,Mindig megjelennek a többjátékos tárgyak,Fai sempre apparire gli oggetti di multigiocatore,常にマルチプレイ用の物を出現,,,Pozwól na przedmioty dla trybu wielu graczy,Permitir surgimento de objetos multijogador,,Permite apariția obiectelor din multiplayer,Появление объектов из сетевой игры, +Allow Vertical Bullet Spread,GMPLYMNU_NOVERTSPREAD,,,,Povolit svislý rozptyl střelby,,,Permesi Vertikalan Kuglan Disvastiĝon,,,,,Vertikális fegyverszórás engedélyezve,Permetti la diffusione dei proiettili in verticale,,,,,Permitir espalhamento vertical das balas,,,Разрешить вертикальный разброс пуль, +Weapons give extra ammo (DM),GMPLYMNU_NOEXTRAAMMO,,,,Zbraně dávají munici navíc (DM),,,,,,,,,Le armi danno munizioni extra (DM),,,,,Armas dão munição extra (DM),,,, +Compatibility Options,OPTMNU_COMPATIBILITY,,,,Kompatibilita,Kompatibilitätseinstellungen,Ρυθμίσεις Συμβατότητας,Kongruo-Agordoj,Opciones de Compatibilidad,,Yhteensopivuusasetukset,Options de Compatibilité,Kompatibilitási beállítások,Opzioni Compatibilità,互換性 オプション,호환 설정,Compatibiliteitsopties,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Совместимость,Компатибилност +Compatibility Options,CMPTMNU_TITLE,,,,Nastavení kompatibility,Kompatibilitätsoptionen,Ρυθμίσεις Συμβατότητας,Kongruo-Agordoj,Opciones de compatibilidad,,Yhteensopivuusasetukset,Options Compatibilité,Kompatibilitási beállítások,Opzioni compatibilità,互換性 オプション,호환성 설정,Compatibiliteitsopties,Opcje Zgodności,Opções de compatibilidade,,Setări de Compatibilitate,Настройки совместимости,Компатибилна подешавања Compatibility mode,CMPTMNU_MODE,,,,Režim kompatibility,Kompatibilitätsmodus,,Kongruo-reĝimo,Modo de Compatibilidad,,Yhteensopivuustila,Mode de compatibilité,Kompatibilitási mód,Modalità compatibilità,互換性モード,호환 모드,Compatibiliteitsmodus,Tryb Zgodności,Modo de compatibilidade,,Mod Compatibilitate,Режим совместимости,Компатибилни мод -Actor Behavior,CMPTMNU_ACTORBEHAVIOR,,,Actor Behaviour,Chování objektů,Verhalten der Akteure,,Aktorkonduto,Comportamiento del actor,,Olioiden käyttäytyminen,Comportement des Acteurs,,Comportamento degli attori,アクターの挙動,개체 관련 설정,Gedrag van de acteur,Zachowanie Aktorów,Comportamento de Atores,,Comportament actori,Поведение акторов,Понашање актора -Crushed monsters can be resurrected,CMPTMNU_CORPSEGIBS,,,,Rozmáčklé příšery mohou být oživeny,Zermalmte Monster können wiederbelebt werden,,Pistitaj monstroj povas reviviĝi,Los monstruos aplastados pueden resucitar,,Murskatut hirviöt voidaan herättää henkiin,Monstres écrasés résucitables,Összenyomott szörnyek újraszületnek,I mostri schiacciati possono essere resuscitati,潰れた敵が復活可能,으깨진 개체는 부활 불가,Verpletterde monsters kunnen herrezen worden,Zmiażdżone potwory mogą być wskrzeszone,Monstros esmagados podem ser ressucitados,,Monștrii striviți pot fi înviați,Раздавленные монстры могут быть воскрешены,Згњечена чудовишта могу ускрснути +Actor Behavior,CMPTMNU_ACTORBEHAVIOR,,,Actor Behaviour,Objekty,Verhalten der Akteure,,Aktorkonduto,Comportamiento del actor,,Olioiden käyttäytyminen,Comportement des Acteurs,Actor viselkedés,Comportamento degli attori,アクターの挙動,개체 관련 설정,Gedrag van de acteur,Zachowanie Aktorów,Comportamento de atores,,Comportament actori,Поведение объектов,Понашање актора Friendly monsters aren't blocked,CMPTMNU_NOBLOCKFRIENDS,,,,Spojenecké příšery nejsou blokovány,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.,Przyjazne potwory nie mogą być blokowane,Monstros aliados não são bloqueados,,Monștrii aliați nu pot fi blocați,Не блокировать дружественных монстров,Пријатељска чудовишта се не блокирају -Limit Pain Elementals' Lost Souls,CMPTMNU_LIMITPAIN,,,,Omezit počet Elementálových Ztracených duší,Limit für Verlorene Seelen,,Limigi Perditajn Animojn de Doloro-Elementuloj,Limitar Almas Perdidas de los Dolores Elementales,,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,Ogranicz Zagubione Dusze Elementala Bólu,Limitar Almas Penadas de Elementais da Dor,,Limitează numărul Sufletelor Pierdute create de Elementalii Durerii,Ограничить число потерянных душ из элементалей боли,Ограничи изгубљене душе од елементала патње +Limit Pain Elementals' Lost Souls,CMPTMNU_LIMITPAIN,,,,Omezit počet Ztrac. duší (Lost Souls) od Živlů (Pain Elementals),Limit für Verlorene Seelen,,Limigi Perditajn Animojn de Doloro-Elementuloj,Limitar Almas Perdidas de los Dolores Elementales,,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,Ogranicz Zagubione Dusze Elementala Bólu,Limitar Almas Perdidas criadas por Elementais da Dor,,Limitează numărul Sufletelor Pierdute create de Elementalii Durerii,Ограничить число потерянных душ из элементалей боли,Ограничи изгубљене душе од елементала патње Monster movement is affected by effects,CMPTMNU_MBFMONSTERMOVE,,,,Pohyb příšer je ovlivněn efekty,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,Efekty wpływają na ruch potworów,Movimento dos monstros é afetado por efeitos,,Efectele afectează deplasarea monștrilor,Эффекты влияют на движение монстров,Ефекти утицају на покретљивост чудовишта Monsters cannot cross dropoffs,CMPTMNU_CROSSDROPOFF,,,,Příšery nemohou překročit výšiny,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,Potwory nie mogą przekraczać spadków,Monstros não podem atravessar penhascos,,Monștrii nu pot trece peste prăpăstii,Монстрам нельзя пересекать уступы,Чудовишта не могу прећи падове Monsters get stuck over dropoffs,CMPTMNU_DROPOFF,,,,Příšery se zasekávají na výšinách,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,Potwory mogą utknąć nad spadkami,Monstros ficam presos em penhascos,,Monștrii înțepenesc peste prăpăstii,Монстры застревают на уступах,Чудовишта се заглављују на падовима -Monsters see invisible players,CMPTMNU_INVISIBILITY,,,,Příšery vidí neviditelné hráče,Monster können unsichtbare Spieler sehen,,Monstroj povas vidi invisiblajn 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,Potwory widzą niewidzialnych graczy,Monstros enxergam jogadores invisíveis,,Monștrii pot vedea jucătorii invizibili,Монстры видят невидимых игроков,Чудовишта могу да виде невидљиве играче -No Minotaur floor flames in water,CMPTMNU_MINOTAUR,,,,Mínotauři nemohou tvořit plameny ve vodě,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,Brak płomieni Minotaura w wodzie,Desativar fogo do Marretauro na água,,Minotaurii nu pot folosi atacul de foc pe apă,Минотавры не создают огонь в воде,Минотаури не пале ватру у води -Spawn item drops on the floor,CMPTMNU_NOTOSSDROPS,,,,Spadlé předměty se objeví na zemi,Gegenstände erscheinen auf dem Fußboden,,Ekaperi 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,Obiekty pojawiają się na podłodze,Itens spawnados caem direto no chão,,Obiectele scăpate vor apărea la nivelul podelei,Выброшенные предметы создаются на земле,Одбачени предмети се појављују на поду -DehackEd Behavior,CMPTMNU_DEHACKEDBEHAVIOR,,,DehackEd Behaviour,Chování DeHackEd,DehackEd Verhalten,,Konduto de DehackEd,Comportamiento de DehackEd,,DehackEd-käyttäytyminen,Comportement DeHackEd,DeHackEd viselkedés,Comportamento DehackEd,Dehackedの挙動,DehackEd 관련 설정,DehackEd Gedrag,Zachowanie DehackEd,Comportamento DehackEd,,Comportament DehackEd,Поведение DeHackEd,DehackEd понашање -DEH health settings like Doom2.exe,CMPTMNU_DEHHEALTH,,,,Nastavení DEH jako v 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,Ustawienia zrowia DEH jak w Doom2.exe,Configurações de saúde DEH como em Doom2.exe,,Setări sănătate în DEH precum în Doom2.exe,Настройки здоровья DEH как в Doom2.exe,DEH подешавања здравља као у Doom2.exe -Original A_Mushroom speed in DEH mods,CMPTMNU_MUSHROOM,,,,Původní rychlost pro A_Mushroom,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,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 модовима -Map/Action Behavior,CMPTMNU_MAPACTIONBEHAVIOR,,,Map/Action Behaviour,Chování levelů a aktivací,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,Zachowanie Mapy/Akcji,Comportamento Mapa/Ação,,Comportament hartă/actori,Поведение уровней/действий,Понашање нивоа/догађаја +Monsters see invisible players,CMPTMNU_INVISIBILITY,,,,Příšery vidí neviditelné hráče,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,Potwory widzą niewidzialnych graczy,Monstros enxergam jogadores invisíveis,,Monștrii pot vedea jucătorii invizibili,Монстры видят невидимых игроков,Чудовишта могу да виде невидљиве играче +No Minotaur floor flames in water,CMPTMNU_MINOTAUR,,,,Minotauři nemohou tvořit plameny ve vodě,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,Brak płomieni Minotaura w wodzie,Desativar fogo do Marretauro na água,,Minotaurii nu pot folosi atacul de foc pe apă,Минотавры не создают огонь в воде,Минотаури не пале ватру у води +Spawn item drops on the floor,CMPTMNU_NOTOSSDROPS,,,,Spadlé předměty se objeví na zemi,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,Obiekty pojawiają się na podłodze,Itens surgidos caem direto no chão,,Obiectele scăpate vor apărea la nivelul podelei,Выброшенные предметы создаются на земле,Одбачени предмети се појављују на поду +DehackEd Behavior,CMPTMNU_DEHACKEDBEHAVIOR,,,DehackEd Behaviour,DeHackEd,DehackEd Verhalten,,Konduto de DehackEd,Comportamiento de DehackEd,,DehackEd-käyttäytyminen,Comportement DeHackEd,DeHackEd viselkedés,Comportamento DehackEd,Dehackedの挙動,DehackEd 관련 설정,DehackEd Gedrag,Zachowanie DehackEd,Comportamento DehackEd,,Comportament DehackEd,Поведение DeHackEd,DehackEd понашање +DEH health settings like Doom2.exe,CMPTMNU_DEHHEALTH,,,,Nastavení DEH jako v 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,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 +Original A_Mushroom speed in DEH mods,CMPTMNU_MUSHROOM,,,,Původní rychlost pro A_Mushroom,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,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 модовима +Map/Action Behavior,CMPTMNU_MAPACTIONBEHAVIOR,,,Map/Action Behaviour,Levely a akce,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,Zachowanie Mapy/Akcji,Comportamento de Mapa/Ação,,Comportament hartă/actori,Поведение уровней/действий,Понашање нивоа/догађаја All special lines can block ,CMPTMNU_USEBLOCKING,,,,Veškeré akční čáry blokují použití hráčem,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.,Wszystkie specjalne linie mogą blokować ,Todas as linhas especiais podem bloquear o comando ,,Toate liniile speciale pot bloca ,Все специальные линии могут блокировать ,Све специјалне линије могу да блокирају Allow any bossdeath for level special,CMPTMNU_ANYBOSSDEATH,,,,Smrt jakéhokoli bosse může aktivovat speciální akci levelu,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....,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 на нивоу -Disable BOOM door light effect,CMPTMNU_NODOORLIGHT,,,,Zakázat světelný efekt dveří z BOOMu,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,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-а на вратима -Find neighboring light like Doom,CMPTMNU_LIGHT,,,Find neighbouring light like Doom,Nacházet nejbližší světlo jako 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,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-у -Find shortest textures like Doom,CMPTMNU_SHORTTEX,,,,Nacházet nejkratší textury jako 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,Znajdź najkrótsze tekstury jak w Doomie,Encontrar menores texturas como em Doom,,Caută cele mai scurte texturi ca în Doom,Искать кратчайшие текстуры как в Doom,Нађи најкраће текстуре као у Doom-у +Disable BOOM door light effect,CMPTMNU_NODOORLIGHT,,,,Zakázat světelný efekt dveří z BOOMu,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,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-а на вратима +Find neighboring light like Doom,CMPTMNU_LIGHT,,,Find neighbouring light like Doom,Nacházet nejbližší světlo jako 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,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-у +Find shortest textures like Doom,CMPTMNU_SHORTTEX,,,,Nacházet nejkratší textury jako 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,Znajdź najkrótsze tekstury jak w Doomie,Encontrar menores texturas como em Doom,,Caută cele mai scurte texturi ca în Doom,Искать кратчайшие текстуры как в Doom,Нађи најкраће текстуре као у Doom-у Use buggier stair building,CMPTMNU_STAIRS,,,,Použít méně stabilní stavění schodů,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,Użyj wadliwej funkcji budowania schodów,Usar construção defeituosa de escadas,,Utilizare mod de ridicare al scărilor incorect,Использовать неисправленное построение лестниц,Користи непоправљено грађење степеница -Use Doom's floor motion behavior,CMPTMNU_FLOORMOVE,,,Use Doom's floor motion behaviour,Použít původní chování Doomu pro pohyb podlah,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,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-ово подно моционо понашање -Use Doom's point-on-line algorithm,CMPTMNU_POINTONLINE,,,,Použít původní algoritmus bod-na-čáře z Doomu,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,Użyj algorytmu punktu na linii z Dooma,Usar algorítmo de ponto-em-linha de Doom,,Utilizare algoritm point-on-line din Doom,Использовать алгоритм point-on-line из Doom,Користи Doom-ов point-on-line алгоритам +Use Doom's floor motion behavior,CMPTMNU_FLOORMOVE,,,Use Doom's floor motion behaviour,Použít původní chování Doomu pro pohyb podlah,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,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-ово подно моционо понашање +Use Doom's point-on-line algorithm,CMPTMNU_POINTONLINE,,,,Použít původní algoritmus bod-na-čáře z Doomu,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,Użyj algorytmu punktu na linii z Dooma,Usar algorítmo de ponto-em-linha de Doom,,Utilizare algoritm point-on-line din Doom,Использовать алгоритм point-on-line из Doom,Користи Doom-ов point-on-line алгоритам Level exit can be triggered more than once,CMPTMNU_MULTIEXIT,,,,Odchod z levelu může být spuštěn vícekrát,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,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,Выходы могут быть активированы более одного раза,Излаз нивоа може бити активиран више пута -Physics Behavior,CMPTMNU_PHYSICSBEHAVIOR,,,Physics Behaviour,Chováni fyziky,Physik-Verhalten,,Fizikokonduto,Comportamiento de la física,,Fysiikan käyttäytyminen,Comportement Physique,Fizika viselkedés,Comportamento della fisica,物理の挙動,물리 관련 설정,Fysica gedrag,Zachowanie Fizyki,Comportamento de Física,Comportamento das Físicas,Comportament fizică,Поведение физики,Физичко понашање -Actors are infinitely tall,CMPTMNU_NOPASSOVER,,,,Objekty jsou nekonečně vysoké,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,Aktorzy są nieskończenie wysocy,Atores são infinitamente altos,,Actorii au înălțime infinită,Акторы бесконечно высокие,Глумци су бесконачно велики -Boom scrollers are additive,CMPTMNU_BOOMSCROLL,,,,Boom posuvníky jsou aditivní,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,Przewijane tekstury Boom są addytywne,Scrollers de Boom são aditivos,,Elementele derulante BOOM sunt aditive,Скроллеры из BOOM являются аддитивными,Boom скролери су додаци +Physics Behavior,CMPTMNU_PHYSICSBEHAVIOR,,,Physics Behaviour,Fyzika,Physik-Verhalten,,Fizikokonduto,Comportamiento de la física,,Fysiikan käyttäytyminen,Comportement Physique,Fizika viselkedés,Comportamento della fisica,物理の挙動,물리 관련 설정,Fysica gedrag,Zachowanie Fizyki,Comportamento de Física,Comportamento das Físicas,Comportament fizică,Поведение физики,Физичко понашање +Actors are infinitely tall,CMPTMNU_NOPASSOVER,,,,Objekty jsou nekonečně vysoké,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,Aktorzy są nieskończenie wysocy,Atores são infinitamente altos,,Actorii au înălțime infinită,Объекты бесконечно высокие,Глумци су бесконачно велики +Boom scrollers are additive,CMPTMNU_BOOMSCROLL,,,,Boom posuvníky jsou aditivní,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,Przewijane tekstury Boom są addytywne,Scrollers de Boom são aditivos,,Elementele derulante BOOM sunt aditive,Скроллеры из BOOM являются аддитивными,Boom скролери су додаци Cannot travel straight NSEW,CMPTMNU_BADANGLES,,,,Nelze se pohybovat přímo na SJVZ,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,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 Enable wall running,CMPTMNU_WALLRUN,,,,Povolit wall running (běhaní pomocí zdi),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,Włącz szybkie bieganie wzdłuż ścian,Habilitar corrida por paredes,Permitir corrida pelas paredes,Permite fuga cu ajutorul pereților (Wallrun),Включить быстрый бег вдоль стен (Wallrun),Омогући пролажење кроз зида -Raven scrollers use original speed,CMPTMNU_RAVENSCROLL,,,,Raven posuvníky používají původní rychlost,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,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 scrollers use original speed,CMPTMNU_RAVENSCROLL,,,,Raven posuvníky používají původní rychlost,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,Przwijane tekstury podłogi Raven używają oryginalną prędkość,Scrollers da Raven usam velocidade original,,Elementele derulante Raven folosesc viteza originală,Raven-скроллеры используют изначальную скорость,Raven скролери користе оригиналну брзину Self ref. sectors don't block shots,CMPTMNU_TRACE,,,,Sebe-odkazující sektory neblokují střely,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,Sektory odnoszoce się do siebie nie blokują strzałów,Setores autorreferidos não bloqueiam tiros,,Sectoarele cu referință proprie blochează focurile,Самоссылающиеся секторы не блокируют выстрелы,Самореф. сектори не блокирају пуцњеве -Use Doom code for hitscan checks,CMPTMNU_HITSCAN,,,,Použít původní Doom kód pro kontrolu hitscanů,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,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 для проверок хит-сканов,Користи Doom код за хитскен проверу -Use Doom heights for missile clipping,CMPTMNU_MISSILECLIP,,,,Použít původní výšky z Doomu pro kolizi raket,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,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 висине за клиповање ракета -Rendering Behavior,CMPTMNU_RENDERINGBEHAVIOR,,,Rendering Behaviour,Chování renderingu,Renderverhalten,,Bildigado-Konduto,Comportamiento de renderizado,,Hahmonnuksen käyttäytyminen,Comportement d'affichage,Renderelés viselkedése,Comportamento della grafica,レンダリングの挙動,렌더링 관련 설정,Rendering gedrag,Zachowanie Renderowania,Comportamento de Renderização,,Comportament Video,Поведение рендеринга,Понашање рендовања -Draw polyobjects like Hexen,CMPTMNU_POLYOBJ,,,,Vykreslovat polyobjekty jako 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,Rysuj poliobiekty jak w Hexenie,Desenhar poliobjetos como em Hexen,,Afișează poliobiectele precum în Hexen,Рисовать полиобъекты как в Hexen,Цртај поли-објекте као Hexen +Use Doom code for hitscan checks,CMPTMNU_HITSCAN,,,,Použít původní Doom kód pro kontrolu hitscanů,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,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 для проверок мест мгновенного попадания,Користи Doom код за хитскен проверу +Use Doom heights for missile clipping,CMPTMNU_MISSILECLIP,,,,Použít původní výšky z Doomu pro kolizi raket,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,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 висине за клиповање ракета +Rendering Behavior,CMPTMNU_RENDERINGBEHAVIOR,,,Rendering Behaviour,Vykreslování,Renderverhalten,,Bildigado-Konduto,Comportamiento de renderizado,,Hahmonnuksen käyttäytyminen,Comportement d'affichage,Renderelés viselkedése,Comportamento della grafica,レンダリングの挙動,렌더링 관련 설정,Rendering gedrag,Zachowanie Renderowania,Comportamento de Renderização,,Comportament Video,Поведение отображения,Понашање рендовања +Draw polyobjects like Hexen,CMPTMNU_POLYOBJ,,,,Vykreslovat polyobjekty jako 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,Rysuj poliobiekty jak w Hexenie,Desenhar poliobjetos como em Hexen,,Afișează poliobiectele precum în Hexen,Показывать полиобъекты как в Hexen,Цртај поли-објекте као Hexen Ignore Y offsets on masked midtextures,CMPTMNU_MASKEDMIDTEX,,,,Ignorovat Y posuny na průhledných mid-texturách,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,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 на скрытых мид-текстурах,Игнориши Y нагиб на маскиране средње текстуре Invert sprite sorting,CMPTMNU_SPRITESORT,,,,Obrátit řazení spritů,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,Odwróć sortowanie sprite'ów,Inverter ordem de sprites,,Inversare sortare sprite-uri,Инвертировать сортировку спрайтов,Обрнуто сортирање спрајтова -Sound Behavior,CMPTMNU_SOUNDBEHAVIOR,,,Sound Behaviour,Chování zvuku,Sound-Verhalten,,Sonkonduto,Comportamiento de sonido,,Äänen käyttäytyminen,Comportement Sonore,Hang viselkedés,Comportamento suono,音の挙動,효과음 관련 설정,Geluidsgedrag,Zachowanie dźwięku,Comportamento de Áudio,,Comportament Sunet,Поведение звуков,Понашање звука +Sound Behavior,CMPTMNU_SOUNDBEHAVIOR,,,Sound Behaviour,Zvuk,Sound-Verhalten,,Sonkonduto,Comportamiento de sonido,,Äänen käyttäytyminen,Comportement Sonore,Hang viselkedés,Comportamento suono,音の挙動,효과음 관련 설정,Geluidsgedrag,Zachowanie dźwięku,Comportamento de Áudio,,Comportament Sunet,Поведение звуков,Понашање звука Cripple sound for silent BFG trick,CMPTMNU_SOUNDSLOTS,,,,Zmrzačit zvukový systém pro trik tichého BFG,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,Obetnij dźwięk dla triku cichego BFG,Bloquear som para o truque da BFG silenciosa,,Taie sunetul pentru trucul BFG silențios,Исказить звуки для трюка бесшумной BFG,Онемогући звук за тихи ВЈП трик -Don't let others hear your pickups,CMPTMNU_SILENTPICKUP,,,,Ostatní tě neslyší sbírat předměty,Andere können deine Gegenstandsaufnahmen nicht hören,,Ne lasi aliulojn aŭdi 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,"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,Запрещать другим слышать Ваш подбор предметов,Не допусти да други чују ваше скупљање +Don't let others hear your pickups,CMPTMNU_SILENTPICKUP,,,,Ostatní tě neslyší sbírat předměty,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,"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,Запрещать другим слышать ваш подбор предметов,Не допусти да други чују ваше скупљање Inst. moving floors are not silent,CMPTMNU_SILENTINSTANTFLOORS,,,,Okamžitě pohybující se podlahy nejsou tiché,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,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,Мгновенно двигающиеся полы не беззвучны,Инстантно покрећући нивои нису тихи Sector sounds use center as source,CMPTMNU_SECTORSOUNDS,,,Sector sounds use centre as source,Sektorové zvuky používají jeho střed jako zdroj,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,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,Звуки секторов используют центр как источник,Секторски звукови су центрисани -Sounds stop when actor vanishes,CMPTMNU_SOUNDCUTOFF,,,,"Utnout zvuky, když jejich objekt zmizí","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,Dźwięki zatrzymują się kiedy aktor znika,Som para quando o ator desaparece,,Sunetele se opresc când actorul sursă dispare,Останавливать звуки при исчезновении актора,Звукови престају кад глумац нестане -Use original sound target handling,CMPTMNU_SOUNDTARGET,,,,Použít původní chování pro uchování zvukového cíle,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,Użyj oryginalną obsługę celu dźwięku,Usar método original de destino de som,,Procesare originală pentru sursele de sunet,Оригинальная обработка источников звука,Користи оригинални звук руковања метом -Scripted teleports don't trigger sector actions,CMPTMNU_TELEPORT,,,,Skriptované teleportace neaktivují sektorové akce,Teleports in Skripten lösen keine Sektoraktionen aus,,Skriptataj 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.,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,Скриптовые телепорты не инициируют действия секторов,Скриптовани телепортери не активирају секторске радње +Sounds stop when actor vanishes,CMPTMNU_SOUNDCUTOFF,,,,"Utnout zvuky, když jejich objekt zmizí","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,Dźwięki zatrzymują się kiedy aktor znika,Som para quando o ator desaparece,,Sunetele se opresc când actorul sursă dispare,Останавливать звуки при исчезновении объекта,Звукови престају кад глумац нестане +Use original sound target handling,CMPTMNU_SOUNDTARGET,,,,Použít původní chování pro uchování zvukového cíle,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,Użyj oryginalną obsługę celu dźwięku,Usar método original de destino de som,,Procesare originală pentru sursele de sunet,Изначальная обработка источников звука,Користи оригинални звук руковања метом +Scripted teleports don't trigger sector actions,CMPTMNU_TELEPORT,,,,Skriptované teleportace neaktivují sektorové akce,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.,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,Скриптовые телепорты не инициируют действия секторов,Скриптовани телепортери не активирају секторске радње Non-blocking lines can be pushed,CMPTMNU_PUSHWINDOW,,,,Neblokující čáry mohou být zmáčknuty,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,Nieblokujące ściany mogą być pchnięte,Linhas não-bloqueadoras podem ser pressionadas,,Liniile care nu blochează pot fi împinse înapoi,Неблокирующие линии могут быть отодвинуты,Неблокирабе линје могу бити гурнуте -Enable buggy CheckSwitchRange behavior,CMPTMNU_CHECKSWITCHRANGE,,,,Povolit nestabilní chování pro CheckSwitchRange,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,Zezwól na zepsute zachowanie CheckSwitchRange,Habilitar comportamento CheckSwitchRange defeituoso,,Comportament incorect pentru CheckSwitchRange,Включить багнутое поведение CheckSwitchRange,Омогући баговано CheckSwitchRange понашање -Enable buggy Strife railing,CMPTMNU_RAILINGHACK,,,,Povolit nestabilní zábradlí ze Strifu,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,Włącz wadliwe bariery Strife'a,Habilitar railing defeituoso do Strife,Permitir railing defeituoso do Strife,Utilizare comportament grilaj Strife incorect,Вернуть багнутые перила в Strife,Омогући непоправљену ограду у Strife-у -No vertical thrust from explosions,CMPTMNU_EXPLODE1,,,,Exploze neodhazují do výšky,Keine vertikale Bewegung durch Explosionen,Καθόλου κατακόρυφη ώθηση απο εκρήξεις,Neniuj vertikalaj puŝoj el 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,Brak pionowego nacisku od eksplozji,Desativar propulsão vertical das explosões,,Fără împingere verticală de la explozii,Взрывы не отбрасывают вверх/вниз,Нема вертикалног гурања од експлозија -Use original Doom explosion behavior,CMPTMNU_EXPLODE2,,,Use original Doom explosion behaviour,Používat původní chování explozí Doomu,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,Użyj oryginalnego zachowania eksplozji z Dooma,Usar comportamento original de explosões do Doom,,Utilizare comportament original pentru explozii,Использовать модель взрывов из оригинального Doom,Користи оригнално Doom понашање за експлозије +Enable buggy CheckSwitchRange behavior,CMPTMNU_CHECKSWITCHRANGE,,,,Povolit nestabilní chování pro CheckSwitchRange,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,Zezwól na zepsute zachowanie CheckSwitchRange,Permitir comportamento CheckSwitchRange defeituoso,,Comportament incorect pentru CheckSwitchRange,Включить ошибочное поведение CheckSwitchRange,Омогући баговано CheckSwitchRange понашање +Enable buggy Strife railing,CMPTMNU_RAILINGHACK,,,,Povolit nestabilní zábradlí ze Strifu,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,Włącz wadliwe bariery Strife'a,Permitir railing defeituoso do Strife,Permitir railing defeituoso do Strife,Utilizare comportament grilaj Strife incorect,Вернуть ошибочные перила в Strife,Омогући непоправљену ограду у Strife-у +No vertical thrust from explosions,CMPTMNU_EXPLODE1,,,,Exploze neodhazují do výšky,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,Brak pionowego nacisku od eksplozji,Desativar propulsão vertical das explosões,,Fără împingere verticală de la explozii,Взрывы не отбрасывают вверх/вниз,Нема вертикалног гурања од експлозија +Use original Doom explosion behavior,CMPTMNU_EXPLODE2,,,Use original Doom explosion behaviour,Používat původní chování explozí Doomu,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,Użyj oryginalnego zachowania eksplozji z Dooma,Usar comportamento original de explosões do Doom,,Utilizare comportament original pentru explozii,Использовать модель взрывов из Doom,Користи оригнално Doom понашање за експлозије Player,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,, Red,PLYRMNU_RED,,,,Červená,Rot,,Ruĝo,Rojo,,Punainen,Rouge,Piros,Rosso,赤の量,빨강,Rood,Czerwony,Vermelho,,Roșu,Красный,Црвева Green,PLYRMNU_GREEN,,,,Zelená,Grün,,Verdo,Verde,,Vihreä,Vert,Zöld,Verde,緑の量,초록,Groen,Zielony,Verde,,Verde,Зелёный,Зелена Blue,PLYRMNU_BLUE,,,,Modrá,Blau,,Bluo,Azul,,Sininen,Bleu,Kék,Blu,青の量,파랑,Blauw,Niebieski,Azul,,Albastru,Синий,Плава Class,PLYRMNU_PLAYERCLASS,,,,Třída,Klasse,,Klaso,Clase,,Luokka,Classe,Kaszt,Classe,役職,클래스,Klasse,Klasa,Classe,,Clasă,Класс,Класа -Skin,PLYRMNU_PLAYERSKIN,,,,Skin,Skin,,Haŭto,Piel,,Ulkoasu,,Kinézet,Skin,外装,스킨,Uiterlijk,Wygląd,Skin,,Textură,Скин,Скин -Switch on pickup,PLYRMNU_SWITCHONPICKUP,,,,Přepnout zbraň při sebrání,Waffenwechsel bei Aufnahme,,Ŝanĝi sur prenado,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,Przełącz po podniesieniu,Mudar de arma ao pegar,,Schimbare armă la ridicare,Смена оружия при подборе,Пребаци на покупљено оружје -Press \cjSPACE,PLYRMNU_PRESSSPACE,,,,Zmáčkni \cjMEZERNÍK,\cjLeertaste,,Premu \cjSPACON,Presiona \cjEspacio,,Paina \cjVÄLI \cfnähdäk-,\cjEspace,Nyomj \cjSPACE-t,Premi \cjSPAZIO,\cjスペースキー,회전: \cjSPACE바,Druk op \cjSPACE,\cjSPACJA,Aperte \cjESPAÇO,,Apasă \cjSPACE,Нажмите \cjПРОБЕЛ,Притисните \cjSPACE -to see front,PLYRMNU_SEEFRONT,,,,pro pohled zepředu,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,by widzieć przód,para ver pela frente,,pentru a vedea fața,Посмотреть спереди,да видите спреда -to see back,PLYRMNU_SEEBACK,,,,pro pohled zezadu,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,by widzieć tył,para ver por trás,,pentru a vedea spatele,Посмотреть сзади,да видите позади +Skin,PLYRMNU_PLAYERSKIN,,,,Skin,Skin,,Haŭto,Piel,,Ulkoasu,,Kinézet,Skin,外装,스킨,Uiterlijk,Wygląd,Skin,,Textură,Облик,Скин +Switch on pickup,PLYRMNU_SWITCHONPICKUP,,,,Přepnout zbraň při sebrání,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,Przełącz po podniesieniu,Mudar de arma ao pegar,,Schimbare armă la ridicare,Смена оружия при подборе,Пребаци на покупљено оружје +Press \cjSPACE,PLYRMNU_PRESSSPACE,,,,Zmáčkni \cjMEZERNÍK,\cjLeertaste,,Premu \cjSPACON,Presiona \cjEspacio,,Paina \cjVÄLI \cfnähdäk-,\cjEspace,Nyomj \cjSPACE -t,Premi \cjSPAZIO,\cjスペースキー,회전: \cjSPACE바,Druk op \cjSPACE,\cjSPACJA,Aperte \cjESPAÇO,,Apasă \cjSPACE,Нажмите \cjПРОБЕЛ,Притисните \cjSPACE +to see front,PLYRMNU_SEEFRONT,,,,pro pohled zepředu,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,by widzieć przód,para ver a frente,,pentru a vedea fața,Посмотреть спереди,да видите спреда +to see back,PLYRMNU_SEEBACK,,,,pro pohled zezadu,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,by widzieć tył,para ver atrás,,pentru a vedea spatele,Посмотреть сзади,да видите позади +Vertical Bullet Spread,PLYRMNU_VERTSPREAD,,,,Svislý rozptyl střelby,,,Vertikala Kugla Disvastiĝo,,,,,Vertikális fegyver szórás,Diffusione dei proiettili in verticale,垂直軸の散弾,,,,Espalhamento Vertical das Balas,,Recul Vertical Gloanțe,Вертикальный разброс пуль, ,,controls,,,,,,,,,,,,,,,,,,,,, Weapon Zoom,CNTRLMNU_ZOOM,,,,Přiblížení zbraně,Waffenzoom,Ζοομ,Armilzumo,Zoom del arma,,Aseen kiikaritähtäys,Zoom avec Arme,Ráközelítés fegyverrel,Zoom dell'arma,ズーム,무기 조준,Wapen Zoom,Przybliżenie Broni,Zoom da Arma,,Zoom Armă,Приближение,Зум Weapon State 1,CNTRLMNU_USER1,,,,Akce zbraně 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,Stan Broni 1,Estado da Arma 1,,Poziție Armă 1,Положение оружия (1),Стање оружја (1) @@ -2609,19 +2609,19 @@ Fly / Swim up,CNTRLMNU_MOVEUP,,,,Letět / plavat vzhůru,Fliegen / Hochschwimmen Fly / Swim down,CNTRLMNU_MOVEDOWN,,,,Letět / plavat dolů,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,Lot / Pływanie w dół,Voar / Nadar para baixo,,Zbor / Înot în Jos,Лететь/плыть вниз,Лети/пливај надоле Stop flying,CNTRLMNU_LAND,,,,Přestat létat,Landen,Σταμάτα πέταμα,Ĉesi flugadon,Dejar de volar,,Lopeta lentäminen,Arrêter de voler,Repülés abbahagyása,Stop al volo,飛行停止,비행 정지,Stoppen met vliegen,Przestań latać,Parar de voar,,Încetare Zbor,Приземлиться,Престани летети Keyboard look,CNTRLMNU_KEYBOARDLOOK,,,,Pohled klávesnicí,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,Rozglądanie się klawiaturą,Vista com o teclado,,Utilizare Tastatură pentru a Privi în Jur,Обзор клавиатурой,Гледај тастатуром -Strife Popup Screens Controls,CNTRLMNU_POPUPS_TITLE,,,,Ovládání vyskakovacích oken ve Strife,Strife Popup Steuerung einstellen,,Strife Ŝprucfenestrajn Regilojn,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,Ustaw Klawisze Okienek Strife'a,Comandos de Popups do Strife,Controlos de Popups do Strife,Control pentru Mesaje Strife,Всплывающие окна Strife,Искакајући прикази контроле у Strife-у +Strife Popup Screens Controls,CNTRLMNU_POPUPS_TITLE,,,,Ovládání vyskakovacích oken ve Strife,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,Ustaw Klawisze Okienek Strife'a,Comandos de Popups do Strife,Controlos de Popups do Strife,Control pentru Mesaje Strife,Всплывающие окна Strife,Искакајући прикази контроле у Strife-у Team say,CNTRLMNU_TEAMSAY,,,,Říct týmu,Readen im Team,Πές στην ομάδα,Teama diro,Hablar al equipo,,Sano omille,Parler (équipe),Üzenet csapattársaknak,Parla nella squadra,チーム内発言,팀 채팅하기,Zeggen in team,Powiedz do Drużyny,Fala (equipe),Falar à equipa,Vorbește cu Echipa Proprie,Сообщение команде,Пиши тиму Drop item,CNTRLMNU_DROPITEM,,,,Odhodit předmět,Gegenstand fallen lassen,Πέτα Aντικείμενο,Faligi objekton,Arrojar objeto,,Pudota varuste,Lâcher objet,Tárgy eldobása,Fai cadere l'oggetto,"アイテムを捨てる ",아이템 버리기,Item laten vallen,Upuść przedmiot,Largar item,,Aruncare Obiect,Сбросить предмет,Баци предмет -Query item,CNTRLMNU_QUERYITEM,,,,Informace o předmětu,Informationen über Gegenstand,,Informpeti objekton,Consultar objeto,,Hae varustetta,Vérifier objet,,Indaga sull'oggetto,アイテム名を表示,아이템 정보 표시,Vraag item op,Zapytaj o przedmiot,Consultar item,,Cercetare Obiect,Показать предмет,Прикажи предмет -Drop weapon,CNTRLMNU_DROPWEAPON,,,,Odhodit zbraň,Waffe fallen lassen,Πέτα Όπλο,Faligi armilon,Arrojar arma,,Pudota ase,Lâcher arme,Fegyver eldobása,Fai cadere l'arma,武器を捨てる,무기 버리기,Wapen laten vallen,Upuść broń,Largar arma,,Aruncare Armă,Сбросить оружие,Баци оружје +Query item,CNTRLMNU_QUERYITEM,,,,Informace o předmětu,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,Zapytaj o przedmiot,Consultar item,,Cercetare Obiect,Показать предмет,Прикажи предмет +Drop weapon,CNTRLMNU_DROPWEAPON,,,,Odhodit zbraň,Waffe fallen lassen,Πέτα Όπλο,Faligi armilon,Arrojar arma,,Pudota ase,Lâcher arme,Fegyver eldobása,Butta l'arma,武器を捨てる,무기 버리기,Wapen laten vallen,Upuść broń,Largar arma,,Aruncare Armă,Сбросить оружие,Баци оружје Other,CNTRLMNU_OTHER,,,,Ostatní,Andere,Άλλα,Alia,Otros,,Muu,Autres,Más,Altro,その他,그 외 조작,Andere,Inne,Outro,,Altele,Прочее,Остало -Coop spy,CNTRLMNU_COOPSPY,,,,Co-op špión,Coop Spion,,Kunlabora spiono,Espía cooperativo,,Vakoile joukkuetovereita,Espionner Coéquiper,Coop leskelődés,Spia cooperativa,他者視点,멀티플레이 카메라,Coöpspion,Śledź (kooperacja),Visualização coop,,Vedere prin Ochii Altui Jucător,Вид от другого игрока,Поглед од другог играча -Strife Popup Screens,CNTRLMNU_POPUPS,,,,Vyskakovací okna Strife,Strife Popups,,Malpacaj Ekmontraĵaj Ekranoj,Pop-ups de Strife,,Strifen ponnahdusruudut,Popups de Strife,Strife Felugró Ablakok,Schermate popup di Strife,Strife ポップアップ画面,스트라이프 팝업 화면,Strife Popup Schermen,Okienka Strife'a,Popup do Strife,,Mesaje Strife,Strife,Информација у Strife-у +Coop spy,CNTRLMNU_COOPSPY,,,,Co-op špehování,Coop Spion,,Kunlabora spiono,Espía cooperativo,,Vakoile joukkuetovereita,Espionner Coéquiper,Coop leskelődés,Spia cooperativa,他者視点,멀티플레이 카메라,Coöpspion,Śledź (kooperacja),Visualização coop,,Vedere prin Ochii Altui Jucător,Вид от другого игрока,Поглед од другог играча +Strife Popup Screens,CNTRLMNU_POPUPS,,,,Vyskakovací okna Strife,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,Okienka Strife'a,Popup do Strife,,Mesaje Strife,Strife,Информација у Strife-у Mission objectives,CNTRLMNU_MISSION,,,,Úkoly mise,Missionsziele,Στόχοι Αποστολής,Misiobjektivoj,Objetivos de misión,,Tehtävätavoitteet,Objectifs de Mission,Küldetési célok,Obiettivi della missione,ミッションオブジェクト,임무 목록,Missiedoelen,Cele misji,Objetivos da missão,,Obiectivele Misiunii,Текущее задание,Циљ мисије -Keys list,CNTRLMNU_KEYS,,,,Seznam klíčů,Schlüsselliste,Λίστα Κλειδιών,Ŝlosilolisto,Lista de llaves,,Avainlista,Liste des Clés,Kulcslista,Lista delle chiavi,キー類リスト,열쇠 목록,Lijst van toetsen,Lista kluczy,Lista de chaves,,Listă Chei,Список ключей,Списка кључева +Keys list,CNTRLMNU_KEYS,,,,Seznam klíčů,Schlüsselliste,Λίστα Κλειδιών,Ŝlosilolisto,Lista de llaves,,Avainlista,Liste des Clés,Kulcslista,Lista delle chiavi,キー類リスト,열쇠 목록,Lijst van toetsen,Lista kluczy,Lista de teclas,,Listă Chei,Список ключей,Списка кључева Weapons/ammo/stats,CNTRLMNU_STATS,,,,Zbraně/munice/staty,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,Bronie/amunicja/statystyki,Armas/munição/estatísticas,,Arme/muniție/statistici,"Оружие, патроны и показатели",Оружје/муниција/статистика -Toggle Scoreboard,CNTRLMNU_TOGGLESCOREBOARD,,,,Zap. / Vyp. tabulku skóre,Punktetafel an/aus,Ενεργοποίηση Πίνακα Σκόρ,Baskuligi poentotabulon,Alternar Marcador,,Pistetaulun vaihtokytkin,Afficher Scores (alterner),Eredményjelző kapcsoló,Abilita/disabilita tabella punteggio,スコアボード切替,점수창 토글,Scorebord aan/uit,Włącz / Wyłącz tablicę wyników,Ativar/Desativar pontuação na tela,Ligar/desligar Pontuação no Ecrã,Comutator pentru Tabela de Marcaj,Таблица очков (перекл.),Табела (без држања) +Toggle Scoreboard,CNTRLMNU_TOGGLESCOREBOARD,,,,Přepnout tabulku skóre,Punktetafel an/aus,Ενεργοποίηση Πίνακα Σκόρ,Baskuligi poentotabulon,Alternar Marcador,,Pistetaulun vaihtokytkin,Afficher Scores (alterner),Eredményjelző kapcsoló,Abilita/disabilita tabella punteggio,スコアボード切替,점수창 토글,Scorebord aan/uit,Włącz / Wyłącz tablicę wyników,Ativar/desativar placar,Ligar/desligar Pontuação no Ecrã,Comutator pentru Tabela de Marcaj,Таблица очков (перекл.),Табела (без држања) 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,Передвижение мышью,Покрет мишем 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,Движение боком мышью,Стрејф мишем ,,Map colors,,,,,,,,,,,,,,,,,,,,, @@ -2633,89 +2633,89 @@ You,MAPCOLORMNU_YOURCOLOR,,,,Ty,Du,,Vi,Tú,,Sinä,Votre couleur,Te,Tu,自分,당 2-sided walls with 3D floors,MAPCOLORMNU_EFWALLCOLOR,,,,Oboustranné zdi s 3D podlahami,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,Dwustronne ściany z piętrami 3D,Paredes de 2 lados com pisos 3D,,Pereți cu două fețe si podele 3D,Двусторонние стены с разными полами,Двострани зид са 3D нивоима Map grid,MAPCOLORMNU_GRIDCOLOR,,,,Mřížka,Kartengitter,,Mapkrado,Cuadrícula del mapa,Rejilla del mapa,Kartan ruudukko,Quadrillage,Pálya szél,Griglia mappa,マップグリッド,맵 격자,Kaart raster,Siatka mapy,Grade do mapa,Grelha do mapa,Grilă hartă,Цвет сетки,Мапа координатне мреже Center point,MAPCOLORMNU_XHAIRCOLOR,,,Centre point,Středobod,Mittelpunkt,,Centra punkto,Punto central,,Keskipiste,Point Central,Pálya közepe,Punto centrale,中心点,중간 지점,Middenpunt,Środek,Ponto central,,Punct în centru,Курсор,Централна тачка -Not-yet-seen walls,MAPCOLORMNU_NOTSEENCOLOR,,,,Neobjevené zdi,Ungesehene Wände,,Ne-ankoraŭ-viditaj 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,Jeszcze niewidziane ściany,Paredes não vistas até o momento,,Ziduri încă neobservate,Необнаруженные стены,Неоткривени зидови +Not-yet-seen walls,MAPCOLORMNU_NOTSEENCOLOR,,,,Neobjevené zdi,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,Jeszcze niewidziane ściany,Paredes não vistas até o momento,,Ziduri încă neobservate,Необнаруженные стены,Неоткривени зидови Locked doors,MAPCOLORMNU_LOCKEDCOLOR,,,,Zamčené dveře,Verschlossene Türen,,Ŝlositaj pordoj,Puertas bloqueadas,,Lukitut ovet,Portes verouillées,Zárt ajtók,Porte bloccate,鍵の掛かったドア,잠긴 문들,Gesloten deuren,Zablokowane drzwi,Portas trancadas,,Uși închise,Запертые двери,Закључана врата Teleporter to the same map,MAPCOLORMNU_INTRALEVELCOLOR,,,,Teleportér,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 do tej samej mapy,Teletransportador para o mesmo mapa,,Teleportor către aceeași hartă,Телепорт в пределах уровня,Телепортер до истог нивоа Teleporter to a different map,MAPCOLORMNU_INTERLEVELCOLOR,,,,Teleportér do jiného levelu,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 do innej mapy,Teletransportador para outro mapa,,Teleportor către altă hartă,Телепорт на другой уровень,Телепортер до различитог нивоа -Secret sector,MAPCOLORMNU_SECRETSECTORCOLOR,,,,Tajný sektor,Geheimer Sektor,,Sekreta sektoro,Sector secreto,,Salasektori,Secteur Secret,Rejtekhely szektora,Settore segreto,シークレット,비밀 섹터,Geheime sector,Sekretny sektor,Setor secreto,,Sector secret,Тайный сектор,Тајни сектор -Unexplored secret,MAPCOLORMNU_UNEXPLOREDSECRETCOLOR,,,,Neobjevená tajemství,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,Niezbadany sekret,Segredo não-explorado,,Secret neexplorat,Необнаруженный тайник,Ноткривена тајна +Secret sector,MAPCOLORMNU_SECRETSECTORCOLOR,,,,Skrýš,Geheimer Sektor,,Sekreta sektoro,Sector secreto,,Salasektori,Secteur Secret,Rejtekhely szektora,Settore segreto,シークレット,비밀 섹터,Geheime sector,Sekretny sektor,Setor secreto,,Sector secret,Тайный сектор,Тајни сектор +Unexplored secret,MAPCOLORMNU_UNEXPLOREDSECRETCOLOR,,,,Neobjevená skrýš,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,Niezbadany sekret,Segredo não-explorado,,Secret neexplorat,Необнаруженный тайник,Ноткривена тајна Special trigger lines,MAPCOLORMNU_SPECIALWALLCOLOR,,,,Akční čáry,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,Specjalne linie przełączników,Linhas de ativação especiais,,Linii declașatoare speciale,Специальные триггер-линии,Специјалне линије окидача -Cheat Mode,MAPCOLORMNU_CHEATMODE,,,,Cheatovací režim,Cheat-Modus,,Tromp-Reĝimo,Modo de truco,,Huijaustila,Mode Cheat,Csalás mód,Modalità cheat,チートモード時,치트 모드,Bedriegingsmodus,Tryb oszustwa,Modo Trapaça,Modo de Batota,Modul Trișor,Чит-режим,Чит мод +Cheat Mode,MAPCOLORMNU_CHEATMODE,,,,Cheatovací režim,Cheat-Modus,,Tromp-Reĝimo,Modo de truco,,Huijaustila,Mode Cheat,Csalás mód,Modalità cheat,チートモード時,치트 모드,Bedriegingsmodus,Tryb oszustwa,Modo trapaça,Modo de Batota,Modul Trișor,Чит-режим,Чит мод Invisible 2-sided walls,MAPCOLORMNU_TSWALLCOLOR,,,,Neviditelné oboustranné zdi,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,Niewidzialne dwustronne ściany,Paredes invisíveis de 2 lados,,Pereți cu două fețe invizibili,Невидимые двусторонние стены,Невидљиви двострани зидови Secret walls,MAPCOLORMNU_SECRETWALLCOLOR,,,,Tajné zdi,Geheime Wände,,Sekretaj muroj,Paredes secretas,,Salaiset seinät,Murs Secrets,Titkos falak,Muri segreti,シークレットの壁,비밀 벽,Geheime muren,Sekretne ściany,Paredes secretas,,Pereți ascunși,Тайные стены,Тајни зидови -Actors,MAPCOLORMNU_THINGCOLOR,,,,Objekty,Akteure,,Aktoroj,Actores,,Oliot,Acteurs,Játékos,Attori,アクター,개체,Acteurs,Aktorzy,Atores,,Actori,Акторы,Актори +Actors,MAPCOLORMNU_THINGCOLOR,,,,Objekty,Akteure,,Aktoroj,Actores,,Oliot,Acteurs,Játékos,Attori,アクター,개체,Acteurs,Aktorzy,Atores,,Actori,Объекты,Актори Monsters,MAPCOLORMNU_MONSTERCOLOR,,,,Příšery,Monster,,Monstroj,Monstruos,,Hirviöt,Monstres,Szörnyek,Mostri,モンスター,적들,Monsters,Potwory,Monstros,,Monștri,Монстры,Чудовишта -Non-counting Monsters,MAPCOLORMNU_NONCOUNTINGMONSTERCOLOR,,,,Nepočítané příšery,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,Niezliczane Potwory,Monstros Não Contados,,Monștri neacoperiți de numărătoare,Неучитываемые монстры,Не рачунајући чудовишта +Non-counting Monsters,MAPCOLORMNU_NONCOUNTINGMONSTERCOLOR,,,,Nepočítané příšery,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,Niezliczane Potwory,Monstros não contados,,Monștri neacoperiți de numărătoare,Неучитываемые монстры,Не рачунајући чудовишта Friends,MAPCOLORMNU_FRIENDCOLOR,,,,Přátelé,Freunde,,Amikoj,Amigos,,Omat,Amis,Barátok,Amici,仲間,친구들,Vrienden,Przyjaciele,Amigos,,Prieteni,Дружественные,Пријатељи Items,MAPCOLORMNU_ITEMCOLOR,,,,Předměty,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Przedmioty,Itens,,Obiecte,Предметы,Предмети -Count Items,MAPCOLORMNU_COUNTITEMCOLOR,,,,Počítané předměty,gezählte Gegenstände,,Nombri Objektojn,Objetos contados,Conteo de objetos,Laske esineet,Objets comptés,Tárgyak számolása,Oggetti contati,カウント対象アイテム,아이템 계산,Tellen,Zlicz przedmioty,Itens Contados,,Numără obiectele,Учитываемые предметы,Рачунајући предмети -Overlay Mode,MAPCOLORMNU_OVERLAY,,,,Překryvný režim,Überlagerungsmodus,,Surmeto-Reĝimo,Modo sobrepuesto,,Projisointitila,Mode surimpression,Overlay mód,Modalità sovrapposizione,オーバーレイモード,오버레이 모드,Overlaadmodus,Tryb Nakładki,Modo de Sobreposição,,Mod acoperit,Прозрачный режим,Провидна аутомапа -Overlay Cheat Mode,MAPCOLORMNU_OVCHEATMODE,,,,Překryvný cheatovací režim,Überlagerungsmodus Cheats,,Surmeto-Tromp-Reĝimo,Sobreposición modo de truco,,Projisointihuijaustila,Mode Cheat Surimpression,overlay csaló mód,Modalità cheat sovrapposizione,オーバーレイ チートモード,치트 모드 오버레이,Overlaadmodus Cheats,Tryb Nakładki Oszustwa,Modo Trapaça de Sobreposição,Modo Batota de Sobreposição,Mod acoperit trișor,Прозрачный чит-режим,Провидни читови +Count Items,MAPCOLORMNU_COUNTITEMCOLOR,,,,Počítané předměty,gezählte Gegenstände,,Nombri Objektojn,Objetos contados,Conteo de objetos,Laske esineet,Objets comptés,Tárgyak számolása,Oggetti contati,カウント対象アイテム,아이템 계산,Tellen,Zlicz przedmioty,Itens contados,,Numără obiectele,Учитываемые предметы,Рачунајући предмети +Overlay Mode,MAPCOLORMNU_OVERLAY,,,,Překryvný režim,Überlagerungsmodus,,Surmeto-Reĝimo,Modo sobrepuesto,,Projisointitila,Mode surimpression,Overlay mód,Modalità sovrapposizione,オーバーレイモード,오버레이 모드,Overlaadmodus,Tryb Nakładki,Modo de sobreposição,,Mod acoperit,Прозрачный режим,Провидна аутомапа +Overlay Cheat Mode,MAPCOLORMNU_OVCHEATMODE,,,,Překryvný cheatovací režim,Überlagerungsmodus Cheats,,Surmeto-Tromp-Reĝimo,Sobreposición modo de truco,,Projisointihuijaustila,Mode Cheat Surimpression,overlay csaló mód,Modalità cheat sovrapposizione,オーバーレイ チートモード,치트 모드 오버레이,Overlaadmodus Cheats,Tryb Nakładki Oszustwa,Modo trapaça de sobreposição,Modo Batota de Sobreposição,Mod acoperit trișor,Прозрачный чит-режим,Провидни читови Portal Overlays,MAPCOLORMNU_PORTAL,,,,Portálové překryvy,Portalüberlagerung,,Portalo-Surmetoj,Sobreposición de portal,,Portaaliprojisoinnit,Portails superposés,Portál overlay-ek,Sovrapposizioni del portale,ポータル オーバーレイ,포탈 오버레이,Portaaloverlays,Nakładanie się Portali,Sobreposição de portais,,Acoperiri portaluri,Порталы в прозрачном режиме,Провидни портали ,,Messages,,,,,,,,,,,,,,,,,,,,, -Messages,MSGMNU_TITLE,,,,Zprávy,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지들,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке -Show messages,MSGMNU_SHOWMESSAGES,,,,Zobrazit zprávy,Zeige Nachrichten,,Montri mesaĝojn,Mostrar Mensajes,,Näytä viestit,Afficher messages,Üzenetek mutatása,Mostra messaggi,メッセージ表示,메시지 표시,Berichten tonen,Pokaż wiadomości,Mostrar mensagens,,Afișare mesaje,Отображение сообщений,Прикажи поруке -Show obituaries,MSGMNU_SHOWOBITUARIES,,,,Zobrazit zprávy o smrtích,Zeige Todesanzeigen,,Montri nekrologojn,Mostrar obituarios,,Näytä kuolinviestit,Afficher avis de décès,Halálok mutatása,Mostra i necrologi,訃報表示,사망 메시지 표시,Doodsbrieven tonen,Pokaż nekrologi,Mostrar obituários,,Afișare necrologuri,Отображение некрологов,Прикажи читуље -Show secret notifications,MSGMNU_SHOWSECRETS,,,,Zobrazit upozornění na tajemství,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,Pokaż wiadomości znalezienia sekretu,Mostrar notificação de segredos,,Afișare notificări pentru secrete,Отображение сообщений о тайниках,Прикажи тајне нотификације -Minimum message level,MSGMNU_MESSAGELEVEL,,,,Minimální úroveň zpráv,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,Poziom minimalnych wiadomości,Nível mínimo de mensagem,,Nivel minim de afișare mesaje,Минимальный уровень сообщений,Минимум левел порука -Message Colors,MSGMNU_MESSAGECOLORS,,,Message Colours,Barva zpráv,Nachrichtenfarben,,Mesaĝkoloroj,Colores de los Mensajes,,Viestien värit,Couleur des messages,Üzenet színek,Colore dei messaggi,メッセージ色,메시지 색상,Bericht Kleuren,Kolory Wiadomości,Cores de Mensagem,,Culori Mesaje,Цвета сообщений,Боје порука -Item Pickup,MSGMNU_ITEMPICKUP,,,,Sebrání předmětu,Genommene Gegenstände,,Objektoprenado,Toma de objetos,,Esineen poimiminen,Objets ramassés,Tárgy felvétele,Raccolta oggetti,アイテム取得,아이템 획득,Puntafhaling,Podniesienie Przedmiotu,Coleta de Item,Aquisição de Itens,Ridicare obiecte,Подбор предмета,Покупити предмет -Obituaries,MSGMNU_OBITUARIES,,,,Zprávy o úmrtí,Todesanzeigen,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologi,死亡時メッセージ,사망 메시지,Doodsbrieven,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље -Critical Messages,MSGMNU_CRITICALMESSAGES,,,,Kritické zprávy,Kritische Nachrichten,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages d'erreur,Fontos üzenetek,Messaggi critici,致命的なメッセージ,중요한 메시지,Kritische berichten,Wiadomości krytyczne,Mensagens Críticas,,Mesaje Critice,Важные сообщения,Критичне поруке -Chat Messages,MSGMNU_CHATMESSAGES,,,,Chatové zprávy,Chatnachrichten,,Babilmesaĝoj,Mensajes de chat,,Keskusteluviestit,Message de Chat,Chat üzenetek,Messaggi chat,チャットメッセージ,채팅 메시지,Chatberichten,Wiadomości czatu,Mensagens de Chat,,Mesaje Conversație,Сообщения в чате,Ћаскања -Team Messages,MSGMNU_TEAMMESSAGES,,,,Týmové zprávy,Teamnachrichten,,Teammesaĝoj,Mensajes de equipo,,Joukkueen viestit,Messages d'équipe,Csapat chat üzenetek,Messaggi chat di squadra,チームメッセージ,팀 채팅 메시지,Team Berichten,Wiadomości czatu drużynowego,Mensagens de Equipe,Mensagens de Equipa,Mesajele Echipei Proprii,Командные сообщения в чате,Тимске поруке -Centered Messages,MSGMNU_CENTEREDMESSAGES,,,Centred Messages,Vycentrované zprávy,Zentrierte Nachrichten,,Centritaj Mesaĝoj,Mensajes centrados,,Keskitetyt viestit,Messages centrés,Üzenet középre igazítása,Messaggi centrati,スクリプトメッセージ,중간에 위치한 메시지,Gecentreerde berichten,Wyśrodkowane wiadomości,Mensagens Centralizadas,Mensagens Centradas,Mesaje Centrate,Центрированные сообщения,Централне поруке -Screenshot messages,MSGMNU_SCREENSHOTMESSAGES,,,,Zprávy o snímcích obrazovky,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,Wiadomości o zrobieniu zrzutu ekranu,Mensagens de captura de tela,Mensagen de captura de ecrã,Mesaje Capturi Ecran,Сообщения о скриншотах,Скриншот поруке -Detailed save messages,MSGMNU_LONGSAVEMESSAGES,,,,Detailní zprávy o uložené hře,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,Szczegółowe wiadomości o zapisie,Mensagens detalhadas de salvamento,Mensagens detalhadas de gravação,Mesaje detaliate pentru salvări,Подробные сообщения о сохранениях,Детаљно сачуване поруке -Developer message mode,MSGMNU_DEVELOPER,,,,Vývojářský režim zpráv,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,Tryb wiadomości deweloperskich,Modo de mensagens de desenvolvedor,,Mod mesaje pentru dezvoltator,Режим сообщений для разработчиков,Поруке девелопера +Messages,MSGMNU_TITLE,,,,Nastavení oznámení,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,,Üzenetek,Messaggi,メッセージ類,메시지들,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке +Show messages,MSGMNU_SHOWMESSAGES,,,,Zobrazit oznámení,Zeige Nachrichten,,Montri mesaĝojn,Mostrar Mensajes,,Näytä viestit,Afficher messages,Üzenetek mutatása,Mostra messaggi,メッセージ表示,메시지 표시,Berichten tonen,Pokaż wiadomości,Exibir mensagens,,Afișare mesaje,Отображение сообщений,Прикажи поруке +Show obituaries,MSGMNU_SHOWOBITUARIES,,,,Zobrazit oznámení o smrtích,Zeige Todesanzeigen,,Montri nekrologojn,Mostrar obituarios,,Näytä kuolinviestit,Afficher avis de décès,Halálok mutatása,Mostra i necrologi,訃報表示,사망 메시지 표시,Doodsbrieven tonen,Pokaż nekrologi,Exibir obituários,,Afișare necrologuri,Отображение некрологов,Прикажи читуље +Show secret notifications,MSGMNU_SHOWSECRETS,,,,Zobrazit zprávy o skrýších,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,Pokaż wiadomości znalezienia sekretu,Exibir notificação de segredos,,Afișare notificări pentru secrete,Отображение сообщений о тайниках,Прикажи тајне нотификације +Minimum message level,MSGMNU_MESSAGELEVEL,,,,Minimální úroveň oznámení,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,Poziom minimalnych wiadomości,Nível mínimo de mensagem,,Nivel minim de afișare mesaje,Минимальный уровень сообщений,Минимум левел порука +Message Colors,MSGMNU_MESSAGECOLORS,,,Message Colours,Barva oznámení,Nachrichtenfarben,,Mesaĝkoloroj,Colores de los Mensajes,,Viestien värit,Couleur des messages,Üzenet színek,Colore dei messaggi,メッセージ色,메시지 색상,Bericht Kleuren,Kolory Wiadomości,Cores de mensagem,,Culori Mesaje,Цвета сообщений,Боје порука +Item Pickup,MSGMNU_ITEMPICKUP,,,,Sebrání předmětu,Genommene Gegenstände,,Objektoprenado,Toma de objetos,,Esineen poimiminen,Objets ramassés,Tárgy felvétele,Raccolta oggetti,アイテム取得,아이템 획득,Puntafhaling,Podniesienie Przedmiotu,Coleta de item,Aquisição de Itens,Ridicare obiecte,Подбор предмета,Покупити предмет +Obituaries,MSGMNU_OBITUARIES,,,,Oznámení o úmrtí,Todesanzeigen,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologi,死亡時メッセージ,사망 메시지,Doodsbrieven,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље +Critical Messages,MSGMNU_CRITICALMESSAGES,,,,Kritická oznámení,Kritische Nachrichten,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages d'erreur,Fontos üzenetek,Messaggi critici,致命的なメッセージ,중요한 메시지,Kritische berichten,Wiadomości krytyczne,Mensagens críticas,,Mesaje Critice,Важные сообщения,Критичне поруке +Chat Messages,MSGMNU_CHATMESSAGES,,,,Chatová oznámení,Chatnachrichten,,Babilmesaĝoj,Mensajes de chat,,Keskusteluviestit,Message de Chat,Chat üzenetek,Messaggi chat,チャットメッセージ,채팅 메시지,Chatberichten,Wiadomości czatu,Mensagens de chat,,Mesaje Conversație,Сообщения в чате,Ћаскања +Team Messages,MSGMNU_TEAMMESSAGES,,,,Týmová oznámení,Teamnachrichten,,Teammesaĝoj,Mensajes de equipo,,Joukkueen viestit,Messages d'équipe,Csapat chat üzenetek,Messaggi chat di squadra,チームメッセージ,팀 채팅 메시지,Team Berichten,Wiadomości czatu drużynowego,Mensagens de equipe,Mensagens de Equipa,Mesajele Echipei Proprii,Командные сообщения в чате,Тимске поруке +Centered Messages,MSGMNU_CENTEREDMESSAGES,,,Centred Messages,Oznámení na střed,Zentrierte Nachrichten,,Centritaj Mesaĝoj,Mensajes centrados,,Keskitetyt viestit,Messages centrés,Üzenet középre igazítása,Messaggi centrati,スクリプトメッセージ,중간에 위치한 메시지,Gecentreerde berichten,Wyśrodkowane wiadomości,Mensagens centralizadas,Mensagens Centradas,Mesaje Centrate,Центрированные сообщения,Централне поруке +Screenshot messages,MSGMNU_SCREENSHOTMESSAGES,,,,Oznámení o snímcích obrazovky,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,Wiadomości o zrobieniu zrzutu ekranu,Mensagens de captura de tela,Mensagen de captura de ecrã,Mesaje Capturi Ecran,Сообщения о скриншотах,Скриншот поруке +Detailed save messages,MSGMNU_LONGSAVEMESSAGES,,,,Detailní oznámení o uložené hře,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,Szczegółowe wiadomości o zapisie,Mensagens detalhadas de salvamento,Mensagens detalhadas de gravação,Mesaje detaliate pentru salvări,Подробные сообщения о сохранениях,Детаљно сачуване поруке +Developer message mode,MSGMNU_DEVELOPER,,,,Vývojářská oznámení,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,Tryb wiadomości deweloperskich,Modo de mensagens de desenvolvedor,,Mod mesaje pentru dezvoltator,Режим сообщений для разработчиков,Поруке девелопера ,,Automap,,,,,,,,,,,,,,,,,,,,, -Map color set,AUTOMAPMNU_COLORSET,,,Map colour set,Nastavit barvy mapy,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,Zestaw kolorów mapy,Definir cores de mapa,,Set culori hartă,Цвета автокарты,Боје за мапу -Allow map defined colors,AUTOMAPMNU_CUSTOMCOLORS,,,Allow map defined colours,Povolit barvy nastavené v modech,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,Pozwól na kolory zdefiniowne przez mapę,Permitir cores definidas por mapa,,Permite culorilor să fie definite de hartă,Настроить цвета автокарты,Дозволи дефинисане боје за мапу -Set custom colors,AUTOMAPMNU_SETCUSTOMCOLORS,,,Set custom colours,Nastavit vlastní barvy,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,Spersonalizuj kolory,Definir cores personalizadas,,Setare culori personalizate,Выбор цветов,Промени боје -Customize map controls,AUTOMAPMNU_CONTROLS,,,,Nastavit ovládání mapy,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,Ustaw klawisze mapy,Configurar comandos de mapa,,Personalizare schemă de control a hărții,Управление,Промени контроле мапе -Overlay automap,AUTOMAPMNU_OVERLAY,,,,Použít překryvnou mapu,Überlagere Automap,,Surmeti aŭtomapon,Superponer automapa,,Projisoi automaattikartta,Carte en Surimpression,,Copri l'automappa,オートマップを重ねる,오토맵을 오버레이,Overlay automap,Nałożenie mapy,Sobreposição de automapa,,Acoperire hartă computerizată,Прозрачная автокарта,Провидна аутомапа -Enable textured display,AUTOMAPMNU_TEXTURED,,,,Povolit textury,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,Włącz oteksturowanie mapy,Habilitar automapa texturizado,Permitir automapa texturizado,Activare mod texturat,Текстуры на автокарте,Омогући приказ текстура -Show item counts,AUTOMAPMNU_SHOWITEMS,,,,Zobrazit počet předmětů,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,Pokaż liczbę przedmiotów,Mostrar contagem de itens,,Afișare numărătoare obiecte,Количество предметов,Прикажи бројач за предмете -Show monster counts,AUTOMAPMNU_SHOWMONSTERS,,,,Zobrazit počet příšer,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,Pokaż liczbę potworów,Mostrar contagem de monstros,,Afișare numărătoare monștri,Количество монстов,Прикажи бројач за чудовишта -Show secret counts,AUTOMAPMNU_SHOWSECRETS,,,,Zobrazit počet tajemství,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,Pokaż liczbę sekretów,Mostrar contagem de segredos,,Afișare numărătoare secrete,Количество тайников,Прикажи бројач за тајне -Show time elapsed,AUTOMAPMNU_SHOWTIME,,,,Zobrazit uplynulý čas,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,Pokaż ile czasu upłynęło,Mostrar tempo decorrido,,Afișare timp petrecut pe hartă,Прошедшее время,Прикажи протекло време -Show total time elapsed,AUTOMAPMNU_SHOWTOTALTIME,,,,Zobrazit celkový uplynulý čas,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,"Pokaż całkowity czas, który upłynął",Mostrar tempo total decorrido,,Afișare timp total petrecut în joc,Общее время,Прикажи укупно протекло време -Show secrets on map,AUTOMAPMNU_MAPSECRETS,,,,Zobrazit tajemství na mapě,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,Pokaż sekrety na mapie,Mostrar segredos no mapa,,Afișare secrete,Тайники на карте,Прикажи тајне на аутомапи -Show map label,AUTOMAPMNU_SHOWMAPLABEL,,,,Zobrazit kód mapy,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,Pokaż etykietę mapy,Mostrar etiqueta do mapa,,Afișare etichetă hartă,Название карты,Прикажи ознаку мапе -Draw map background,AUTOMAPMNU_DRAWMAPBACK,,,,Vykreslovat pozadí mapy,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,Rysuj tło mapy,Desenhar fundo do mapa,,Afișare fundal hartă,Отображать фон автокарты,Нацртај позадину мапе -Show keys (cheat),AUTOMAPMNU_SHOWKEYS,,,,Zobrazovat klíče (cheat),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),Pokaż klucze (oszustwo),Mostrar chaves (trapaça),,Afișare chei (trișare),Отображать ключи (только чит),Прикажи кључеве (чит) -Show trigger lines,AUTOMAPMNU_SHOWTRIGGERLINES,,,,Zobrazovat aktivující čáry,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,Pokaż linie przełączników,Mostrar linhas de ativação,,Afișare linii declanșatoare,Отображать триггеры,Прикажи триггер линије -Show things as sprites,AUTOMAPMNU_SHOWTHINGSPRITES,,,,Zobrazit objekty jako sprity,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,Pokaż rzeczy jako sprite'y,Mostrar objetos como sprites,,Afișare obiecte drept sprite,Отображать спрайты предметов,Прикажи ствари као спрајтове +Map color set,AUTOMAPMNU_COLORSET,,,Map colour set,Barevné schéma,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,Zestaw kolorów mapy,Definir cores de mapa,,Set culori hartă,Цвета автокарты,Боје за мапу +Allow map defined colors,AUTOMAPMNU_CUSTOMCOLORS,,,Allow map defined colours,Povolit barvy dle modů,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,Pozwól na kolory zdefiniowne przez mapę,Permitir cores definidas por mapa,,Permite culorilor să fie definite de hartă,Настроить цвета автокарты,Дозволи дефинисане боје за мапу +Set custom colors,AUTOMAPMNU_SETCUSTOMCOLORS,,,Set custom colours,Vlastní barvy,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,Spersonalizuj kolory,Definir cores personalizadas,,Setare culori personalizate,Выбор цветов,Промени боје +Customize map controls,AUTOMAPMNU_CONTROLS,,,,Ovládání mapy,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,Ustaw klawisze mapy,Configurar comandos de mapa,,Personalizare schemă de control a hărții,Управление,Промени контроле мапе +Overlay automap,AUTOMAPMNU_OVERLAY,,,,Překryvná mapa,Überlagere Automap,,Surmeti aŭtomapon,Superponer automapa,,Projisoi automaattikartta,Carte en Surimpression,Képen felüli térkép,Copri l'automappa,オートマップを重ねる,오토맵을 오버레이,Overlay automap,Nałożenie mapy,Sobreposição de automapa,,Acoperire hartă computerizată,Прозрачная автокарта,Провидна аутомапа +Enable textured display,AUTOMAPMNU_TEXTURED,,,,Textury,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,Włącz oteksturowanie mapy,Habilitar automapa texturizado,Permitir automapa texturizado,Activare mod texturat,Текстуры на автокарте,Омогући приказ текстура +Show item counts,AUTOMAPMNU_SHOWITEMS,,,,Počet předmětů,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,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișare numărătoare obiecte,Количество предметов,Прикажи бројач за предмете +Show monster counts,AUTOMAPMNU_SHOWMONSTERS,,,,Počet příšer,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,Pokaż liczbę potworów,Exibir contagem de monstros,,Afișare numărătoare monștri,Количество монстов,Прикажи бројач за чудовишта +Show secret counts,AUTOMAPMNU_SHOWSECRETS,,,,Počet skrýší,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,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișare numărătoare secrete,Количество тайников,Прикажи бројач за тајне +Show time elapsed,AUTOMAPMNU_SHOWTIME,,,,Uplynulý čas na mapě,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,Pokaż ile czasu upłynęło,Exibir tempo decorrido,,Afișare timp petrecut pe hartă,Прошедшее время,Прикажи протекло време +Show total time elapsed,AUTOMAPMNU_SHOWTOTALTIME,,,,Celkový uplynulý čas,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,"Pokaż całkowity czas, który upłynął",Exibir tempo total decorrido,,Afișare timp total petrecut în joc,Общее время,Прикажи укупно протекло време +Show secrets on map,AUTOMAPMNU_MAPSECRETS,,,,Zobrazit skrýše,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,Pokaż sekrety na mapie,Exibir segredos no mapa,,Afișare secrete,Тайники на карте,Прикажи тајне на аутомапи +Show map label,AUTOMAPMNU_SHOWMAPLABEL,,,,Zobrazit název mapy,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,Pokaż etykietę mapy,Exibir etiqueta do mapa,,Afișare etichetă hartă,Название карты,Прикажи ознаку мапе +Draw map background,AUTOMAPMNU_DRAWMAPBACK,,,,Pozadí mapy,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,Rysuj tło mapy,Desenhar fundo do mapa,,Afișare fundal hartă,Отображать фон автокарты,Нацртај позадину мапе +Show keys (cheat),AUTOMAPMNU_SHOWKEYS,,,,Zobrazení klíčů (podvod),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),Pokaż klucze (oszustwo),Exibir chaves (trapaça),,Afișare chei (trișare),Отображать ключи (чит-коды),Прикажи кључеве (чит) +Show trigger lines,AUTOMAPMNU_SHOWTRIGGERLINES,,,,Zobrazení aktivujících čar,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,Pokaż linie przełączników,Exibir linhas de ativação,,Afișare linii declanșatoare,Отображать триггеры,Прикажи триггер линије +Show things as sprites,AUTOMAPMNU_SHOWTHINGSPRITES,,,,Zobrazení objektů jako spritů,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,Pokaż rzeczy jako sprite'y,Exibir objetos como sprites,,Afișare obiecte drept sprite,Отображать спрайты предметов,Прикажи ствари као спрајтове Overlay portals,AUTOMAPMNU_PTOVERLAY,,,,Překrývat portály,Überlagere Portale,,Surmeti portalojn,Sobreponer portales,,Projisoi portaalit,Superposer les portails,Overlay portálok,Sovrapponi i portali,オーバーレイ ポータルズ,포탈을 오버레이,Overlappende portalen,Nałóż portale,Sobreposição de portais,,Acoperire portaluri,Порталы в прозрачном режиме,Провидни портали Empty space margin,AUTOMAPMNU_EMPTYSPACEMARGIN,,,,Práh prázdného prostoru,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,Opróżnij margines przestrzeni,Margem de espaço vazio,,Margine spațiu gol,Край автокарты,Празна маргина -Mark font,AUTOMAPMNU_MARKFONT,,,,Font značek,Zeichensatz für Markierungen,,Marki tiparon,Fuente para Marcas,,Karttamerkkien fontti,Police Marqueur,Jelzés betűtípus,Font del segnaposto,マークフォント,미니맵 마킹 폰트,Font voor markers,Czcionka oznaczeń,Fonte das marcações,,Font marcaj,Шрифт отметок,Фонт ознака +Mark font,AUTOMAPMNU_MARKFONT,,,,Písmo značek,Zeichensatz für Markierungen,,Marki tiparon,Fuente para Marcas,,Karttamerkkien fontti,Police Marqueur,Jelzés betűtípus,Font del segnaposto,マークフォント,미니맵 마킹 폰트,Font voor markers,Czcionka oznaczeń,Fonte das marcações,,Font marcaj,Шрифт отметок,Фонт ознака Mark color,AUTOMAPMNU_MARKCOLOR,,,,Barva značek,Farbe für Markierungen,,Marki koloron,Color de las Marcas,,Karttamerkkien väri,Couleur Marqueur,Jelzés szín,Colore del segnaposto,マーク色,미니맵 마킹 색상,Markeer kleur,Kolor oznaczeń,Cor das marcações,,Culoare marcaj,Цвет отметок,Боја ознака Set mark,MAPCNTRLMNU_SETMARK,,,,Umístit značku,Setze Markierung,,Meti markon,Fijar marca,,Aseta merkki,Placer repère,Jelzés beállítása,Aggiungi segnaposto,マークを置く,마크 추가,Markering instellen,Ustaw znacznik,Posicionar marcação,,Marcare,Поставить отметку,Постави ознаку -Clear mark,MAPCNTRLMNU_CLEARMARK,,,,Vyčistit značky,Lösche Markierung,,Forigi markon,Limpiar marca,,Pyyhi merkit,Enlever repères,Jelzések törlése,Pulisci il segnaposto,マーククリア,마크 삭제,Duidelijke markering,Usuń znacznik,Limpar marcação,,Ștergere marcaj,Убрать отметку,Уклони ознаку +Clear mark,MAPCNTRLMNU_CLEARMARK,,,,Smazat značky,Lösche Markierung,,Forigi markon,Limpiar marca,,Pyyhi merkit,Enlever repères,Jelzések törlése,Pulisci il segnaposto,マーククリア,마크 삭제,Duidelijke markering,Usuń znacznik,Limpar marcação,,Ștergere marcaj,Убрать отметку,Уклони ознаку ,,Scoreboard,,,,,,,,,,,,,,,,,,,,, -Scoreboard Options,DSPLYMNU_SCOREBOARD,,,,Nastavení tabulky skóre,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Options Tableau des Scores,Eredményjelző beállítások,Opzioni tabella punteggio,スコアボード オプション,점수창 설정,Scorebord opties,Opcje Tablicy Wyników,Opções de Tela de Pontuação,,Opțiuni Tabelă de Marcaj,Таблица очков,Табеларне подешавања +Scoreboard Options,DSPLYMNU_SCOREBOARD,,,,Tabulka skóre,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Options Tableau des Scores,Eredményjelző beállítások,Opzioni tabella punteggio,スコアボード オプション,점수창 설정,Scorebord opties,Opcje Tablicy Wyników,Opções de Tela de Pontuação,,Opțiuni Tabelă de Marcaj,Таблица очков,Табеларне подешавања Scoreboard Options,SCRBRDMNU_TITLE,,,,Nastavení tabulky skóre,Punktetabellenoptionen,,Poentotabulo-Agordoj,Opciones de marcador,,Pistetauluasetukset,Tableau des Scores,Eredményjelző beállítások,Opzioni per la tabella punteggio,スコアボード オプション,점수판 설정,Scorebord opties,Opcje Tablicy Wyników,Opções de Tela de Pontuação,Opções do Ecrã de Pontuação,Setări Tabelă de Marcaj,Настройки таблицы очков,Подешавања бодовања -Cooperative Options,SCRBRDMNU_COOPERATIVE,,,,Nastavení co-op módu,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,Opcje Kooperacji,Opções de Jogo Cooperativo,,Setări Mod Cooperativ,Настройки для команд,Подешавања сарадње +Cooperative Options,SCRBRDMNU_COOPERATIVE,,,,Kooperativní mód,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,Opcje Kooperacji,Opções de Jogo Cooperativo,,Setări Mod Cooperativ,Настройки для команд,Подешавања сарадње Enable Scoreboard,SCRBRDMNU_ENABLE,,,,Povolit tabulku skóre,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,Zezwól na Tablicę Wyników,Habilitar Tela de Pontuação,Permitir Ecrã de Pontuação,Activare Tabelă de Marcaj,Включить таблицу очков,Омогући бодовање Header Color,SCRBRDMNU_HEADERCOLOR,,,Header Colour,Barva hlavičky,Kopfzeilenfarbe,,Kapokoloro,Color de cabecera,,Otsikon väri,Couleur du Titre,Fejléc szín,Colore della testata,ヘッダー色,헤더의 색깔,Kleur koptekst,Kolor Nagłówka,Cor de Cabeçalho,,Culoare Antet,Цвет заголовка,Боја заглавља Your Player Color,SCRBRDMNU_YOURCOLOR,,,Your Player Colour,Barva tvého hráče,Deine Spielerfarbe,,Via Ludantkoloro,Color de tu jugador,,Pelaajasi väri,Votre couleur,Játékos színe,Colore del giocatore 'Tu',自分の色,플레이어의 색깔,Uw Spelerskleur,Twoje Kolory,Cor do Seu Jogador,Cor do teu Jogador,Culoarea Jucătorului Tău,Ваш цвет,Боја твога играча Other Players' Color,SCRBRDMNU_OTHERPLAYERCOLOR,,,Other Players' Colour,Barva ostatních hráčů,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,Kolory Innych Graczy,Cor de Outros Jogadores,Cor dos Outros Jogadores,Culorile Celorlalți Jucători,Цвет других игроков,Боја другог играча -Deathmatch Options,SCRBRDMNU_DEATHMATCH,,,,Nastavení deathmatche,Deathmatch-Optionen,,Mortmaĉo-Agordoj,Opciones modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch Beállítások,Opzioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch opties,Opcje Deathmatchu,Opções de Deathmatch,,Setări Deathmatch,Настройки Deathmatch,Детмеч подешавања -Team Deathmatch Options,SCRBRDMNU_TEAMDEATHMATCH,,,,Nastavení týmového deathmatche,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,Opcje Drużynowego Deathmatchu,Opções de Deathmatch de Equipe,Opções de Deathmatch de Equipa,Setări Deathmatch în Echipă,Настройки командного Deathmatch,Тимски детмеч подешавања +Deathmatch Options,SCRBRDMNU_DEATHMATCH,,,,Deathmatch,Deathmatch-Optionen,,Mortmaĉo-Agordoj,Opciones modo a muerte,,Kuolonotteluasetukset,Options Deathmatch,Deathmatch Beállítások,Opzioni deathmatch,デスマッチの設定,데스매치 설정,Deathmatch opties,Opcje Deathmatchu,Opções de Deathmatch,,Setări Deathmatch,Настройки боя насмерть,Детмеч подешавања +Team Deathmatch Options,SCRBRDMNU_TEAMDEATHMATCH,,,,Týmový 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,Opcje Drużynowego Deathmatchu,Opções de Deathmatch de Equipe,Opções de Deathmatch de Equipa,Setări Deathmatch în Echipă,Настройки командного боя насмерть,Тимски детмеч подешавања ,,Alt HUD,,,,,,,,,,,,,,,,,,,,, -Alternative HUD,ALTHUDMNU_TITLE,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD Alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный HUD,Алтернативни HUD -Enable alternative HUD,ALTHUDMNU_ENABLE,,,,Povolit alternativní 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,Włącz alternatywny HUD,Habilitar HUD alternativo,,Activează Interfața pe Timp de Joc Alternativă,Альтернативный HUD,Укључи алтернативни HUD -Show secret count,ALTHUDMNU_SHOWSECRETS,,,,Zobrazit počet skrýší,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,Pokaż liczbę sekretów,Mostrar contagem de segredos,,Afișează numărul secretelor,Отображение обнаруженных тайников,Прикажи количину тајна -Show monster count,ALTHUDMNU_SHOWMONSTERS,,,,Zobrazit počet příšer,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,Pokaż liczbę zabójstw,Mostrar contagem de monstros,,Afișează numărul de monștri,Отображение количества монстров,Прикажи количину чудовишта -Show item count,ALTHUDMNU_SHOWITEMS,,,,Zobrazit počet předmětů,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,Pokaż liczbę przedmiotów,Mostrar contagem de itens,,Afișează numărul de obiecte,Отображение количества предметов,Прикажи количину предмета -Show stamina and accuracy,ALTHUDMNU_SHOWSTATS,,,,Zobrazit výdrž a přesnost,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,Pokaż wytrzymałość i precyzję,Mostrar resistência e precisão,,Afișează rezistența fizică si acuratețea,Отображение стойкости и точности,Прикажи издржљивост и прецизност -Show berserk,ALTHUDMNU_SHOWBERSERK,,,,Zobrazit berserk,Zeige Berserk,,Montri frenezecon,Mostrar berserker,,Näytä raivo,Afficher Berserk,Berserk mutatása,Mostra il berserk,バーサーク表示,버서크 아이템을 표시,Toon berserk,Pokaż szał,Mostrar berserk,,Afișează pachetul de forță mărită,Отображение берсерка,Прикажи берсерк -Show weapons,ALTHUDMNU_SHOWWEAPONS,,,,Zobrazit zbraně,Zeige Waffen,,Montri armojn,Mostrar armas,,Näytä aseet,Afficher Armes,Fegyverek mutatása,Mostra le armi,武器表示,무기들을 표시,Toon wapens,Pokaż bronie,Mostrar armas,,Afișează armele,Отображение оружия,Прикажи оружја -Show ammo for,ALTHUDMNU_SHOWAMMO,,,,Zobrazit munici pro,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,Pokaż amunicję dla,Mostrar munição para,,Afișează muniția pentru,Показывать патроны для,Прикажи муниције за -Show time,ALTHUDMNU_SHOWTIME,,,,Zobrazit čas,Zeige Zeit,,Montri tempon,Mostrar tiempo,,Näytä aika,Afficher temps niveau,Idő mutatása,Mostra il tempo,時間の表示,시간 표시,Toon tijd,Pokaż czas,Mostrar tempo,,Afișează timpul,Отображение времени,Прикажи време +Alternative HUD,ALTHUDMNU_TITLE,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD Alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный интерфейс,Алтернативни HUD +Enable alternative HUD,ALTHUDMNU_ENABLE,,,,Povolit alternativní 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,Włącz alternatywny HUD,Habilitar HUD alternativo,,Activează Interfața pe Timp de Joc Alternativă,Альтернативный интерфейс,Укључи алтернативни HUD +Show secret count,ALTHUDMNU_SHOWSECRETS,,,,Zobrazit počet skrýší,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,Pokaż liczbę sekretów,Exibir contagem de segredos,,Afișează numărul secretelor,Отображение обнаруженных тайников,Прикажи количину тајна +Show monster count,ALTHUDMNU_SHOWMONSTERS,,,,Zobrazit počet příšer,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,Pokaż liczbę zabójstw,Exibir contagem de monstros,,Afișează numărul de monștri,Отображение количества монстров,Прикажи количину чудовишта +Show item count,ALTHUDMNU_SHOWITEMS,,,,Zobrazit počet předmětů,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,Pokaż liczbę przedmiotów,Exibir contagem de itens,,Afișează numărul de obiecte,Отображение количества предметов,Прикажи количину предмета +Show stamina and accuracy,ALTHUDMNU_SHOWSTATS,,,,Zobrazit výdrž a přesnost,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,Pokaż wytrzymałość i precyzję,Exibir resistência e precisão,,Afișează rezistența fizică si acuratețea,Отображение стойкости и точности,Прикажи издржљивост и прецизност +Show berserk,ALTHUDMNU_SHOWBERSERK,,,,Zobrazit berserk,Zeige Berserk,,Montri frenezecon,Mostrar berserker,,Näytä raivo,Afficher Berserk,Berserk mutatása,Mostra il berserk,バーサーク表示,버서크 아이템을 표시,Toon berserk,Pokaż szał,Exibir berserk,,Afișează pachetul de forță mărită,Отображение берсерка,Прикажи берсерк +Show weapons,ALTHUDMNU_SHOWWEAPONS,,,,Zobrazit zbraně,Zeige Waffen,,Montri armojn,Mostrar armas,,Näytä aseet,Afficher Armes,Fegyverek mutatása,Mostra le armi,武器表示,무기들을 표시,Toon wapens,Pokaż bronie,Exibir armas,,Afișează armele,Отображение оружия,Прикажи оружја +Show ammo for,ALTHUDMNU_SHOWAMMO,,,,Zobrazit munici pro,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,Pokaż amunicję dla,Exibir munição para,,Afișează muniția pentru,Показывать патроны для,Прикажи муниције за +Show time,ALTHUDMNU_SHOWTIME,,,,Zobrazit čas,Zeige Zeit,,Montri tempon,Mostrar tiempo,,Näytä aika,Afficher temps niveau,Idő mutatása,Mostra il tempo,時間の表示,시간 표시,Toon tijd,Pokaż czas,Exibir tempo,,Afișează timpul,Отображение времени,Прикажи време Time color,ALTHUDMNU_TIMECOLOR,,,Time colour,Barva času,Zeiot-Farbe,,Tempkoloro,Color del tiempo,,Ajan väri,Couleur du timer,Idő színe,Colore del tempo,時間の字色,시간 색상,Tijdskleur,Kolor czasu,Cor do tempo,,Culoare timp,Цвет времени,Боја времена -Show network latency,ALTHUDMNU_SHOWLAG,,,,Zobrazit latenci sitě,Zeige Netzwerk-Latenz,,Montri reto-respondotempo,Mostrar latencia de red,,Näytä verkon viive,Afficher latence réseau,Válaszidő mutatása,Mostra la latenza del network,ネットのラグ表示,내트워크 트래픽 표시,Toon netwerklatentie,Pokaż czas oczekiwania sieci,Mostrar latência de rede,,Afișează perioada de întârziere a conexiunii,Отображение задержки сети,Прикажи кашњење мреже -Ammo display order,ALTHUDMNU_AMMOORDER,,,,Pořadí zobrazení munice,Munitionsreihenfolge,,Municividiga aranĝo,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,Kolejność pokazywania amunicji,Ordem de exibição de munição,,Ordine afișare muniție,Порядок отображения боеприпасов,Редослед муниција +Show network latency,ALTHUDMNU_SHOWLAG,,,,Zobrazit latenci sitě,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,Pokaż czas oczekiwania sieci,Exibir latência de rede,,Afișează perioada de întârziere a conexiunii,Отображение задержки сети,Прикажи кашњење мреже +Ammo display order,ALTHUDMNU_AMMOORDER,,,,Pořadí zobrazení munice,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,Kolejność pokazywania amunicji,Ordem de exibição de munição,,Ordine afișare muniție,Порядок отображения боеприпасов,Редослед муниција Red ammo display below %,ALTHUDMNU_AMMORED,,,,Červený indikátor munice pod %,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 %,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 %,"Отображение боеприпасов красным ниже, %",Прикажи муниције црвеном испод % Yellow ammo display below %,ALTHUDMNU_AMMOYELLOW,,,,Žlutý indikátor munice pod %,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 %,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 %,"Отображение боеприпасов жёлтым ниже, %",Прикажи муниције жутом испод % Red health display below,ALTHUDMNU_HEALTHRED,,,,Červený indikátor zdraví pod,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,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 %,"Отображение здоровья красным ниже, %",Прикажи здравље црвеном испод @@ -2724,7 +2724,7 @@ Green health display below,ALTHUDMNU_HEALTHGREEN,,,,Zelený indikátor zdraví p Red armor display below,ALTHUDMNU_ARMORRED,,,Red armour display below,Červený indikátor brnění pod,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,Wyświetl czerwony pancerz pod ,Porcentagem de armadura em vermelho até,Percentagem de armadura em vermelho até,Armura schimbă culoarea în galben sub %,"Отображение брони красным ниже, %",Прикажи оклоп црвеном испод Yellow armor display below,ALTHUDMNU_ARMORYELLOW,,,Yellow armour display below,Žlutý indikátor brnění pod,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,Wyświetl żółty pancerz pod ,Porcentagem de armadura em amarelo até,Percentagem de armadura em amarelo até,Armura schimbă culoarea în galben sub %,"Отображение брони жёлтым ниже, %",Прикажи оклоп жутом испод Green armor display below,ALTHUDMNU_ARMORGREEN,,,Green armour display below,Zelený indikátor brnění pod,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,Wyświetl zielony pancerz pod ,Porcentagem de armadura em verde até,Percentagem de armadura em verde até,Armura schimbă culoarea în verde sub %,"Отображение брони зелёным ниже, %",Прикажи оклоп зеленом испод -Alternative Automap HUD,ALTHUDMNU_AUTOMAPHUD,,,,Alternativní HUD automapy,Alternatives Automap HUD,,Alternativa Aŭtomapa HUD,HUD alternativo del automapa,,Vaihtoehtoinen automaattikartan tilanäyttö,ATH Alternatif pour carte,Alternatív Automap HUD,HUD automappa alternativo,オルタナティブ オートマップHUD,대체 오토맵 HUD,Alternatieve Automap HUD,Alternatywny HUD mapy,HUD alternativo de automapa,,Hartă Computerizată Alternativă,Альтернативный HUD на автокарте,Алтернативни HUD за аутомапу +Alternative Automap HUD,ALTHUDMNU_AUTOMAPHUD,,,,Alternativní HUD automapy,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,Alternatywny HUD mapy,HUD alternativo de automapa,,Hartă Computerizată Alternativă,Альтернативный интерфейс на автокарте,Алтернативни HUD за аутомапу Map title color,ALTHUDMNU_TITLECOLOR,,,Map title colour,Barva názvu levelu,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,Kolor nazwy mapy,Cor do título do fase,Cor do título do nível,Culoare titlu hartă,Цвет названия уровня,Боја назива нивоа Map time color,ALTHUDMNU_MAPTIMECOLOR,,,Map time colour,Barva času levelu,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,Kolor czasu na mapie,Cor do tempo da fase,Cor do tempo do nível,Culoare timp petrecut pe hartă,Цвет времени для уровней,Боја времена на нивоу Hub time color,ALTHUDMNU_HUBTIMECOLOR,,,Hub time colour,Barva času hubu,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,Kolor czasu w hubie,Cor do tempo no HUD,,Culoare timp petrecut în hub,Цвет времени для хабов,Боја времена на хабу @@ -2734,83 +2734,84 @@ Coordinate mode,ALTHUDMNU_COORDINATEMODE,,,,Režim souřadnic,Koordinatenmodus,, Statistics name color,ALTHUDMNU_STATSNAMECOLOR,,,Statistics name colour,Barva názvu statistik,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,Kolor nazw statystyk,Cor do nome das estatísticas,,Culoare nume statistici,Цвет имён в статистике,Боја назива статистика Statistics color,ALTHUDMNU_STATSCOLOR,,,Statistics colour,Barva statistik,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,Kolor statystyk,Cor das estatísticas,,Culoare statistici,Цвет статистики,Боја статистика ,,Display (game related),,,,,,,,,,,,,,,,,,,,, -Rendering Interpolation,DSPLYMNU_CAPFPS,,,,Interpolace renderingu,Renderinterpolation,,Bildigo-Interpolado,Interpolación de rend.,,Hahmonnuksen interpolointi,Interpolation du rendu,Render animáció simítás,Interpolazione grafica,レンダリング補間,프레임 제한,Interpolatie renderen,Interpolacja Renderowania,Interpolação de renderização,,Interpolare Imagine,Сглаживание рендеринга,Интерполација рендеринга +Rendering Interpolation,DSPLYMNU_CAPFPS,,,,Interpolace vykreslování,Renderinterpolation,,Bildigo-Interpolado,Interpolación de rend.,,Hahmonnuksen interpolointi,Interpolation du rendu,Render animáció simítás,Interpolazione grafica,レンダリング補間,프레임 제한,Interpolatie renderen,Interpolacja Renderowania,Interpolação de renderização,,Interpolare Imagine,Сглаживание рендеринга,Интерполација рендеринга Transparency render mode,DSPLYMNU_BLENDMETHOD,,,,Režim vykreslování průhlednosti,Transparenzmodus,,Travidebleco-bildigo-reĝimo,Modo rend. 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,Tryb renderowania przezroczystości,Modo de renderiz. de transparência,,Mod Transparență,Режим рендеринга прозрачности,Режим рендеринга транспарентности -Screen wipe style,DSPLYMNU_WIPETYPE,,,,Styl přechodů,Bildschirmwechseleffekt,,Forigi kaŝmemorajn nodojn,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,Styl przejścia ekranu,Tipo de transição de tela,Tipo de transição de ecrã,Stil ștergere imagine,Эффект плавной смены экранов,Ефект брисања екрана -Show ENDOOM screen,DSPLYMNU_SHOWENDOOM,,,,Zobrazit ENDOOM obrazovku,Zeige ENDOOM,,Montri ENDOOM-ekrano,Mostrar pantalla ENDOOM,,Näytä ENDOOM-ruutu,Montrer la fenêtre ENDOOM,ENDOOM képernyő mutatása,Mostra lo screen ENDOOM,ENDOOM画面を表示,종료화면 표시,Toon ENDOOM scherm,Pokaż ekran ENDOOM,Mostrar tela ENDOOM,,Afișare fereastră ENDOOM,Показать экран ENDOOM,Прикажи ENDOOM екран +Screen wipe style,DSPLYMNU_WIPETYPE,,,,Styl přechodů,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,Styl przejścia ekranu,Tipo de transição de tela,Tipo de transição de ecrã,Stil ștergere imagine,Эффект плавной смены экранов,Ефект брисања екрана +Show ENDOOM screen,DSPLYMNU_SHOWENDOOM,,,,Zobrazit ENDOOM obrazovku,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,Pokaż ekran ENDOOM,Exibir tela ENDOOM,,Afișare fereastră ENDOOM,Показать экран ENDOOM,Прикажи ENDOOM екран Blood Flash Intensity,DSPLYMNU_BLOODFADE,,,,Intenzita bliknutí při zranění,Intensität für Bluteffekt,,Egeco de Sango-Ekbrilo,Intensidad Destello de Sangre,,Verivälähdyksen voimakkuus,Intensité du flash dommages,Sebzéskor villanás mértéke,Intensità Bagliore Sangue,血粉の濃度,피격 표시 강도,Intensiteit van de bloedflitser,Intensywność Efektów Krwi,Intensidade de Flash de Sangue,,Intensitate strălucire sânge,Интенсивность вспышки при ранении,Интензивност треперења током повређивања Pickup Flash Intensity,DSPLYMNU_PICKUPFADE,,,,Intenzita bliknutí při sebrání předmětu,Intensität für Aufnehmen-Effekt,,Egeco de Prenado-Ekbrilo,Intensidad Destello de Recogida,,Poimintavälähdyksen voimakkuus,Intensité du flash objets,Fegyver felvételekor villanás mértéke,Intensità Bagliore Raccolta,取得の視界色濃度,습득 표시 강도,Intensiteit van de oppakflitser,Intesnywność Efektów Podnoszenia Przedmiotów,Intensidade de Flash ao Pegar Itens,,Intensitate strălucire la ridicarea obiectelor,Интенсивность вспышки при подборе,Интензивност треперења током купљења -Underwater Blend Intensity,DSPLYMNU_WATERFADE,,,,Intenzita podvodního obarvení,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,Intensywność Efektów Pod Wodą,Intensidade de Efeito Debaixo d'Água,Intensidade de Efeito Debaixo de Água,Intensitate amestec culori subacvatice,Интенсивность эффекта под водой,Интензивност подводног треперења -Sky render mode,DSPLYMNU_SKYMODE,,,,Režim vykreslování oblohy,Rendermodus für Himmel,,Ĉielo-bildigo-reĝimo,Modo de Rend. de Cielo,,Taivaan hahmonnustila,Mode du rendu du Ciel,Égbolt render mód,Modalità resa grafica del cielo,空の表示方法,하늘 표시 모드,Luchtrendermodus,Tryb renderowania nieba,Modo de renderização de céu,,Mod de vizualizare al cerului,Режим отрисовки неба,Режим рендеринга неба -Linear skies,DSPLYMNU_LINEARSKY,,,,Lineární obloha,Lineare Himmel,,Lineraj ĉieloj,Cielo lineal,,Lineaariset taivaat,Ciel linéaire,Lineáris égboltok,Cieli lineari,空の歪み,선형 하늘,Lineaire lucht,Liniowe niebo,Céus lineares,,Cer rectiliniu,Линейное небо,Линеарна неба -Fullbright overrides sector color,DSPLYMNU_GZDFULLBRIGHT,,,,Plný jas ignoruje barvu sektoru,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,Ignoruj kolor sektora przy pełnej jasności,Brilho máximo anula cor de setor,,Luminozitatea maximă suprascrie culoarea sectorului,Полная яркость замещает цвет сектора,Пуно осветљење премошћује боју сектора +Underwater Blend Intensity,DSPLYMNU_WATERFADE,,,,Intenzita zbarvení pod vodou,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,Intensywność Efektów Pod Wodą,Intensidade de Efeito Debaixo d'Água,Intensidade de Efeito Debaixo de Água,Intensitate amestec culori subacvatice,Интенсивность эффекта под водой,Интензивност подводног треперења +Sky render mode,DSPLYMNU_SKYMODE,,,,Režim vykreslování oblohy,Rendermodus für Himmel,,Ĉielo-bildigo-reĝimo,Modo de Rend. de Cielo,,Taivaan hahmonnustila,Mode du rendu du Ciel,Égbolt render mód,Modalità resa grafica del cielo,空の表示方法,하늘 표시 모드,Luchtrendermodus,Tryb renderowania nieba,Modo de renderização de céu,,Mod de vizualizare al cerului,Режим отображения неба,Режим рендеринга неба +Linear skies,DSPLYMNU_LINEARSKY,,,,Lineární obloha,Lineare Himmel,,Linearaj ĉieloj,Cielo lineal,,Lineaariset taivaat,Ciel linéaire,Lineáris égboltok,Cieli lineari,空の歪み,선형 하늘,Lineaire lucht,Liniowe niebo,Céus lineares,,Cer rectiliniu,Линейное небо,Линеарна неба +Fullbright overrides sector color,DSPLYMNU_GZDFULLBRIGHT,,,,Při plném jasu ignorovat barvu sektoru,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,Ignoruj kolor sektora przy pełnej jasności,Brilho máximo anula cor de setor,,Luminozitatea maximă suprascrie culoarea sectorului,Полная яркость замещает цвет сектора,Пуно осветљење премошћује боју сектора Scale fuzz effect,DSPLYMNU_SCALEFUZZ,,,,Škálovat velikost fuzz efektu,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,Skalowanie efektu szumu,Escala de efeito difuso,,Putere efect de strălucire,Масштабировать эффект шума,Повечавај шумни ефект -Use fuzz effect,DSPLYMNU_DRAWFUZZ,,,,Použít fuzz efekt,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,Użyj efektu szumu,Usar efeito difuso,,Mod efect de strălucire,Использовать эффект шума,Користи шумни ефект +Use fuzz effect,DSPLYMNU_DRAWFUZZ,,,,Typ fuzz efektu,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,Użyj efektu szumu,Usar efeito difuso,,Mod efect de strălucire,Использовать эффект шума,Користи шумни ефект Classic Transparency,DSPLYMNU_OLDTRANS,,,,Klasická průhlednost,Klasssische Transparenz,,Klasika Travidebleco,Transp. Clásicas,,Perinteinen läpinäkyvyys,Transparence classique,Klasszikus átlátszóság,Trasparenza classica,旧式の透明度,구형 투명도,Klassieke transparantie,Klasyczna Przezroczystość,Transparência Clássica,,Transparență Clasică,Классическая прозрачность,Класична транспарентност -Lost Soul translucency,DSPLYMNU_TRANSSOUL,,,,Průhlednost ztracených duší,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,Przezroczystość Zagubionych Dusz,Translucência da Alma Perdida,Translucidez da Alma Penada,Transparență Suflete Pierdute,Прозрачность потерянных душ,Транспарентност изгубљених душа +Lost Soul translucency,DSPLYMNU_TRANSSOUL,,,,Průhlednost Ztracených duší,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,Przezroczystość Zagubionych Dusz,Translucência da Alma Perdida,Translucidez da Alma Penada,Transparență Suflete Pierdute,Прозрачность потерянных душ,Транспарентност изгубљених душа Use fake contrast,DSPLYMNU_FAKECONTRAST,,,,Použít falešný 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,Użyj sztuczny kontrast,Usar contraste falso,,Utilizare contrast fals,Имитация контрастного освещения стен,Користи фејк-контраст Rocket Trails,DSPLYMNU_ROCKETTRAILS,,,,Kouř raket,Raketenschweife,,Raketospuroj,Rastro de cohetes,,Rakettivanat,Trainées des Roquettes,Rakéta füstnyomok,Scia del razzo,ロケットの軌跡,로켓 추진 효과,Raketsporen,Wiązki Rakiet,Rastro de Foguete,Rasto dos Mísseis,Dâră Rachete,Дымовой след у ракет,Траг дима код ракета Blood Type,DSPLYMNU_BLOODTYPE,,,,Druh krve,Blut-Typ,,Sangotipo,Tipo de sangre,,Verityyli,Type de particules Sang,Vér fajta,Tipo di sangue,血の種類,혈흔 효과,Bloedtype,Typ Krwi,Tipo de Sangue,,Tip efecte sângeroase,Тип крови,Тип крви Bullet Puff Type,DSPLYMNU_PUFFTYPE,,,,Druh kouře nábojů,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,Typ Dymu,Tipo de Ricochete de Bala,,Tip efecte pentru gloanțe,Тип рикошетов,Тип рикошета Number of particles,DSPLYMNU_MAXPARTICLES,,,,Množství částic,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,Liczba cząsteczek,Número de partículas,,Număr particule,Количество частиц,Број честица Number of decals,DSPLYMNU_MAXDECALS,,,,Množství decalů,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,Liczba kalk,Número de decalques,,Număr autocolante,Количество декалей,Број декала -Show player sprites,DSPLYMNU_PLAYERSPRITES,,,,Zobrazit hráčovy sprity,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,Pokaż sprite'y gracza,Mostrar sprites do jogador,,Afișare arme,Показывать спрайты игрока,Прикажи спрајтове играча +Show player sprites,DSPLYMNU_PLAYERSPRITES,,,,Zobrazit hráčovy sprity,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,Pokaż sprite'y gracza,Exibir sprites do jogador,,Afișare arme,Показывать спрайты игрока,Прикажи спрајтове играча Death camera,DSPLYMNU_DEATHCAM,,,,Posmrtná kamera,Todeskamera,,Mortkamerao,Cámara de muerte,,Kuolonkamera,Caméra 3ème pers à la mort,Halál kamera,Telecamera all'atto della morte,死亡時の三人称視点,사망 화면 표시,Doodscamera,Kamera śmierci,Câmera de morte,Câmara da morte,Cameră de Deces,Вид от 3-го лица при смерти,Смртна камера -Teleporter zoom,DSPLYMNU_TELEZOOM,,,,Zoom při teleportaci,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,Przybliżenie teleportowania,Zoom de teletransporte,,Apropriere Cameră la Teleportare,Зум при телепортации,Зум током телепортације +Teleporter zoom,DSPLYMNU_TELEZOOM,,,,Zoom při teleportaci,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,Przybliżenie teleportowania,Zoom de teletransporte,,Apropriere Cameră la Teleportare,Приближение при телепортации,Зум током телепортације Earthquake shake intensity,DSPLYMNU_QUAKEINTENSITY,,,,Intenzita zemětřesení,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,Siła trzęsienia ziemi,Intensidade do tremor de terremoto,,Intensitate zguduire la cutremur,Интенсивность землетрясений,Интенсивност земљотреса -Interpolate monster movement,DSPLYMNU_NOMONSTERINTERPOLATION,,,,Interpolovat pohyb příšer,Interpoliere Monsterbewegung,,Intermeti monstro-movo,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,Interpolacja ruchu potworów,Interpolar movimento de monstros,,Interpolare mișcare monștri (efect vizual),Сглаживание движения монстров,Интерполирај кретање чудовишта +Interpolate monster movement,DSPLYMNU_NOMONSTERINTERPOLATION,,,,Interpolovat pohyb příšer,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,Interpolacja ruchu potworów,Interpolar movimento de monstros,,Interpolare mișcare monștri (efect vizual),Сглаживание движения монстров,Интерполирај кретање чудовишта Menu dim,DSPLYMNU_MENUDIM,,,,Síla barvy pozadí v menu,Menüabdunklung,,Menuo-malheleco,Atenuación del menú,,Valikon himmennys,Assombrissement menu,Menü homályosítása,Offuscamento menu,メニュー背景,메뉴 배경색 강도,Donkere menuachtergrond,Mgła w menu,Atenuação do menu,,Întunecare meniu,Затемнение фона меню,Пригушивање менија -Dim color,DSPLYMNU_DIMCOLOR,,,Dim colour,Barva pozadí v menu,Abdunklungsfarbe,,Malhela koloro,Color de la atenuación,,Himmennysväri,Couleur de l'assombrissement,Homályosítás színe,Colore offuscamento,背景色,배경색 설정,Donkere kleur,Kolor mgły,Cor da atenuação,,Culoare întunecare,Цвет затемнения,Боја пригушивања -View bob amount while moving,DSPLYMNU_MOVEBOB,,,,Intenzita pohupování v pohybu,Waffenpendeln beim Bewegen,,Vidi kapo-ekmova kvanto dum movas,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,視点揺れする移動値,이동 시 화면 흔들림 강도,,Dygaj kiedy się ruszasz,Quantidade de balanço durante movimento,,Mișcare cameră în timpul deplasării,Покачивание камеры при движении,Тресење камере током кретања -View bob amount while not moving,DSPLYMNU_STILLBOB,,,,Intenzita pohupování v klidu,Waffenpendeln bei Nichtbewegen,,Vidi kapo-ekmova kvanto dum ne movas,Cantidad de balanceo al no moverse,,Aseen heilumisvoimakkuus levossa,Chaloupage arme statique,Fegyver mozgása egy helyben,Ammontare di bob di movimento da fermo,視点揺れしない移動値,정지 시 화면 움직임 강도,,Dygaj kiedy się nie ruszasz,Quantidade de balanço parado,,Mișcare cameră în timpul staționării,Покачивание камеры при бездействии,Тресење камере током неактивности -Weapon bob speed,DSPLYMNU_BOBSPEED,,,,Rychlost pohupování zbraně,Waffenpendelgeschwindigkeit,,Rapido de armilo-ekmova,Velocidad de balanceo de Arma,,Aseen heilumisnopeus,Vitesse du chaloupage,Fegyver mozgás sebesség,Velocità di bob dell'arma,武器揺れ速度,무기 흔들림 속도,Snelheid wapenzwaaieffect,Szybkość ruchu broni,Velocidade de balanço de arma,,Viteză mișcare arme,Скорость покачивания оружия,Брзина трсења оружја +Dim color,DSPLYMNU_DIMCOLOR,,,Dim colour,Barva pozadí v menu,Abdunklungsfarbe,,Malheleca koloro,Color de la atenuación,,Himmennysväri,Couleur de l'assombrissement,Homályosítás színe,Colore offuscamento,背景色,배경색 설정,Donkere kleur,Kolor mgły,Cor da atenuação,,Culoare întunecare,Цвет затемнения,Боја пригушивања +View bob amount while moving,DSPLYMNU_MOVEBOB,,,,Pohupování pohledu při pohybu,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,視点揺れする移動値,이동 시 화면 흔들림 강도,,Dygaj kiedy się ruszasz,Quantidade de balanço durante movimento,,Mișcare cameră în timpul deplasării,Покачивание камеры при движении,Тресење камере током кретања +View bobbing while flying,MISCMNU_FVIEWBOB,,,,,,,,,,,,,,,,,,,,,, +View bob amount while not moving,DSPLYMNU_STILLBOB,,,,Pohupování pohledu v klidu,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,視点揺れしない移動値,정지 시 화면 움직임 강도,,Dygaj kiedy się nie ruszasz,Quantidade de balanço parado,,Mișcare cameră în timpul staționării,Покачивание камеры при бездействии,Тресење камере током неактивности +Weapon bob speed,DSPLYMNU_BOBSPEED,,,,Rychlost pohupování zbraně,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,Szybkość ruchu broni,Velocidade de balanço de arma,,Viteză mișcare arme,Скорость покачивания оружия,Брзина трсења оружја ,,Scaling,,,,,,,,,,,,,,,,,,,,, -Scaling Options,SCALEMNU_TITLE,,,,Nastavení velikosti,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezési Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере +Scaling Options,SCALEMNU_TITLE,,,,Nastavení škálování rozhraní,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezési Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере Overrides for above setting,SCALEMNU_OVERRIDE,,,,Potlačení nastavení výše,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,Nadpisuje dla powyższego ustawienia,Anular configurações acima,,Suprascriere pentru setările de mai sus,Задать специальные настройки,Специјална подешавања -Messages,SCALEMNU_MESSAGES,,,,Zprávy,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке +Messages,SCALEMNU_MESSAGES,,,,Oznámení,Nachrichten,,Mesaĝoj,Mensajes,,Viestit,Messages,Üzenetek,Messaggi,メッセージ類,메시지,Berichten,Wiadomości,Mensagens,,Mesaje,Сообщения,Поруке Console,SCALEMNU_CONSOLE,,,,Konzole,Konsole,,Konzolo,Consola,,Konsoli,Console,Konzol,Console,コンソール,콘솔,Console,Konsola,Console,Consola,Consolă,Консоль,Конзола Status bar,SCALEMNU_STATBAR,,,,Stavový panel,Statusleiste,,Stata baro,Barra de estado,,Tilapalkki,Barre d'état,Státusz sáv,Barra di stato,ステータスバー,상태 바,Statusbalk,Pasek statusu,Barra de status,Barra de estado,Bară de Stare,Строка состояния,Статусна трака -Fullscreen HUD,SCALEMNU_HUD,,,,HUD přes celou obrazovku,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 pełnoekranowy,HUD de tela cheia,HUD de ecrã cheio,Interfață pe Timp de Joc tip Fullscreen,Полноэкранный HUD,HUD преко целог екрана -Alternative HUD,SCALEMNU_ALTHUD,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный HUD,Алтернативни HUD -HUD preserves aspect ratio,SCALEMNU_HUDASPECT,,,,HUD uchovává poměr stran,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 zachowuje współczynnik proporcji,HUD deve preservar proporções,,Interfața pe Timp de Joc își Păstrează Aspectul,Сохранение соотношения сторон HUD,Сачувај пропорције HUD-а +Fullscreen HUD,SCALEMNU_HUD,,,,HUD přes celou obrazovku,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 pełnoekranowy,HUD de tela cheia,HUD de ecrã cheio,Interfață pe Timp de Joc tip Fullscreen,Полноэкранный интерфейс,HUD преко целог екрана +Alternative HUD,SCALEMNU_ALTHUD,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный интерфейс,Алтернативни HUD +HUD preserves aspect ratio,SCALEMNU_HUDASPECT,,,,HUD zachovává poměr stran,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 zachowuje współczynnik proporcji,HUD deve preservar proporções,,Interfața pe Timp de Joc își Păstrează Aspectul,Сохранение соотношения сторон интерфейса,Сачувај пропорције HUD-а Use default scale,SCALEMNU_USEUI,,,,Použít výchozí velikost,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,Użyj domyślnej skali,Usar escala padrão,,Folosește dimensiunea implicită,Размер по умолчанию,Уобичајена размера -Scale to fullscreen,SCALEMNU_USEFS,,,,Škalovat přes celou obrazovku,Skaliere auf Vollbild,,Skali al tutekranon,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,Przeskaluj do pełnego ekranu,Escala de tela cheia,Escalar para ecrã cheio,Dimensionare la modul Fullscreen,Масштабировать со всем экраном,Проширење преко целог екрана -Adapt to screen size,SCALEMNU_ADAPT,,,,Přizpůsobit velikosti obrazovky,Passe an Bildschirmgröße an,,Adapti al ekranamplekson,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,Dostosuj do pełnego ekranu,Adaptar ao tamanho de tela,,Adaptează la dimensiunea ecranului,Адаптироваться к размеру экрана,Прилагоди размери екрана +Scale to fullscreen,SCALEMNU_USEFS,,,,Škalovat přes celou obrazovku,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,Przeskaluj do pełnego ekranu,Escala de tela cheia,Escalar para ecrã cheio,Dimensionare la modul Fullscreen,Масштабировать со всем экраном,Проширење преко целог екрана +Adapt to screen size,SCALEMNU_ADAPT,,,,Přizpůsobit velikosti obrazovky,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,Dostosuj do pełnego ekranu,Adaptar ao tamanho de tela,,Adaptează la dimensiunea ecranului,Адаптироваться к размеру экрана,Прилагоди размери екрана ,,HUD,,,,,,,,,,,,,,,,,,,,, -HUD Options,HUDMNU_TITLE,,,,Nastavení HUD,HUD Optionen,,HUD Agordoj,Opciones del HUD,,Tilanäytön asetukset,Options ATH,HUD beállításai,Opzioni HUD,HUDオプション,HUD 설정,HUD-opties,Opcje HUD,Opções de HUD,,Setări Interfață pe Timp de Joc,Настройки HUD,HUD подешавања -Alternative HUD,HUDMNU_ALTHUD,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD Alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный HUD,Алтернативни HUD -Message Options,HUDMNU_MESSAGE,,,,Nastavení zpráv,Nachrichtenoptionen,,Mesaĝo-Agordoj,Opciones de mensajes,,Viestiasetukset,Options des Messages,Üzenet beállítások,Opzioni messaggi,メッセージの設定,메시지 설정,Berichtopties,Opcje wiadomości,Opções de Mensagem,,Setări Mesaje,Настройки сообщений,Подешавања порука -User interface scale,HUDMNU_UISCALE,,,,Velikost rozhraní,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,Skala interfejsu,Escala de interface de usuário,Escala de interface do utilizador,Dimensiune Interfață Utilizator,Масштабирование интерфейса,Размера интерфејса +HUD Options,HUDMNU_TITLE,,,,Nastavení rozhraní a HUD,HUD Optionen,,HUD Agordoj,Opciones del HUD,,Tilanäytön asetukset,Options ATH,HUD beállításai,Opzioni HUD,HUDオプション,HUD 설정,HUD-opties,Opcje HUD,Opções de HUD,,Setări Interfață pe Timp de Joc,Настройки интерфейса,HUD подешавања +Alternative HUD,HUDMNU_ALTHUD,,,,Alternativní HUD,Alternatives HUD,,Alternativa HUD,HUD alternativo,,Vaihtoehtoinen tilanäyttö,ATH Alternatif,Alternatív HUD,HUD alternativo,オルタナティブHUD,대체 HUD,Alternatieve HUD,Alternatywny HUD,HUD Alternativo,,Interfață pe Timp de Joc Alternativă,Альтернативный интерфейс,Алтернативни HUD +Message Options,HUDMNU_MESSAGE,,,,Oznámení,Nachrichtenoptionen,,Mesaĝo-Agordoj,Opciones de mensajes,,Viestiasetukset,Options des Messages,Üzenet beállítások,Opzioni messaggi,メッセージの設定,메시지 설정,Berichtopties,Opcje wiadomości,Opções de Mensagem,,Setări Mesaje,Настройки сообщений,Подешавања порука +User interface scale,HUDMNU_UISCALE,,,,Velikost rozhraní,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,Skala interfejsu,Escala de interface de usuário,Escala de interface do utilizador,Dimensiune Interfață Utilizator,Размер интерфейса,Размера интерфејса Force default crosshair,HUDMNU_FORCECROSSHAIR,,,,Vynutit výchozí zaměřovač,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,Wymuś domyślny celownik,Forçar mira padrão,,Forțare țintă implicită,Всегда стандартный прицел,Форсирај уобичајени нишан Grow crosshair when picking up items,HUDMNU_GROWCROSSHAIR,,,,Zvětšit zaměřovač při sebrání předmětu,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,"Powiększ celownik, gdy podnosisz przedmioty",Aumentar mira ao pegar itens,Aumentar mira ao apanhar itens,Mărește ținta la ridicarea obiectelor,Увеличение прицела при подборе,Побољшај нишан током купљења предмета -Display nametags,HUDMNU_NAMETAGS,,,,Zobrazovat jmenovky,Zeige Gegenstandsnamen,,Montri nometikedojn,Mostrar etiquetas,,Näytä nimitunnisteet,Afficher noms des objets,Névtábla mutatása,Mostra le targhette identificative,ディスプレイネームタグ,이름표 표시,Naamlabels weergeven,Pokazuj nazwy przedmiotów,Mostrar nomes,,Indică numele obiectelor,Указание названия предметов,Прикажи имена предмета +Display nametags,HUDMNU_NAMETAGS,,,,Zobrazovat jmenovky,Zeige Gegenstandsnamen,,Montri nometikedojn,Mostrar etiquetas,,Näytä nimitunnisteet,Afficher noms des objets,Névtábla mutatása,Mostra le targhette identificative,ディスプレイネームタグ,이름표 표시,Naamlabels weergeven,Pokazuj nazwy przedmiotów,Exibir nomes,,Indică numele obiectelor,Указание названия предметов,Прикажи имена предмета Nametag color,HUDMNU_NAMETAGCOLOR,,,Nametag colour,Barva jmenovek,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,Kolor nazw przedmiotów,Cor dos nomes,,Culoare nume obiecte,Цвет названия предметов,Боја имена предмета Use old ouch mug shot formula,HUDMNU_OLDOUCH,,,,Použít starý vzorec pro 'ouch' portrét,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",Używaj starej formuły twarzy przy dostaniu obrażeń,Usar fórmula original do rosto de dor,,Utilizează modul portret vechi,Старая формула для портрета,Стара формула за приказ лика Hexen weapon flashes,HUDMNU_HEXENFLASHES,,,,Druh bliknutí zbraní v Hexenu,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,Błysk przy podnoszeniu broni z Hexena,Flash de arma do Hexen,,Tip strălucire arme Hexen,Тип вспышки оружия в Hexen,Треперење оружја у Hexen-у Poison damage flashes,HUDMNU_POISONFLASHES,,,,Druh bliknutí při otrávení,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,Efekt obrażeń przy zatruciu,Flash de dano por veneno,,Tip strălucire efect de otrăvire,Тип вспышки яда,Треперење током тровања Ice death flashes,HUDMNU_ICEFLASHES,,,,Druh bliknutí při smrti umrznutím,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,Błysk przy śmierci poprzez zamrożenie,Flash de morte por congelamento,,Tip strălucire deces prin înghețare,Тип вспышки при смерти от льда,Треперење током смрти од леда Poison Buildup flashes,HUDMNU_HAZARDFLASHES,,,,Druh blikání při kumulaci jedu,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,Miganie przy nasilaniu się trucizny,Flash por acúmulo de dano por veneno,,Tip strălucire acumulare de otravă,Тип вспышки при скоплении яда,Треперење током гомилања отрова -Scaling Options,HUDMNU_SCALEOPT,,,,Nastavení velikosti,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezés Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере -Show IWAD selection dialog,MISCMNU_QUERYIWAD,,,,Zobrazit dialog pro výběr IWADu,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,Pokaż ekran wyboru gry (IWAD),Mostrar janela de seleção de IWAD,,Afișează fereastra de selectare a jocurilor,Выбор IWAD-файла при запуске,Покажи IWAD дијалог за избор +Scaling Options,HUDMNU_SCALEOPT,,,,Škálování velikosti rozhraní,Skalierungsoptionen,,Skalo-Agordoj,Opciones de escalado,,Skaalausasetukset,Option de mise à l'échelle,Méretezés Beállítások,Opzioni di scala,スケーリング オプション,배율 설정,Schaalopties,Opcje skalowania,Opções de Escala,,Setări Dimensiuni,Настройки масштабирования,Подешавања размере +Show IWAD selection dialog,MISCMNU_QUERYIWAD,,,,Zobrazit dialog pro výběr IWADu,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,Pokaż ekran wyboru gry (IWAD),Exibir janela de seleção de IWAD,,Afișează fereastra de selectare a jocurilor,Выбор IWAD-файла при запуске,Покажи IWAD дијалог за избор Enable cheats from all games,MISCMNU_ALLCHEATS,,,,Povolit cheaty ze všech her,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,Włącz oszustwa ze wszystkich gier,Habilitar trapaças de todos os jogos,Permitir batotas de todos os jogos,Permite codurile din toate jocurile,Читы из всех игр,Омогући читове од свих игара ,,Option Menus,,,,,,,,,,,,,,,,,,,,, -Enable making screenshots by scripts,MISCMNU_ENABLESCRIPTSCREENSHOTS,,,,Povolit skriptům pořizovat snímky obrazovky,"Erlaube Skripts, Screenshots zu machen",,Ebligi faranto ekrankopiojn 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,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,Возможность делать скриншоты через скрипты,Омогући прављење скриншотова по скрипти -Load *.deh/*.bex lumps,MISCMNU_DEHLOAD,,,,Načítat *.deh/*.bex soubory,Lade *.deh/*.bex Daten,,Ŝarĝi *.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,Załaduj dane *.deh/*.bex,Carregar lumps *.deh/*.bex,,Încarcă nodurile *.deh/*.bex,Загружать файлы *.deh/*.bex,Учитај *.deh/*.bex фајлове +Enable making screenshots by scripts,MISCMNU_ENABLESCRIPTSCREENSHOTS,,,,Povolit skriptům pořizovat snímky obrazovky,"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,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,Возможность делать скриншоты через скрипты,Омогући прављење скриншотова по скрипти +Load *.deh/*.bex lumps,MISCMNU_DEHLOAD,,,,Načítat *.deh/*.bex soubory,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,Załaduj dane *.deh/*.bex,Carregar lumps *.deh/*.bex,,Încarcă nodurile *.deh/*.bex,Загружать файлы *.deh/*.bex,Учитај *.deh/*.bex фајлове 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,Węzły pamięci podręcznej,Cachê de nodes,Cache de nodes,Depozitare noduri cache,Кэширование нодов,Кеширани чворови Time threshold for node caching,MISCMNU_CACHETIME,,,,Časový práh pro cachování nodes,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,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,Временной порог для кэширования нодов,Временски праг за кеширање чвора Clear node cache,MISCMNU_CLEARNODECACHE,,,,Vyčistit 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,Wyczyść pamięć podręczną,Limpar cachê de nodes,Limpar cache de nodes,Ștergere noduri cache,Очистить кэш нодов,"Избриши кеширане чворове " -Allow skipping of intermission scrollers,MISCMNU_INTERSCROLL,,,,Povolit přeskakování intermission posuvníků,Erlaube Überspringen von Intermission-Scrollern,,Permesi transsalti intermitajn rulumojn,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,クリア結果集計のスキップを許可,인터미션 스크롤러 생략 허용,,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,Разрешение пропуска текстовых вставок,Дозволи прескакање прелаза са текстовима +Allow skipping of intermission scrollers,MISCMNU_INTERSCROLL,,,,Povolit přeskakování skrolujících obrázků,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,クリア結果集計のスキップを許可,인터미션 스크롤러 생략 허용,,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,Разрешение пропуска текстовых вставок,Дозволи прескакање прелаза са текстовима Network Options,NETMNU_TITLE,,,,Nastavení sítě,Netzwerkeinstellungen,,Reta Agordoj,Opciones de Red,,Verkkoasetukset,Options Réseau,Hálózati Beállítások,Opzioni network,ネットワーク オプション,네트워크 설정,Netwerkopties,Opcje Sieci,Opções de Rede,,Setări de Rețea,Настройки сети,Мрежна подешавања Local options,NETMNU_LOCALOPTIONS,,,,Lokální nastavení,Lokale Einstellungen,,Lokaj agordoj,Opciones locales,,Paikallisasetukset,Options Locales,Helyi beállítások,Opzioni locali,ローカル オプション,로컬 설정,Lokale opties,Opcje Lokalne,Opções locais,,Setări Locale,Локальные настройки,Локална подешавања Movement prediction,NETMNU_MOVEPREDICTION,,,,Predikce pohybu,Bewegungsvorausberechnung,,Movprognozado,Predicción de Movimiento,,Liikkeen ennakoiminen,Prédiction de Mouvement,Mozgás előrejelzés,Predizione movimenti,移動予測,움직임 예측도,Voorspelling van bewegingen,Przewidywanie Ruchu,Previsão de movimento,,Anticipare mișcare,Предсказание движения,Предвиђање покрета Predict line actions,NETMNU_LINESPECIALPREDICTION,,,,Predikce čárových akcí,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,Przewidź akcje linii,Prever ações de linha,,Anticipează acționarea liniilor,Предсказание действий на уровне,Предвиђање линијске радње -Prediction Lerp Scale,NETMNU_PREDICTIONLERPSCALE,,,,Velikost interpolace predikce,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,Przewidywanie Skali Lerp,Escala de previsão de LERP,,Anticipare scară lerp,Предсказание масштаба лэрпа,Предвиђање лерп скале -Lerp Threshold,NETMNU_LERPTHRESHOLD,,,,Práh interpolace,Lerp-Schwellwert,,Limito de Linia Interpolado,Umbral de interp. lineal,,Interpolaatiokynnys,Limite LERP,LERP küszöbérték,Soglia Lerp,リープしきい値,러프 계산,Lerp Threshold,Próg Lerp,Limite de LERP,,Prag Lerp,Порог лэрпа,Лерп праг -Host options,NETMNU_HOSTOPTIONS,,,,Nastavení hostitele,Gastoptionen,,Agordoj de Gastiganto,Opciones de Host,,Isäntäasetukset,Options Hôte,Host beállítások,Opzioni ospitante,ホスト オプション,호스트 설정,Verhuurders opties,Opcje hosta,Opções de host,,Setări gazdă,Настройки хоста,Подешавања домаћина -Extra Tics,NETMNU_EXTRATICS,,,,Extra tiky,,,Ekstraj Tikoj,Tics Extra,,Lisäticit,Tics supplémentaires,Extra Tic-ek,Tics extra,予備秒数,추가 틱,,Dodatkowe tiki,Tics extras,,Ticăituri suplimentare,Дополнительные тики,Додатни тикови +Prediction Lerp Scale,NETMNU_PREDICTIONLERPSCALE,,,,Velikost interpolace predikce,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,Przewidywanie Skali Lerp,Escala de previsão de LERP,,Anticipare scară lerp,Предсказание масштаба доп. задержки,Предвиђање лерп скале +Lerp Threshold,NETMNU_LERPTHRESHOLD,,,,Práh interpolace,Lerp-Schwellwert,,Limito de Linia Interpolado,Umbral de interp. lineal,,Interpolaatiokynnys,Limite LERP,LERP küszöbérték,Soglia Lerp,リープしきい値,러프 계산,Lerp Threshold,Próg Lerp,Limite de LERP,,Prag Lerp,Порог доп. задержки,Лерп праг +Host options,NETMNU_HOSTOPTIONS,,,,Nastavení hostitele,Gastoptionen,,Agordoj de Gastiganto,Opciones de Host,,Isäntäasetukset,Options Hôte,Host beállítások,Opzioni ospitante,ホスト オプション,호스트 설정,Verhuurders opties,Opcje hosta,Opções de host,,Setări gazdă,Настройки сервера,Подешавања домаћина +Extra Tics,NETMNU_EXTRATICS,,,,Extra tiky,,,Ekstraj Tikoj,Tics Extra,,Lisäticit,Tics supplémentaires,Extra Tic-ek,Tics extra,予備秒数,추가 틱,,Dodatkowe tiki,Tics extras,,Ticăituri suplimentare,Дополнительные секунды,Додатни тикови Latency balancing,NETMNU_TICBALANCE,,,,Vyrovnání latence,Latenzbalance,,Respondotempo-balancado,Balanceo de latencia,,Viiveen tasapainoitus,Equilibrage de latence,Válaszidő balanszolás,Bilanciamento latenza,レイテンシーバランス,지연 시간 조정,Latency balans,Balans czasu oczekiwania,Equilíbrio de latência,,Întârzierea echilibrării,Балансировка задержки,Балансирање кашњења -Original,OPTVAL_ORIGINAL,,,,Původní,,,Originala,,,Alkuperäinen,Original,Eredeti,Originale,オリジナル,원형,Origineel,Oryginalny,Original,,,Оригинальный,Оригинално +Original,OPTVAL_ORIGINAL,,,,Původní,,,Originala,,,Alkuperäinen,Original,Eredeti,Originale,オリジナル,원형,Origineel,Oryginalny,Original,,,Изначальный,Оригинално Optimized,OPTVAL_OPTIMIZED,,,,Optimalizovaný,Optimiert,,Optimumigita,Optimizado,,Optimoitu,Optimisé,Optimalizált,Ottimizzato,最適化,최적화 형,Geoptimaliseerd,Zoptymalizowany,Otimizado,,Optimizat,Оптимизированный,Оптимизовано Classic (Faster),OPTVAL_CLASSIC,,,,Klasický (rychlejší),Klassisch (schneller),,Klasika (Pli rapide),Clásico (Más rápido),,Perinteinen (nopeampi),Classique (+ Rapide),Klasszikus (gyorsabb),Classico (più veloce),旧式(速度重視),구형 (빠르게),Klassiek (sneller),Klasyczny (szybszy),Clássico (Mais rápido),,Clasic (Mai rapid),Классический (быстрее),Класични (бржи) Precise,OPTVAL_PRECISE,,,,Přesný,Genau,,Preciza,Preciso,,Tarkka,Précis,Pontos,Preciso,精密,정확하게,Nauwkeurig,Dokładny,Preciso,,Precis,Точный,Прецизно @@ -2824,7 +2825,7 @@ Crossfade,OPTVAL_CROSSFADE,,,,Prolínačka,Überblenden,,Transvelki,Entrelazar,, 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ý,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Gładki,Suavizado,,Fin,Плавная,Глатко Smooth,OPTVAL_SMOOTH_2,,,,Vyhlazené,Glatt,,Glata,Fluido,,Pehmeä,Lisse,Simítás,Liscio,スムーズ,부드럽게,Glad,Gładka,Suavizado,,Fin,Плавные,Глатко Translucent,OPTVAL_TRANSLUCENT,,,,Průhledný,Transparent,,Diafana,Translúcido,,Läpikuultava,Transparent,Áttetsző,Traslucido,半透明,투명하게,Doorschijnend,Przeświecający,Translúcido,,Transparent,Полупрозрачный,Прозрачно -Fuzz,OPTVAL_FUZZ,,,,Šum,Fuzz,,Lanugo,Borroso,,Sumeus,Bruit Blanc,Homályosítás,,ファズ,퍼즈 효과,Fuzz,Szum,Difuso,,Sclipitor,Шумовой,Фаз +Fuzz,OPTVAL_FUZZ,,,,Šum,Fuzz,,Lanugo,Borroso,,Sumeus,Bruit Blanc,Homályosítás,Annebbiato,ファズ,퍼즈 효과,Fuzz,Szum,Difuso,,Sclipitor,Шумовой,Фаз Shadow,OPTVAL_SHADOW,,,,Stín,Schatten,,Ombro,Sombra,,Varjo,Ombre,Árnyék,Ombra,シャドウ,그림자 효과,Schaduw,Cień,Sombra,,Umbră,Теневой,Сенка Items,OPTVAL_ITEMS,,,,Předměty,Gegenstände,,Objektoj,Objetos,,Esineet,Objets,Tárgyak,Oggetti,アイテム,아이템들,Artikelen,Przedmioty,Itens,,Obiecte,Предметы,Предмет Weapons,OPTVAL_WEAPONS,,,,Zbraně,Waffen,,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기들,Wapens,Bronie,Armas,,Arme,Оружие,Оружја @@ -2833,9 +2834,9 @@ ZDoom,OPTVAL_ZDOOM,,,,,,,,,,,,,,,Z둠,,,,,,, Strife,OPTVAL_STRIFE,,,,,,,,,,,,,,,스트라이프,,,,,,, Player,OPTVAL_PLAYER,,,,Hráč,Spieler,,Ludanto,Jugador,,Pelaaja,Joueur,Játékos,Giocatore,プレイヤー,플레이어,Speler,Gracz,Jogador,,Jucător,Игрок,Играч Map,OPTVAL_MAP,,,,Level,Level,,Mapo,Mapa,,Kartta,Niveau,Pálya,Mappa,マップ,맵,Kaart,Mapa,Mapa,,Hartă,Карта,Мапа -Scale to 640x400,OPTVAL_SCALETO640X400,,,,Zvětšit na 640x400,Skaliere auf 640x400,,Skali al 640x400,Escalar a 640x400,,Skaalaa resoluutioon 640x400,Echelle 640x400,640x480-hoz arányosít,Scala a 640x400,640x400スケール,640x400까지 확대,Schaal tot 640x400,Skaluj do 640x400,Escalar para 640x400,,Dimensionare la 640x480,Масштабировать до 640x400,Скалирај на 640x400 +Scale to 640x400,OPTVAL_SCALETO640X400,,,,Zvětšit na 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,Skaluj do 640x400,Escalar para 640x400,,Dimensionare la 640x480,Масштабировать до 640x400,Скалирај на 640x400 Pixel double,OPTVAL_PIXELDOUBLE,,,,Zdvojení pixelů,Pixelverdopplung,,Bilderon duobligi,Pixel doble,,Kuvapistekaksinkertaistus,,Pixel duplázás,Pixel doppi,ピクセル2倍,2배 픽셀,Pixel dubbel,Dwukrotnie więcej pikseli,Pixel duplo,,Dublare pixeli,Двойные пиксели,Дупли пиксел -Pixel quadruple,OPTVAL_PIXELQUADRUPLE,,,,Zčtyřnásobení pixelů,Pixelvervierfachung,,Bilderon kavarobligi,Pixel cuádruple,,Kuvapistenelinkertaistus,,Pixel négyszerezés,Pixel quadrupli,ピクセル4倍,4배 픽셀,Pixel viervoudig,Czterokrotnie więcej pikseli,Pixel quádruplo,,Împătrire pixeli,Четверные пиксели,Четвороструки пиксел +Pixel quadruple,OPTVAL_PIXELQUADRUPLE,,,,Zčtyřnásobení pixelů,Pixelvervierfachung,,Bilderon kvarobligi,Pixel cuádruple,,Kuvapistenelinkertaistus,,Pixel négyszerezés,Pixel quadrupli,ピクセル4倍,4배 픽셀,Pixel viervoudig,Czterokrotnie więcej pikseli,Pixel quádruplo,,Împătrire pixeli,Четверные пиксели,Четвороструки пиксел Current weapon,OPTVAL_CURRENTWEAPON,,,,Současná zbraň,Aktuelle Waffe,,Nuntempa armilo,Arma actual,,Nykyinen ase,Arme actuelle,Jelenlegi fegyver,Arma corrente,使用中の武器,현 무기,Huidig wapen,Aktualna broń,Arma atual,,Arma curentă,текущего оружия,Тренутно оружје Available weapons,OPTVAL_AVAILABLEWEAPONS,,,,Dostupně zbraně,Verfügbare Waffen,,Haveblaj armiloj,Armas disponibles,,Käytettävissä olevat aseet,Armes Disponibles,Elérhető fegyverek,Armi disponibili,所持してる武器,사용 가능한 무기들,Beschikbare wapens,Dostępne bronie,Armas disponíveis,,Arme disponibile,доступного оружия,Доступно оружје All weapons,OPTVAL_ALLWEAPONS,,,,Všechny zbraně,Alle Waffen,,Ĉiuj armiloj,Todas las armas,,Kaikki aseet,Toutes les armes,Minden fegyver,Tutte le armi,全ての武器,모든 무기들,Alle wapens,Wszystkie bronie,Todas as armas,,Toate armele,всех видов оружия,Сва оружја @@ -2844,17 +2845,17 @@ All weapons,OPTVAL_ALLWEAPONS,,,,Všechny zbraně,Alle Waffen,,Ĉiuj armiloj,Tod Level,OPTVAL_LEVEL,,,,Level,Level,,Nivelo,Nivel,,Taso,Niveau,Pálya,Livello,現場,레벨,Niveau,Poziom,Fase,Nível,Nivel,Уровень,Ниво "Hub, seconds",OPTVAL_HUBSECONDS,,,,"Hub, vteřiny","Hub, Sekunden",,"Rekontejo, sekundoj","Hub, segundos",,"Tasokokoelma, sekunnit","Hub, secondes","Csomópont, másodpercek","Hub, secondi","区間, 秒","허브, 초당","Naaf, seconden","Hub, sekundy","Hub, segundos",,"Hub, secunde",Хаб (секунды),"Хуб, секунде" Hub,OPTVAL_HUB,,,,Hub,Hub,,Rekontejo,Hub,,Tasokokoelma,Hub,Csomópont,Hub,区間,허브,Naaf,,,,,Хаб,Хуб -"Total, seconds",OPTVAL_TOTALSECONDS,,,,"Celkem, vteřiny","Gesamt, Sekunden",,"Tuto, sekundoj","Total, segundos",,"Yhteensä, sekunnit","Total, secondes","Teljes, másodpercek","Totale, secondi","合計, 秒","누적 경과, 초당","Totaal, seconden","Razem, sekundy","Total, segundos",,"Total, secunde",Общее (секунды),"Тотал, секунде" -Total,OPTVAL_TOTAL,,,,Celkem,Gesamt,,Tuto,,,Yhteensä,Total,Teljes,Totale,合計,누적 경과,Totaal,Razem,,,Total,Общее,Тотал -"System, seconds",OPTVAL_SYSTEMSECONDS,,,,"Systém, vteřiny","System, Sekunden",,"Sistemo, sekundoj","Sistema, segundos",,"Järjestelmä, sekunnit","Système, secondes","Rendszer, másodpercek","Sistema, secondi","PC時刻, 秒","시스템, 초당","Systeem, seconden","System, sekundy","Sistema, segundos",,"Sistem, secunde",Система (секунды),"Систем, секунде" -System,OPTVAL_SYSTEM,,,,Systém,System,,Sistemo,Sistema,,Järjestelmä,Système,Rendszer,Sistema,PC時刻,시스템,Systeem,System,Sistema,,Sistem,Система,Систем +"Total, seconds",OPTVAL_TOTALSECONDS,,,,"Celkový, vteřiny","Gesamt, Sekunden",,"Tuto, sekundoj","Total, segundos",,"Yhteensä, sekunnit","Total, secondes","Teljes, másodpercek","Totale, secondi","合計, 秒","누적 경과, 초당","Totaal, seconden","Razem, sekundy","Total, segundos",,"Total, secunde",Общее (секунды),"Тотал, секунде" +Total,OPTVAL_TOTAL,,,,Celkový,Gesamt,,Tuto,,,Yhteensä,Total,Teljes,Totale,合計,누적 경과,Totaal,Razem,,,Total,Общее,Тотал +"System, seconds",OPTVAL_SYSTEMSECONDS,,,,"Systémový, vteřiny","System, Sekunden",,"Sistemo, sekundoj","Sistema, segundos",,"Järjestelmä, sekunnit","Système, secondes","Rendszer, másodpercek","Sistema, secondi","PC時刻, 秒","시스템, 초당","Systeem, seconden","System, sekundy","Sistema, segundos",,"Sistem, secunde",Система (секунды),"Систем, секунде" +System,OPTVAL_SYSTEM,,,,Systémový,System,,Sistemo,Sistema,,Järjestelmä,Système,Rendszer,Sistema,PC時刻,시스템,Systeem,System,Sistema,,Sistem,Система,Систем Netgames only,OPTVAL_NETGAMESONLY,,,,Pouze v síťové hře,Nur Netzwerkspiele,,Retludoj sole,Sólo para juegos en red,,Vain verkkopelit,Parties en Ligne seulement,Csak Netgames,Solo giochi net,オンラインのみ,멀티플레이에만,Alleen Netspellen,Tylko gry sieciowe,Jogos em rede apenas,,Doar în rețea,Только сетевые игры,Мрежне игре само Image and Text,OPTVAL_AMMOIMAGETEXT,,,,Obrázek a text,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,Obraz i Tekst,Imagem e texto,,Imagine și Text,Изображение и текст,Слика и текст Text and Image,OPTVAL_AMMOTEXTIMAGE,,,,Text a obrázek,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 i Obraz,Texto e imagem,,Text și Imagine,Текст и изобр.,Текст и слика Scripts Only,OPTVAL_SCRIPTSONLY,,,,Pouze skripty,Nur Skripte,,Skriptoj Sole,Sólo scripts,,Vain komentosarjat,Scripts seulement,Csak szkript,Solo script,スクリプトのみ,스크립트에만,Alleen scripts,Tylko skrypty,Scripts apenas,,Numai scripturi,Только скрипты,Само скрипте All,OPTVAL_ALL,,,,Všechny,Alle,,Ĉiuj,Todos,,Kaikki,Tout,Mind,Tutti,全て,모두 작동,Alle,Wszystko,Todos,,Tot,Все,Све Only last one,OPTVAL_ONLYLASTONE,,,,Pouze poslední,Nur das letzte,,Nur fina unu,Sólo el ultimo,,Vain viimeinen,Dernier seulement,Csak a legutolsó,Solo l'ultimo,最後のみ,오직 마지막 것만,Alleen de laatste,Tylko ostatni,Somente o último,Apenas o último,Doar ultimul,Только последнее,Само последњи -Traditional Doom,OPTVAL_TRADITIONALDOOM,,,,Tradiční Doom,Doom traditionell,,Tradicia Doom,Doom tradicional,,Perinteinen Doom,Doom Traditionnel,Tradícionális Doom,Doom tradizionale,正式DOOM,전형적인 둠 스타일,Traditioneel Doom,Tradycyjny Doom,Doom Tradicional,,Tradițional Doom,Цвета из Doom,Традиционални Doom +Traditional Doom,OPTVAL_TRADITIONALDOOM,,,,Tradiční Doom,Doom traditionell,,Tradicia Doom,Doom tradicional,,Perinteinen Doom,Doom Traditionnel,Tradícionális Doom,DOOM tradizionale,正式DOOM,전형적인 둠 스타일,Traditioneel Doom,Tradycyjny Doom,Doom Tradicional,,Tradițional Doom,Цвета из Doom,Традиционални Doom Traditional Strife,OPTVAL_TRADITIONALSTRIFE,,,,Tradiční Strife,Strife traditionell,,Tradicia Strife,Strife tradicional,,Perinteinen Strife,Strife Traditionnel,Tradícionális Strife,Strife tradizionale,正式Strife,전형적인 스트라이프 스타일,Traditionele Strife,Tradycyjny Strife,Strife Tradicional,,Tradițional Strife,Цвета из Strife,Традиционални Strife Traditional Raven,OPTVAL_TRADITIONALRAVEN,,,,Tradiční Raven,Raven traditionell,,Tradicia Raven,Raven tradicional,,Perinteinen Raven,Raven Traditionnel,Tradícionális Raven,Raven tradizionale,正式Raven,전형적인 레이븐 스타일,Traditionele Raven,Tradycyjny Raven,Raven Tradicional,,Tradițional Raven,Цвета из Raven,Традиционални Raven Only when found,OPTVAL_ONLYWHENFOUND,,,,Pouze po nalezení,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,Tylko gdy znaleziono,Somente quando encontrado,Apenas quando encontrado,Doar la descoperire,После обнаружения,Само кад је пронађен @@ -2871,8 +2872,8 @@ Double,OPTVAL_DOUBLE,,,,Dvojitý,Doppel,,Duobligi,Doble,,Kaksinkertainen,,Dupla, Triple,OPTVAL_TRIPLE,,,,Trojitý,Dreifach,,Triobligi,,,Kolminkertainen,,Tripla,Triplo,トリプル,3배,Drievoudig,Potrójny,Triplo,,Triplu,Тройной,Тродупло Quadruple,OPTVAL_QUADRUPLE,,,,Čtveritý,Vierfach,,Kvarobligi,Cuádruple,,Nelinkertainen,,Négyszeres,Quadruplo,クァッド,4배,Viervoudig,Poczwórny,Quádruplo,,Cvadruplu,Четверной,Четвороструко Item Pickup,OPTVAL_ITEMPICKUP,,,,Sebrání předmětu,Gegenstand genommen,,Objektoprenado,Recogida de objetos,,Esineen poiminta,Objets Ramassés,Tárgy felvétele,Raccolta oggetto,アイテム取得,아이템 획득시,Puntafhaling,Podniesienie Przedmiotu,Coleta de Item,Aquisição de Itens,Obiect Ridicat,Подбор,Подигнут предмет -Obituaries,OPTVAL_OBITUARIES,,,,Zprávy o smrti,Todesanzeige,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologio,死亡時,사망 메시지,Doodsbrieven,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље -Critical Messages,OPTVAL_CRITICALMESSAGES,,,,Kritické zprávy,Kritische Meldungen,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages Critiques,Fontos üzenetek,Messaggi critici,重要メッセージ,중요한 메시지,Kritische berichten,Wiadomości krytyczne,Mensagens Críticas,,Mesaje Critice,Важные сообщения,Критичне поруке +Obituaries,OPTVAL_OBITUARIES,,,,Oznámení o smrti,Todesanzeige,,Nekrologoj,Obituarios,,Kuolinviestit,Avis de décès,Halálok,Necrologio,死亡時,사망 메시지,Doodsbrieven,Nekrologi,Obituários,,Necrologuri,Некрологи,Читуље +Critical Messages,OPTVAL_CRITICALMESSAGES,,,,Kritická oznámení,Kritische Meldungen,,Gravaj Mesaĝoj,Mensajes críticos,,Tärkeät viestit,Messages Critiques,Fontos üzenetek,Messaggi critici,重要メッセージ,중요한 메시지,Kritische berichten,Wiadomości krytyczne,Mensagens Críticas,,Mesaje Critice,Важные сообщения,Критичне поруке Never friends,OPTVAL_NEVERFRIENDS,,,,Nikdy spojence,Keine Freunde,,Neniam amikoj,Nunca amigos,,Ei koskaan ystäviä,Jamais les Amis,Barátokat sose,Mai amici,フレンド以外,아군 무시,Nooit vrienden,Żadnych przyjaciół,Nunca amigos,,Nu aliați,Не по союзникам,Никад за пријатеље Only monsters,OPTVAL_ONLYMONSTERS,,,,Pouze příšery,Nur Monster,,Nur monstroj,Solo monstruos,,Vain hirviöt,Monstres Seulement,Csak szörnyeket,Solo i mostri,モンスターのみ,적에게만,Alleen monsters,Tylko potwory,Somente monstros,Monstros apenas,Doar monștri,Для монстров,Само чудовишста Hexen,OPTVAL_HEXEN,,,,,,,,,,,Hexen,,,,헥센,,,,,,, @@ -2887,20 +2888,20 @@ ZDoom 2.0.63,OPTVAL_ZDOOM2063,,,,,,,,,,,,,,,Z둠 2.0.63,,,,,,, All unacknowledged,OPTVAL_ALLUNACKNOWLEDGED,,,,Všechny nepotrvzené,Alle unbestätigten,,Ĉiuj neagnoskitaj,Todos no reconocidos,,Kaikki kuittaamattomat,Tout non-acknowledged,Minden visszaigazolatlan,Tutti non riconosciuti,未確認全て,모두 미확인함,Allemaal onbekend,Wszystkie niepotwierdzone,Todos não-reconhecidos,,Toate necunoscute,Всё неизвестное,Све неусвојено Errors,OPTVAL_ERRORS,,,,Chyby,Fehler,,Eraroj,Errores,,Virheet,Erreurs,Hibák,Errori,エラー,에러,Fouten,Błędy,Erros,,Erori,Ошибки,Грешка Warnings,OPTVAL_WARNINGS,,,,Varování,Warnungen,,Avertoj,Advertencias,,Varoitukset,Avertissements,Figyelmeztetések,Avvisi,警告,경고,Waarschuwingen,Ostrzeżenia,Avisos,,Atenționări,Предупреждения,Упозорење -Notifications,OPTVAL_NOTIFICATIONS,,,,Zprávy,Benachrichtigungen,,Sciigoj,Notificaciones,,Ilmoitukset,,Üzenetek,Notifiche,通知,알림,Kennisgevingen,Powiadomienia,Notificações,,Notificări,Уведомления,Обавештење +Notifications,OPTVAL_NOTIFICATIONS,,,,Oznámení,Benachrichtigungen,,Sciigoj,Notificaciones,,Ilmoitukset,,Üzenetek,Notifiche,通知,알림,Kennisgevingen,Powiadomienia,Notificações,,Notificări,Уведомления,Обавештење Everything,OPTVAL_EVERYTHING,,,,Všechno,Alles,,Ĉio,Todo,,Kaikki,Tout,Minden,Tutti,全て,전체,Alles,Wszystko,Tudo,,Tot,Всё,Све Hardware accelerated,OPTVAL_HWPOLY,,,,Hardwarová akcelerace,Hardwarebeschleunigt,,Aparatara Plirapidigo,Acelerado por Hardware,,Laitteistokiihdytetty,Accéléré par Hardware,Hardveres gyorsítás,Accelerazione Hardware,ハードウェア アクセラレート,오픈지엘 가속,Hardware versneld,Napędzane sprzętowo,Acelerado por hardware,,Accelerat Hardware,Аппаратный,Харвер убрзан -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,Motore grafico Doom software,Doom ソフトウェアレンダー,둠 소프트웨어 렌더러,,Renderer Oprogramowania Dooma,Renderizador Software do Doom,,Software,Программный,Doom софтверски рендерер -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,,Motore grafico software a pieni colori,トゥルーカラー SWレンダー,트루 컬러 소프트웨어 렌더러,,Renderer True Color,Renderizador Software True Color,,Software Color Complet,Полноцветный програмный,SW рендерер праве боје -Softpoly Renderer,OPTVAL_SWPOLY,,,,Softpoly renderer,,,Plurlatera Program-bildigilo,Renderizado Softpoly,,Softpoly-hahmonnin,Rendu Softpoly,,Motore grafico Softpoly,ソフトポリ レンダー,소프트폴리 렌더러,,Renderer Softpoly,Renderizador Softpoly,,Softpoly,Полирендер,Softpoly рендерер +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 софтверски рендерер +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 рендерер праве боје +Softpoly Renderer,OPTVAL_SWPOLY,,,,Softpoly renderer,,,Plurlatera Program-bildigilo,Renderizado Softpoly,,Softpoly-hahmonnin,Rendu Softpoly,,Rendering Softpoly,ソフトポリ レンダー,소프트폴리 렌더러,,Renderer Softpoly,Renderizador Softpoly,,Softpoly,Полирендер,Softpoly рендерер True Color Softpoly,OPTVAL_SWPOLYTC,,,,,,,Plurlatera Program-bildigilo kun Plenkoloro,Softpoly Color Verdadero,Softpoly True Color,True Color -Softpoly,Softpoly Couleurs Réeles,,Softpoly a pieni colori,トゥルーカラー ソフトポリ,트루 컬러 소프트폴리,,,Softpoly True Color,,Softpoly Color Complet,Полноцветный полирендер,Softpoly праве боје -High-Performance,OPTVAL_DEDICATED,,,,Vysoký výkon,Volle Leistung,,Alta Rendimento,Alto rendimiento,,Korkea suorituskyky,Hautes Performances,Nagy teljesítmény,Performance elevate,ハイパフォーマンス,고 성능,Hoogwaardige prestaties,Wysoka Wydajność,Alta-Performance,,De înaltă performanță,Высокая производительность,Високо-перформанси +High-Performance,OPTVAL_DEDICATED,,,,Vysoký výkon,Volle Leistung,,Alta Rendimento,Alto rendimiento,,Korkea suorituskyky,Hautes Performances,Nagy teljesítmény,Prestazioni massime,ハイパフォーマンス,고 성능,Hoogwaardige prestaties,Wysoka Wydajność,Alta-Performance,,De înaltă performanță,Высокая производительность,Високо-перформанси Power-Saving,OPTVAL_INTEGRATED,,,,Nízká spotřeba,energiesparend,,Energikonservo,Ahorro de energía,,Virransäästö,Economie d'Energie,Energia takarékos,Risparmio energetico,パワーセービング,저전력,Energiebesparing,Oszczędzanie Energii,Economia de Energia,,Economie de energie,Энергосбережение,Енергетско-штедљиви Vanilla,OPTVAL_VANILLA,,,,Původní,,,Originala,,,Alkuperäinen,,Hagyományos,Vanilla,バニラ,바닐라,,Czysty,,,Original,Ванильный,Ванила ZDoom (Forced),OPTVAL_VTFZDOOM,,,,ZDoom (vynucený),ZDoom (erzwungen),,ZDoom (Devigita),ZDoom (forzado),,ZDoom (pakotettu),ZDoom (Forcé),ZDoom (erőltetett),ZDoom (forzato),ZDoom(強制),ZDoom (강제 설정),ZDoom (Gedwongen),ZDoom (Wymuszony),ZDoom (Forçar),,ZDoom (Forțat),ZDoom (принудительно),ZDoom (присиљен) Vanilla (Forced),OPTVAL_VTFVANILLA,,,,Původní (vynucený),Vanilla (erzwungen),,Originala (Devigita),Vanilla (Forzado),,Perus (pakotettu),Vanilla (Forcé),Hagyományos (erőltettt),Vanilla (forzato),バニラ(強制),바닐라 (강제 설정),Vanilla (Gedwongen),Czysty (Wymuszony),Vanilla (Forçar),DOS Original (Forçar),Original (Forțat),Vanilla (принудительно),Ванила (присиљен) -Auto (ZDoom Preferred),OPTVAL_VTAZDOOM,,,,Auto (preferován ZDoom),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),Automatyczny (Preferowany ZDoom),Automático (De preferência ZDoom),,Auto (ZDoom preferat),Автоматически (предпочитать ZDoom),Аутоматски (ZDoom преферијални) -Auto (Vanilla Preferred),OPTVAL_VTAVANILLA,,,,Auto (preferován původní),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),Automatyczny (Preferowany czysty),Automático (De preferência Vanilla),Automático (De preferência DOS Original),Auto (Original preferat),Автоматически (предпочитать оригинал),Аутоматски (ванила преферијални) +Auto (ZDoom Preferred),OPTVAL_VTAZDOOM,,,,Auto (preferován ZDoom),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),Automatyczny (Preferowany ZDoom),Automático (De preferência ZDoom),,Auto (ZDoom preferat),Автоматически (выбирать ZDoom),Аутоматски (ZDoom преферијални) +Auto (Vanilla Preferred),OPTVAL_VTAVANILLA,,,,Auto (preferován původní),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),Automatyczny (Preferowany czysty),Automático (De preferência Vanilla),Automático (De preferência DOS Original),Auto (Original preferat),Автоматически (выбирать изначальный),Аутоматски (ванила преферијални) Small,OPTVAL_SMALL,,,,Malé,Klein,,Malgranda,Pequeño,,Pieni,Petit,Kicsi,Piccolo,小,작게,Klein,Mały,Pequeno,,Mic,Мелкий,Мало Large,OPTVAL_LARGE,,,,Velké,Groß,,Granda,Grande,,Suuri,Grand,Nagy,Grande,大,크게,Groot,Duży,Grande,,Mare,Крупный,Велико Console,OPTVAL_CONSOLE,,,,Konzole,Konsole,,Konzolo,Consola,,Konsoli,Console,Konzol,,コンソール,콘솔,Console,Konsola,Console,Consola,Consolă,Консольный,Конзола @@ -2933,53 +2934,41 @@ Console,OPTVAL_CONSOLE,,,,Konzole,Konsole,,Konzolo,Consola,,Konsoli,Console,Konz Heretic,OPTSTR_HERETIC,,,,,,,,,,,,,,,헤러틱 커서,,,,,,, Chex,OPTSTR_CHEX,,,,,,,,,,,,,,,첵스 커서,,,,,,, No Sound,OPTSTR_NOSOUND,,,,Bez zvuku,Kein Sound,,Neniu Sono,Sin sonido,,Ei ääntä,Pas de son,Hang nélkül,Nessun suono,サウンドなし,음향 없음,Geen geluid,Brak dźwięku,Sem som,,Fără Sunet,Без звука,Без-звучни -No interpolation,OPTSTR_NOINTERPOLATION,,,,Bez interpolace,Keine Interpolation,,Neniu interpolado,Sin interpolación,,Ei interpolaatiota,Pas d'interpolation,Nincs simítás,No interpolazione,補間無し,보간 없음,Geen interpolatie,Brak interpolacji,Sem interpolação,,Fără interpolare,Без интерполяции,Нема уметања +No interpolation,OPTSTR_NOINTERPOLATION,,,,Bez interpolace,Keine Interpolation,,Neniu interpolado,Sin interpolación,,Ei interpolaatiota,Pas d'interpolation,Nincs interoláció,No interpolazione,補間無し,보간 없음,Geen interpolatie,Brak interpolacji,Sem interpolação,,Fără interpolare,Без сглаживания,Нема уметања 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,Motore grafico Hardware,ハードウェア レンダラー,오픈지엘 렌더러,,Renderer Sprzętowy,Renderizador Hardware,,Setări Mod OpenGL,Рендерер OpenGL,Хардвер рендерер -Software Renderer,DSPLYMNU_SWOPT,,,,Softwarový renderer,,,Programa Bildigilo,Renderizado por Software,,Ohjelmistohahmonnin,Moteur de Rendu Software,Szoftver Render,Motore grafico Software,ソフトウェア レンダラー,소프트웨어 렌더러,,Renderer Oprogramowania,Renderizador Software,,Setări Mod Software,Программный рендерер,Софтвер рендерер +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,Хардвер рендерер +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,Программное отображение,Софтвер рендерер Hardware Rendering Options,GLMNU_TITLE,,,,Nastavení hardwarového rendereru,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,Opcje Renderowania Sprzętowego,Opções de Renderização por Hardware,,Setări Redare OpenGL,Настройки OpenGL,Опција хардвер рендера Dynamic Light Options,GLMNU_DYNLIGHT,,,,Nastavení dynamických světel,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,Opcje Dynamicznego Oświetlenia,Opções de Luz Dinâmica,,Setări Lumini Dinamice,Динамическое освещение,Подешавања динамичког осветљења Texture Options,GLMNU_TEXOPT,,,,Nastavení textur,Texturoptionen,,Agordoj de Teksturoj,Opciones de texturas,,Pintakuviointiasetukset,Options Textures,Textúra Beállítások,Opzioni Texture,テクスチャー オプション,텍스쳐 설정,Textuur Opties,Opcje Tekstur,Opções de Textura,,Setări Texturi,Настройки текстур,Подешавања текстура Preferences,GLMNU_PREFS,,,,Možnosti,Einstellungen,,Preferoj,Preferencias,,Asetukset,Préférences,Preferenciák,Preferenze,環境設定,성능,Voorkeuren,Preferencje,Preferências,,Preferințe,Настройки,Преференција -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,, Trim sprite edges,GLTEXMNU_TRIMSPREDGE,,,,Oříznout okraje spritů,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,スプライトの角を取る,스프라이트 모서리 다듬기,,Przycinanie krawędzi sprite'ów,Cortar bordas de sprites,,Tundere margini sprite-uri,Обрезание краёв спрайтов,Подсећи ивице спрајтова Sort draw lists by texture,GLTEXMNU_SORTDRAWLIST,,,,Seřadit vykreslování podle textury,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,Sortowanie list renderowania wdług tekstur,Organizar listas de renderização por textura,,Sortează listele de texturi,Сортировать списки текстур,Сортирано цртај листе од текстуре Dynamic Lights,GLLIGHTMNU_TITLE,,,,Dynamická světla,Dynamische Lichter,,Dinamikaj Lumoj,Luces dinámicas,,Dynaamiset valot,Lumières Dynamiques,Dinamikus Fények,Luci Dinamiche,ダイナミックライト,다이나믹 라이트,Dynamische verlichting,Dynamiczne Oświetlenie,Luzes Dinâmicas,,Lumini Dinamice,Динамическое освещение,Динамичко осветљење Dynamic Lights (Hardware),GLLIGHTMNU_LIGHTSENABLED,,,,Dynamická světla (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),Dynamiczne Oświetlenie (Sprzętowe),Luzes Dinâmicas (Hardware),,Lumini Dinamice (OpenGL),Динамическое освещение (OpenGL),Динамичко осветљење (хардвер) -Enable light definitions,GLLIGHTMNU_LIGHTDEFS,,,Activer les définitions GLDEFS,Povolit definice světel,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,Włącz definicje światła,Habilitar definições de luz,Permitir definições de luz,Activează definiții lumini,Включить определения света,Омогући светлосне дефиниције +Enable light definitions,GLLIGHTMNU_LIGHTDEFS,,,,Povolit definice světel,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,Włącz definicje światła,Habilitar definições de luz,Permitir definições de luz,Activează definiții lumini,Включить определения света,Омогући светлосне дефиниције Lights affect sprites,GLLIGHTMNU_LIGHTSPRITES,,,,Světla ovlivňují sprity,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,Światło ma wpływ na sprite'y,Luzes afetam sprites,,Luminile afectează sprite-urile,Освещение спрайтов,Светло утиче на спрајтове -Lights affect particles,GLLIGHTMNU_LIGHTPARTICLES,,,,Světla ovlivňují částice,Partikel werden beleuchtet,,Spritoj 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,Światło ma wpływ na cząsteczki,Luzes afetam partículas,,Luminile afectează particulele,Освещение частиц,Светло утиче на честице -Light shadowmaps,GLLIGHTMNU_LIGHTSHADOWMAP,,,,Mapy stínů,Shadowmaps für Lichter,,Lum-ombro-mapojn,Mapeo de sombra de Luz,,Valojen varjokartat,Shadowmaps,,Mappe shadow,ライトのシャドウマッピング,조명에 영향받는 섀도우맵,Lichte schaduwkaarten,Oświetlenie map cieni,Shadowmaps,,Umbre lumini,Свет на теневых картах,Светло мапе сенки -Shadowmap quality,GLLIGHTMNU_LIGHTSHADOWMAPQUALITY,,,,Kvalita map stínů,Shadowmap Qualität,,Kvalito de ombro-mapo,Calidad de Mapeo de Sombras,,Varjokarttojen laatu,Qualité Shadowmap,Shadowmap minőség,Qualità mappe shadow,シャドウマップ 品質,섀도우맵 퀄리티,Schaduwkaart kwaliteit,Jakość map cieni,Qualidade de shadowmap,,Calitate umbre,Качество теневых карт,Мапа сенки квалитет -Shadowmap filter,GLLIGHTMNU_LIGHTSHADOWMAPFILTER,,,,Filtrování map stínů,Shadowmap Filter,,Filtro de ombro-mapo,Filtro de Mapeo de Sombras,,Varjokarttojen suodatus,Filtre de Shadowmaps,,Filtro mappe shadow,シャドウマップ フィルター,섀도우맵 필터,Schaduwkaart filter,Filtr map cieni,Filtro de shadowmap,,Filtru umbre,Фильтр теневых карт,Мапа сенки филтер -Sector light mode,GLPREFMNU_SECLIGHTMODE,,,,Režim osvětlení sektorů,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,Tryb oświetlenia sektorów,Modo de luz de setor,,Mod iluminare sectorial,Режим освещения секторов,Секторско светло мод +Lights affect particles,GLLIGHTMNU_LIGHTPARTICLES,,,,Světla ovlivňují částice,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,Światło ma wpływ na cząsteczki,Luzes afetam partículas,,Luminile afectează particulele,Освещение частиц,Светло утиче на честице +Light shadowmaps,GLLIGHTMNU_LIGHTSHADOWMAP,,,,Mapy stínů,Shadowmaps für Lichter,,Lum-ombro-mapoj,Mapeo de sombra de Luz,,Valojen varjokartat,Shadowmaps,,Ombre proiettate,ライトのシャドウマッピング,조명에 영향받는 섀도우맵,Lichte schaduwkaarten,Oświetlenie map cieni,Shadowmaps,,Umbre lumini,Свет на теневых картах,Светло мапе сенки +Shadowmap quality,GLLIGHTMNU_LIGHTSHADOWMAPQUALITY,,,,Kvalita map stínů,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,Jakość map cieni,Qualidade de shadowmap,,Calitate umbre,Качество теневых карт,Мапа сенки квалитет +Shadowmap filter,GLLIGHTMNU_LIGHTSHADOWMAPFILTER,,,,Filtrování map stínů,Shadowmap Filter,,Filtro de ombro-mapo,Filtro de Mapeo de Sombras,,Varjokarttojen suodatus,Filtre de Shadowmaps,,Filtro ombre proiettate,シャドウマップ フィルター,섀도우맵 필터,Schaduwkaart filter,Filtr map cieni,Filtro de shadowmap,,Filtru umbre,Фильтр теневых карт,Мапа сенки филтер Fog mode,GLPREFMNU_FOGMODE,,,,Režim mlhy,Nebelmodus,,Reĝimo de nebulo,Modo de niebla,,Sumutila,Mode du broullard,Köd mód,Modalità nebbia,フォグモード,안개 모드,Mistmodus,Tryb mgły,Modo de neblina,,Mod ceață,Режим тумана,Магла мод Fog forces fullbright,GLPREFMNU_FOGFORCEFULLBRIGHT,,,,Mlha vynucuje plný jas,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,Mgła wymusza pełną jasność,Neblina força brilho máximo,,Ceața forțează luminozitate maximă,Туман включает режим максимальной яркости,Магла присиљава пуну светлост Weapon light strength,GLPREFMNU_WPNLIGHTSTR,,,,Intenzita světel zbraní,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,Natężenie światła broni,Intensidade de luz da arma,,Intensitate lumină armă,Интенсивность вспышек оружия,Блага снага оружја -Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,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 sugli specchi,マップオンミラーの画像表示,거울 주변의지도 활성,Milieukaart op spiegels,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Reflecții pe oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима +Environment map on mirrors,GLPREFMNU_ENVIRONMENTMAPMIRROR,,,,Mapa prostředí na zrcadlech,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,Mapa środowiska w lustrach,Mapa de ambiente em espelhos,,Reflecții pe oglinzi,Карта окружения на зеркалах,Околинска мапа на прозорима Enhanced night vision mode,GLPREFMNU_ENV,,,,Vylepšený režim nočního vidění,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,Ulepszony tryb widzenia w ciemności,Modo de visão noturna avançada,,Vedere infraroșie avansată,Улучшенный режим ночного видения,Побољшана ноћна визија мод -ENV shows stealth monsters,GLPREFMNU_ENVSTEALTH,,,,Noční vidění ukazuje skryté příšery,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,UTWC pokazuje ukrywających się przeciwników,Visão noturna mostra monstros invisíveis,,PNV afișează monștri ascunși,ПНВ показывает скрытых монстров,ПНВ показује скривена чудовишта +ENV shows stealth monsters,GLPREFMNU_ENVSTEALTH,,,,Vylepšené noční vidění ukazuje skryté příšery,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,Ulepszony noktowizor pokazuje ukrywających się przeciwników,Visão noturna mostra monstros invisíveis,,PNV afișează monștri ascunși,ПНВ показывает скрытых монстров,ПНВ показује скривена чудовишта Adjust sprite clipping,GLPREFMNU_SPRCLIP,,,,Vyladění clippingu spritů,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,Ustaw wcięcie sprite'ów,Ajustar clipping de sprite,,Ajustare poziții sprite-uri,Режим обрезки спрайтов,Подеси спрајт клипинг Smooth sprite edges,GLPREFMNU_SPRBLEND,,,,Vyhladit okraje spritů,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,Gładkie krawędzie sprite'ów,Suavizar bordas de sprites,,Netezire margini sprite-uri,Размытие краёв спрайтов,Углачати ивице спрајта -Fuzz Style,GLPREFMNU_FUZZSTYLE,,,,Styl šumu,Fuzz Stil,,Stilo de lenugo,Estilo de difuminación,,Sumennustyyli,Style de bruit blanc,Homályosítás stílusa,Stile fuzz,ファズスタイル,퍼즈 스타일,Fuzz stijl,Styl Szumu,Estilo de difusão,,Stil sclipire,Тип шума,Фаз стајл -Sprite billboard,GLPREFMNU_SPRBILLBOARD,,,,Orientace spritů,,,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,Поворот спрайтов,Спрајт билборд +Fuzz Style,GLPREFMNU_FUZZSTYLE,,,,Styl šumu,Fuzz Stil,,Stilo de Lenugo,Estilo de difuminación,,Sumennustyyli,Style de bruit blanc,Homályosítás stílusa,Stile fuzz,ファズスタイル,퍼즈 스타일,Fuzz stijl,Styl Szumu,Estilo de difusão,,Stil sclipire,Тип шума,Фаз стајл +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,Поворот спрайтов,Спрајт билборд Sprites face camera,GLPREFMNU_SPRBILLFACECAMERA,,,,Sprity čelí kameře,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,Sprite'y skierowane w kamerę,Sprites de frente pra câmera,,Sprite-urile privesc înspre cameră,Спрайты направлены к камере,Спрајт камера фаце -Particle style,GLPREFMNU_PARTICLESTYLE,,,,Styl částic,Partikelstil,,Partiklstilo,Estilo de partículas,,Hiukkastyyli,Style de particules,Részecske stílusa,Stile particelle,パーティクル スタイル,입자 스타일,Deeltjes stijl,Styl Cząsteczek,Tipo de partícula,,Stil particule,Тип частиц,Честице стајл +Particle style,GLPREFMNU_PARTICLESTYLE,,,,Styl částic,Partikelstil,,Partikla stilo,Estilo de partículas,,Hiukkastyyli,Style de particules,Részecske stílusa,Stile particelle,パーティクル スタイル,입자 스타일,Deeltjes stijl,Styl Cząsteczek,Tipo de partícula,,Stil particule,Тип частиц,Честице стајл Rendering quality,GLPREFMNU_RENDERQUALITY,,,,Kvalita vykreslování,Renderqualität,,Kvalito de bildigado,Calidad de Renderizado,,Hahmonnuslaatu,Qualité du rendu,Renderelés minősége,Qualità resa grafica,レンダリング品質,렌더링 품질,Het teruggeven van kwaliteit,Jakość Renderowania,Qualidade de renderização,,Calitate video,Качество рендеринга,Квалитет рендовања 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,VR-режим,Стереотоно 3D VR Enable Quad Stereo,GLPREFMNU_VRQUADSTEREO,,,,Povolit 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,Włącz Poczwórne Stereo,Habilitar Quad Stereo,Permitir Quad Stereo,Activare Quad Stereo,Четырёхкратный стереорежим,Омогући четвороструки стерео -Banded SW Lightmode,GLPREFMNU_SWLMBANDED,,,,Režim pruhovaného SW osvětlení,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,,Softare Lightmode bandata,バンデドSWライトモード,단결된 SW 라이트 모드,SW-lichtmodus met banden,Naznaczony Tryb Oświetlenia Oprogramowania,Modo de luz por bandas em software,,Mod limitat de iluminare Software,Ограниченный программный режим освещения,Повезани SW режим осветљења +Banded SW Lightmode,GLPREFMNU_SWLMBANDED,,,,Režim pruhovaného SW osvětlení,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,Naznaczony Tryb Oświetlenia Oprogramowania,Modo de luz por bandas em software,,Mod limitat de iluminare Software,Ограниченный программный режим освещения,Повезани SW режим осветљења Distance Between Your Eyes,GLPREFMNU_VRIPD,,,,Vzdálenost mezi očima,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,Odległość Pomiędzy Twoimi Oczami,Distância entre os olhos,,Distanța dintre ochi,Расстояние между глазами,Даљина између твојих очију Distance From Your Screen,GLPREFMNU_VRSCREENDIST,,,,Vzdálenost od obrazovky,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,Odległość Od Twojego Ekranu4,Distância a partir da tela,,Distanța față de ecranul tău,Расстояние от экрана,Даљина од окрена Smart,OPTVAL_SMART,,,,Chytré,,,Inteligenta,Inteligente,,Älykäs,Intelligent,Okos,Intelligente,スマート,자동 조정,Slim,Mądry,Inteligente,,Inteligent,Умный,Паметно @@ -2990,14 +2979,11 @@ Any fixed colormap,OPTVAL_ANYFIXEDCOLORMAP,,,Any fixed colourmap,Jakákoli fixn Use as palette,OPTVAL_USEASPALETTE,,,,Použít jako paletu,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,"Użyj jako palety ",Usar como paleta,Usar como palete,Utilizare drept paletă,Использовать как палитру,Користи као палету Blend,OPTVAL_BLEND,,,,Míchat,Überblenden,,Miksi,Mezclar,,Sekoitus,Mélanger,Kever,Miscela,混合,혼합,Mengen,Połącz,Mesclar,Misturar,Amestec,Смешать,Бленд -Standard,OPTVAL_STANDARD,,,,Standardní,,,Norma,Estándar,,Normaali,,Szabvány,Standard,標準,기본,Standaard,Standard,Padrão,,,Стандартный,Стандардно Bright,OPTVAL_BRIGHT,,,,Světlý,Hell,,Hela,Brillante,,Kirkas,Clair,Világos,Chiara,明るい,밝은,Helder,Jasne,Claro,,Luminos,Яркий,Свијетло Dark,OPTVAL_DARK,,,,Tmavý,Dunkel,,Malhela,Oscuro,,Tumma,Sombre,Sötét,Scura,暗い,어두운,Donker,Ciemne,Escuro,,Întunecat,Тёмный,Тамно Doom Legacy,OPTVAL_LEGACY,,,,,Doom Legacy,,,,,Doom Legacy,,Hagyományos Doom,,DOOM調,둠 레거시,,,,,,, Software,OPTVAL_SOFTWARE,,,,,,,Programa bildigilo,,,Ohjelmisto,,Szoftver,,ソフトウェア,소프트웨어,,Oprogramowanie,,,,Программный,Софтвер -Speed,OPTVAL_SPEED,,,,Rychlost,Geschwindigkeit,,Rapido,Velocidad,,Nopeus,Vitesse,Sebesség,Velocità,速度寄り,성능,Snelheid,Szybkość,Velocidade,,Viteză,Скорость,Брзина -Quality,OPTVAL_QUALITY,,,,Kvalita,Qualität,,Kvalito,Calidad,,Laatu,Qualité,Minőség,Qualità,品質寄り,고품질,Kwaliteit,Jakość,Qualidade,,Calitate,Качество,Квалитет -Optimal,OPTVAL_OPTIMAL,,,,Optimální,,,Optima,Óptimo,,Tasapainoinen,Optimiser,Optimális,Ottimale,最適,최적함,Optimaal,Optymalne,Otimizado,,Optim,Оптимальный,Оптимал +Optimal,OPTVAL_OPTIMAL,,,,Optimální,,,Optima,Óptimo,,Optimaalinen,Optimiser,Optimális,Ottimale,最適,최적함,Optimaal,Optymalne,Otimizado,,Optim,Оптимальный,Оптимал Y Axis,OPTVAL_YAXIS,,,,Po ose Y,Y-Achse,,Y-Akso,Eje Y,,Y-akseli,Axe Y,Y tengely,Asse Y,縦軸,Y 축,Y-as,Oś Y,Eixo Y,,Axa Y,По горизонтали,Y оса X/Y Axis,OPTVAL_XYAXIS,,,,Po osách X/Y,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,Oś X/Y,Eixo X/Y,,Axa Y/Z,По обеим осям,X/Y оса Square,OPTVAL_SQUARE,,,,Čtvercové,Quadratisch,,Kvadrata,Cuadrado,,Kulmikas,Carrées,Négyzet,Quadrato,平方,정사각형,Vierkant,Kwadrat,Quadrado,,Pătrat,Квадратные,Квадрат @@ -3018,8 +3004,8 @@ Right Eye,OPTVAL_RIGHTEYE,,,,Pravé oko,Rechtes Auge,Δεξί μάτι,Dekstra O Side-by-side Full,OPTVAL_SBSFULL,,,,"Vedle sebe, plné",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,Pełne Obok Siebie,Lado a lado completo,,Una lângă alta Pline,"Бок о бок, полно",Раме уз раме цело Side-by-side Narrow,OPTVAL_SBSNARROW,,,,"Vedle sebe, úzké",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,Wąskie Obok Siebie,Lado a lado estreito,,Una lângă alta Înguste,"Бок о бок, узко",Раме уз раме уско Top/Bottom,OPTVAL_TOPBOTTOM,,,,Nad sebou,Übereinander,Πάνω/Κάτω,Supero/Subo,Superior/Inferior,,Ylä-/Alaosa,Dessus/Dessous,Fent/Lent,Sopra/Sotto,天/底,위/아래,Boven/onderkant,Góra/Dół,Superior/Inferior,,Sus/Jos,Сверху/снизу,Врх/Дно -Row Interleaved,OPTVAL_ROWINTERLEAVED,,,,Po řádcích,Zeilenversetzt,,Vicoj interteksitaj,Fila intercalada,,Vaakalomitus,Entrelacement rangée,,Riga interfogliata,行インターリーブ,열 교차 배치,Rij interleaved,Przepleciony Szereg,Linha Intercalada,,Rând intercalat,Чередование строк,Редно прошарано -Column Interleaved,OPTVAL_COLUMNINTERLEAVED,,,,Po sloupcích,Spaltenversetzt,,Kolonoj interteksitaj,Columna intercalada,,Pystylomitus,Entralcement colonne,,Colonna interfogliata,列インターリーブ,세로줄 교차 배치,Kolom Interleaved,Przepleciona Kolumna,Coluna Intercalada,,Coloană intercalată,Чередование столбцов,Колонско прошарано +Row Interleaved,OPTVAL_ROWINTERLEAVED,,,,Po řádcích,Zeilenversetzt,,Vicoj interteksitaj,Fila intercalada,,Vaakalomitus,Entrelacement rangée,Sor beillesztés,Riga interfogliata,行インターリーブ,열 교차 배치,Rij interleaved,Przepleciony Szereg,Linha Intercalada,,Rând intercalat,Чередование строк,Редно прошарано +Column Interleaved,OPTVAL_COLUMNINTERLEAVED,,,,Po sloupcích,Spaltenversetzt,,Kolonoj interteksitaj,Columna intercalada,,Pystylomitus,Entralcement colonne,Oszlop beillesztés,Colonna interfogliata,列インターリーブ,세로줄 교차 배치,Kolom Interleaved,Przepleciona Kolumna,Coluna Intercalada,,Coloană intercalată,Чередование столбцов,Колонско прошарано Checkerboard,OPTVAL_CHECKERBOARD,,,,Šachovnice,Schachbrettmuster,,Ŝaktablo,Tablero de damas,,Shakkilautakuvio,Damier,Tábla,Scacchiere,市松模様,체크무늬,Dambord,Szachownica,Xadrez,,Tablă de Șah,Шахматная доска,Шаховска табла Quad-buffered,OPTVAL_QUADBUFFERED,,,,Quad buffer,Vierfachgepuffert,,Kvarobla bufro,Cuádruple búfer,,Neloispuskurointi,Quadruple-tampon,Négyszeresen bufferelt,Quad buffer,クワッドバッファー,쿼드 버퍼,Viervoudig gebufferd,Poczwórnie zbuforowane,Buffer quádruplo,,Împătrit,Четырёхкратный,Квад-унапређено TrueColor Options,DSPLYMNU_TCOPT,,,,Nastavení True color,TrueColor Optionen,TrueColor Ρυθμίσεις,Plenkolora Agordoj,Opciones TrueColor,,TrueColor-asetukset,Options TrueColor,TrueColor Beállítások,Opzioni TrueColor,トゥルーカラー オプション,트루 컬러 설정,TrueColor Opties,Opcje TrueColor,Opções de TrueColor,,Setări Mod Culori Complete,Полноцветный режим,Подешавања правих боја @@ -3034,21 +3020,21 @@ Search for any term,OS_ANY,,,,Hledat jakékoli klíčové slovo,Suche nach belie Search for all terms,OS_ALL,,,,Hledat všechna klíčová slova,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,Szukaj wszystkich wyrażeń,Buscar por todos os termos,Procurar por todos os termos,Căutare după toți termenii,Искать все слова,Тражи све речи No results found.,OS_NO_RESULTS,,,,Nic nenalezeno.,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.,Brak wyników,Nenhum resultado encontrado.,,Niciun rezultat găsit.,Результатов не найдено.,Нема резултата. Search:,OS_LABEL,,,,Hledat:,Suche:,Αναζήτηση:,Serĉi:,Buscar:,,Etsi:,Recherche:,Keresés:,Trova:,検索:,검색:,Zoeken:,Szukaj:,Busca:,Procura:,Căutare:,Поиск:,Претрага: -Always show keys,AUTOMAPMNU_SHOWKEYS_ALWAYS,,,,Vždy zobrazit klíče,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,Zawsze pokazuj klucze,Sempre mostrar chaves,Mostrar chaves sempre,Afișează cheile în permanență,Всегда отображать ключи,Увек приказуј кључеве +Always show keys,AUTOMAPMNU_SHOWKEYS_ALWAYS,,,,Vždy zobrazit klíče,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,Zawsze pokazuj klucze,Sempre mostrar chaves,Exibir chaves sempre,Afișează cheile în permanență,Всегда отображать ключи,Увек приказуј кључеве ,,Newly added content,,,,,,,,,,,,,,,,,,,,, -Team changing has been disabled!,TXT_NO_TEAM_CHANGE,,,,Změna týmu je vypnuta!,Teamwechsel ist deaktiviert!,Η αλαγγή ομάδον απαγορεύεται!,Teamŝanĝanta 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!,Zmiana drużyn została wyłączona!,Troca de equipe foi desativada!,Troca de equipa foi desativada!,Schimbarea echipelor a fost dezactivată!,Смена команды была отключена!,Мењање тима је искључено! -%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 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 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 тим +Team changing has been disabled!,TXT_NO_TEAM_CHANGE,,,,Změna týmu je vypnuta!,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!,Zmiana drużyn została wyłączona!,Troca de equipe foi desativada!,Troca de equipa foi desativada!,Schimbarea echipelor a fost dezactivată!,Смена команды была отключена!,Мењање тима је искључено! +%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 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 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 is now a loner.,TXT_LONER,,,,%s je teď @[self_cs].,%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 jest teraz sam@[ao_pl],%s está sozinh@[ao_ptb] agora.,,%s este singur acum,Игрок %s теперь одиночка.,%s је сада самотњак. %s left the game with %d frags,TXT_LEFTWITHFRAGS,,,,%s opustil@[ao_cs] hru s %d fragy,%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 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 left the game,TXT_LEFTTHEGAME,,,,%s opustil@[ao_cs] hru,%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 opuścił@[ao_pl] grę,%s saiu do jogo,,%s a părăsit jocul,Игрок %s покинул игру,%s је изаш@[ao_2_sr] из игре +",%s 이(가) 게임에서 %d 의 점수를 기록하고 퇴장 함.,%s verliet het spel met %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 left the game,TXT_LEFTTHEGAME,,,,%s opustil@[ao_cs] hru,%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 opuścił@[ao_pl] grę,%s saiu do jogo,,%s a părăsit jocul,Игрок %s покидает игру,%s је изаш@[ao_2_sr] из игре This savegame needs these files,TXT_SAVEGAMENEEDS,,,,Uložená hra potřebuje tyto soubory,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,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,Данное сохранение требует следующие файлы,Овој сачуваној игри требају ови фајлови Could not read savegame '%s'.,TXT_COULDNOTREAD,,,,Nepodařilo se načíst uloženou hru '%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.,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' is not a valid savegame: Missing 'info.json'.,TXT_NOINFOJSON,,,,%s' není funkční uloženou hrou: Chybí '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” 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“. -Failed to access savegame info in '%s'.,TXT_FAILEDTOREADSG,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Konnte Spielstandinfo in '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informon de la konservludo 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'.,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. +Failed to access savegame info in '%s'.,TXT_FAILEDTOREADSG,,,,Nepodařilo se načíst informace v uložené hře '%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'.,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. Savegame '%s' is from an incompatible version.,TXT_INCOMPATIBLESG,,,,Uložená hra '%s' je z nekompatibilní verze.,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.,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 је из инкомпетабилне верзије. Savegame '%s' is from another ZDoom-based engine:,TXT_OTHERENGINESG,,,,Uložená hra '%s' je z jiného enginu založeného na ZDoomu:,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:,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-базиран енџин: 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),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).,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 је најстарија подржана) @@ -3061,67 +3047,71 @@ Savegame '%s' is missing the current map.,TXT_NOMAPSG,,,,Uložená hra '%s' neob %s' is not a valid savegame: Missing 'globals.json'.,TXT_NOGLOBALSJSON,,,,%s' není funkční uloženou hrou: Chybí '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” 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“. -Failed to access savegame info in '%s',TXT_SGINFOERR,,,,Nepodařilo se načíst informace v uložené hře '%s'.,Konnte Spielstandinformationen von '%s' nicht lesen.,Η πρόσβαση πληροφοριών του αρχείου αποθήκευσης %s δέν ήταν επιτυχής,Malsukcesis aliri informo 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'.,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 +Failed to access savegame info in '%s',TXT_SGINFOERR,,,,Nepodařilo se načíst informace v uložené hře '%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'.,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 A game save is still pending.,TXT_SAVEPENDING,,,,Stále se čeká na uložení hry.,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.,Zapis gry jest wciąż w toku.,Jogo salvo ainda pendente.,Jogo gravado ainda pendente.,O salvare este încă în așteptare.,Сохранение в очереди.,Сачувана игра идаље чека Not in a saveable game.,TXT_NOTSAVEABLE,,,,Nejsi v uložitelné hře.,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.,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.,Не в сохраняемой игре.,Није у сачувајућој игри Not in a level,TXT_NOTINLEVEL,,,,Nejsi v levelu.,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,Nie w poziomie.,Não está em uma fase.,Não estás em nenhum nível.,Nu ești în niciun nivel,Не на уровне,Није у нивоу Player is dead in a single-player game,TXT_SPPLAYERDEAD,,,,Hráč je mrtvý v singleplayer hře.,Spieler ist tot in einem Einzelspieler-Spiel.,Ο παίχτης έιναι νεκρός σε ένα singleplayer παιχνίδι,Ludanto estas mortita en sol-ludanta ludo,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,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,Игрок мёртв в одиночной игре,Играч је мртав у сингл-плејер игри -Save failed,TXT_SAVEFAILED,,,,Uložení se nezdařilo.,Speichern fehlgeschlagen.,Η αποθήκευση απέτυχε,Konservado malsukcesis,Guardado fallido,,Tallennus epäonnistui,La sauvegarde à échoué.,Mentés meghiusult,Salvataggio fallito,セーブに失敗した。,저장 실패,Opslaan mislukt,Nie udało się zapisać,Falha ao salvar,Falha ao gravar,Salvare eșuată,Ошибка сохранения игры,Сачување није успело +Save failed,TXT_SAVEFAILED,,,,Uložení se nezdařilo.,Speichern fehlgeschlagen.,Η αποθήκευση απέτυχε,Konservo malsukcesis,Guardado fallido,,Tallennus epäonnistui,La sauvegarde à échoué.,Mentés meghiusult,Salvataggio fallito,セーブに失敗した。,저장 실패,Opslaan mislukt,Nie udało się zapisać,Falha ao salvar,Falha ao gravar,Salvare eșuată,Ошибка сохранения игры,Сачување није успело Could not create screenshot.,TXT_SCREENSHOTERR,,,,Nepodařilo se pořídit snímek obrazovky.,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.,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ă.,Ошибка создания скриншота,Није успело направити снимак екрана. By %s,TXT_BY,As in paused by player %s.,,,hráčem %s,Von %s,Απο @[pro_gr] %s,De %s,Por %s,,Pelaajan %s toimesta,Par %s,%s által,Da %s,"%s より ",%s 에 의해,Met %s,Przez %s,Por %s,,De către %s,игроком %s,играчем %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ě.",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.,Presiona una tecla o da 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.,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.,"Нажмите любую клавишу или кликните по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете. -Screen Blend Options,HUDMNU_FLASH,,,,Nastavení barvení obrazovky,Ü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,Opcje scalania ekranu,Opções de mescla de tela,Opções de mistura de ecrã,Setări Amestec Imagine,Настройки смешивания экрана,Подешавања блед екрана +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ě.",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.,Presiona una tecla o da 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.,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.,"Нажмите любую клавишу или нажмите по окну, чтобы выйти.",Притисните било који тастер или кликните било где на екрану да одустанете. +Screen Blend Options,HUDMNU_FLASH,,,,Barvení obrazovky,Ü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,Opcje scalania ekranu,Opções de mescla de tela,Opções de mistura de ecrã,Setări Amestec Imagine,Настройки смешивания экрана,Подешавања блед екрана 3D mode,GLMNU_3DMODE,,,,3D režim,3D Modus,3D λειτουργία,3D-reĝimo,Modo 3D,,3D-tila,Mode 3D,3D mód,Modalità 3D,3Dモード,3D 모드 적용,3D-modus,Tryb 3D,Modo 3D,,Mod 3D,Режим 3D,3D режим Crosshair,HUDMNU_CROSSHAIRON,,,,Zaměřovač,Fadenkreuz,Crosshair,Reteto,Retícula,,Tähtäin,Viseur,Célkereszt,Mirino,クロスヘア,조준점,Draadkruis,Celownik,Mira,,Țintă,Прицел,Нишан Subtitles,MSGMNU_SUBTITLES,,,,Titulky,Untertitel,Υπότιτλοι,Subtekstoj,Subtitulos,,Tekstitys,Sous-titres,Feliratok,Sottotitoli,サブタイトル,자막,Ondertitels,Napisy,Legendas,,Subtitrări,Субтитры,Титлови Tonemap Palette Colormap,GLPREFMNU_PALTONECMAP,This line of text is under review,,,,,,Tonmapo Paletro Kolormapo,Colormap para Paleta de Mapa de Tonos,,Sävykartan paletin värikartta,Tonemap type colormap palette,,,トーンマップ パレット カラーマップ,톤맵 팔레트 컬러맵 설정,,Mapa Tonów jako paleta mapy kolorów,Colormap da Paleta de Tonemap,,,, Prevent gray shadows,GLPREFMNU_PALTONENOGREY,,,Prevent grey shadows,Předejít šedým stínům,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,Zapobiegaj szarym cieniom,Prevenir sombras cinzentas,,Prevenire umbre gri,Убрать серые тени,Онемогући сиве сенке -Font Options,HUDMNU_FONTOPTIONS,,,,Nastavení fontů,Zeichensatzoptionen,Ρυθμίσεις Γραμματοσειρών,Tiparo-Agordoj,Opciones de fuentes,,Fonttiasetukset,Options de police,Betű Beállítások,Opzioni di font,フォント オプション,폰트 설정,Lettertype opties,Opcje czcionek,Opções de Fonte,,Setări Font,Настройки шрифта,Подешавања фонта -Use standard font for log display,FONTMNU_LOG,,,,Použít standardní font pro záznamy,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 font standard per la visualizzazione dei messaggi di log,ログ表示に標準フォントを使用,로그 표시에서 기본 폰트 사용,Gebruik het standaardlettertype voor de weergave van logboekberichten,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,Использовать стандартный шрифт для панели задач,Користи стандардни фонт за приказ лога -Use standard font for dialogues,FONTMNU_DLG,,,,Použít standardní font pro dialogy,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 font standard per la visualizzazione dei dialoghi,ダイアログに標準フォントを使用,대화에서 기본 폰트 사용,Gebruik het standaardlettertype voor dialoogweergave,Użyj standardowej czcionki do dialogów,Usar fonte padrão para diálogos,,Utiliează fontul standard pentru căsuțele de dialog,Использовать стандартный шрифт для диалогов,Користи стандардни фонт за дијалоге +Font Options,HUDMNU_FONTOPTIONS,,,,Písma,Zeichensatzoptionen,Ρυθμίσεις Γραμματοσειρών,Tiparo-Agordoj,Opciones de fuentes,,Fonttiasetukset,Options de police,Betű Beállítások,Opzioni per il tipo di carattere,フォント オプション,폰트 설정,Lettertype opties,Opcje czcionek,Opções de Fonte,,Setări Font,Настройки шрифта,Подешавања фонта +Use standard font for log display,FONTMNU_LOG,,,,Použít standardní font pro záznamy,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,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,Использовать стандартный шрифт для панели задач,Користи стандардни фонт за приказ лога +Use standard font for dialogues,FONTMNU_DLG,,,,Použít standardní font pro dialogy,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,Użyj standardowej czcionki do dialogów,Usar fonte padrão para diálogos,,Utiliează fontul standard pentru căsuțele de dialog,Использовать стандартный шрифт для диалогов,Користи стандардни фонт за дијалоге Quick Exit,MISCMNU_QUICKEXIT,,,,Rychlé ukončení,"Schnelles Beenden ",Γρήγορη Έξοδος,Rapida Eliro,Salida Rápida,,Pikapoistuminen,Sortie rapide,Gyors kilépés,Uscita rapida,終了メッセージ無し,빠른 종료,Snel eindigen,Szybkie wyjście,Saída Rápida,,Ieșire Rapidă,Быстрый выход,Брзи излаз -Custom Inverse Map,DSPLYMNU_CUSTOMINVERTMAP,,,,Vlastní inverzní mapování,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,Niestandardowe odwrócone kolory,Personalizar Cores Invertidas,,Personalizare Inverse Map,Настроить цвета при неуязвимости,Прилагођена обрнута мапа +Custom Inverse Map,DSPLYMNU_CUSTOMINVERTMAP,,,,Vlastní inverzní barvení,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,Niestandardowe odwrócone kolory,Personalizar Cores Invertidas,,Personalizare Inverse Map,Настроить цвета при неуязвимости,Прилагођена обрнута мапа "Custom Inverse Color Dark ",DSPLYMNU_CUSTOMINVERTC1,,,Custom Inverse Colour Dark,Vlastní inverzní tmavá barva,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,Ciemny kolor do inwersji,Personalizar Cores Invertidas - Cor escura,,Personalizare Culoare Inverse Map Închisă,Темный цвет,Прилагођена инверзна боја тамна +",,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,Ciemny kolor do inwersji,Personalizar Cores Invertidas - Cor escura,,Personalizare Culoare Inverse Map Închisă,Тёмный цвет,Прилагођена инверзна боја тамна Custom Inverse Color Light,DSPLYMNU_CUSTOMINVERTC2,,,Custom Inverse Colour Light,Vlastní inverzní světlá barva,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,Luce inversa di colore personalizzata,反転色カスタム 明,사용자 지정 밝은 반전 색상,Aangepaste lichte inversiekleur,Jasny kolor do inwersji,Personalizar Cores Invertidas - Cor clara,,Personalizare Culoare Inverse Map Deschisă,Светлый цвет,Прилагођено инверзно светло у боји -View bob amount when firing,DSPLYMNU_BOBFIRE,,,,Intenzita pohupování při střílení,Waffenpendeln beim Schießen,,Vidi kapo-ekmova kvanto dum pafas,Balanceo de pantalla al disparar,,Aseen heilumisvoimakkuus ammuttaessa,,Fegyvermozgás lövésnél,,攻撃時の視点揺れ値,,Op en neer tijdens schieten,Częstotliwość bujania się broni przy strzelaniu,Quantidade de balanço ao atirar,,Intensitate mișcare arme în timpul deplasării,, -Intermission and Screen Border Classic Scaling,SCALEMNU_SCALECLASSIC,HUD->Scaling Options,,,Klasické škálování text. obrazovek a okrajů stav. panelu,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,,旧式スケールのクリア結果と画面ボーダー,,Intermissie en schermrand schalen,Klasyczne skalowanie wstawek i ramek,Escala clássica para tela de intervalo e borda de tela,,Scară bordură antract și ecran,, -Intermission background,SCALEMNU_INTER,,,,Pozadí textových obrazovek,Texthintergrund,,Fono de intermito,Fondo de intermisión,,Väliruutujen tausta,Fond d'écran intermission,Megszakító háttér,,クリア結果の背景,,Intermissieachtergrond,Tło wstawek,Fundo da tela de intervalo,,Fundal antract,, -Screen border,SCALEMNU_BORDER,,,,Okraje stavového řádku,Rahmen,,Ekranbordero,Bordes de pantalla,,Ruudunreunus,Bordure d'écran,Kép széle,,画面ボーダー,,Schermrand,Ramka,Borda de tela,,Bordură ecran,, -Scaling factor,SCALEMNU_FACTOR,,,,Měřítko,Skalierungsfaktor,,Skalfaktoro,Factor de escalado,,Skaalauskerroin,Facteur de mise à l'échelle,Arányosító faktor,,スケール倍率,,Schaalfactor,Współczynnik skalowania,Fator de escala,,Factor de scalare,, -Aspect ratio,SCALEMNU_RATIO,,,,Poměr stran,Seitenverhältnis,,Proporcio,Ratio de aspecto,,Kuvasuhde,,Képarány,,アスペクト比,,Beeldverhouding,Rozdzielczość,Proporção de tela,,Aspect imagine,, -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,Zeige Ergebnisse beim Verlassen des Levels,,Montri Kalkulekrano 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,,Exit時にタリー画面を表示,,Toon tellingen na eind van het level,Pokazuj wyniki pod koniec poziomu,Exibir tela de pontuação no fim da fase,,Afișează Totalul la Ieșirea din Nivel,Показывать экран статистики при выходе с уровня, -Mod Defined,OPTVAL_MODDEFINED,this is '==0',,,Určeno mody,Mod-definiert,,Modifo Difinita,Definido por mod,,Modin määrittämä,Défini par Mod,,,Mod定義,,Volgens de mod,Zdefiniowane przez modyfikację,Definir por mod,,Definit de către moduri,В зависимости от модификации, -"Always, except within hubs",OPTVAL_NOTHUBS,,,,Vždy kromě hubů,"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",,区間を除き、常に,,"Altijd, behalve binnen hubs","Zawsze, oprócz hubów","Sempre, exceto em hubs",,"Mereu, mai puțin în hub-uri",Всегда (кроме хаб-уровней), -"Always, even within hubs",OPTVAL_WITHHUBS,,,,Vždy včetně hubů,"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",,区間内でも、常に,,"Altijd, zelfs binnen hubs","Zawsze, nawet w hubach","Sempre, inclusive em hubs",,"Mereu, inclusiv în hub-uri",Всегда (включая хаб-уровни), -Preferred keyboard layout,CNTRLMNU_LAYOUT,,,,Preferované rozložení klávesnice,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,,優先するキー配列,,,Preferowany układ klawiatury,Layout de teclado preferido,,Schemă de control preferată,, -Classic ZDoom,OPTVAL_CLASSICZ,,,,Klasický ZDoom,ZDoom klassisch,,Klasika ZDoom,ZDoom clásico,,Perinteinen ZDoom,Zdoom Classique,Klasszikus ZDoom,,従来のZDOOM,,,Klasyczny ZDoom,ZDoom Clássico,,ZDoom Clasic,, -Modern (WASD),OPTVAL_MODERN,,,,Moderní (WASD),,,Moderna (WASD),Moderno (WASD),,Nykyaikainen (WASD),Moderne (ZQSD),,,現代的(WASD),,,Współczesny (WSAD),Moderno (WASD),,Modernă (WASD),, -Modern (Keypad),OPTVAL_MODERNLEFT,,,,Moderní (číselník),,,Moderna (Cifera klavaro),Moderno (Teclado Numérico),,Nykyaikainen (numeronäppäimistö),Moderne (Pavé numérique),,,現代的(Keypad),,,Współczesny (klawiatura numeryczna),Moderno (Teclado numérico),,Modernă (Tastatură),, -Strict KEYCONF Weapons/Players,MISCMNU_SETSLOTSTRICT,,,,Striktně zbraně/hráči z KEYCONF,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の武器/プレイヤー,,,Surowe opcje KEYCONF dla broni/graczy,Armas/Jogadores estritamente de acordo com KEYCONF,,KEYCONF Strictă pentru Arme/Jucători,, +",Couleur claire pour l'inversion,Egyéni inverz világos szín,Colore inverso personalizzato chiaro,反転色カスタム 明,사용자 지정 밝은 반전 색상,Aangepaste lichte inversiekleur,Jasny kolor do inwersji,Personalizar Cores Invertidas - Cor clara,,Personalizare Culoare Inverse Map Deschisă,Светлый цвет,Прилагођено инверзно светло у боји +View bob amount when firing,DSPLYMNU_BOBFIRE,,,,Intenzita pohupování při střelbě,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,Częstotliwość bujania się broni przy strzelaniu,Quantidade de balanço ao atirar,,Intensitate mișcare arme în timpul deplasării,Количество тряски экрана при стрельбе, +Intermission and Screen Border Classic Scaling,SCALEMNU_SCALECLASSIC,HUD->Scaling Options,,,Klasické škálování text. obrazovek a okrajů obrazovky,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,Klasyczne skalowanie wstawek i ramek,Escala clássica para tela de intervalo e borda de tela,,Scară bordură antract și ecran,Размер экрана при запуске игры и границ классического экрана, +Intermission background,SCALEMNU_INTER,,,,Pozadí textových obrazovek,Texthintergrund,,Fono de intermito,Fondo de intermisión,,Väliruutujen tausta,Fond d'écran intermission,Megszakító háttér,Sottofondi delle intermissioni,クリア結果の背景,,Intermissieachtergrond,Tło wstawek,Fundo da tela de intervalo,,Fundal antract,Фон при запуске игры, +Screen border,SCALEMNU_BORDER,,,,Okraje obrazovky,Rahmen,,Ekranbordero,Bordes de pantalla,,Ruudunreunus,Bordure d'écran,Kép széle,Bordo dello schermo,画面ボーダー,,Schermrand,Ramka,Borda de tela,,Bordură ecran,Границы экрана, +Scaling factor,SCALEMNU_FACTOR,,,,Měřítko,Skalierungsfaktor,,Skalfaktoro,Factor de escalado,,Skaalauskerroin,Facteur de mise à l'échelle,Arányosító faktor,Fattore di scala,スケール倍率,,Schaalfactor,Współczynnik skalowania,Fator de escala,,Factor de scalare,Значение масштабирования, +Aspect ratio,SCALEMNU_RATIO,,,,Poměr stran,Seitenverhältnis,,Proporcio,Ratio de aspecto,,Kuvasuhde,,Képarány,Proporzioni,アスペクト比,,Beeldverhouding,Rozdzielczość,Proporção de tela,,Aspect imagine,Соотношение сторон, +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,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,Pokazuj wyniki pod koniec poziomu,Exibir tela de pontuação no fim da fase,,Afișează Totalul la Ieșirea din Nivel,Показывать экран статистики при выходе с уровня, +Mod Defined,OPTVAL_MODDEFINED,this is '==0',,,Určeno mody,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,Zdefiniowane przez modyfikację,Definir por mod,,Definit de către moduri,В зависимости от модификации, +"Always, except within hubs",OPTVAL_NOTHUBS,,,,Vždy kromě hubů,"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","Zawsze, oprócz hubów","Sempre, exceto em hubs",,"Mereu, mai puțin în hub-uri",Всегда (кроме хаб-уровней), +"Always, even within hubs",OPTVAL_WITHHUBS,,,,Vždy včetně hubů,"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","Zawsze, nawet w hubach","Sempre, inclusive em hubs",,"Mereu, inclusiv în hub-uri",Всегда (включая хаб-уровни), +Preferred keyboard layout,CNTRLMNU_LAYOUT,,,,Preferované rozložení klávesnice,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,Preferowany układ klawiatury,Layout de teclado preferido,,Schemă de control preferată,Раскладка клавиатуры, +Classic ZDoom,OPTVAL_CLASSICZ,,,,Klasický ZDoom,ZDoom klassisch,,Klasika ZDoom,ZDoom clásico,,Perinteinen ZDoom,Zdoom Classique,Klasszikus ZDoom,ZDoom Classico,従来のZDOOM,,Klassiek ZDoom,Klasyczny ZDoom,ZDoom Clássico,,ZDoom Clasic,Классика ZDoom, +Modern (WASD),OPTVAL_MODERN,,,,Moderní (WASD),,,Moderna (WASD),Moderno (WASD),,Nykyaikainen (WASD),Moderne (ZQSD),,Moderno (WASD),現代的(WASD),,,Współczesny (WSAD),Moderno (WASD),,Modernă (WASD),Современная (ЦФЫВ), +Modern (Keypad),OPTVAL_MODERNLEFT,,,,Moderní (číselník),,,Moderna (Cifera klavaro),Moderno (Teclado Numérico),,Nykyaikainen (numeronäppäimistö),Moderne (Pavé numérique),Modern (numpad),Moderno (tastierino numerico),現代的(Keypad),,Modern (nummeriek toetsenbord),Współczesny (klawiatura numeryczna),Moderno (Teclado numérico),,Modernă (Tastatură),Современная (цифровая клавиатура), +Strict KEYCONF Weapons/Players,MISCMNU_SETSLOTSTRICT,,,,Striktně zbraně/hráči z KEYCONF,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,Surowe opcje KEYCONF dla broni/graczy,Armas/Jogadores estritamente de acordo com KEYCONF,,KEYCONF Strictă pentru Arme/Jucători,Строгая настройка клавиш для оружия/игроков, Classic ZDoom menu scaling,"MISCMNU_CLEANMENU -",,,,Škálování menu dle původního ZDoomu,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,,従来のZDメニュースケール,,,Klasyczne skalowanie menu z ZDooma,Escala clássica para menu do ZDoom,,Scară meniuri ZDoom clasică,, -Use percents on summary screen,MISCMNU_WIPERCENT,,,,Použít procenta ve výsledcích mapy,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,,集計画面でパーセント表示,,,Używaj procentów w ekranie wyników pod koniec poziomu,Usar porcentagem na tela de sumário,,Folosește procentaje la totaluri,, -Classic ZDoom scaling on summary screen,MISCMNU_CLEANSTAT,,,,Škálování výsledků mapy dle původního ZDoomu,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,,集計画面で従来のZDスケール,,,Klasyczne skalowanie ekranu z wynikami poziomu,Escala clássica do ZDoom na tela de sumário,,Scară ZDoom clasică a tabelei de marcaj,, -Citizen,TAG_STRIFEZOMBIE,"Called ""citizens"" according to Doomwiki",,,Občan,Bürger,,Civilulo,Ciudadano,,,,Polgár,,住民,,,Mieszkańcy,Cidadão,,Cetățean,, -Ceiling Turret,TAG_CEILINGTURRET,,,,Střílna,Deckengeschütz,,Plafona Tureto,Torreta de Techo,,,,Plafon lövésztorony,,警備システム,,,Wieżyczka,Defesa Automática,,Turetă de Tavan,, -Crusader,TAG_CRUSADER,,,,Křižák,Ordensritter,,Krucmilitisto,Cruzado,,,,Keresztes,,クルセーダー,,,Krzyżowiec,Cruzado,,Cruciat,, -Inquisitor,TAG_INQUISITOR,,,,Inkvizitář,,,Inkvizitoro,Inquisidor,,,,Inkvizítor,,審問官,,,Inkwizytor,Inquisidor,,Inchizitor,, -Peasant,TAG_PEASANT,,,,Rolník,Bauer,,Kamparano,Campesino,,,,Jobbágy,,庶民,,,Mieszczuch,Camponês,,Sărman,, -Reaver,TAG_REAVER,,,,Ničitel,Plünderer,,Misilroboto,Raptor,,,,Fosztogató,,リーバー,,,Rozbójnik,Saqueador,,Hoț,, -Sentinel,TAG_SENTINEL,,,,Strážbot,Wächter,,Gardspektisto,Centinela,,,,Őrszem,,センティネル,,,Strażnik,Sentinela,,Santinelă,, -Stalker,TAG_STALKER,,,,Slídil,Jäger,,Gvatanto,Acechador,,,,Lesipuskás,,ストーカー,,,Prześladowca,Caçador,,Hărțuitor,, -The Bishop,TAG_BISHOP,,,,Biskup,Bischof,,La Episkopo,El Obispo,,,,A Püspök,,ビショップ,,,Biskup,O Bispo,,Episcopul,, -The One God,TAG_ENTITY,,,,Jeden Bůh,Der Eine Gott,,La Unu Dio,El Dios Único,,,,Az Egy Isten,,唯一神,,,Jedyny Bóg,O Deus Único,,Adevăratul Zeu,, -The Programmer,TAG_PROGRAMMER,,,,Programátor,Programmierer,,La Programisto,El Programador,,,,A Programozó,,プログラマー,,,Programista,O Programador,,Programatorul,, -The Spectre,TAG_ALIENSPECTRE,,,,Přízrak,Schemen,,La Fantomo,El Espectro,,,,A Kísértet,,スペクトル,,,Widmo,O Espectro,,Spectrul,, -Kneeling Guy,TAG_KNEELINGGUY,,,,Ctitel,Kniender Typ,,Genuantulo,Tipo arrodillado,,,,Térdelő,,礼拝者,,,Oddający pokłon,Crente,,Tip Îngenunchiat,, -Spawn multiplayer things in coop,GMPLYMNU_MULTIPLAYERTHINGS,,,,Spawnovat multiplayerové předměty v co-opu,Multispielergegenstände in Coop,,Ekaperi plurludantajn objekojn en koopera reĝimo,Hacer aparecer cosas del multijugador en cooperativo,,,,Multiplayer tárgyak létrehozása Együttműködő módban,,協力モードでマルチプレイ用thingsを出す,,,Daj przedmioty trybu wieloosobowego w trybie kooperacji,Spawnar objetos de multijogador no modo coop,,Afișează obiectele marcate pentru modul online,, -Sprite shadows,DSPLYMNU_SPRITESHADOW,,,,Stíny spritů,Spriteschatten,,Ombroj de spritoj,Sombras de sprites,,,,Sprite árnyékok,,スプライト シャドウ,,,Cienie sprite'ów,Sombra de sprites,,Umbre pentru sprite-uri,, -Monsters and players,OPTVAL_SPRSHADALWAYS,Will enable sprite shadows for monster and player sprites,,,Monstra a hráči,Monster und Spieler,,Monstroj kaj ludantoj,Monstruos y jugadores,,,,Szörnyek és játékosok,,敵とプレイヤー,,,Potwory i Gracze,Monstros e jogadores,,Monștrii și jucători,, -FOV,DSPLYMNU_FOV,the FOV slider,,,Zorné pole (FOV),,,Vidkampo,,,,,,,,,,,Campo de visão,,Câmp vizual,, \ No newline at end of file +",,,,Škálování menu dle starého ZDoomu,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メニュースケール,,Klassieke ZDoom-menuschaal,Klasyczne skalowanie menu z ZDooma,Escala clássica para menu do ZDoom,,Scară meniuri ZDoom clasică,Классический размер меню ZDoom, +Use percents on summary screen,MISCMNU_WIPERCENT,,,,Použít procenta ve výsledcích mapy,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,Używaj procentów w ekranie wyników pod koniec poziomu,Usar porcentagem na tela de resumo,,Folosește procentaje la totaluri,Использовать проценты на экране после завершения уровня, +Classic ZDoom scaling on summary screen,MISCMNU_CLEANSTAT,,,,Škálovat obrazovky se shrnutím dle starého ZDoomu,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スケール,,Klassieke ZDoom-schaalverdeling op overzichtsscherm,Klasyczne skalowanie ekranu z wynikami poziomu,Escala clássica do ZDoom na tela de resumo,,Scară ZDoom clasică a tabelei de marcaj,Классический размер экрана ZDoom после завершения уровня, +Citizen,TAG_STRIFEZOMBIE,"Called ""citizens"" according to Doomwiki",,,Občan,Bürger,Πολίτης,Civilulo,Ciudadano,,Kansalainen,Citoyen,Polgár,Cittadino,住民,,Burger,Mieszkańcy,Cidadão,,Cetățean,Горожанин, +Ceiling Turret,TAG_CEILINGTURRET,,,,Střílna,Deckengeschütz,,Plafona Tureto,Torreta de Techo,,Kattotykkitorni,Tourelle de plafond,Plafon lövésztorony,Torretta da soffitto,警備システム,,Plafond torentje,Wieżyczka,Defesa Automática,,Turetă de Tavan,Потолочная турель, +Crusader,TAG_CRUSADER,Names need to match the obituaries!,,,Křižák,Ordensritter,,Krucmilitisto,Cruzado,,Ristiretkeläinen,Croisé,Keresztes,Crociato,クルセーダー,,Kruisvaarder,Krzyżowiec,Cruzado,,Cruciat,Крестоносец, +Inquisitor,TAG_INQUISITOR,,,,Inkvizitor,,,Inkvizitoro,Inquisidor,,Inkvisiittori,Inquisiteur,Inkvizítor,Inquisitore,審問官,,Inquisiteur,Inkwizytor,Inquisidor,,Inchizitor,Инквизитор, +Peasant,TAG_PEASANT,,,,Rolník,Bauer,Χωρικός,Kamparano,Campesino,,Maallikko,Paysan,Jobbágy,Civile,庶民,,Onderdaan,Mieszczuch,Camponês,,Sărman,Рабочий, +Reaver,TAG_REAVER,,,,Plenitel,Plünderer,,Misilroboto,Raptor,,Raastaja,Reaver,Fosztogató,Saccheggiatore,リーバー,,,Rozbójnik,Saqueador,,Hoț,Похититель, +Sentinel,TAG_SENTINEL,,,,Strážbot,Wächter,,Gardspektisto,Centinela,,Vartija,Sentinelle,Őrszem,Sentinella,センティネル,,,Strażnik,Sentinela,,Santinelă,Страж, +Stalker,TAG_STALKER,,,,Slídil,Jäger,,Gvatanto,Acechador,,Vaanija,Chasseur,Lesipuskás,Cacciatore,ストーカー,,,Prześladowca,Caçador,,Hărțuitor,Сталкер, +The Bishop,TAG_BISHOP,,,,Biskup,Bischof,,La Episkopo,El Obispo,,Piispa,Evèque,A Püspök,Vescovo,ビショップ,,De Bisschop,Biskup,O Bispo,,Episcopul,Епископ, +The One God,TAG_ENTITY,,,,Jeden Bůh,Der Eine Gott,Ο ένας Θεός,La Unu Dio,El Dios Único,,Yksi Ainoa Jumala,Le Seui Dieu,Az Egy Isten,Unico Dio,唯一神,,De ene god,Jedyny Bóg,O Deus Único,,Adevăratul Zeu,Единый Бог, +The Programmer,TAG_PROGRAMMER,,,,Programátor,Programmierer,,La Programisto,El Programador,,Ohjelmoija,Programmeur,A Programozó,Programmatore,プログラマー,,Programmeur,Programista,O Programador,,Programatorul,Программист, +The Spectre,TAG_ALIENSPECTRE,,,,Přízrak,Schemen,,La Fantomo,El Espectro,,Haamu,Le spectre,A Lidérc,Spettro,スペクトル,,Het spook,Widmo,O Espectro,,Spectrul,Призрак, +Kneeling Guy,TAG_KNEELINGGUY,,,,Ctitel,Kniender Typ,,Genuantulo,Tipo arrodillado,,Polvistunut mies,Homme agenouillé,Térdelő,Uomo inchinato,礼拝者,,Knielende man,Oddający pokłon,Crente,,Tip Îngenunchiat,Парень на коленях, +Spawn multiplayer things in coop,GMPLYMNU_MULTIPLAYERTHINGS,,,,Spawnovat multiplayerové předměty v co-opu,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を出す,,,Daj przedmioty trybu wieloosobowego w trybie kooperacji,Surgir objetos de multijogador no modo coperativo,,Afișează obiectele marcate pentru modul online,Появление вещей из сетевой игры в совместном режиме, +Sprite shadows,DSPLYMNU_SPRITESHADOW,,,,Stíny spritů,Spriteschatten,,Ombroj de spritoj,Sombras de sprites,,Spritevarjot,Ombres de sprites,Sprite árnyékok,Ombre per sprite,スプライト シャドウ,,Sprite schaduwen,Cienie sprite'ów,Sombras de sprites,,Umbre pentru sprite-uri,Тени спрайтов, +Monsters and players,OPTVAL_SPRSHADALWAYS,Will enable sprite shadows for monster and player sprites,,,Monstra a hráči,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,Potwory i Gracze,Monstros e jogadores,,Monștrii și jucători,Монстры и игроки, +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,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-functies uitschakelen,Wyłącz funkcje portu MBF21,Desativar recursos do MBF21,,Dezactivare caracteristici MBF21,Отключить функции MBF21, +Show time widget,ALTHUDMNU_SHOWTIMESTAT,,,,Zobrazit widget s časem,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,Pokaż widżet czasu,Mostrar widget de tempo,,Afișare dispozitiv pt. timp,Показать виджет времени, +MBF21,OPTVAL_MBF21,,,,,,,,,,,,,,,,,,,,,, +Crushed monsters get resurrected as ghosts,CMPTMNU_VILEGHOSTS,,,,Oživovat rozdrcené příšery jako duchy,Zermalmte Monster werden als Geister wiedererweckt,Συνθλιμένα τέρατα αναστήνοντε ως φαντάσματα,Dispremitaj monstroj reviviĝas kiel fantomoj,Los monstruos aplastados son resucitados como fantasmas,,,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,,Monstros esmagados ressucitam como fantasmas,,Monștrii striviți sunt readuși la viață ca fantome.,Раздавленные монстры воскресают в виде призраков, \ No newline at end of file diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 6a31743b4..6982a5bce 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -136,6 +136,10 @@ DoomEdNums 9872 = SpotLightFlickerAttenuated 9873 = SectorSpotLightAttenuated 9874 = SpotLightFlickerRandomAttenuated + 9875 = None // ZDRay light probe + 9876 = None // ZDRay static point light + 9881 = None // ZDRay static spotlight + 9890 = None // ZDRayInfo 9982 = SecActEyesAboveC 9983 = SecActEyesBelowC 9988 = CustomSprite @@ -408,9 +412,6 @@ Intermission Inter_Underwater { Background = "E2END", 0 } - GotoTitle - { - } } Intermission Inter_Demonscroll diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 19f109ac3..50cc8ef48 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -380,6 +380,9 @@ OptionMenu "OptionsMenu" protected SafeCommand "$OPTMNU_WRITEINI", "writeini" Command "$OPTMNU_CONSOLE", "menuconsole" + Command "$OPTMNU_OPENCONFIG", "openconfig" + Command "$OPTMNU_OPENSCREENSHOTS", "openscreenshots" + Command "$OPTMNU_OPENSAVES", "opensaves" StaticText " " } @@ -443,6 +446,7 @@ OptionMenu "NewPlayerMenu" protected PlayerSkinItem "$PLYRMNU_PLAYERSKIN", "PlayerSkin" PlayerGenderItem "$PLYRMNU_PLAYERGENDER", "Gender" AutoaimSlider "$PLYRMNU_AUTOAIM" + Option "$PLYRMNU_VERTSPREAD", vertspread, "OnOff" PlayerSwitchOnPickupItem "$PLYRMNU_SWITCHONPICKUP", "OffOn" Option "$PLYRMNU_ALWAYSRUN", cl_run, "OnOff" Class "NewPlayerMenu" @@ -488,6 +492,7 @@ ListMenu "PlayerMenu" ValueText "$PLYRMNU_PLAYERSKIN", "Skin" ValueText "$PLYRMNU_PLAYERGENDER", "Gender", "Gender" Slider "$PLYRMNU_AUTOAIM", "Autoaim", 0, 35, 1 + ValueText "$PLYRMNU_VERTSPREAD", vertspread, "OnOff" ValueText "$PLYRMNU_SWITCHONPICKUP", "Switch", "OffOn" ValueText "$PLYRMNU_ALWAYSRUN", "AlwaysRun", "OnOff" Class "PlayerMenu" @@ -733,9 +738,8 @@ OptionMenu "MouseOptions" protected } Option "$MOUSEMNU_CURSOR", "vid_cursor", "Cursors" StaticText "" - Slider "$MOUSEMNU_SENSITIVITY_X", "m_sensitivity_x", 0.5, 8, 0.25 - Slider "$MOUSEMNU_SENSITIVITY_Y", "m_sensitivity_y", 0.5, 8, 0.25 - Option "$MOUSEMNU_SMOOTHMOUSE", "m_filter", "YesNo" + Slider "$MOUSEMNU_SENSITIVITY_X", "m_sensitivity_x", 0.1, 8, 0.05 + Slider "$MOUSEMNU_SENSITIVITY_Y", "m_sensitivity_y", 0.1, 8, 0.05 StaticText "" Slider "$MOUSEMNU_TURNSPEED", "m_yaw", 0, 2.5, 0.1 Slider "$MOUSEMNU_MOUSELOOKSPEED", "m_pitch", 0, 2.5, 0.1 @@ -893,8 +897,7 @@ OptionValue PreferBackend { 0, "$OPTVAL_OPENGL" 1, "$OPTVAL_VULKAN" - 2, "$OPTVAL_SOFTPOLY" - 3, "$OPTVAL_OPENGLES" + 2, "$OPTVAL_OPENGLES" } OptionMenu "TrueColorOptions" protected @@ -945,7 +948,6 @@ OptionMenu "VideoOptions" protected Option "$DSPLYMNU_WIPETYPE", "wipetype", "Wipes" Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness" Option "$DSPLYMNU_OLDTRANS", "r_vanillatrans", "VanillaTrans" - Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2 Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast" Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes" Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes" @@ -1151,6 +1153,7 @@ OptionMenu "AltHUDOptions" protected Option "$ALTHUDMNU_SHOWSTATS", "hud_showstats", "OnOff" Option "$ALTHUDMNU_SHOWBERSERK", "hud_berserk_health", "OnOff" Option "$ALTHUDMNU_SHOWWEAPONS", "hud_showweapons", "OnOff" + Option "$ALTHUDMNU_SHOWTIMESTAT", "hud_showtimestat", "OnOff" Option "$ALTHUDMNU_SHOWAMMO", "hud_showammo", "AltHUDAmmo" Option "$ALTHUDMNU_SHOWTIME", "hud_showtime", "AltHUDTime" Option "$ALTHUDMNU_TIMECOLOR", "hud_timecolor", "TextColors" @@ -1218,6 +1221,7 @@ OptionMenu "MiscOptions" protected } 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" @@ -1229,6 +1233,7 @@ OptionMenu "MiscOptions" protected 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" Slider "$MISCMNU_CACHETIME", "gl_cachetime", 0.0, 2.0, 0.1 @@ -1239,11 +1244,9 @@ OptionMenu "MiscOptions" protected StaticText " " Option "$MISCMNU_QUICKEXIT", "m_quickexit", "OnOff" - IfOption(Windows) - { - StaticText " " - Option "$DSPLYMNU_SHOWENDOOM", "showendoom", "Endoom" - } + StaticText " " + Option "$DSPLYMNU_SHOWENDOOM", "showendoom", "Endoom" + StaticText " " Option "$MISCMNU_CLEANMENU", "m_cleanscale", "OffOn" Option "$MISCMNU_CLEANSTAT", "wi_cleantextscale", "OnOff" @@ -1344,6 +1347,7 @@ OptionMenu AutomapOptions protected Option "$AUTOMAPMNU_TEXTURED", "am_textured", "OnOff" Slider "$AUTOMAPMNU_LINEALPHA", "am_linealpha", 0.1, 1.0, 0.1, 1 Slider "$AUTOMAPMNU_LINETHICKNESS", "am_linethickness", 1, 8, 1, 0 + Option "$AUTOMAPMNU_LINEANTIALIASING", "am_lineantialiasing", "OnOff" StaticText "" Option "$AUTOMAPMNU_SHOWITEMS", "am_showitems", "OnOff" @@ -1644,6 +1648,7 @@ OptionMenu GameplayOptions protected Option "$GMPLYMNU_INSTANTREACTION", "sv_instantreaction", "YesNo" Option "$GMPLYMNU_DEGENERATION", "sv_degeneration", "YesNo" Option "$GMPLYMNU_NOAUTOAIM", "sv_noautoaim", "NoYes" + Option "$GMPLYMNU_NOVERTSPREAD", "sv_novertspread", "NoYes" Option "$GMPLYMNU_ALLOWSUICIDE", "sv_disallowsuicide", "NoYes" Option "$GMPLYMNU_ALLOWJUMP", "sv_jump", "JumpCrouchFreeLook" Option "$GMPLYMNU_ALLOWCROUCH", "sv_crouch", "JumpCrouchFreeLook" @@ -1679,6 +1684,7 @@ OptionMenu DeathmatchOptions protected Option "$GMPLYMNU_LOSEFRAG", "sv_losefrag", "YesNo" Option "$GMPLYMNU_KEEPFRAGS", "sv_keepfrags", "YesNo" Option "$GMPLYMNU_NOTEAMSWITCH", "sv_noteamswitch", "YesNo" + Option "$GMPLYMNU_NOEXTRAAMMO", "sv_noextraammo", "NoYes" Class "GameplayMenu" } @@ -1697,6 +1703,7 @@ OptionMenu CoopOptions protected Option "$GMPLYMNU_KEEPAMMO", "sv_cooploseammo", "NoYes" Option "$GMPLYMNU_LOSEHALFAMMO", "sv_coophalveammo", "YesNo" Option "$GMPLYMNU_SPAWNWHEREDIED", "sv_samespawnspot", "YesNo" + Option "$GMPLYMNU_NOPLAYERCLIP", "sv_noplayerclip", "YesNo" Class "GameplayMenu" } @@ -1738,7 +1745,7 @@ OptionMenu "CompatActorMenu" protected { Position -35 Title "$CMPTMNU_ACTORBEHAVIOR" - Option "$CMPTMNU_CORPSEGIBS", "compat_CORPSEGIBS", "YesNo" + Option "$CMPTMNU_VILEGHOSTS", "compat_VILEGHOSTS", "YesNo" Option "$CMPTMNU_NOBLOCKFRIENDS", "compat_NOBLOCKFRIENDS", "YesNo" Option "$CMPTMNU_LIMITPAIN", "compat_LIMITPAIN", "YesNo" Option "$CMPTMNU_MBFMONSTERMOVE", "compat_MBFMONSTERMOVE", "YesNo" @@ -1776,6 +1783,7 @@ OptionMenu "CompatMapMenu" protected Option "$CMPTMNU_PUSHWINDOW", "compat_pushwindow", "YesNo" Option "$CMPTMNU_CHECKSWITCHRANGE", "compat_checkswitchrange", "YesNo" Option "$CMPTMNU_RAILINGHACK", "compat_railing", "YesNo" + Option "$CMPTMNU_NOMBF21", "compat_nombf21", "YesNo" Class "CompatibilityMenu" } @@ -1815,7 +1823,6 @@ OptionMenu "CompatSoundMenu" protected Option "$CMPTMNU_SILENTPICKUP", "compat_SILENTPICKUP", "YesNo" Option "$CMPTMNU_SILENTINSTANTFLOORS", "compat_silentinstantfloors", "YesNo" Option "$CMPTMNU_SECTORSOUNDS", "compat_SECTORSOUNDS", "YesNo" - Option "$CMPTMNU_SOUNDCUTOFF", "compat_soundcutoff", "YesNo" Option "$CMPTMNU_SOUNDTARGET", "compat_SOUNDTARGET", "YesNo" Class "CompatibilityMenu" } @@ -2102,7 +2109,7 @@ OptionMenu ModReplayerOptions protected Title "$ADVSNDMNU_TIMIDITY" LabeledSubMenu "$ADVSNDMNU_SELCONFIG", "timidity_config", "TimidityConfigMenu" Option "$ADVSNDMNU_REVERB", "timidity_reverb", "TimidityReverb" - Slider "$ADVSNDMNU_REVERB_LEVEL", "timidity_reverb_level", 9, 127, 1, 0 + Slider "$ADVSNDMNU_REVERB_LEVEL", "timidity_reverb_level", 0, 127, 1, 0 Option "$ADVSNDMNU_CHORUS", "timidity_chorus", "OnOff" // other CVARs need to be revieved for usefulness } @@ -2267,7 +2274,10 @@ OptionMenu VideoModeMenu protected Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" StaticText " " - Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + IfOption(SWRender) + { + Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + } Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" IfOption(Mac) @@ -2286,7 +2296,7 @@ OptionMenu VideoModeMenu protected StaticText " " Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" - Option "$VIDMNU_MAXFPS", "vid_maxfps", "MaxFps" + Slider "$VIDMNU_MAXFPS", "vid_maxfps", 35, 500, 1 Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn" StaticText "" @@ -2636,6 +2646,7 @@ OptionMenu "OpenGLOptions" protected Option "$GLPREFMNU_SPRBILLFACECAMERA", gl_billboard_faces_camera, "OnOff" Option "$GLPREFMNU_PARTICLESTYLE", gl_particles_style, "Particles" Option "$GLPREFMNU_RENDERQUALITY", gl_seamless, "Precision" + //Option "$GLPREFMNU_CORONAS", gl_coronas, "OnOff" StaticText " " Slider "$GLPREFMNU_MENUBLUR", gl_menu_blur, 0, 5.0, 0.5, 2 StaticText " " @@ -2774,6 +2785,7 @@ OptionString "LanguageOptions" "eo", "Esperanto" "fi", "Suomi (Finnish)" "fr", "Français (French)" + "hu", "Magyar (Hungarian)" "it", "Italiano (Italian)" "jp", "日本語 (Japanese)" "ko", "한국어 (Korean)" @@ -2813,7 +2825,7 @@ OptionValue "os_isanyof_values" OptionMenu "vkoptions" { Title "$VK_TITLE" - StaticText "$VK_WARNING" + //StaticText "$VK_WARNING" StaticText "$VK_RESTART" StaticText "" TextField "$VKMNU_DEVICE", vk_device diff --git a/wadsrc/static/menudef.zsimple b/wadsrc/static/menudef.zsimple index 2ebc60430..512dc3a0b 100644 --- a/wadsrc/static/menudef.zsimple +++ b/wadsrc/static/menudef.zsimple @@ -6,7 +6,7 @@ OptionMenu "OptionsMenuSimple" protected { Title "$OPTMNU_TITLE" Submenu "$OPTMNU_CONTROLS", "CustomizeControls" - Submenu "$OPTMNU_MOUSE", "MouseOptions" + Submenu "$OPTMNU_MOUSE", "MouseOptionsSimple" Submenu "$OPTMNU_JOYSTICK", "JoystickOptions" StaticText " " Submenu "$OPTMNU_PLAYER", "NewPlayerMenu" @@ -47,7 +47,10 @@ OptionMenu VideoOptionsSimple protected Title "$DSPLYMNU_TITLE" Option "$VIDMNU_PREFERBACKEND", "vid_preferbackend", "PreferBackend" - Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + IfOption(SWRender) + { + Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + } Option "$VIDMNU_FULLSCREEN", "vid_fullscreen", "YesNo" IfOption(Mac) { @@ -63,7 +66,7 @@ OptionMenu VideoOptionsSimple protected Option "$GLPREFMNU_SECLIGHTMODE", gl_lightmode, "LightingModes" StaticText " " Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" - Option "$VIDMNU_MAXFPS", "vid_maxfps", "MaxFps" + 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 @@ -100,4 +103,22 @@ OptionMenu MiscOptionsSimple protected Option "$MISCMNU_DEHLOAD", "dehload", "dehopt" Option "$MISCMNU_ENABLESCRIPTSCREENSHOTS", "enablescriptscreenshot", "OnOff" Option "$OPTMNU_LANGUAGE", "language", "LanguageOptions" + Option "$MSGMNU_LONGSAVEMESSAGES", "longsavemessages", "OnOff" +} + +OptionMenu "MouseOptionsSimple" protected +{ + Title "$MOUSEMNU_TITLE" + Option "$MOUSEMNU_ENABLEMOUSE", "use_mouse", "YesNo" + Option "$MOUSEMNU_MOUSEINMENU", "m_use_mouse", "MenuMouse", "use_mouse" + IfOption(Windows) + { + Option "$MOUSEMNU_SWAPBUTTONS", "m_swapbuttons", "YesNo" + } + Option "$MOUSEMNU_CURSOR", "vid_cursor", "Cursors" + StaticText "" + Slider "$MOUSEMNU_SENSITIVITY_X", "m_sensitivity_x", 0.1, 8, 0.05 + Slider "$MOUSEMNU_SENSITIVITY_Y", "m_sensitivity_y", 0.1, 8, 0.05 + StaticText "" + Option "$MOUSEMNU_INVERTMOUSE", "invertmouse", "OnOff" } diff --git a/wadsrc/static/shaders/glsl/burn.fp b/wadsrc/static/shaders/glsl/burn.fp index 486789f54..ff9c1d699 100644 --- a/wadsrc/static/shaders/glsl/burn.fp +++ b/wadsrc/static/shaders/glsl/burn.fp @@ -9,6 +9,6 @@ void main() vec4 t1 = texture(tex, vTexCoord.xy); vec4 t2 = texture(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y)); - + FragColor = frag * vec4(t1.r, t1.g, t1.b, t2.a); } diff --git a/wadsrc/static/shaders/glsl/fogboundary.fp b/wadsrc/static/shaders/glsl/fogboundary.fp index 9494a9ca9..3bfa059c0 100644 --- a/wadsrc/static/shaders/glsl/fogboundary.fp +++ b/wadsrc/static/shaders/glsl/fogboundary.fp @@ -15,7 +15,7 @@ void main() { float fogdist; float fogfactor; - + // // calculate fog factor // diff --git a/wadsrc/static/shaders/glsl/fuzz_smooth.fp b/wadsrc/static/shaders/glsl/fuzz_smooth.fp index 3c642c399..b2af9a2e5 100644 --- a/wadsrc/static/shaders/glsl/fuzz_smooth.fp +++ b/wadsrc/static/shaders/glsl/fuzz_smooth.fp @@ -13,6 +13,6 @@ vec4 ProcessTexel() basicColor.a = basicColor.a * test; basicColor.r = basicColor.g = basicColor.b = 0.0; - + return basicColor; } diff --git a/wadsrc/static/shaders/glsl/fuzz_standard.fp b/wadsrc/static/shaders/glsl/fuzz_standard.fp index 3eb3b67e6..fd166760a 100644 --- a/wadsrc/static/shaders/glsl/fuzz_standard.fp +++ b/wadsrc/static/shaders/glsl/fuzz_standard.fp @@ -17,6 +17,6 @@ vec4 ProcessTexel() basicColor.a = basicColor.a * test; basicColor.r = basicColor.g = basicColor.b = 0.0; - + return basicColor; } diff --git a/wadsrc/static/shaders/glsl/fuzz_swirly.fp b/wadsrc/static/shaders/glsl/fuzz_swirly.fp index 266858999..0bb584cd5 100644 --- a/wadsrc/static/shaders/glsl/fuzz_swirly.fp +++ b/wadsrc/static/shaders/glsl/fuzz_swirly.fp @@ -13,6 +13,6 @@ vec4 ProcessTexel() basicColor.a = basicColor.a * test; basicColor.r = basicColor.g = basicColor.b = 0.0; - + return basicColor; } diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index a27f113c0..32891e564 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -7,6 +7,7 @@ layout(location = 3) in vec3 glowdist; layout(location = 4) in vec3 gradientdist; layout(location = 5) in vec4 vWorldNormal; layout(location = 6) in vec4 vEyeNormal; +layout(location = 9) in vec3 vLightmap; #ifdef NO_CLIPDISTANCE_SUPPORT layout(location = 7) in vec4 ClipDistanceA; @@ -98,27 +99,27 @@ const int Tex_Blend_Alpha = 1; const int Tex_Blend_Screen = 2; const int Tex_Blend_Overlay = 3; const int Tex_Blend_Hardlight = 4; - + vec4 ApplyTextureManipulation(vec4 texel, int blendflags) { // Step 1: desaturate according to the material's desaturation factor. texel = dodesaturate(texel, uTextureModulateColor.a); - + // Step 2: Invert if requested if ((blendflags & 8) != 0) { texel.rgb = vec3(1.0 - texel.r, 1.0 - texel.g, 1.0 - texel.b); } - + // Step 3: Apply additive color texel.rgb += uTextureAddColor.rgb; - + // Step 4: Colorization, including gradient if set. texel.rgb *= uTextureModulateColor.rgb; - + // Before applying the blend the value needs to be clamped to [0..1] range. texel.rgb = clamp(texel.rgb, 0.0, 1.0); - + // Step 5: Apply a blend. This may just be a translucent overlay or one of the blend modes present in current Build engines. if ((blendflags & 7) != 0) { @@ -163,7 +164,7 @@ const int Tex_Blend_Hardlight = 4; vec4 getTexel(vec2 st) { vec4 texel = texture(tex, st); - + // // Apply texture modes // @@ -172,33 +173,33 @@ vec4 getTexel(vec2 st) case 1: // TM_STENCIL texel.rgb = vec3(1.0,1.0,1.0); break; - + case 2: // TM_OPAQUE texel.a = 1.0; break; - + case 3: // TM_INVERSE texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a); break; - + case 4: // TM_ALPHATEXTURE { float gray = grayscale(texel); texel = vec4(1.0, 1.0, 1.0, gray*texel.a); break; } - + case 5: // TM_CLAMPY if (st.t < 0.0 || st.t > 1.0) { texel.a = 0.0; } break; - + case 6: // TM_OPAQUEINVERSE texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, 1.0); break; - + case 7: //TM_FOGLAYER return texel; @@ -211,7 +212,7 @@ vec4 getTexel(vec2 st) texel.a = 0.0; } } - + // Apply the texture modification colors. int blendflags = int(uTextureAddColor.a); // this alpha is unused otherwise if (blendflags != 0) @@ -318,7 +319,7 @@ float R_DoomLightingEquation(float light) { z = pixelpos.w; } - + if ((uPalLightLevels >> 16) == 5) // gl_lightmode 5: Build software lighting emulation. { // This is a lot more primitive than Doom's lighting... @@ -340,10 +341,86 @@ float R_DoomLightingEquation(float light) //=========================================================================== // -// Check if light is in shadow according to its 1D shadow map +// Check if light is in shadow // //=========================================================================== +#ifdef SUPPORTS_RAYTRACING + +bool traceHit(vec3 origin, vec3 direction, float dist) +{ + rayQueryEXT rayQuery; + rayQueryInitializeEXT(rayQuery, TopLevelAS, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, 0.01f, direction, dist); + while(rayQueryProceedEXT(rayQuery)) { } + return rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT; +} + +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 shadowAttenuation(vec4 lightpos, float lightcolorA) +{ + float shadowIndex = abs(lightcolorA) - 1.0; + if (shadowIndex >= 1024.0) + return 1.0; // Don't cast rays for this light + + 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 + + vec3 direction = normalize(target - origin); + float dist = distance(origin, target); + + if (uShadowmapFilter <= 0) + { + return traceHit(origin, direction, dist) ? 0.0 : 1.0; + } + else + { + vec3 v = (abs(direction.x) > abs(direction.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); + vec3 xdir = normalize(cross(direction, v)); + vec3 ydir = cross(direction, xdir); + + float sum = 0.0; + int step_count = uShadowmapFilter * 9; + for (int i = 0; i <= step_count; i++) + { + vec3 pos = target + xdir * softshadow[i].x + ydir * softshadow[i].y; + sum += traceHit(origin, normalize(pos - origin), dist) ? 0.0 : 1.0; + } + return sum / step_count; + } +} + +#else #ifdef SUPPORTS_SHADOWMAPS float shadowDirToU(vec2 dir) @@ -432,7 +509,7 @@ float sampleShadowmapPCF(vec3 planePoint, float v) float sum = 0.0; float step_count = uShadowmapFilter; - + texelPos -= step_count + 0.5; for (float x = -step_count; x <= step_count; x++) { @@ -487,6 +564,7 @@ float shadowAttenuation(vec4 lightpos, float lightcolorA) return 1.0; } +#endif #endif float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle) @@ -575,13 +653,13 @@ void SetMaterialProps(inout Material material, vec2 texCoord) #ifndef NO_LAYERS if ((uTextureMode & TEXF_Brightmap) != 0) material.Bright = desaturate(texture(brighttexture, texCoord.st)); - + if ((uTextureMode & TEXF_Detailmap) != 0) { vec4 Detail = texture(detailtexture, texCoord.st * uDetailParms.xy) * uDetailParms.z; material.Base.rgb *= Detail.rgb; } - + if ((uTextureMode & TEXF_Glowmap) != 0) material.Glow = desaturate(texture(glowtexture, texCoord.st)); #endif @@ -604,7 +682,7 @@ void SetMaterialProps(inout Material material, vec2 texCoord) vec4 getLightColor(Material material, float fogdist, float fogfactor) { vec4 color = vColor; - + if (uLightLevel >= 0.0) { float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel); @@ -617,13 +695,13 @@ vec4 getLightColor(Material material, float fogdist, float fogfactor) { color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0); } - + // // apply light diminishing through fog equation // color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor); } - + // // handle glowing walls // @@ -649,12 +727,20 @@ vec4 getLightColor(Material material, float fogdist, float fogfactor) // color.rgb = min(color.rgb + material.Bright.rgb, 1.0); #endif - + // // apply other light manipulation by custom shaders, default is a NOP. // color = ProcessLight(material, color); + // + // apply lightmaps + // + if (vLightmap.z >= 0.0) + { + color.rgb += texture(LightMap, vLightmap).rgb; + } + // // apply dynamic lights // @@ -682,7 +768,7 @@ vec3 AmbientOcclusionColor() { float fogdist; float fogfactor; - + // // calculate fog factor // @@ -695,7 +781,7 @@ vec3 AmbientOcclusionColor() fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); } fogfactor = exp2 (uFogDensity * fogdist); - + return mix(uFogColor.rgb, vec3(0.0), fogfactor); } @@ -713,7 +799,7 @@ void main() #ifndef LEGACY_USER_SHADER Material material; - + material.Base = vec4(0.0); material.Bright = vec4(0.0); material.Glow = vec4(0.0); @@ -729,7 +815,7 @@ void main() Material material = ProcessMaterial(); #endif vec4 frag = material.Base; - + #ifndef NO_ALPHATEST if (frag.a <= uAlphaThreshold) discard; #endif @@ -738,7 +824,7 @@ void main() { float fogdist = 0.0; float fogfactor = 0.0; - + // // calculate fog factor // @@ -754,7 +840,7 @@ void main() } fogfactor = exp2 (uFogDensity * fogdist); } - + if ((uTextureMode & 0xffff) != 7) { frag = getLightColor(material, fogdist, fogfactor); diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index a410d5a4d..f718d73bc 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -5,11 +5,15 @@ layout(location = 2) in vec4 aColor; layout(location = 0) out vec4 vTexCoord; layout(location = 1) out vec4 vColor; +layout(location = 9) out vec3 vLightmap; #ifndef SIMPLE // we do not need these for simple shaders 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 = 7) in vec4 aBoneWeight; +layout(location = 8) in uvec4 aBoneSelector; layout(location = 2) out vec4 pixelpos; layout(location = 3) out vec3 glowdist; @@ -23,15 +27,25 @@ layout(location = 7) out vec4 ClipDistanceA; layout(location = 8) out vec4 ClipDistanceB; #endif +struct BonesResult +{ + vec3 Normal; + vec4 Position; +}; + +BonesResult ApplyBones(); + void main() { float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4; vec2 parmTexCoord; vec4 parmPosition; - + + BonesResult bones = ApplyBones(); + parmTexCoord = aTexCoord; - parmPosition = aPosition; + parmPosition = bones.Position; #ifndef SIMPLE vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor); @@ -51,6 +65,8 @@ void main() #endif #ifndef SIMPLE + vLightmap = aLightmap; + pixelpos.xyz = worldcoord.xyz; pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w; @@ -62,7 +78,7 @@ void main() glowdist.y = worldcoord.y - bottomatpoint; glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0); } - + if (uObjectColor2.a != 0) { float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z; @@ -71,24 +87,17 @@ void main() gradientdist.y = worldcoord.y - bottomatpoint; gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0); } - + if (uSplitBottomPlane.z != 0.0) { ClipDistance3 = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; ClipDistance4 = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); } - #ifdef HAS_UNIFORM_VERTEX_DATA - if ((useVertexData & 2) == 0) - vWorldNormal = NormalModelMatrix * vec4(normalize(uVertexNormal.xyz), 1.0); - else - vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); - #else - vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); - #endif + vWorldNormal = NormalModelMatrix * vec4(normalize(bones.Normal), 1.0); vEyeNormal = NormalViewMatrix * vec4(normalize(vWorldNormal.xyz), 1.0); #endif - + #ifdef SPHEREMAP vec3 u = normalize(eyeCoordPos.xyz); vec4 n = normalize(NormalViewMatrix * vec4(parmTexCoord.x, 0.0, parmTexCoord.y, 0.0)); @@ -99,7 +108,7 @@ void main() #else vTexCoord = TextureMatrix * vec4(parmTexCoord, 0.0, 1.0); #endif - + gl_Position = ProjectionMatrix * eyeCoordPos; #ifdef VULKAN_COORDINATE_SYSTEM @@ -142,3 +151,66 @@ void main() gl_PointSize = 1.0; } + +#if !defined(SIMPLE) +vec3 GetAttrNormal() +{ + #ifdef HAS_UNIFORM_VERTEX_DATA + if ((useVertexData & 2) == 0) + return uVertexNormal.xyz; + else + return mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor); + #else + return mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor); + #endif +} + +void AddWeightedBone(uint boneIndex, float weight, inout vec4 position, inout vec3 normal) +{ + if (weight != 0.0) + { + mat4 transform = bones[uBoneIndexBase + int(boneIndex)]; + mat3 rotation = mat3(transform); + position += (transform * aPosition) * weight; + normal += (rotation * aNormal.xyz) * weight; + } +} + +BonesResult ApplyBones() +{ + BonesResult result; + if (uBoneIndexBase >= 0 && aBoneWeight != vec4(0.0)) + { + result.Position = vec4(0.0); + result.Normal = vec3(0.0); + + // We use low precision input for our bone weights. Rescale so the sum still is 1.0 + float totalWeight = aBoneWeight.x + aBoneWeight.y + aBoneWeight.z + aBoneWeight.w; + float weightMultiplier = 1.0 / totalWeight; + vec4 boneWeight = aBoneWeight * weightMultiplier; + + AddWeightedBone(aBoneSelector.x, boneWeight.x, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.y, boneWeight.y, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.z, boneWeight.z, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.w, boneWeight.w, result.Position, result.Normal); + + result.Position.w = 1.0; // For numerical stability + } + else + { + result.Position = aPosition; + result.Normal = GetAttrNormal(); + } + return result; +} + +#else + +BonesResult ApplyBones() +{ + BonesResult result; + result.Position = aPosition; + return result; +} + +#endif diff --git a/wadsrc/static/shaders/glsl/material_normal.fp b/wadsrc/static/shaders/glsl/material_normal.fp index add128812..b9d25852c 100644 --- a/wadsrc/static/shaders/glsl/material_normal.fp +++ b/wadsrc/static/shaders/glsl/material_normal.fp @@ -13,7 +13,7 @@ vec3 lightContribution(int i, vec3 normal) vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz); float dotprod = dot(normal, lightdir); if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues. - + float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0); if (lightspot1.w == 1.0) @@ -59,7 +59,21 @@ vec3 ProcessMaterialLight(Material material, vec3 color) } } - vec3 frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); + vec3 frag; + + if ( uLightBlendMode == 1 ) + { // COLOR_CORRECT_CLAMPING + vec3 lightcolor = color + desaturate(dynlight).rgb; + frag = material.Base.rgb * ((lightcolor / max(max(max(lightcolor.r, lightcolor.g), lightcolor.b), 1.4) * 1.4)); + } + else if ( uLightBlendMode == 2 ) + { // UNCLAMPED + frag = material.Base.rgb * (color + desaturate(dynlight).rgb); + } + else + { + frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); + } if (uLightIndex >= 0) { @@ -67,7 +81,7 @@ vec3 ProcessMaterialLight(Material material, vec3 color) if (lightRange.w > lightRange.z) { vec4 addlight = vec4(0.0,0.0,0.0,0.0); - + // additive lights for(int i=lightRange.z; i= 300 +attribute vec4 aBoneWeight; +attribute uvec4 aBoneSelector; +#endif varying vec4 pixelpos; varying vec3 glowdist; @@ -23,6 +27,15 @@ varying vec4 ClipDistanceA; varying vec4 ClipDistanceB; #endif +struct BonesResult +{ + vec3 Normal; + vec4 Position; +}; + +BonesResult ApplyBones(); + + void main() { float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4; @@ -30,8 +43,10 @@ void main() vec2 parmTexCoord; vec4 parmPosition; + BonesResult bones = ApplyBones(); + parmTexCoord = aTexCoord; - parmPosition = aPosition; + parmPosition = bones.Position; #ifndef SIMPLE vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor); @@ -77,15 +92,9 @@ void main() ClipDistance3 = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; ClipDistance4 = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); } + + vWorldNormal = NormalModelMatrix * vec4(normalize(bones.Normal), 1.0); - #ifdef HAS_UNIFORM_VERTEX_DATA - if ((useVertexData & 2) == 0) - vWorldNormal = NormalModelMatrix * vec4(uVertexNormal.xyz, 1.0); - else - vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); - #else - vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); - #endif vEyeNormal = NormalViewMatrix * vWorldNormal; #endif @@ -129,3 +138,82 @@ void main() gl_Position = ProjectionMatrix * eyeCoordPos; } + +#if !defined(SIMPLE) + +vec3 GetAttrNormal() +{ + #ifdef HAS_UNIFORM_VERTEX_DATA + if ((useVertexData & 2) == 0) + return uVertexNormal.xyz; + else + return mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor); + #else + return mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor); + #endif +} + +#if __VERSION__ >= 300 + +void AddWeightedBone(uint boneIndex, float weight, inout vec4 position, inout vec3 normal) +{ + if (weight != 0.0) + { + mat4 transform = bones[uBoneIndexBase + int(boneIndex)]; + mat3 rotation = mat3(transform); + position += (transform * aPosition) * weight; + normal += (rotation * aNormal.xyz) * weight; + } +} + +BonesResult ApplyBones() +{ + BonesResult result; + if (uBoneIndexBase >= 0 && aBoneWeight != vec4(0.0)) + { + result.Position = vec4(0.0); + result.Normal = vec3(0.0); + + // We use low precision input for our bone weights. Rescale so the sum still is 1.0 + float totalWeight = aBoneWeight.x + aBoneWeight.y + aBoneWeight.z + aBoneWeight.w; + float weightMultiplier = 1.0 / totalWeight; + vec4 boneWeight = aBoneWeight * weightMultiplier; + + AddWeightedBone(aBoneSelector.x, boneWeight.x, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.y, boneWeight.y, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.z, boneWeight.z, result.Position, result.Normal); + AddWeightedBone(aBoneSelector.w, boneWeight.w, result.Position, result.Normal); + + result.Position.w = 1.0; // For numerical stability + } + else + { + result.Position = aPosition; + result.Normal = GetAttrNormal(); + } + return result; +} + +#else + +BonesResult ApplyBones() +{ + BonesResult result; + + result.Position = aPosition; + result.Normal = GetAttrNormal(); + + return result; +} +#endif + +#else // SIMPLE + +BonesResult ApplyBones() +{ + BonesResult result; + result.Position = aPosition; + return result; +} + +#endif diff --git a/wadsrc/static/vga-rom-font.16 b/wadsrc/static/vga-rom-font.16 deleted file mode 100644 index 672d0e1a9..000000000 Binary files a/wadsrc/static/vga-rom-font.16 and /dev/null differ diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a447a9b73..409acc2e3 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,11 +1,14 @@ -version "4.6" +version "4.10" // Generic engine code #include "zscript/engine/base.zs" #include "zscript/engine/dynarrays.zs" +#include "zscript/engine/maps.zs" #include "zscript/engine/dictionary.zs" #include "zscript/engine/inputevents.zs" #include "zscript/engine/service.zs" +#include "zscript/engine/ppshader.zs" +#include "zscript/engine/screenjob.zs" #include "zscript/engine/ui/menu/colorpickermenu.zs" #include "zscript/engine/ui/menu/joystickmenu.zs" @@ -16,6 +19,7 @@ version "4.6" #include "zscript/engine/ui/menu/menucustomize.zs" #include "zscript/engine/ui/menu/menuitembase.zs" #include "zscript/engine/ui/menu/messagebox.zs" +#include "zscript/engine/ui/menu/custommessagebox.zs" #include "zscript/engine/ui/menu/optionmenu.zs" #include "zscript/engine/ui/menu/optionmenuitems.zs" #include "zscript/engine/ui/menu/reverbedit.zs" @@ -90,6 +94,7 @@ version "4.6" #include "zscript/actors/shared/fastprojectile.zs" #include "zscript/actors/shared/randomspawner.zs" #include "zscript/actors/shared/dynlights.zs" +#include "zscript/actors/shared/corona.zs" #include "zscript/actors/doom/doomplayer.zs" #include "zscript/actors/doom/possessed.zs" @@ -289,6 +294,8 @@ version "4.6" #include "zscript/ui/statusbar/statusbar.zs" #include "zscript/ui/statusbar/strife_sbar.zs" +#include "zscript/ui/intermission.zs" + #include "zscript/compatibility.zs" #include "zscript/scriptutil/scriptutil.zs" #include "zscript/actors/mbf21.zs" diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 5184e3fdf..9a007dd49 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -67,6 +67,12 @@ struct LinkContext voidptr render_list; } +class ViewPosition native +{ + native readonly Vector3 Offset; + native readonly int Flags; +} + class Actor : Thinker native { @@ -89,10 +95,12 @@ class Actor : Thinker native // for some comments on these fields, see their native representations in actor.h. native readonly Actor snext; // next in sector list. native PlayerInfo Player; + native readonly ViewPosition ViewPos; // Will be null until A_SetViewPos() is called for the first time. native readonly vector3 Pos; native vector3 Prev; native uint ThruBits; native vector2 SpriteOffset; + native vector3 WorldOffset; native double spriteAngle; native double spriteRotation; native float VisibleStartAngle; @@ -159,6 +167,7 @@ class Actor : Thinker native native readonly int TID; native readonly int TIDtoHate; native readonly int WaterLevel; + native readonly double WaterDepth; native int Score; native int Accuracy; native int Stamina; @@ -245,9 +254,11 @@ class Actor : Thinker native native readonly int BloodTranslation; native int RenderHidden; native int RenderRequired; - native readonly int FriendlySeeBlocks; + native int FriendlySeeBlocks; + native int16 lightlevel; native readonly int SpawnTime; private native int InventoryID; // internal counter. + native uint freezetics; meta String Obituary; // Player was killed by this actor meta String HitObituary; // Player was killed by this actor in melee @@ -267,6 +278,7 @@ class Actor : Thinker native meta double MissileHeight; meta Name MissileName; meta double FastSpeed; // speed in fast mode + meta Sound PushSound; // Sound being played when pushed by something // todo: implement access to native meta properties. // native meta int infighting_group; @@ -312,6 +324,7 @@ class Actor : Thinker native property DeathSound: DeathSound; property ActiveSound: ActiveSound; property CrushPainSound: CrushPainSound; + property PushSound: PushSound; property Alpha: Alpha; property MaxTargetRange: MaxTargetRange; property MeleeThreshold: MeleeThreshold; @@ -347,6 +360,7 @@ class Actor : Thinker native property RenderRequired: RenderRequired; property FriendlySeeBlocks: FriendlySeeBlocks; property ThruBits: ThruBits; + property LightLevel: LightLevel; // need some definition work first //FRenderStyle RenderStyle; @@ -371,6 +385,7 @@ class Actor : Thinker native Default { + LightLevel -1; Scale 1; Health DEFAULT_HEALTH; Reactiontime 8; @@ -455,6 +470,7 @@ class Actor : Thinker native MarkSound(CrushPainSound); MarkSound(HowlSound); MarkSound(MeleeSound); + MarkSound(PushSound); } bool IsPointerEqual(int ptr_select1, int ptr_select2) @@ -475,7 +491,8 @@ class Actor : Thinker native virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0, Name MeansOfDeath = 'none'); virtual native bool Slam(Actor victim); - virtual native void Touch(Actor toucher); + virtual void Touch(Actor toucher) {} + virtual native void FallAndSink(double grav, double oldfloorz); private native void Substitute(Actor replacement); native ui void DisplayNameTag(); @@ -494,6 +511,12 @@ class Actor : Thinker native return true; } + // Called by PIT_CheckLine to check if an actor can cross a line. + virtual bool CanCrossLine(Line crossing, Vector3 next) + { + return true; + } + // Called by revival/resurrection to check if one can resurrect the other. // "other" can be null when not passive. virtual bool CanResurrect(Actor other, bool passive) @@ -615,7 +638,7 @@ class Actor : Thinker native native static int GetSpriteIndex(name sprt); native clearscope static double GetDefaultSpeed(class type); native static class GetSpawnableType(int spawnnum); - native static int ApplyDamageFactors(class itemcls, Name damagetype, int damage, int defdamage); + native clearscope static int ApplyDamageFactors(class itemcls, Name damagetype, int damage, int defdamage); native void RemoveFromHash(); native void ChangeTid(int newtid); deprecated("3.8", "Use Level.FindUniqueTid() instead") static int FindUniqueTid(int start = 0, int limit = 0) @@ -646,6 +669,7 @@ class Actor : Thinker native native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); native void ClearInterpolation(); + native void ClearFOVInterpolation(); native clearscope Vector3 PosRelative(sector sec) const; native void RailAttack(FRailParams p); @@ -684,7 +708,7 @@ class Actor : Thinker native native Actor, Actor SpawnPlayerMissile(class type, double angle = 1e37, double x = 0, double y = 0, double z = 0, out FTranslatedLineTarget pLineTarget = null, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0); native void SpawnTeleportFog(Vector3 pos, bool beforeTele, bool setTarget); native Actor RoughMonsterSearch(int distance, bool onlyseekable = false, bool frontonly = false, double fov = 0); - native int ApplyDamageFactor(Name damagetype, int damage); + native clearscope int ApplyDamageFactor(Name damagetype, int damage); native int GetModifiedDamage(Name damagetype, int damage, bool passive, Actor inflictor = null, Actor source = null, int flags = 0); native bool CheckBossDeath(); native bool CheckFov(Actor target, double fov); @@ -785,6 +809,25 @@ class Actor : Thinker native native clearscope double GetCameraHeight() const; native clearscope double GetGravity() const; native void DoMissileDamage(Actor target); + native void PlayPushSound(); + native bool BounceActor(Actor blocking, bool onTop); + native bool BounceWall(Line l = null); + native bool BouncePlane(SecPlane plane); + native void PlayBounceSound(bool onFloor); + + clearscope double PitchTo(Actor target, double zOfs = 0, double targZOfs = 0, bool absolute = false) const + { + Vector3 origin = (pos.xy, pos.z - floorClip + zOfs); + Vector3 dest = (target.pos.xy, target.pos.z - target.floorClip + targZOfs); + + Vector3 diff; + if (!absolute) + diff = level.Vec3Diff(origin, dest); + else + diff = dest - origin; + + return -atan2(diff.z, diff.xy.Length()); + } //========================================================================== // @@ -1082,6 +1125,7 @@ class Actor : Thinker native native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class pufftype = "BulletPuff"); deprecated("4.3", "Use A_StartSound() instead") native clearscope void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false, double pitch = 0.0); native clearscope void A_StartSound(sound whattoplay, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0, double startTime = 0.0); + native clearscope void A_StartSoundIfNotSame(sound whattoplay, sound checkagainst, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0, double startTime = 0.0); native void A_SoundVolume(int slot, double volume); native void A_SoundPitch(int slot, double pitch); deprecated("2.3", "Use A_StartSound(, CHAN_WEAPON) instead") void A_PlayWeaponSound(sound whattoplay, bool fullvol = false) { A_StartSound(whattoplay, CHAN_WEAPON, 0, 1, fullvol? ATTN_NONE : ATTN_NORM); } @@ -1090,7 +1134,7 @@ class Actor : Thinker native native void A_StopSounds(int chanmin, int chanmax); deprecated("2.3", "Use A_StartSound() instead") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0); deprecated("2.3", "Use A_StopSound() instead") native void A_StopSoundEx(name slot); - native clearscope bool IsActorPlayingSound(int channel, Sound snd = 0); + native clearscope bool IsActorPlayingSound(int channel, Sound snd = -1); native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); native action state A_Jump(int chance, statelabel label, ...); native Actor A_SpawnProjectile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); @@ -1107,11 +1151,13 @@ class Actor : Thinker native native void A_FadeTo(double target, double amount = 0.1, int flags = 0); native void A_SpawnDebris(class spawntype, bool transfer_translation = false, double mult_h = 1, double mult_v = 1); native void A_SpawnParticle(color color1, int flags = 0, int lifetime = TICRATE, double size = 1, double angle = 0, double xoff = 0, double yoff = 0, double zoff = 0, double velx = 0, double vely = 0, double velz = 0, double accelx = 0, double accely = 0, double accelz = 0, double startalphaf = 1, double fadestepf = -1, double sizestep = 0); + native void A_SpawnParticleEx(color color1, TextureID texture, int style = STYLE_None, int flags = 0, int lifetime = TICRATE, double size = 1, double angle = 0, double xoff = 0, double yoff = 0, double zoff = 0, double velx = 0, double vely = 0, double velz = 0, double accelx = 0, double accely = 0, double accelz = 0, double startalphaf = 1, double fadestepf = -1, double sizestep = 0, double startroll = 0, double rollvel = 0, double rollacc = 0); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype, int amount = -1); native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.); deprecated("2.3", "Use 'b = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); + action native void A_ChangeModel(name modeldef, int modelindex = 0, string modelpath = "", name model = "", int skinindex = 0, string skinpath = "", name skin = "", int flags = 0, int generatorindex = -1, int animationindex = 0, string animationpath = "", name animation = ""); void A_SetFriendly (bool set) { @@ -1157,12 +1203,13 @@ class Actor : Thinker native native void A_SetViewAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetViewPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetViewRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT); + native void SetViewPos(Vector3 offset, int flags = -1); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVar(name varname, int value); 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(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); - native void A_QuakeEx(int intensityX, int intensityY, int 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, 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); 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); @@ -1278,6 +1325,35 @@ class Actor : Thinker native } } + virtual void PlayerLandedMakeGruntSound(actor onmobj) + { + bool grunted; + + // [RH] only make noise if alive + if (self.health > 0 && self.player.morphTics == 0) + { + grunted = false; + // Why should this number vary by gravity? + if (self.Vel.Z < -self.player.mo.GruntSpeed) + { + A_StartSound("*grunt", CHAN_VOICE); + grunted = true; + } + bool isliquid = (pos.Z <= floorz) && HitFloor (); + if (onmobj != NULL || !isliquid) + { + if (!grunted) + { + A_StartSound("*land", CHAN_AUTO); + } + else + { + A_StartSoundIfNotSame("*land", "*grunt", CHAN_AUTO); + } + } + } + } + //---------------------------------------------------------------------------- // // PROC A_CheckSkullDone @@ -1307,6 +1383,9 @@ class Actor : Thinker native GenericCrush: POL5 A -1; Stop; + DieFromSpawn: + TNT1 A 1; + TNT1 A 1 { self.Die(null, null); } } // Internal functions diff --git a/wadsrc/static/zscript/actors/chex/chexweapons.zs b/wadsrc/static/zscript/actors/chex/chexweapons.zs index 5bf6fe757..e135683a0 100644 --- a/wadsrc/static/zscript/actors/chex/chexweapons.zs +++ b/wadsrc/static/zscript/actors/chex/chexweapons.zs @@ -106,7 +106,7 @@ class PhasingZorcher : PlasmaRifle States { Fire: - PLSG A 0 A_GunFlash; + PLSG A 0 A_GunFlash('Flash', GFF_NOEXTCHANGE); PLSG A 3 A_FireProjectile("PhaseZorchMissile"); PLSG B 20 A_ReFire; Goto Ready; diff --git a/wadsrc/static/zscript/actors/doom/bossbrain.zs b/wadsrc/static/zscript/actors/doom/bossbrain.zs index a2fb6f267..b0033cb2b 100644 --- a/wadsrc/static/zscript/actors/doom/bossbrain.zs +++ b/wadsrc/static/zscript/actors/doom/bossbrain.zs @@ -12,6 +12,7 @@ class BossBrain : Actor Health 250; Mass 10000000; PainChance 255; + Radius 16; +SOLID +SHOOTABLE +NOICEDEATH +OLDRADIUSDMG diff --git a/wadsrc/static/zscript/actors/doom/lostsoul.zs b/wadsrc/static/zscript/actors/doom/lostsoul.zs index f44a24754..7feb8553b 100644 --- a/wadsrc/static/zscript/actors/doom/lostsoul.zs +++ b/wadsrc/static/zscript/actors/doom/lostsoul.zs @@ -20,7 +20,6 @@ class LostSoul : Actor PainSound "skull/pain"; DeathSound "skull/death"; ActiveSound "skull/active"; - RenderStyle "SoulTrans"; Obituary "$OB_SKULL"; Tag "$FN_LOST"; } diff --git a/wadsrc/static/zscript/actors/doom/weaponpistol.zs b/wadsrc/static/zscript/actors/doom/weaponpistol.zs index cddd8647a..0665a67af 100644 --- a/wadsrc/static/zscript/actors/doom/weaponpistol.zs +++ b/wadsrc/static/zscript/actors/doom/weaponpistol.zs @@ -65,6 +65,11 @@ extend class StateProvider if (!accurate) { ang += Random2[GunShot]() * (5.625 / 256); + + if (GetCVar ("vertspread") && !sv_novertspread) + { + pitch += Random2[GunShot]() * (3.549 / 256); + } } LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', pufftype); diff --git a/wadsrc/static/zscript/actors/heretic/weaponblaster.zs b/wadsrc/static/zscript/actors/heretic/weaponblaster.zs index 23830eb08..d2048e594 100644 --- a/wadsrc/static/zscript/actors/heretic/weaponblaster.zs +++ b/wadsrc/static/zscript/actors/heretic/weaponblaster.zs @@ -65,6 +65,11 @@ class Blaster : HereticWeapon if (player.refire) { ang += Random2[FireBlaster]() * (5.625 / 256); + + if (GetCVar ("vertspread") && !sv_novertspread) + { + pitch += Random2[FireBlaster]() * (3.549 / 256); + } } LineAttack (ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "BlasterPuff"); A_StartSound ("weapons/blastershoot", CHAN_WEAPON); diff --git a/wadsrc/static/zscript/actors/heretic/weaponwand.zs b/wadsrc/static/zscript/actors/heretic/weaponwand.zs index 52d5136e2..65829a8d4 100644 --- a/wadsrc/static/zscript/actors/heretic/weaponwand.zs +++ b/wadsrc/static/zscript/actors/heretic/weaponwand.zs @@ -64,6 +64,11 @@ class GoldWand : HereticWeapon if (player.refire) { ang += Random2[FireGoldWand]() * (5.625 / 256); + + if (GetCVar ("vertspread") && !sv_novertspread) + { + pitch += Random2[FireGoldWand]() * (3.549 / 256); + } } LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "GoldWandPuff1"); A_StartSound("weapons/wandhit", CHAN_WEAPON); diff --git a/wadsrc/static/zscript/actors/hexen/flechette.zs b/wadsrc/static/zscript/actors/hexen/flechette.zs index cce5784ab..0526cebe5 100644 --- a/wadsrc/static/zscript/actors/hexen/flechette.zs +++ b/wadsrc/static/zscript/actors/hexen/flechette.zs @@ -449,7 +449,7 @@ class PoisonCloud : Actor PSBG D 1; PSBG D 1 A_Scream; PSBG DEEEFFFGGGHHHII 2 A_PoisonBagDamage; - PSBG I 2 A_PoisonBagCheck; + PSBG I 2 A_PoisonBagDamage; PSBG I 1 A_PoisonBagCheck; Goto Spawn + 3; Death: diff --git a/wadsrc/static/zscript/actors/hexen/teleportother.zs b/wadsrc/static/zscript/actors/hexen/teleportother.zs index 93608470e..200eece06 100644 --- a/wadsrc/static/zscript/actors/hexen/teleportother.zs +++ b/wadsrc/static/zscript/actors/hexen/teleportother.zs @@ -163,8 +163,9 @@ class TelOtherFX1 : Actor double destAngle; [dest, destAngle] = level.PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); - dest.Z = ONFLOORZ; - victim.Teleport ((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); + if (!level.useplayerstartz) + dest.Z = ONFLOORZ; + victim.Teleport (dest, destangle, TELF_SOURCEFOG | TELF_DESTFOG); } //=========================================================================== diff --git a/wadsrc/static/zscript/actors/inventory/ammo.zs b/wadsrc/static/zscript/actors/inventory/ammo.zs index 52b3d8f22..e30a5de60 100644 --- a/wadsrc/static/zscript/actors/inventory/ammo.zs +++ b/wadsrc/static/zscript/actors/inventory/ammo.zs @@ -94,7 +94,7 @@ class Ammo : Inventory if (!item.bIgnoreSkill) { // extra ammo in baby mode and nightmare mode - receiving = int(receiving * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + receiving = int(receiving * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } int oldamount = Amount; @@ -140,7 +140,7 @@ class Ammo : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } let type = GetParentAmmo(); @@ -258,7 +258,7 @@ class BackpackItem : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } if (amount < 0) amount = 0; if (ammoitem == NULL) @@ -323,7 +323,7 @@ class BackpackItem : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammoitem.Amount += amount; if (ammoitem.Amount > ammoitem.MaxAmount && !sv_unlimited_pickup) diff --git a/wadsrc/static/zscript/actors/inventory/inv_misc.zs b/wadsrc/static/zscript/actors/inventory/inv_misc.zs index da3625743..1d31022ad 100644 --- a/wadsrc/static/zscript/actors/inventory/inv_misc.zs +++ b/wadsrc/static/zscript/actors/inventory/inv_misc.zs @@ -37,6 +37,9 @@ class Key : Inventory Inventory.PickupSound "misc/k_pkup"; } + static native clearscope bool IsLockDefined(int locknum); + static native clearscope Color GetMapColorForLock(int locknum); + static native clearscope Color GetMapColorForKey(Key key); static native clearscope int GetKeyTypeCount(); static native clearscope class GetKeyType(int index); @@ -92,9 +95,11 @@ class PuzzleItem : Inventory { meta int PuzzleItemNumber; meta String PuzzFailMessage; + meta Sound PuzzFailSound; property Number: PuzzleItemNumber; property FailMessage: PuzzFailMessage; + property FailSound: PuzzFailSound; Default { @@ -104,6 +109,7 @@ class PuzzleItem : Inventory Inventory.UseSound "PuzzleSuccess"; Inventory.PickupSound "misc/i_pkup"; PuzzleItem.FailMessage("$TXT_USEPUZZLEFAILED"); + PuzzleItem.FailSound "*puzzfail"; } override bool HandlePickup (Inventory item) @@ -124,7 +130,7 @@ class PuzzleItem : Inventory return true; } // [RH] Always play the sound if the use fails. - Owner.A_StartSound ("*puzzfail", CHAN_VOICE); + Owner.A_StartSound (PuzzFailSound, CHAN_VOICE); if (Owner.CheckLocalView()) { Console.MidPrint (null, PuzzFailMessage, true); diff --git a/wadsrc/static/zscript/actors/inventory/stateprovider.zs b/wadsrc/static/zscript/actors/inventory/stateprovider.zs index 1295c8283..21295c315 100644 --- a/wadsrc/static/zscript/actors/inventory/stateprovider.zs +++ b/wadsrc/static/zscript/actors/inventory/stateprovider.zs @@ -207,7 +207,7 @@ class StateProvider : Inventory // //========================================================================== - action Actor A_FireProjectile(class missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0) + 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; @@ -234,14 +234,17 @@ class StateProvider : Inventory // Temporarily adjusts the pitch double saved_player_pitch = self.Pitch; self.Pitch += pitch; - let misl = SpawnPlayerMissile (missiletype, shootangle, ofs.X, ofs.Y, spawnheight, t, false, (flags & FPF_NOAUTOAIM) != 0); + + Actor misl, realmisl; + [misl, realmisl] = SpawnPlayerMissile (missiletype, shootangle, ofs.X, ofs.Y, spawnheight, t, false, (flags & FPF_NOAUTOAIM) != 0); self.Pitch = saved_player_pitch; + if (realmisl && flags & FPF_TRANSFERTRANSLATION) + realmisl.Translation = Translation; + // automatic handling of seeker missiles if (misl) { - if (flags & FPF_TRANSFERTRANSLATION) - misl.Translation = Translation; if (t.linetarget && !t.unlinked && misl.bSeekerMissile) misl.tracer = t.linetarget; if (!(flags & FPF_AIMATANGLE)) @@ -252,9 +255,9 @@ class StateProvider : Inventory misl.VelFromAngle(misl.Vel.XY.Length()); } } - return misl; + return misl, realmisl; } - return null; + return null, null; } //========================================================================== diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index 9c3519b48..d4aa0e57d 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -25,6 +25,7 @@ class Weapon : StateProvider int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs. float BobRangeX, BobRangeY; // [XA] Bobbing range. Defines how far a weapon bobs in either direction. + double WeaponScaleX, WeaponScaleY; // [XA] Weapon scale. Defines the scale for the held weapon sprites (PSprite). Defaults to (1.0, 1.2) since that's what Doom does. Ammo Ammo1, Ammo2; // In-inventory instance variables Weapon SisterWeapon; double FOVScale; @@ -36,6 +37,8 @@ class Weapon : StateProvider // AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works meta int SlotNumber; meta double SlotPriority; + + Vector3 BobPivot3D; // Pivot used for BobWeapon3D property AmmoGive: AmmoGive1; property AmmoGive1: AmmoGive1; @@ -57,9 +60,12 @@ class Weapon : StateProvider property BobSpeed: BobSpeed; property BobRangeX: BobRangeX; property BobRangeY: BobRangeY; + property WeaponScaleX: WeaponScaleX; + property WeaponScaleY: WeaponScaleY; property SlotNumber: SlotNumber; property SlotPriority: SlotPriority; property LookScale: LookScale; + property BobPivot3D : BobPivot3D; flagdef NoAutoFire: WeaponFlags, 0; // weapon does not autofire flagdef ReadySndHalf: WeaponFlags, 1; // ready sound is played ~1/2 the time @@ -95,8 +101,11 @@ class Weapon : StateProvider Weapon.BobSpeed 1.0; Weapon.BobRangeX 1.0; Weapon.BobRangeY 1.0; + Weapon.WeaponScaleX 1.0; + Weapon.WeaponScaleY 1.2; Weapon.SlotNumber -1; Weapon.SlotPriority 32767; + Weapon.BobPivot3D (0.0, 0.0, 0.0); +WEAPONSPAWN DefaultStateUsage SUF_ACTOR|SUF_OVERLAY|SUF_WEAPON; } @@ -218,6 +227,8 @@ class Weapon : StateProvider { if (!psp) return; psp.rotation = 0; + psp.baseScale.x = invoker.WeaponScaleX; + psp.baseScale.y = invoker.WeaponScaleY; psp.scale.x = 1; psp.scale.y = 1; psp.pivot.x = 0; @@ -453,6 +464,7 @@ class Weapon : StateProvider if (flags & 1) { // Make the zoom instant. player.FOV = player.DesiredFOV * zoom; + player.cheats |= CF_NOFOVINTERP; } if (flags & 2) { // Disable pitch/yaw scaling. @@ -735,13 +747,13 @@ class Weapon : StateProvider // [BC] This behavior is from the original Doom. Give 5/2 times as much ammoitem when // we pick up a weapon in deathmatch. - if (( deathmatch ) && ( gameinfo.gametype & GAME_DoomChex )) + if (( deathmatch && !sv_noextraammo ) && ( gameinfo.gametype & GAME_DoomChex )) amount = amount * 5 / 2; // extra ammoitem in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammoitem = Ammo(other.FindInventory (ammotype)); if (ammoitem == NULL) @@ -776,7 +788,7 @@ class Weapon : StateProvider // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammo.Amount += amount; if (ammo.Amount > ammo.MaxAmount && !sv_unlimited_pickup) @@ -994,7 +1006,7 @@ class Weapon : StateProvider // //=========================================================================== - virtual bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1) + virtual bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1, bool forceammouse = false) { if (!(sv_infiniteammo || (Owner.FindInventory ('PowerInfiniteAmmo', true) != null))) { @@ -1006,7 +1018,7 @@ class Weapon : StateProvider { if (Ammo1 != null) { - if (ammouse >= 0 && bDehAmmo) + if (ammouse >= 0 && (bDehAmmo || forceammouse)) { Ammo1.Amount -= ammouse; } diff --git a/wadsrc/static/zscript/actors/inventory_util.zs b/wadsrc/static/zscript/actors/inventory_util.zs index 6b65b6420..e1820a86d 100644 --- a/wadsrc/static/zscript/actors/inventory_util.zs +++ b/wadsrc/static/zscript/actors/inventory_util.zs @@ -814,6 +814,46 @@ extend class Actor } } + + int GetAmmoCapacity(class type) + { + if (type != NULL) + { + let item = FindInventory(type); + if (item != NULL) + { + return item.MaxAmount; + } + else + { + return GetDefaultByType(type).MaxAmount; + } + } + return 0; + } + + void SetAmmoCapacity(class type, int amount) + { + if (type != NULL) + { + let item = FindInventory(type); + if (item != NULL) + { + item.MaxAmount = amount; + } + else + { + item = GiveInventoryType(type); + if (item != NULL) + { + item.MaxAmount = amount; + item.Amount = 0; + } + } + } + } + + diff --git a/wadsrc/static/zscript/actors/mbf21.zs b/wadsrc/static/zscript/actors/mbf21.zs index b6eb4ef89..c7fc2a8fb 100644 --- a/wadsrc/static/zscript/actors/mbf21.zs +++ b/wadsrc/static/zscript/actors/mbf21.zs @@ -198,7 +198,9 @@ extend class Actor // void A_FindTracer(double fov, int dist) { - if (!tracer) tracer = RoughMonsterSearch(dist, fov: fov); + // note: mbf21 fov is the angle of the entire cone, while + // zdoom fov is defined as 1/2 of the cone, so halve it. + if (!tracer) tracer = RoughMonsterSearch(dist, fov: fov/2); } // @@ -316,11 +318,9 @@ extend class Weapon FTranslatedLineTarget t; angle += self.angle; - double x = Spawnofs_xy * cos(angle); - double y = Spawnofs_xy * sin(angle); - let pos = self.Vec3Offset(x, y, Spawnofs_z); + Vector2 ofs = AngleToVector(self.Angle - 90, spawnofs_xy); - let mo = SpawnPlayerMissile(type, angle, pos.X, pos.Y, pos.Z, pLineTarget: t); + let mo = SpawnPlayerMissile(type, angle, ofs.x, ofs.y, Spawnofs_z, pLineTarget: t); if (!mo) return; Pitch += mo.PitchFromVel(); @@ -432,7 +432,7 @@ extend class Weapon if (!weap) return; if (consume == 0) consume = -1; - weap.DepleteAmmo(weap.bAltFire, false, consume); + weap.DepleteAmmo(weap.bAltFire, false, consume, true); } // @@ -503,5 +503,11 @@ extend class Weapon player.SetPsprite(PSP_FLASH, tstate); } + // needed to call A_SeekerMissile with proper defaults. + deprecated("2.3", "for Dehacked use only") + void MBF21_SeekTracer(double threshold, double turnmax) + { + A_SeekerMissile(int(threshold), int(turnmax), flags: SMF_PRECISE); // args get truncated to ints here, but it's close enough + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index be17e160b..7039f9436 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -46,7 +46,9 @@ class PlayerPawn : Actor double AirCapacity; // Multiplier for air supply underwater. Class FlechetteType; color DamageFade; // [CW] Fades for when you are being damaged. + double FlyBob; // [B] Fly bobbing mulitplier double ViewBob; // [SP] ViewBob Multiplier + double WaterClimbSpeed; // [B] Speed when climbing up walls in water double FullHeight; double curBob; double prevBob; @@ -75,7 +77,9 @@ class PlayerPawn : Actor property FlechetteType: FlechetteType; property Portrait: Portrait; property TeleportFreezeTime: TeleportFreezeTime; + property FlyBob: FlyBob; property ViewBob: ViewBob; + property WaterClimbSpeed : WaterClimbSpeed; flagdef NoThrustWhenInvul: PlayerFlags, 0; flagdef CanSuperMorph: PlayerFlags, 1; @@ -117,7 +121,9 @@ class PlayerPawn : Actor Player.MugShotMaxHealth 0; Player.FlechetteType "ArtiPoisonBag3"; Player.AirCapacity 1; + Player.FlyBob 1; Player.ViewBob 1; + Player.WaterClimbSpeed 3.5; Player.TeleportFreezeTime 18; Obituary "$OB_MPDEFAULT"; } @@ -254,6 +260,11 @@ class PlayerPawn : Actor invul.EffectTics = 3 * TICRATE; invul.BlendColor = 0; // don't mess with the view invul.bUndroppable = true; // Don't drop self + if (!invul.CallTryPickup(self)) + { + invul.Destroy(); + return; + } bRespawnInvul = true; // [RH] special effect } } @@ -555,7 +566,7 @@ class PlayerPawn : Actor } else if (bNoGravity && !player.onground) { - player.bob = 0.5; + player.bob = min(abs(0.5 * FlyBob), MAXBOB); } else { @@ -585,7 +596,11 @@ class PlayerPawn : Actor return; } - if (still) + if (bFly && !GetCVar("FViewBob")) + { + bob = 0; + } + else if (still) { if (player.health > 0) { @@ -633,6 +648,7 @@ class PlayerPawn : Actor bob = 0; } player.viewz = pos.Z + player.viewheight + (bob * clamp(ViewBob, 0. , 1.5)); // [SP] Allow DECORATE changes to view bobbing speed. + if (Floorclip && player.playerstate != PST_DEAD && pos.Z <= floorz) { @@ -2432,6 +2448,12 @@ class PlayerPawn : Actor } return p1 * (1. - ticfrac) + p2 * ticfrac; } + + virtual Vector3 /*translation*/ , Vector3 /*rotation*/ BobWeapon3D (double ticfrac) + { + Vector2 oldBob = BobWeapon(ticfrac); + return (0, 0, 0) , ( oldBob.x / 4, oldBob.y / -4, 0); + } //---------------------------------------------------------------------------- // @@ -2600,6 +2622,7 @@ class PSprite : Object native play native double y; native double oldx; native double oldy; + native Vector2 baseScale; native Vector2 pivot; native Vector2 scale; native double rotation; @@ -2788,6 +2811,7 @@ struct PlayerInfo native play // self is what internally is known as player_t native double GetWBobSpeed() const; native double GetWBobFire() const; native double GetMoveBob() const; + native bool GetFViewBob() const; native double GetStillBob() const; native void SetFOV(float fov); native clearscope bool GetClassicFlight() const; diff --git a/wadsrc/static/zscript/actors/player/player_cheat.zs b/wadsrc/static/zscript/actors/player/player_cheat.zs index d1e8d2694..adacdfb52 100644 --- a/wadsrc/static/zscript/actors/player/player_cheat.zs +++ b/wadsrc/static/zscript/actors/player/player_cheat.zs @@ -42,6 +42,11 @@ extend class PlayerPawn } native void CheatSuicide(); + + private bool CheckArtifact(class type) + { + return !(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor") && !(type is "Key") && !(type is "Weapon"); + } virtual void CheatGive (String name, int amount) { @@ -175,7 +180,7 @@ extend class PlayerPawn for (i = 0; i < AllActorClasses.Size(); ++i) { let type = (class)(AllActorClasses[i]); - if (type != null && type != "Weapon") + if (type != null && type != "Weapon" && !type.isAbstract()) { // Don't give replaced weapons unless the replacement was done by Dehacked. let rep = GetReplacement(type); @@ -207,8 +212,7 @@ extend class PlayerPawn if (type!= null) { let def = GetDefaultByType (type); - if (def.Icon.isValid() && def.MaxAmount > 1 && - !(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor")) + if (def.Icon.isValid() && (def.MaxAmount > 1 || def.bAutoActivate == false) && CheckArtifact(type)) { // Do not give replaced items unless using "give everything" if (giveall == ALL_YESYES || GetReplacement(type) == type) @@ -364,7 +368,7 @@ extend class PlayerPawn for (int i = 0; i < AllActorClasses.Size(); ++i) { type = (class)(AllActorClasses[i]); - if (type!= null && !(type is "PuzzleItem") && !(type is "Powerup") && !(type is "Ammo") && !(type is "Armor")) + if (type!= null && CheckArtifact(type)) { let pack = FindInventory(type); if (pack) pack.Destroy(); diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index e6ca560a4..77df1ef26 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -220,6 +220,7 @@ extend class PlayerPawn { p.camera = morphed; } + morphed.ClearFOVInterpolation(); morphed.ScoreIcon = ScoreIcon; // [GRB] if (eflash) eflash.target = morphed; @@ -336,6 +337,7 @@ extend class PlayerPawn { player.camera = altmo; } + altmo.ClearFOVInterpolation(); // [MH] // If the player that was morphed is the one diff --git a/wadsrc/static/zscript/actors/raven/artitele.zs b/wadsrc/static/zscript/actors/raven/artitele.zs index 3f61176a1..042ae67df 100644 --- a/wadsrc/static/zscript/actors/raven/artitele.zs +++ b/wadsrc/static/zscript/actors/raven/artitele.zs @@ -36,7 +36,8 @@ class ArtiTeleport : Inventory { [dest, destAngle] = level.PickPlayerStart(Owner.PlayerNumber()); } - dest.Z = ONFLOORZ; + if (!level.useplayerstartz) + dest.Z = ONFLOORZ; Owner.Teleport (dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG); bool canlaugh = true; Playerinfo p = Owner.player; diff --git a/wadsrc/static/zscript/actors/shared/corona.zs b/wadsrc/static/zscript/actors/shared/corona.zs new file mode 100644 index 000000000..996921f82 --- /dev/null +++ b/wadsrc/static/zscript/actors/shared/corona.zs @@ -0,0 +1,10 @@ +/*class Corona : Actor native +{ + Default + { + RenderStyle "Add"; + RenderRadius 1024.0; + +NOINTERACTION + +FORCEXYBILLBOARD + } +}*/ diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index e0ac0253c..8c5d0850d 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -15,6 +15,8 @@ class DynamicLight : Actor flagdef noshadowmap: lightflags, 4; flagdef dontlightactors: lightflags, 5; flagdef spot: lightflags, 6; + flagdef dontlightothers: lightflags, 7; + flagdef dontlightmap: lightflags, 8; enum EArgs { @@ -35,7 +37,9 @@ class DynamicLight : Actor LF_ATTENUATE = 8, LF_NOSHADOWMAP = 16, LF_DONTLIGHTACTORS = 32, - LF_SPOT = 64 + LF_SPOT = 64, + LF_DONTLIGHTOTHERS = 128, + LF_DONTLIGHTMAP = 256, }; enum ELightType diff --git a/wadsrc/static/zscript/actors/shared/movingcamera.zs b/wadsrc/static/zscript/actors/shared/movingcamera.zs index 132370008..8f76bd179 100644 --- a/wadsrc/static/zscript/actors/shared/movingcamera.zs +++ b/wadsrc/static/zscript/actors/shared/movingcamera.zs @@ -488,19 +488,19 @@ class ActorMover : PathFollower Super.Activate (activator); let tracer = self.tracer; special1 = tracer.bNoGravity + (tracer.bNoBlockmap<<1) + (tracer.bSolid<<2) + (tracer.bInvulnerable<<4) + (tracer.bDormant<<8); - bNoGravity = true; + tracer.bNoGravity = true; if (args[2] & 128) { LinkContext ctx; tracer.UnlinkFromWorld (ctx); - bNoBlockmap = true; - bSolid = false; + tracer.bNoBlockmap = true; + tracer.bSolid = false; tracer.LinkToWorld (ctx); } if (tracer.bIsMonster) { - bInvulnerable = true; - bDormant = true; + tracer.bInvulnerable = true; + tracer.bDormant = true; } // Don't let the renderer interpolate between the actor's // old position and its new position. diff --git a/wadsrc/static/zscript/actors/strife/klaxon.zs b/wadsrc/static/zscript/actors/strife/klaxon.zs index d6c5a44f2..dab56f6cd 100644 --- a/wadsrc/static/zscript/actors/strife/klaxon.zs +++ b/wadsrc/static/zscript/actors/strife/klaxon.zs @@ -45,6 +45,7 @@ class CeilingTurret : Actor +DONTFALL MinMissileChance 150; Tag "$TAG_CEILINGTURRET"; + Obituary "$OB_TURRET"; DeathSound "turret/death"; } States diff --git a/wadsrc/static/zscript/actors/strife/weaponmauler.zs b/wadsrc/static/zscript/actors/strife/weaponmauler.zs index b805c3ac5..276402ee2 100644 --- a/wadsrc/static/zscript/actors/strife/weaponmauler.zs +++ b/wadsrc/static/zscript/actors/strife/weaponmauler.zs @@ -240,6 +240,7 @@ class MaulerTorpedo : Actor action void A_MaulerTorpedoWave() { + if (target == null) return; readonly wavedef = GetDefaultByType("MaulerTorpedoWave"); double savedz = pos.z; angle += 180.; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index a3cf30519..66426a125 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -140,6 +140,7 @@ enum EChaseFlags CHF_NODIRECTIONTURN = 64, CHF_NOPOSTATTACKTURN = 128, CHF_STOPIFBLOCKED = 256, + CHF_DONTIDLE = 512, CHF_DONTTURN = CHF_NORANDOMTURN | CHF_NOPOSTATTACKTURN | CHF_STOPIFBLOCKED }; @@ -364,6 +365,14 @@ enum ERadiusGiveFlags RGF_EITHER = 1 << 17, }; +// Change model flags +enum ChangeModelFlags +{ + CMDL_WEAPONTOPLAYER = 1, + CMDL_HIDEMODEL = 1 << 1, + CMDL_USESURFACESKIN = 1 << 2, +}; + // Activation flags enum EActivationFlags { @@ -396,6 +405,13 @@ enum EActivationFlags }; +// [MC] Flags for SetViewPos. +enum EViewPosFlags +{ + VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles. + VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position. +}; + // Flags for A_TakeInventory and A_TakeFromTarget enum ETakeFlags { @@ -419,6 +435,12 @@ enum EPlayerProperties PROP_FLIGHT = 12, // (Deprecated) PROP_SPEED = 15, // (Deprecated) PROP_BUDDHA = 16, + PROP_BUDDHA2 = 17, + PROP_FRIGHTENING = 18, + PROP_NOCLIP = 19, + PROP_NOCLIP2 = 20, + PROP_GODMODE = 21, + PROP_GODMODE2 = 22, } // Line_SetBlocking @@ -432,6 +454,10 @@ enum EBlockFlags BLOCKF_EVERYTHING = 32, BLOCKF_RAILING = 64, BLOCKF_USE = 128, + BLOCKF_SIGHT = 256, + BLOCKF_HITSCAN = 512, + BLOCKF_SOUND = 1024, + BLOCKF_LANDMONSTERS = 2048, }; // Pointer constants, bitfield-enabled @@ -504,6 +530,7 @@ enum EAngleFlags { SPF_FORCECLAMP = 1, SPF_INTERPOLATE = 2, + SPF_SCALEDNOLERP = 4, }; // flags for A_CheckLOF @@ -622,6 +649,10 @@ enum EQuakeFlags QF_MAX = 1 << 3, QF_FULLINTENSITY = 1 << 4, QF_WAVE = 1 << 5, + QF_3D = 1 << 6, + QF_GROUNDONLY = 1 << 7, + QF_AFFECTACTORS = 1 << 8, + QF_SHAKEONLY = 1 << 9, }; // A_CheckProximity flags @@ -659,12 +690,15 @@ 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_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_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; @@ -1110,6 +1144,9 @@ enum EPlayerCheats CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use 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_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. @@ -1372,7 +1409,8 @@ enum ECompatFlags COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked mods. COMPATF_MBFMONSTERMOVE = 1 << 24, // Monsters are affected by friction and pushers/pullers. - COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs. + COMPATF_CORPSEGIBS = 1 << 25, // only needed for some hypothetical mod checking this flag. + 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. diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index f81596199..6ed46159a 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -5,6 +5,7 @@ extend struct _ native readonly Array<@PlayerClass> PlayerClasses; native readonly Array<@PlayerSkin> PlayerSkins; native readonly Array<@Team> Teams; + native readonly Array<@TerrainDef> Terrains; native int validcount; native play @DehInfo deh; native readonly bool automapactive; @@ -26,6 +27,7 @@ extend struct _ extend struct TexMan { native static void SetCameraToTexture(Actor viewpoint, String texture, double fov); + native static void SetCameraTextureAspectRatio(String texture, double aspectScale, bool useTextureRatio = true); deprecated("3.8", "Use Level.ReplaceTextures() instead") static void ReplaceTextures(String from, String to, int flags) { level.ReplaceTextures(from, to, flags); @@ -297,7 +299,7 @@ struct TraceResults native class LineTracer : Object native { native @TraceResults Results; - native bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags); + native bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags, /* Line::ELineFlags */ uint wallMask = 0xFFFFFFFF, bool ignoreAllActors = false, Actor ignore = null); virtual ETraceStatus TraceCallback() { @@ -367,6 +369,29 @@ struct LevelInfo native native static String MapChecksum(String mapname); } +struct FSpawnParticleParams +{ + native Color color1; + native TextureID texture; + native int style; + native int flags; + native int lifetime; + + native double size; + native double sizestep; + + native Vector3 pos; + native Vector3 vel; + native Vector3 accel; + + native double startalpha; + native double fadestep; + + native double startroll; + native double rollvel; + native double rollacc; +}; + struct LevelLocals native { enum EUDMF @@ -384,6 +409,7 @@ struct LevelLocals native native Array<@Line> Lines; native Array<@Side> Sides; native readonly Array<@Vertex> Vertexes; + native readonly Array<@LinePortal> LinePortals; native internal Array<@SectorPortal> SectorPortals; native readonly int time; @@ -435,6 +461,7 @@ struct LevelLocals native native readonly bool no_dlg_freeze; native readonly bool keepfullinventory; native readonly bool removeitems; + native readonly bool useplayerstartz; native readonly int fogdensity; native readonly int outsidefogdensity; native readonly int skyfog; @@ -471,6 +498,7 @@ struct LevelLocals native native vector3, int PickPlayerStart(int pnum, int flags = 0); native int isFrozen() const; native void setFrozen(bool on); + native string LookupString(uint index); native clearscope Sector PointInSector(Vector2 pt) const; @@ -487,6 +515,11 @@ struct LevelLocals native native clearscope vector2 Vec2Offset(vector2 pos, vector2 dir, bool absolute = false) const; native clearscope vector3 Vec2OffsetZ(vector2 pos, vector2 dir, double atz, bool absolute = false) const; native clearscope vector3 Vec3Offset(vector3 pos, vector3 dir, bool absolute = false) const; + native clearscope Vector2 GetDisplacement(int pg1, int pg2) const; + native clearscope int GetPortalGroupCount() const; + native clearscope int PointOnLineSide(Vector2 pos, Line l, bool precise = false) const; + native clearscope int ActorOnLineSide(Actor mo, Line l) const; + native clearscope int BoxOnLineSide(Vector2 pos, double radius, Line l) const; native String GetChecksum() const; @@ -508,6 +541,11 @@ struct LevelLocals native native void ExitLevel(int position, bool keepFacing); native void SecretExitLevel(int position); native void ChangeLevel(string levelname, int position = 0, int flags = 0, int skill = -1); + + native String GetClusterName(); + native String GetEpisodeName(); + + native void SpawnParticle(FSpawnParticleParams p); } // a few values of this need to be readable by the play code. @@ -701,11 +739,31 @@ class Lighting : SectorEffect native struct Shader native { - native clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable); - native clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value); - native clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value); - native clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value); - native clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value); + // This interface was deprecated for the pointless player dependency + private static bool IsConsolePlayer(PlayerInfo player) + { + return player && player.mo && player == players[consoleplayer]; + } + deprecated("4.8", "Use PPShader.SetEnabled() instead") clearscope static void SetEnabled(PlayerInfo player, string shaderName, bool enable) + { + if (IsConsolePlayer(player)) PPShader.SetEnabled(shaderName, enable); + } + deprecated("4.8", "Use PPShader.SetUniform1f() instead") clearscope static void SetUniform1f(PlayerInfo player, string shaderName, string uniformName, float value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform1f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform2f() instead") clearscope static void SetUniform2f(PlayerInfo player, string shaderName, string uniformName, vector2 value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform2f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform3f() instead") clearscope static void SetUniform3f(PlayerInfo player, string shaderName, string uniformName, vector3 value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform3f(shaderName, uniformName, value); + } + deprecated("4.8", "Use PPShader.SetUniform1i() instead") clearscope static void SetUniform1i(PlayerInfo player, string shaderName, string uniformName, int value) + { + if (IsConsolePlayer(player)) PPShader.SetUniform1i(shaderName, uniformName, value); + } } struct FRailParams @@ -727,4 +785,3 @@ struct FRailParams native int SpiralOffset; native int limit; }; // [RH] Shoot a railgun - diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 95b678225..ea6440bbc 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -143,6 +143,41 @@ enum EPrintLevel PRINT_NOLOG = 2048, // Flag - do not print to log file }; +enum EConsoleState +{ + c_up = 0, + c_down = 1, + c_falling = 2, + c_rising = 3 +}; + +/* +// These are here to document the intrinsic methods and fields available on +// the built-in ZScript types +struct Vector2 +{ + Vector2(x, y); + double x, y; + native double Length(); + native Vector2 Unit(); + // The dot product of two vectors can be calculated like this: + // double d = a dot b; +} + +struct Vector3 +{ + Vector3(x, y, z); + double x, y, z; + Vector2 xy; // Convenient access to the X and Y coordinates of a 3D vector + native double Length(); + native Vector3 Unit(); + // The dot product of two vectors can be calculated like this: + // double d = a dot b; + // The cross product of two vectors can be calculated like this: + // Vector3 d = a cross b; +} +*/ + struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this. { native readonly Array AllClasses; @@ -183,6 +218,8 @@ struct _ native // These are the global variables, the struct is only here to av native MenuDelegateBase menuDelegate; native readonly int consoleplayer; native readonly double NotifyFontScale; + native readonly int paused; + native readonly ui uint8 ConsoleState; } struct System native @@ -192,17 +229,20 @@ struct System native native static bool SoundEnabled(); native static bool MusicEnabled(); native static double GetTimeFrac(); - + static bool specialKeyEvent(InputEvent ev) { if (ev.type == InputEvent.Type_KeyDown || ev.type == InputEvent.Type_KeyUp) { int key = ev.KeyScan; - if (key == InputEvent.KEY_VOLUMEDOWN || key == InputEvent.KEY_VOLUMEUP || (key > InputEvent.KEY_LASTJOYBUTTON && key < InputEvent.KEY_PAD_LTHUMB_RIGHT)) return true; + let binding = Bindings.GetBinding(key); + bool volumekeys = key == InputEvent.KEY_VOLUMEDOWN || key == InputEvent.KEY_VOLUMEUP; + bool gamepadkeys = key > InputEvent.KEY_LASTJOYBUTTON && key < InputEvent.KEY_PAD_LTHUMB_RIGHT; + bool altkeys = key == InputEvent.KEY_LALT || key == InputEvent.KEY_RALT; + if (volumekeys || gamepadkeys || altkeys || binding ~== "screenshot") return true; } return false; } - } struct MusPlayingInfo native @@ -267,8 +307,50 @@ struct TexMan native static int CheckRealHeight(TextureID tex); native static bool OkForLocalization(TextureID patch, String textSubstitute); native static bool UseGamePalette(TextureID tex); + native static Canvas GetCanvas(String texture); } +/* +// Intrinsic TextureID methods +// This isn't really a class, and can be used as an integer +struct TextureID +{ + native bool IsValid(); + native bool IsNull(); + native bool Exists(); + native void SetInvalid(); + native void SetNull(); +} + +// 32-bit RGBA color - each component is one byte, or 8-bit +// This isn't really a class, and can be used as an integer +struct Color +{ + // Constructor - alpha channel is optional + Color(int alpha, int red, int green, int blue); + Color(int red, int green, int blue); // Alpha is 0 if omitted + int r; // Red + int g; // Green + int b; // Blue + int a; // Alpha +} + +// Name - a string with an integer ID +struct Name +{ + Name(Name name); + Name(String name); +} + +// Sound ID - can be created by casting from a string (name from SNDINFO) or an +// integer (sound ID as integer). +struct Sound +{ + Sound(String soundName); + Sound(int id); +} +*/ + enum EScaleMode { FSMode_None = 0, @@ -382,12 +464,26 @@ enum DrawTextureTags }; +enum StencilOp +{ + SOP_Keep = 0, + SOP_Increment = 1, + SOP_Decrement = 2 +}; +enum StencilFlags +{ + SF_AllOn = 0, + SF_ColorMaskOff = 1, + SF_DepthMaskOff = 2 +}; + class Shape2DTransform : Object native { native void Clear(); native void Rotate(double angle); native void Scale(Vector2 scaleVec); native void Translate(Vector2 translateVec); + native void From2D(double m00, double m01, double m10, double m11, double vx, double vy); } class Shape2D : Object native @@ -407,21 +503,52 @@ class Shape2D : Object native native void PushTriangle( int a, int b, int c ); } +class Canvas : Object native abstract +{ + native void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1); + native void Dim(Color col, double amount, int x, int y, int w, int h, ERenderStyle style = STYLE_Translucent); + + native vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); + native vararg void DrawShape(TextureID tex, bool animate, Shape2D s, ...); + native vararg void DrawShapeFill(Color col, double amount, Shape2D s, ...); + native vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); + native vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); + native void DrawLine(double x0, double y0, double x1, double y1, Color color, int alpha = 255); + native void DrawLineFrame(Color color, int x0, int y0, int w, int h, int thickness = 1); + native void DrawThickLine(double x0, double y0, double x1, double y1, double thickness, Color color, int alpha = 255); + native Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true); + native void SetClipRect(int x, int y, int w, int h); + native void ClearClipRect(); + native int, int, int, int GetClipRect(); + native double, double, double, double GetFullscreenRect(double vwidth, double vheight, int fsmode); + native Vector2 SetOffset(double x, double y); + native void ClearScreen(color col = 0); + native void SetScreenFade(double factor); + + native void EnableStencil(bool on); + native void SetStencil(int offs, int op, int flags = -1); + native void ClearStencil(); + native void SetTransform(Shape2DTransform transform); + native void ClearTransform(); +} + struct Screen native { native static Color PaletteColor(int index); native static int GetWidth(); native static int GetHeight(); + native static Vector2 GetTextScreenSize(); native static void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1); - native static void Dim(Color col, double amount, int x, int y, int w, int h); + native static void Dim(Color col, double amount, int x, int y, int w, int h, ERenderStyle style = STYLE_Translucent); native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); native static vararg void DrawShape(TextureID tex, bool animate, Shape2D s, ...); + native static vararg void DrawShapeFill(Color col, double amount, Shape2D s, ...); native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); - native static void DrawLine(int x0, int y0, int x1, int y1, Color color, int alpha = 255); + native static void DrawLine(double x0, double y0, double x1, double y1, Color color, int alpha = 255); native static void DrawLineFrame(Color color, int x0, int y0, int w, int h, int thickness = 1); - native static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, Color color, int alpha = 255); + native static void DrawThickLine(double x0, double y0, double x1, double y1, double thickness, Color color, int alpha = 255); native static Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true); native static double GetAspectRatio(); native static void SetClipRect(int x, int y, int w, int h); @@ -432,6 +559,12 @@ struct Screen native native static Vector2 SetOffset(double x, double y); native static void ClearScreen(color col = 0); native static void SetScreenFade(double factor); + + native static void EnableStencil(bool on); + native static void SetStencil(int offs, int op, int flags = -1); + native static void ClearStencil(); + native static void SetTransform(Shape2DTransform transform); + native static void ClearTransform(); } struct Font native @@ -503,7 +636,8 @@ struct Font native const TEXTCOLOR_CHAT = "\034*"; const TEXTCOLOR_TEAMCHAT = "\034!"; - + // native Font(const String name); // String/name to font casts + // native Font(const Name name); native int GetCharWidth(int code); native int StringWidth(String code); @@ -515,6 +649,7 @@ struct Font native native static int FindFontColor(Name color); native double GetBottomAlignOffset(int code); + native double GetDisplayTopOffset(int code); native static Font FindFont(Name fontname); native static Font GetFont(Name fontname); native BrokenLines BreakLines(String text, int maxlen); @@ -526,6 +661,7 @@ struct Console native { native static void HideConsole(); native static vararg void Printf(string fmt, ...); + native static vararg void PrintfEx(int printlevel, string fmt, ...); } struct CVar native @@ -587,12 +723,62 @@ class Object native private native static Object BuiltinClassCast(Object inptr, Class test); native static uint MSTime(); + native static double MSTimeF(); native vararg static void ThrowAbortException(String fmt, ...); 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. virtual virtualscope void OnDestroy() {} + // + // Object intrinsics + // Every ZScript "class" inherits from Object, and so inherits these methods as well + // clearscope bool IsAbstract(); // Query whether or not the class of this object is abstract + // clearscope Object GetParentClass(); // Get the parent class of this object + // clearscope Name GetClassName(); // Get the name of this object's class + // clearscope Class GetClass(); // Get the object's class + // clearscope Object new(class type); // Create a new object with this class. This is only valid for thinkers and plain objects, except menus. For actors, use Actor.Spawn(); + // + // + // Intrinsic random number generation functions. Note that the square + // bracket syntax for specifying an RNG ID is only available for these + // functions. + // clearscope void SetRandomSeed[Name rngId = 'None'](int seed); // Set the seed for the given RNG. + // clearscope int Random[Name rngId = 'None'](int min, int max); // Use the given RNG to generate a random integer number in the range (min, max) inclusive. + // clearscope int Random2[Name rngId = 'None'](int mask); // Use the given RNG to generate a random integer number, and do a "union" (bitwise AND, AKA &) operation with the bits in the mask integer. + // clearscope double FRandom[Name rngId = 'None'](double min, double max); // Use the given RNG to generate a random real number in the range (min, max) inclusive. + // clearscope int RandomPick[Name rngId = 'None'](int choices...); // Use the given RNG to generate a random integer from the given choices. + // clearscope double FRandomPick[Name rngId = 'None'](double choices...); // Use the given RNG to generate a random real number from the given choices. + // + // + // Intrinsic math functions - the argument and return types for these + // functions depend on the arguments given. Other than that, they work the + // same way similarly-named functions in other programming languages work. + // Note that trigonometric functions work with degrees instead of radians + // clearscope T abs(T x); + // clearscope T atan2(T y, T x); // NOTE: Returns a value in degrees instead of radians + // clearscope T vectorangle(T x, T y); // Same as Atan2 with the arguments in a different order + // clearscope T min(T x...); + // clearscope T max(T x...); + // clearscope T clamp(T x, T min, T max); + // + // These math functions only work with doubles - they are defined in FxFlops + // clearscope double exp(double x); + // clearscope double log(double x); + // clearscope double log10(double x); + // clearscope double sqrt(double x); + // clearscope double ceil(double x); + // clearscope double floor(double x); + // clearscope double acos(double x); + // clearscope double asin(double x); + // clearscope double atan(double x); + // clearscope double cos(double x); + // clearscope double sin(double x); + // clearscope double tan(double x); + // clearscope double cosh(double x); + // clearscope double sinh(double x); + // clearscope double tanh(double x); + // clearscope double round(double x); } class BrokenLines : Object native version("2.4") @@ -644,6 +830,7 @@ struct Wads // todo: make FileSystem an alias to 'Wads' native static int CheckNumForName(string name, int ns, int wadnum = -1, bool exact = false); native static int CheckNumForFullName(string name); 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 GetNumLumps(); @@ -659,11 +846,15 @@ enum EmptyTokenType } // Although String is a builtin type, this is a convenient way to attach methods to it. +// All of these methods are available on strings struct StringStruct native { native static vararg String Format(String fmt, ...); native vararg void AppendFormat(String fmt, ...); - + // native int Length(); // Intrinsic + // native bool operator==(String other); // Equality comparison + // native bool operator~==(String other); // Case-insensitive equality comparison + // native String operator..(String other); // Concatenate with another String native void Replace(String pattern, String replacement); native String Left(int len) const; native String Mid(int pos = 0, int len = 2147483647) const; @@ -690,7 +881,9 @@ struct StringStruct native native int CodePointCount() const; native int, int GetNextCodePoint(int position) const; native void Substitute(String str, String replace); + native void StripLeft(String junk = ""); native void StripRight(String junk = ""); + native void StripLeftRight(String junk = ""); } struct Translation version("2.4") @@ -701,3 +894,16 @@ struct Translation version("2.4") } } +// Convenient way to attach functions to Quat +struct QuatStruct native +{ + native static Quat SLerp(Quat from, Quat to, double t); + native static Quat NLerp(Quat from, Quat to, double t); + native static Quat FromAngles(double yaw, double pitch, double roll); + native static Quat AxisAngle(Vector3 xyz, double angle); + native Quat Conjugate(); + native Quat Inverse(); + // native double Length(); + // native double LengthSquared(); + // native Quat Unit(); +} diff --git a/wadsrc/static/zscript/engine/dynarrays.zs b/wadsrc/static/zscript/engine/dynarrays.zs index 009350b8e..f9e6a680d 100644 --- a/wadsrc/static/zscript/engine/dynarrays.zs +++ b/wadsrc/static/zscript/engine/dynarrays.zs @@ -3,53 +3,53 @@ struct DynArray_I8 native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_I8 other); native void Move(DynArray_I8 other); native void Append (DynArray_I8 other); - native uint Find(int item) const; - native uint Push (int item); + native int Find(int item) const; + native int Push(int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, int item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_I16 native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_I16 other); native void Move(DynArray_I16 other); native void Append (DynArray_I16 other); - native uint Find(int item) const; - native uint Push (int item); + native int Find(int item) const; + native int Push(int item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, int item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_I32 native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_I32 other); native void Move(DynArray_I32 other); native void Append (DynArray_I32 other); - native uint Find(int item) const; - native uint Push (int item); + native int Find(int item) const; + native int Push(int item); native vararg uint PushV (int item, ...); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -57,100 +57,100 @@ struct DynArray_I32 native native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_F32 native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_F32 other); native void Move(DynArray_F32 other); native void Append (DynArray_F32 other); - native uint Find(double item) const; - native uint Push (double item); + native int Find(double item) const; + native int Push(double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, double item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_F64 native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_F64 other); native void Move(DynArray_F64 other); native void Append (DynArray_F64 other); - native uint Find(double item) const; - native uint Push (double item); + native int Find(double item) const; + native int Push(double item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, double item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_Ptr native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_Ptr other); native void Move(DynArray_Ptr other); native void Append (DynArray_Ptr other); - native uint Find(voidptr item) const; - native uint Push (voidptr item); + native int Find(voidptr item) const; + native int Push(voidptr item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, voidptr item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_Obj native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_Obj other); native void Move(DynArray_Obj other); native void Append (DynArray_Obj other); - native uint Find(Object item) const; - native uint Push (Object item); + native int Find(Object item) const; + native int Push(Object item); native bool Pop (); native void Delete (uint index, int deletecount = 1); native void Insert (uint index, Object item); native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } struct DynArray_String native { - native readonly uint Size; + native readonly int Size; native void Copy(DynArray_String other); native void Move(DynArray_String other); native void Append (DynArray_String other); - native uint Find(String item) const; - native uint Push (String item); + native int Find(String item) const; + native int Push(String item); native vararg uint PushV(String item, ...); native bool Pop (); native void Delete (uint index, int deletecount = 1); @@ -158,7 +158,7 @@ struct DynArray_String native native void ShrinkToFit (); native void Grow (uint amount); native void Resize (uint amount); - native uint Reserve (uint amount); - native uint Max () const; + native int Reserve(uint amount); + native int Max() const; native void Clear (); } diff --git a/wadsrc/static/zscript/engine/maps.zs b/wadsrc/static/zscript/engine/maps.zs new file mode 100644 index 000000000..87546f7bd --- /dev/null +++ b/wadsrc/static/zscript/engine/maps.zs @@ -0,0 +1,511 @@ + +struct Map_I32_I8 native +{ + native void Copy(Map_I32_I8 other); + native void Move(Map_I32_I8 other); + native void Swap(Map_I32_I8 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") int GetIfExists(int key) const; + native version("4.11") int CheckValue(int key, out bool exists) const; + + native void Insert(int key, int value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_I8 native +{ + native bool Init(Map_I32_I8 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_I32_I16 native +{ + native void Copy(Map_I32_I16 other); + native void Move(Map_I32_I16 other); + native void Swap(Map_I32_I16 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") int GetIfExists(int key) const; + native version("4.11") int CheckValue(int key, out bool exists) const; + + native void Insert(int key, int value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_I16 native +{ + native bool Init(Map_I32_I16 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_I32_I32 native +{ + native void Copy(Map_I32_I32 other); + native void Move(Map_I32_I32 other); + native void Swap(Map_I32_I32 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") int GetIfExists(int key) const; + native version("4.11") int CheckValue(int key, out bool exists) const; + + native void Insert(int key, int value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_I32 native +{ + native bool Init(Map_I32_I32 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_I32_F32 native +{ + native void Copy(Map_I32_F32 other); + native void Move(Map_I32_F32 other); + native void Swap(Map_I32_F32 other); + native void Clear(); + native uint CountUsed() const; + + native double Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") double GetIfExists(int key) const; + native version("4.11") double CheckValue(int key, out bool exists) const; + + native void Insert(int key, double value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_F32 native +{ + native bool Init(Map_I32_F32 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native double GetValue(); + native void SetValue(double value); +} + +struct Map_I32_F64 native +{ + native void Copy(Map_I32_F64 other); + native void Move(Map_I32_F64 other); + native void Swap(Map_I32_F64 other); + native void Clear(); + native uint CountUsed() const; + + native double Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") double GetIfExists(int key) const; + native version("4.11") double CheckValue(int key, out bool exists) const; + + native void Insert(int key, double value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_F64 native +{ + native bool Init(Map_I32_F64 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native double GetValue(); + native void SetValue(double value); +} + +struct Map_I32_Obj native +{ + native void Copy(Map_I32_Obj other); + native void Move(Map_I32_Obj other); + native void Swap(Map_I32_Obj other); + native void Clear(); + native uint CountUsed() const; + + native Object Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") Object GetIfExists(int key) const; + native version("4.11") Object CheckValue(int key, out bool exists) const; + + native void Insert(int key, Object value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_Obj native +{ + native bool Init(Map_I32_Obj other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native Object GetValue(); + native void SetValue(Object value); +} + +struct Map_I32_Ptr native +{ + native void Copy(Map_I32_Ptr other); + native void Move(Map_I32_Ptr other); + native void Swap(Map_I32_Ptr other); + native void Clear(); + native uint CountUsed() const; + + native voidptr Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") voidptr GetIfExists(int key) const; + native version("4.11") voidptr CheckValue(int key, out bool exists) const; + + native void Insert(int key, voidptr value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_Ptr native +{ + native bool Init(Map_I32_Ptr other); + native bool Next(); + + native int GetKey(); + native voidptr GetValue(); + native void SetValue(voidptr value); +} + +struct Map_I32_Str native +{ + native void Copy(Map_I32_Str other); + native void Move(Map_I32_Str other); + native void Swap(Map_I32_Str other); + native void Clear(); + native uint CountUsed() const; + + native String Get(int key); + native bool CheckKey(int key) const; + + native version("4.11") String GetIfExists(int key) const; + native version("4.11") String CheckValue(int key, out bool exists) const; + + native void Insert(int key, String value); + native void InsertNew(int key); + native void Remove(int key); +} + +struct MapIterator_I32_Str native +{ + native bool Init(Map_I32_Str other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native int GetKey(); + native String GetValue(); + native void SetValue(String value); +} + +// --------------- + +struct Map_Str_I8 native +{ + native void Copy(Map_Str_I8 other); + native void Move(Map_Str_I8 other); + native void Swap(Map_Str_I8 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") int GetIfExists(String key) const; + native version("4.11") int CheckValue(String key, out bool exists) const; + + native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_I8 native +{ + native bool Init(Map_Str_I8 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_Str_I16 native +{ + native void Copy(Map_Str_I16 other); + native void Move(Map_Str_I16 other); + native void Swap(Map_Str_I16 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") int GetIfExists(String key) const; + native version("4.11") int CheckValue(String key, out bool exists) const; + + native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_I16 native +{ + native bool Init(Map_Str_I16 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_Str_I32 native +{ + native void Copy(Map_Str_I32 other); + native void Move(Map_Str_I32 other); + native void Swap(Map_Str_I32 other); + native void Clear(); + native uint CountUsed() const; + + native int Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") int GetIfExists(String key) const; + native version("4.11") int CheckValue(String key, out bool exists) const; + + native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_I32 native +{ + native bool Init(Map_Str_I32 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native int GetValue(); + native void SetValue(int value); +} + +struct Map_Str_F32 native +{ + native void Copy(Map_Str_F32 other); + native void Move(Map_Str_F32 other); + native void Swap(Map_Str_F32 other); + native void Clear(); + native uint CountUsed() const; + + native double Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") double GetIfExists(String key) const; + native version("4.11") double CheckValue(String key, out bool exists) const; + + native void Insert(String key, double value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_F32 native +{ + native bool Init(Map_Str_F32 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native double GetValue(); + native void SetValue(double value); +} + +struct Map_Str_F64 native +{ + native void Copy(Map_Str_F64 other); + native void Move(Map_Str_F64 other); + native void Swap(Map_Str_F64 other); + native void Clear(); + native uint CountUsed() const; + + native double Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") double GetIfExists(String key) const; + native version("4.11") double CheckValue(String key, out bool exists) const; + + native void Insert(String key, double value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_F64 native +{ + native bool Init(Map_Str_F64 other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native double GetValue(); + native void SetValue(double value); +} + +struct Map_Str_Obj native +{ + native void Copy(Map_Str_Obj other); + native void Move(Map_Str_Obj other); + native void Swap(Map_Str_Obj other); + native void Clear(); + native uint CountUsed() const; + + native Object Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") Object GetIfExists(String key) const; + native version("4.11") Object CheckValue(String key, out bool exists) const; + + native void Insert(String key, Object value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_Obj native +{ + native bool Init(Map_Str_Obj other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native Object GetValue(); + native void SetValue(Object value); +} + +struct Map_Str_Ptr native +{ + native void Copy(Map_Str_Ptr other); + native void Move(Map_Str_Ptr other); + native void Swap(Map_Str_Ptr other); + native void Clear(); + native uint CountUsed() const; + + native voidptr Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") voidptr GetIfExists(String key) const; + native version("4.11") voidptr CheckValue(String key, out bool exists) const; + + native void Insert(String key, voidptr value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_Ptr native +{ + native bool Init(Map_Str_Ptr other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native voidptr GetValue(); + native void SetValue(voidptr value); +} + +struct Map_Str_Str native +{ + native void Copy(Map_Str_Str other); + native void Move(Map_Str_Str other); + native void Swap(Map_Str_Str other); + native void Clear(); + native uint CountUsed() const; + + native String Get(String key); + native bool CheckKey(String key) const; + + native version("4.11") String GetIfExists(String key) const; + native version("4.11") String CheckValue(String key, out bool exists) const; + + native void Insert(String key, String value); + native void InsertNew(String key); + native void Remove(String key); +} + +struct MapIterator_Str_Str native +{ + native bool Init(Map_Str_Str other); + native bool ReInit(); + + native bool Valid(); + native bool Next(); + + native String GetKey(); + native String GetValue(); + native void SetValue(String value); +} diff --git a/wadsrc/static/zscript/engine/ppshader.zs b/wadsrc/static/zscript/engine/ppshader.zs new file mode 100644 index 000000000..5c94e7e23 --- /dev/null +++ b/wadsrc/static/zscript/engine/ppshader.zs @@ -0,0 +1,8 @@ +struct PPShader native +{ + native clearscope static void SetEnabled(string shaderName, bool enable); + native clearscope static void SetUniform1f(string shaderName, string uniformName, float value); + native clearscope static void SetUniform2f(string shaderName, string uniformName, vector2 value); + native clearscope static void SetUniform3f(string shaderName, string uniformName, vector3 value); + native clearscope static void SetUniform1i(string shaderName, string uniformName, int value); +} diff --git a/wadsrc/static/zscript/engine/screenjob.zs b/wadsrc/static/zscript/engine/screenjob.zs new file mode 100644 index 000000000..a339def91 --- /dev/null +++ b/wadsrc/static/zscript/engine/screenjob.zs @@ -0,0 +1,563 @@ + +class ScreenJob : Object UI +{ + int flags; + float fadetime; // in milliseconds + int fadestate; + + int ticks; + int jobstate; + + bool skipover; + bool nowipe; + + enum EJobState + { + running = 0, // normal operation + skipped = 1, // finished by user skipping + finished = 2, // finished by completing its sequence + stopping = 3, // running ending animations / fadeout, etc. Will not accept more input. + stopped = 4, // we're done here. + }; + enum EJobFlags + { + visible = 0, + fadein = 1, + fadeout = 2, + stopmusic = 4, + stopsound = 8, + transition_shift = 4, + transition_mask = 48, + transition_melt = 16, + transition_burn = 32, + transition_crossfade = 48, + }; + + void Init(int fflags = 0, float fadet = 250.f) + { + flags = fflags; + fadetime = fadet; + jobstate = running; + } + + virtual bool ProcessInput() + { + return false; + } + + virtual void Start() {} + virtual bool OnEvent(InputEvent evt) { return false; } + virtual void OnTick() {} + virtual void Draw(double smoothratio) {} + virtual void OnSkip() {} + + int DrawFrame(double smoothratio) + { + if (jobstate != running) smoothratio = 1; // this is necessary to avoid having a negative time span because the ticker won't be incremented anymore. + Draw(smoothratio); + if (jobstate == skipped) return -1; + if (jobstate == finished) return 0; + return 1; + } + + int GetFadeState() { return fadestate; } + override void OnDestroy() + { + if (flags & stopmusic) System.StopMusic(); + if (flags & stopsound) System.StopAllSounds(); + } + +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class SkippableScreenJob : ScreenJob +{ + void Init(int flags = 0, float fadet = 250.f) + { + Super.Init(flags, fadet); + } + + override bool OnEvent(InputEvent evt) + { + if (evt.type == InputEvent.Type_KeyDown && !System.specialKeyEvent(evt)) + { + jobstate = skipped; + OnSkip(); + } + return true; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class BlackScreen : ScreenJob +{ + int wait; + bool cleared; + + ScreenJob Init(int w, int flags = 0) + { + Super.Init(flags & ~(fadein|fadeout)); + wait = w; + cleared = false; + return self; + } + + static ScreenJob Create(int w, int flags = 0) + { + return new("BlackScreen").Init(w, flags); + } + + override void OnTick() + { + if (cleared) + { + int span = ticks * 1000 / GameTicRate; + if (span > wait) jobstate = finished; + } + } + + override void Draw(double smooth) + { + cleared = true; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class ImageScreen : SkippableScreenJob +{ + int tilenum; + int trans; + int waittime; // in ms. + bool cleared; + TextureID texid; + + ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + { + Super.Init(fade); + waittime = wait; + texid = tile; + trans = translation; + cleared = false; + return self; + } + + ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + { + Super.Init(fade); + waittime = wait; + texid = TexMan.CheckForTexture(tex, TexMan.Type_Any, TexMan.TryAny | TexMan.ForceLookup); + trans = translation; + cleared = false; + return self; + } + + static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int 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) + { + return new("ImageScreen").InitNamed(tex, fade, wait, translation); + } + + override void OnTick() + { + if (cleared) + { + int span = ticks * 1000 / GameTicRate; + if (span > waittime) jobstate = finished; + } + } + + override void Draw(double smooth) + { + if (texid.IsValid()) Screen.DrawTexture(texid, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal, DTA_TranslationIndex, trans); + cleared = true; + } +} + +//--------------------------------------------------------------------------- +// +// internal polymorphic movie player object +// +//--------------------------------------------------------------------------- + +struct MoviePlayer native +{ + enum EMovieFlags + { + NOSOUNDCUTOFF = 1, + FIXEDVIEWPORT = 2, // Forces fixed 640x480 screen size like for Blood's intros. + NOMUSICCUTOFF = 4, + } + + native static MoviePlayer Create(String filename, Array soundinfo, int flags, int frametime, int firstframetime, int lastframetime); + native void Start(); + native bool Frame(double clock); + native void Destroy(); + native TextureID GetTexture(); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class MoviePlayerJob : SkippableScreenJob +{ + MoviePlayer player; + bool started; + int flag; + + ScreenJob Init(MoviePlayer mp, int flags) + { + Super.Init(); + flag = flags; + player = mp; + nowipe = true; // due to synchronization issues wipes must be disabled on any movie. + return self; + } + + override void Start() + { + if (!(flag & MoviePlayer.NOMUSICCUTOFF)) System.StopMusic(); + } + + + static ScreenJob CreateWithSoundInfo(String filename, Array soundinfo, int flags, int frametime, int firstframetime = -1, int lastframetime = -1) + { + let movie = MoviePlayer.Create(filename, soundinfo, flags, frametime, firstframetime, lastframetime); + if (movie) return new("MoviePlayerJob").Init(movie, flags); + return null; + } + static ScreenJob Create(String filename, int flags, int frametime = -1) + { + Array empty; + return CreateWithSoundInfo(filename, empty, flags, frametime); + } + static ScreenJob CreateWithSound(String filename, Sound soundname, int flags, int frametime = -1) + { + Array empty; + empty.Push(1); + empty.Push(int(soundname)); + return CreateWithSoundInfo(filename, empty, flags, frametime); + } + + virtual void DrawFrame() + { + let tex = player.GetTexture(); + let size = TexMan.GetScaledSize(tex); + + if (!(flag & MoviePlayer.FIXEDVIEWPORT) || (size.x <= 320 && size.y <= 200) || size.x >= 640 || size.y >= 480) + { + Screen.DrawTexture(tex, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Masked, false); + } + else + { + Screen.DrawTexture(tex, false, 320, 240, DTA_VirtualWidth, 640, DTA_VirtualHeight, 480, DTA_CenterOffset, true, DTA_Masked, false); + } + + } + + override void Draw(double smoothratio) + { + if (!player) + { + jobstate = stopped; + return; + } + if (!started) + { + started = true; + player.Start(); + } + double clock = (ticks + smoothratio) * 1000000000. / GameTicRate; + if (jobstate == running && !player.Frame(clock)) + { + jobstate = finished; + } + DrawFrame(); + } + + override void OnDestroy() + { + if (player) + { + player.Destroy(); + } + player = null; + } +} + + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class ScreenJobRunner : Object UI +{ + enum ERunState + { + State_Clear, + State_Run, + State_Fadeout, + } + Array jobs; + //CompletionFunc completion; + int index; + float screenfade; + bool clearbefore; + bool skipall; + bool advance; + int actionState; + int terminateState; + int fadeticks; + int last_paused_tic; + + native static void setTransition(int type); + + void Init(bool clearbefore_, bool skipall_) + { + clearbefore = clearbefore_; + skipall = skipall_; + index = -1; + fadeticks = 0; + last_paused_tic = -1; + } + + override void OnDestroy() + { + DeleteJobs(); + } + + protected void DeleteJobs() + { + // Free all allocated resources now. + for (int i = 0; i < jobs.Size(); i++) + { + if (jobs[i]) jobs[i].Destroy(); + } + jobs.Clear(); + } + + void Append(ScreenJob job) + { + if (job != null) jobs.Push(job); + } + + virtual bool Validate() + { + return jobs.Size() > 0; + } + + bool CanWipe() + { + if (index < jobs.Size()) return !jobs[max(0, index)].nowipe; + return true; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + protected void AdvanceJob(bool skip) + { + if (index == jobs.Size()-1) + { + index++; + return; // we need to retain the last element until the runner is done. + } + + if (index >= 0) jobs[index].Destroy(); + index++; + while (index < jobs.Size() && (jobs[index] == null || (skip && jobs[index].skipover))) + { + if (jobs[index] != null && index < jobs.Size() - 1) jobs[index].Destroy(); // may not delete the last element - we still need it for shutting down. + index++; + } + actionState = clearbefore ? State_Clear : State_Run; + if (index < jobs.Size()) + { + jobs[index].fadestate = !paused && jobs[index].flags & ScreenJob.fadein? ScreenJob.fadein : ScreenJob.visible; + jobs[index].Start(); + if (jobs[index].flags & ScreenJob.transition_mask) + { + setTransition((jobs[index].flags & ScreenJob.transition_mask) >> ScreenJob.Transition_Shift); + } + } + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + virtual int DisplayFrame(double smoothratio) + { + if (jobs.Size() == 0) + { + return 1; + } + int x = index >= jobs.Size()? jobs.Size()-1 : index; + let job = jobs[x]; + bool processed = job.ProcessInput(); + + if (job.fadestate == ScreenJob.fadein) + { + double ms = (job.ticks + smoothratio) * 1000 / GameTicRate / job.fadetime; + double screenfade = clamp(ms, 0., 1.); + Screen.SetScreenFade(screenfade); + if (screenfade == 1.) job.fadestate = ScreenJob.visible; + } + int state = job.DrawFrame(smoothratio); + Screen.SetScreenFade(1.); + return state; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + virtual int FadeoutFrame(double smoothratio) + { + int x = index >= jobs.Size()? jobs.Size()-1 : index; + let job = jobs[x]; + double ms = (fadeticks + smoothratio) * 1000 / GameTicRate / job.fadetime; + float screenfade = 1. - clamp(ms, 0., 1.); + Screen.SetScreenFade(screenfade); + job.DrawFrame(1.); + Screen.SetScreenFade(1.); + return (screenfade > 0.); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + virtual bool OnEvent(InputEvent ev) + { + if (paused || index < 0 || index >= jobs.Size()) return false; + if (jobs[index].jobstate != ScreenJob.running) return false; + return jobs[index].OnEvent(ev); + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + virtual bool OnTick() + { + if (paused) return false; + if (index >= jobs.Size() || jobs.Size() == 0) return true; + if (advance || index < 0) + { + advance = false; + AdvanceJob(terminateState < 0); + if (index >= jobs.Size()) + { + return true; + } + } + if (jobs[index].jobstate == ScreenJob.running) + { + jobs[index].ticks++; + jobs[index].OnTick(); + } + else if (jobs[index].jobstate == ScreenJob.stopping) + { + fadeticks++; + } + return false; + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + virtual bool RunFrame(double smoothratio) + { + if (index < 0) + { + AdvanceJob(false); + } + // ensure that we won't go back in time if the menu is dismissed without advancing our ticker + if (index < jobs.Size()) + { + bool menuon = paused; + if (menuon) last_paused_tic = jobs[index].ticks; + else if (last_paused_tic == jobs[index].ticks) menuon = true; + if (menuon) smoothratio = 1.; + } + else smoothratio = 1.; + + if (actionState == State_Clear) + { + actionState = State_Run; + } + else if (actionState == State_Run) + { + terminateState = DisplayFrame(smoothratio); + if (terminateState < 1 && index < jobs.Size()) + { + if (jobs[index].flags & ScreenJob.fadeout) + { + jobs[index].fadestate = ScreenJob.fadeout; + jobs[index].jobstate = ScreenJob.stopping; + actionState = State_Fadeout; + fadeticks = 0; + } + else + { + advance = true; + } + } + } + else if (actionState == State_Fadeout) + { + int ended = FadeoutFrame(smoothratio); + if (ended < 1 && index < jobs.Size()) + { + jobs[index].jobstate = ScreenJob.stopped; + advance = true; + } + } + return true; + } + + void AddGenericVideo(String fn, int snd, int framerate) + { + Array sounds; + if (snd > 0) sounds.Pushv(1, snd); + Append(MoviePlayerJob.CreateWithSoundInfo(fn, sounds, 0, framerate)); + } +} diff --git a/wadsrc/static/zscript/engine/ui/menu/colorpickermenu.zs b/wadsrc/static/zscript/engine/ui/menu/colorpickermenu.zs index f8ce51874..218a215fc 100644 --- a/wadsrc/static/zscript/engine/ui/menu/colorpickermenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/colorpickermenu.zs @@ -73,20 +73,20 @@ class ColorpickerMenu : OptionMenu int mStartItem; CVar mCVar; - + double GetColor(int index) { double v = index == 0? mRed : index == 1? mGreen : mBlue; return v; } - + void SetColor(int index, double val) { if (index == 0) mRed = val; else if (index == 1) mGreen = val; else mBlue = val; } - + //============================================================================= // // @@ -119,7 +119,7 @@ class ColorpickerMenu : OptionMenu mDesc.mIndent = 0; mDesc.CalcIndent(); } - + //============================================================================= // // @@ -273,7 +273,7 @@ class ColorpickerMenu : OptionMenu if (h > fh) h = fh; else if (h < 4) return; // no space to draw it. - + int indent = (screen.GetWidth() / 2); int p = 0; @@ -303,7 +303,7 @@ class ColorpickerMenu : OptionMenu } // Make sure the cursors stand out against similar colors // by pulsing them. - blinky = abs(sin(MSTime()/1000.0)) * 0.5 + 0.5; + blinky = abs(sin(MSTimeF()/1000.0)) * 0.5 + 0.5; col = Color(255, int(r*blinky), int(g*blinky), int(b*blinky)); screen.Clear (box_x, box_y, box_x + w, box_y + 1, col); @@ -328,7 +328,7 @@ class ColorpickerMenu : OptionMenu y += 49*CleanYfac_1; screen.DrawText (SmallFont, Font.CR_GRAY, x+(48-SmallFont.StringWidth("---->")/2)*CleanXfac_1, y, "---->", DTA_CleanNoMove_1, true); } - + override void OnDestroy() { if (mStartItem >= 0) diff --git a/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs b/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs new file mode 100644 index 000000000..68a79417c --- /dev/null +++ b/wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs @@ -0,0 +1,264 @@ +/* +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** Copyright 2022 Ricardo Luis Vaz Silva +** +** 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. +**--------------------------------------------------------------------------- +** +*/ + +class CustomMessageBoxMenuBase : Menu abstract +{ + BrokenLines mMessage; + uint messageSelection; + int mMouseLeft, mMouseRight, mMouseY; + + Font textFont, arrowFont; + int destWidth, destHeight; + String selector; + + abstract uint OptionCount(); + abstract String OptionName(uint index); + abstract int OptionXOffset(uint index); + + abstract int OptionForShortcut(int char_key, out bool activate); // -1 for no shortcut, activate = true if this executes the option immediately + + //============================================================================= + // + // + // + //============================================================================= + + virtual void Init(Menu parent, String message, bool playsound = false) + { + Super.Init(parent); + messageSelection = 0; + mMouseLeft = 140; + mMouseY = 0x80000000; + textFont = null; + + if (!generic_ui) + { + if (SmallFont && SmallFont.CanPrint(message) && SmallFont.CanPrint("$TXT_YES") && SmallFont.CanPrint("$TXT_NO")) textFont = SmallFont; + else if (OriginalSmallFont && OriginalSmallFont.CanPrint(message) && OriginalSmallFont.CanPrint("$TXT_YES") && OriginalSmallFont.CanPrint("$TXT_NO")) textFont = OriginalSmallFont; + } + + if (!textFont) + { + arrowFont = textFont = NewSmallFont; + int factor = (CleanXfac+1) / 2; + destWidth = screen.GetWidth() / factor; + destHeight = screen.GetHeight() / factor; + selector = "▶"; + } + else + { + arrowFont = ConFont; + destWidth = CleanWidth; + destHeight = CleanHeight; + selector = "\xd"; + } + + int mr1 = destWidth/2 + 10 + textFont.StringWidth(Stringtable.Localize("$TXT_YES")); + int mr2 = destWidth/2 + 10 + textFont.StringWidth(Stringtable.Localize("$TXT_NO")); + mMouseRight = MAX(mr1, mr2); + mParentMenu = parent; + mMessage = textFont.BreakLines(Stringtable.Localize(message), int(300/NotifyFontScale)); + if (playsound) + { + MenuSound ("menu/prompt"); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer () + { + int i; + double y; + let fontheight = textFont.GetHeight() * NotifyFontScale; + + y = destHeight / 2; + + int c = mMessage.Count(); + y -= c * fontHeight / 2; + + for (i = 0; i < c; i++) + { + screen.DrawText (textFont, Font.CR_UNTRANSLATED, destWidth/2 - mMessage.StringWidth(i)*NotifyFontScale/2, y, mMessage.StringAt(i), DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true, + DTA_ScaleX, NotifyFontScale, DTA_ScaleY, NotifyFontScale); + y += fontheight; + } + + y += fontheight; + mMouseY = int(y); + + let n = optionCount(); + for(uint i = 0; i < n; i++) + { + screen.DrawText(textFont, messageSelection == i? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, (destWidth / 2) + OptionXOffset(i), y + (fontheight * i), Stringtable.Localize(optionName(i)), DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true, DTA_ScaleX, NotifyFontScale, DTA_ScaleY, NotifyFontScale); + } + + if (messageSelection >= 0) + { + 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); + } + } + } + + + //============================================================================= + // + // + // + //============================================================================= + + protected void CloseSound() + { + MenuSound (GetCurrentMenu() != NULL? "menu/backup" : "menu/dismiss"); + } + + //============================================================================= + // + // + // + //============================================================================= + + abstract void HandleResult(int index); // -1 = escape + + //============================================================================= + // + // + // + //============================================================================= + + override bool OnUIEvent(UIEvent ev) + { + if (ev.type == UIEvent.Type_KeyDown) + { + // tolower + int ch = ev.KeyChar; + ch = ch >= 65 && ch <91? ch + 32 : ch; + + bool activate; + int opt = optionForShortcut(ch,activate); + + if(opt >= 0){ + if(activate || opt == messageSelection) { + HandleResult(messageSelection); + } else { + messageSelection = opt; + } + return true; + } + return false; + } + return Super.OnUIEvent(ev); + } + + override bool OnInputEvent(InputEvent ev) + { + if (ev.type == InputEvent.Type_KeyDown) + { + Close(); + return true; + } + return Super.OnInputEvent(ev); + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent(int mkey, bool fromcontroller) + { + if (mkey == MKEY_Up) + { + MenuSound("menu/cursor"); + if (messageSelection == 0) messageSelection = optionCount(); + messageSelection--; + return true; + } + else if (mkey == MKEY_Down) + { + MenuSound("menu/cursor"); + messageSelection++; + if (messageSelection == optionCount()) messageSelection = 0; + return true; + } + else if (mkey == MKEY_Enter) + { + HandleResult(messageSelection); + return true; + } + else if (mkey == MKEY_Back) + { + HandleResult(-1); + return true; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MouseEvent(int type, int x, int y) + { + int fh = textFont.GetHeight() + 1; + + // convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture + x = x * destWidth / screen.GetWidth(); + y = y * destHeight / screen.GetHeight(); + + int n = OptionCount(); + + if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + (n * fh)) + { + messageSelection = (y - mMouseY) / fh; + } + if (type == MOUSE_Release) + { + return MenuEvent(MKEY_Enter, true); + } + return true; + } + + +} diff --git a/wadsrc/static/zscript/engine/ui/menu/imagescroller.zs b/wadsrc/static/zscript/engine/ui/menu/imagescroller.zs index cab771ae7..5c7865f03 100644 --- a/wadsrc/static/zscript/engine/ui/menu/imagescroller.zs +++ b/wadsrc/static/zscript/engine/ui/menu/imagescroller.zs @@ -41,26 +41,28 @@ class ImageScrollerDescriptor : MenuDescriptor native native double textScale; native bool mAnimatedTransition; native bool mAnimated; + native bool mDontBlur; + native bool mDontDim; native int virtWidth, virtHeight; } class ImageScrollerPage : MenuItemBase { int virtWidth, virtHeight; - + protected void DrawText(Font fnt, int color, double x, double y, String text) { screen.DrawText(fnt, color, x, y, text, DTA_VirtualWidth, virtWidth, DTA_VirtualHeight, virtHeight, DTA_FullscreenScale, FSMode_ScaleToFit43); } - + protected void DrawTexture(TextureID tex, double x, double y) { screen.DrawTexture(tex, true, x, y, DTA_VirtualWidth, virtWidth, DTA_VirtualHeight, virtHeight, DTA_FullscreenScale, FSMode_ScaleToFit43); } - + virtual void OnStartPage() {} - + virtual void OnEndPage() {} } @@ -74,13 +76,13 @@ class ImageScrollerPage : MenuItemBase class ImageScrollerPageImageItem : ImageScrollerPage { TextureID mTexture; - + void Init(ImageScrollerDescriptor desc, String patch) { Super.Init(); mTexture = TexMan.CheckForTexture(patch); } - + override void Drawer(bool selected) { Screen.DrawTexture(mTexture, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal); @@ -100,7 +102,7 @@ class ImageScrollerPageTextItem : ImageScrollerPage TextureID mTexture; Color mBrightness; double mTextScale; - + void Init(ImageScrollerDescriptor desc, String txt, int y = -1) { Super.Init(); @@ -110,16 +112,16 @@ class ImageScrollerPageTextItem : ImageScrollerPage mTextScale = desc.textScale; virtWidth = desc.virtWidth; virtHeight = desc.virtHeight; - + mText = mFont.BreakLines(Stringtable.Localize(txt.Filter()), int(virtWidth / mTextScale)); mYpos = y >= 0? y : virtHeight / 2 - mText.Count() * mFont.GetHeight() * mTextScale / 2; - + } - + override void Drawer(bool selected) { Screen.DrawTexture(mTexture, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal, DTA_Color, mBrightness); - + let fontheight = mFont.GetHeight() * mTextScale; let y = mYpos; let c = mText.Count(); @@ -154,7 +156,7 @@ class ImageScrollerMenu : Menu { if (AnimatedTransition) { - start = MSTime() * (120. / 1000.); + start = MSTimeF() * (120. / 1000.); length = 30; dir = animtype; previous = current; @@ -168,8 +170,10 @@ class ImageScrollerMenu : Menu mParentMenu = parent; index = 0; mDesc = desc; - AnimatedTransition = desc.mAnimatedTransition; - Animated = desc.mAnimated; + AnimatedTransition = mDesc.mAnimatedTransition; + Animated = mDesc.mAnimated; + DontBlur = mDesc.mDontBlur; + DontDim = mDesc.mDontDim; current = mDesc.mItems[0]; current.onStartPage(); previous = null; @@ -180,7 +184,7 @@ class ImageScrollerMenu : Menu // // //============================================================================= - + override bool MenuEvent(int mkey, bool fromcontroller) { if (mDesc.mItems.Size() <= 1) @@ -228,7 +232,7 @@ class ImageScrollerMenu : Menu // // //============================================================================= - + override bool MouseEvent(int type, int x, int y) { // Todo: Implement some form of drag event to switch between pages. @@ -244,10 +248,10 @@ class ImageScrollerMenu : Menu // // //============================================================================= - + private bool DrawTransition() { - double now = MSTime() * (120. / 1000.); + double now = MSTimeF() * (120. / 1000.); if (now < start + length) { double factor = screen.GetWidth()/2; @@ -270,7 +274,7 @@ class ImageScrollerMenu : Menu // // //============================================================================= - + override void Drawer() { if (previous != null) diff --git a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs index 48b5840e7..06b412f17 100644 --- a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs @@ -41,7 +41,7 @@ class OptionMenuSliderJoySensitivity : OptionMenuSliderBase { JoystickConfig mJoy; - + OptionMenuSliderJoySensitivity Init(String label, double min, double max, double step, int showval, JoystickConfig joy) { Super.Init(label, min, max, step, showval); @@ -71,7 +71,7 @@ class OptionMenuSliderJoyScale : OptionMenuSliderBase int mAxis; int mNeg; JoystickConfig mJoy; - + OptionMenuSliderJoyScale Init(String label, int axis, double min, double max, double step, int showval, JoystickConfig joy) { Super.Init(label, min, max, step, showval); @@ -138,7 +138,7 @@ class OptionMenuItemJoyMap : OptionMenuItemOptionBase { int mAxis; JoystickConfig mJoy; - + OptionMenuItemJoyMap Init(String label, int axis, Name values, int center, JoystickConfig joy) { Super.Init(label, 'none', values, null, center); @@ -191,7 +191,7 @@ class OptionMenuItemInverter : OptionMenuItemOptionBase { int mAxis; JoystickConfig mJoy; - + OptionMenuItemInverter Init(String label, int axis, int center, JoystickConfig joy) { Super.Init(label, "none", "YesNo", NULL, center); @@ -223,7 +223,7 @@ class OptionMenuItemInverter : OptionMenuItemOptionBase class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu { JoystickConfig mJoy; - + OptionMenuItemJoyConfigMenu Init(String label, JoystickConfig joy) { Super.Init(label, "JoystickConfigMenu"); @@ -243,7 +243,7 @@ class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu if (res && joymenu != null) joymenu.mJoy = mJoy; return res; } - + static void SetController(OptionMenuDescriptor opt, JoystickConfig joy) { OptionMenuItem it; @@ -296,7 +296,7 @@ class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu opt.mPosition = -25; opt.CalcIndent(); } - + } //============================================================================= diff --git a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs index cc4656d95..672c0ebc7 100644 --- a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs @@ -57,6 +57,8 @@ class ListMenuDescriptor : MenuDescriptor native native bool mCenter; native bool mAnimatedTransition; native bool mAnimated; + native bool mDontBlur; + native bool mDontDim; native int mVirtWidth, mVirtHeight; native void Reset(); @@ -89,6 +91,8 @@ class ListMenu : Menu mDesc = desc; AnimatedTransition = mDesc.mAnimatedTransition; Animated = mDesc.mAnimated; + DontBlur = mDesc.mDontBlur; + DontDim = mDesc.mDontDim; if (desc.mCenter) { double center = 160; @@ -120,7 +124,7 @@ class ListMenu : Menu mDesc.mItems[i].OnMenuCreated(); } } - + //============================================================================= // // @@ -136,7 +140,7 @@ class ListMenu : Menu } return NULL; } - + //============================================================================= // @@ -243,7 +247,7 @@ class ListMenu : Menu int h = mDesc.DisplayHeight(); double fx, fy, fw, fh; [fx, fy, fw, fh] = Screen.GetFullscreenRect(w, h, FSMode_ScaleToFit43); - + x = int((x - fx) * w / fw); y = int((y - fy) * h / fh); } @@ -311,7 +315,7 @@ class ListMenu : Menu } Super.Drawer(); } - + //============================================================================= // // diff --git a/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs index 8b47d288c..9e2257820 100644 --- a/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/listmenuitems.zs @@ -109,7 +109,7 @@ class ListMenuItemStaticPatch : ListMenuItem mColor = desc.mFontColor; } - + override void Draw(bool selected, ListMenuDescriptor desc) { if (!mTexture.Exists()) @@ -163,7 +163,7 @@ class ListMenuItemStaticText : ListMenuItem mColor = color >= 0? color : desc.mFontColor; mCentered = false; } - + void InitDirect(double x, double y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false) { Super.Init(x, y); @@ -172,7 +172,7 @@ class ListMenuItemStaticText : ListMenuItem mColor = color; mCentered = centered; } - + override void Draw(bool selected, ListMenuDescriptor desc) { if (mText.Length() != 0) @@ -216,12 +216,12 @@ class ListMenuItemSelectable : ListMenuItem mParam = param; mHotkey = 0; } - + override bool CheckCoordinate(int x, int y) { return mEnabled > 0 && y >= mYpos && y < mYpos + mHeight; // no x check here } - + override bool Selectable() { return mEnabled > 0; @@ -231,13 +231,13 @@ class ListMenuItemSelectable : ListMenuItem { return c > 0 && c == mHotkey; } - + override bool Activate() { Menu.SetMenu(mAction, mParam); return true; } - + override bool MouseEvent(int type, int x, int y) { if (type == Menu.MOUSE_Release) @@ -250,7 +250,7 @@ class ListMenuItemSelectable : ListMenuItem } return false; } - + override Name, int GetAction() { return mAction, mParam; @@ -279,7 +279,7 @@ class ListMenuItemTextItem : ListMenuItemSelectable mColorSelected = desc.mFontcolor2; mHotkey = hotkey.GetNextCodePoint(0); } - + void InitDirect(double x, double y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0) { Super.Init(x, y, height, child, param); @@ -290,7 +290,7 @@ class ListMenuItemTextItem : ListMenuItemSelectable int pos = 0; mHotkey = hotkey.GetNextCodePoint(0); } - + override void Draw(bool selected, ListMenuDescriptor desc) { let font = menuDelegate.PickFont(mFont); @@ -313,31 +313,31 @@ class ListMenuItemTextItem : ListMenuItemSelectable class ListMenuItemPatchItem : ListMenuItemSelectable { TextureID mTexture; - + void Init(ListMenuDescriptor desc, TextureID patch, String hotkey, Name child, int param = 0) { Super.Init(desc.mXpos, desc.mYpos, desc.mLinespacing, child, param); mHotkey = hotkey.GetNextCodePoint(0); mTexture = patch; } - + void InitDirect(double x, double y, int height, TextureID patch, String hotkey, Name child, int param = 0) { Super.Init(x, y, height, child, param); mHotkey = hotkey.GetNextCodePoint(0); mTexture = patch; } - + override void Draw(bool selected, ListMenuDescriptor desc) { DrawTexture(desc, mTexture, mXpos, mYpos); } - + override int GetWidth() { return TexMan.GetSize(mTexture); } - + } //============================================================================= @@ -357,7 +357,7 @@ class ListMenuItemCaptionItem : ListMenuItem mText = text; mFont = Font.FindFont(fnt); } - + override void Draw(bool selected, ListMenuDescriptor desc) { let font = menuDelegate.PickFont(desc.mFont); diff --git a/wadsrc/static/zscript/engine/ui/menu/loadsavemenu.zs b/wadsrc/static/zscript/engine/ui/menu/loadsavemenu.zs index 3fac8bf40..e15ca266f 100644 --- a/wadsrc/static/zscript/engine/ui/menu/loadsavemenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/loadsavemenu.zs @@ -87,7 +87,7 @@ class LoadSaveMenu : ListMenu int listboxLeft; int listboxTop; int listboxWidth; - + int listboxRows; int listboxHeight; int listboxRight; @@ -101,10 +101,10 @@ class LoadSaveMenu : ListMenu bool mEntering; TextEnterMenu mInput; double FontScale; - + BrokenLines BrokenSaveComment; - + //============================================================================= // @@ -119,13 +119,13 @@ class LoadSaveMenu : ListMenu manager.ReadSaveStrings(); SetWindows(); } - + private void SetWindows() { bool aspect43 = true; int Width43 = screen.GetHeight() * 4 / 3; int Left43 = (screen.GetWidth() - Width43) / 2; - + double wScale = Width43 / 640.; savepicLeft = Left43 + int(20 * wScale); @@ -135,7 +135,7 @@ class LoadSaveMenu : ListMenu FontScale = max(screen.GetHeight() / 480, 1); rowHeight = int(max((NewConsoleFont.GetHeight() + 1) * FontScale, 1)); - + listboxLeft = savepicLeft + savepicWidth + int(20*wScale); listboxTop = savepicTop; listboxWidth = Width43 + Left43 - listboxLeft - int(30 * wScale); @@ -151,7 +151,7 @@ class LoadSaveMenu : ListMenu commentRows = commentHeight / rowHeight; } - + //============================================================================= // // @@ -202,7 +202,7 @@ class LoadSaveMenu : ListMenu if (Selected >= manager.SavegameCount()) Selected = 0; String text = (Selected == -1 || !manager.GetSavegame(Selected).bOldVersion)? Stringtable.Localize("$MNU_NOPICTURE") : Stringtable.Localize("$MNU_DIFFVERSION"); int textlen = NewSmallFont.StringWidth(text); - + screen.DrawText (NewSmallFont, Font.CR_GOLD, (savepicLeft + savepicWidth / 2) / FontScale - textlen/2, (savepicTop+(savepicHeight-rowHeight)/2) / FontScale, text, DTA_VirtualWidthF, screen.GetWidth() / FontScale, DTA_VirtualHeightF, screen.GetHeight() / FontScale, DTA_KeepRatio, true); } @@ -218,7 +218,7 @@ class LoadSaveMenu : ListMenu screen.DrawText(NewConsoleFont, Font.CR_ORANGE, commentLeft / FontScale, (commentTop + rowHeight * i) / FontScale, BrokenSaveComment.StringAt(i), DTA_VirtualWidthF, screen.GetWidth() / FontScale, DTA_VirtualHeightF, screen.GetHeight() / FontScale, DTA_KeepRatio, true); } - + // Draw file area DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight); @@ -257,7 +257,7 @@ class LoadSaveMenu : ListMenu } screen.SetClipRect(listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1)); - + if (j == Selected) { screen.Clear (listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1), mEntering ? Color(255,255,0,0) : Color(255,0,0,255)); @@ -388,7 +388,7 @@ class LoadSaveMenu : ListMenu return Super.MenuEvent(mkey, fromcontroller); } } - + //============================================================================= // // @@ -422,8 +422,8 @@ class LoadSaveMenu : ListMenu return Super.MouseEvent(type, x, y); } - - + + //============================================================================= // // @@ -466,13 +466,13 @@ class LoadSaveMenu : ListMenu return Super.OnUIEvent(ev); } - + } class SaveMenu : LoadSaveMenu { String mSaveName; - + //============================================================================= // // @@ -508,7 +508,7 @@ class SaveMenu : LoadSaveMenu // // //============================================================================= - + override bool MenuEvent (int mkey, bool fromcontroller) { if (Super.MenuEvent(mkey, fromcontroller)) @@ -603,7 +603,7 @@ class SaveMenu : LoadSaveMenu mSaveName = ""; } } - + } //============================================================================= diff --git a/wadsrc/static/zscript/engine/ui/menu/menu.zs b/wadsrc/static/zscript/engine/ui/menu/menu.zs index 8e08870aa..181234808 100644 --- a/wadsrc/static/zscript/engine/ui/menu/menu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/menu.zs @@ -76,14 +76,14 @@ struct JoystickConfig native version("2.4") native float GetAxisDeadZone(int axis); native void SetAxisDeadZone(int axis, float zone); - + native int GetAxisMap(int axis); native void SetAxisMap(int axis, int gameaxis); - + native String GetName(); native int GetNumAxes(); native String GetAxisName(int axis); - + } class Menu : Object native ui version("2.4") @@ -139,7 +139,7 @@ class Menu : Object native ui version("2.4") native static void SetMouseCapture(bool on); native void Close(); native void ActivateMenu(); - + //============================================================================= // // @@ -156,7 +156,7 @@ class Menu : Object native ui version("2.4") AnimatedTransition = false; Animated = false; } - + //============================================================================= // // @@ -230,7 +230,7 @@ class Menu : Object native ui version("2.4") { SetCapture(true); } - + } else if (ev.type == UIEvent.Type_MouseMove) { @@ -259,7 +259,7 @@ class Menu : Object native ui version("2.4") { return false; } - + //============================================================================= // // @@ -289,7 +289,7 @@ class Menu : Object native ui version("2.4") } } } - + //============================================================================= // // @@ -330,34 +330,34 @@ class Menu : Object native ui version("2.4") { menuDelegate.PlaySound(snd); } - + deprecated("4.0") static void DrawConText (int color, int x, int y, String str) { screen.DrawText (ConFont, color, x, y, str, DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); } - + static Font OptionFont() { return NewSmallFont; } - + static int OptionHeight() { return OptionFont().GetHeight(); } - + static int OptionWidth(String s) { return OptionFont().StringWidth(s); } - + static void DrawOptionText(int x, int y, int color, String text, bool grayed = false) { String label = Stringtable.Localize(text); int overlay = grayed? Color(96,48,0,0) : 0; screen.DrawText (OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); } - + } diff --git a/wadsrc/static/zscript/engine/ui/menu/menucustomize.zs b/wadsrc/static/zscript/engine/ui/menu/menucustomize.zs index 75b114e54..390a2a703 100644 --- a/wadsrc/static/zscript/engine/ui/menu/menucustomize.zs +++ b/wadsrc/static/zscript/engine/ui/menu/menucustomize.zs @@ -7,11 +7,11 @@ class MenuDelegateBase ui if (drawit) screen.DrawText(fnt, OptionMenuSettings.mTitleColor, (screen.GetWidth() - fnt.StringWidth(title) * CleanXfac_1) / 2, 10 * CleanYfac_1, title, DTA_CleanNoMove_1, true); return (y + fnt.GetHeight()) * CleanYfac_1; // return is spacing in screen pixels. } - + virtual void PlaySound(Name sound) { } - + virtual bool DrawSelector(ListMenuDescriptor desc) { return false; @@ -21,7 +21,7 @@ class MenuDelegateBase ui { // overriding this allows to execute special actions when the menu closes } - + virtual Font PickFont(Font fnt) { if (generic_ui || !fnt) return NewSmallFont; diff --git a/wadsrc/static/zscript/engine/ui/menu/messagebox.zs b/wadsrc/static/zscript/engine/ui/menu/messagebox.zs index 94f8a38fd..8e76cae31 100644 --- a/wadsrc/static/zscript/engine/ui/menu/messagebox.zs +++ b/wadsrc/static/zscript/engine/ui/menu/messagebox.zs @@ -68,7 +68,7 @@ class MessageBoxMenu : Menu if (SmallFont && SmallFont.CanPrint(message) && SmallFont.CanPrint("$TXT_YES") && SmallFont.CanPrint("$TXT_NO")) textFont = SmallFont; else if (OriginalSmallFont && OriginalSmallFont.CanPrint(message) && OriginalSmallFont.CanPrint("$TXT_YES") && OriginalSmallFont.CanPrint("$TXT_NO")) textFont = OriginalSmallFont; } - + if (!textFont) { arrowFont = textFont = NewSmallFont; @@ -97,7 +97,7 @@ class MessageBoxMenu : Menu } Handler = native_handler; } - + //============================================================================= // // @@ -140,7 +140,7 @@ class MessageBoxMenu : Menu } } - + //============================================================================= // // @@ -227,7 +227,7 @@ class MessageBoxMenu : Menu } return Super.OnUIEvent(ev); } - + override bool OnInputEvent(InputEvent ev) { if (ev.type == InputEvent.Type_KeyDown) diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs index 91b79aae0..7338885bf 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs @@ -55,6 +55,9 @@ class OptionMenuDescriptor : MenuDescriptor native native int mIndent; native int mPosition; native bool mDontDim; + native bool mDontBlur; + native bool mAnimatedTransition; + native bool mAnimated; native Font mFont; void Reset() @@ -65,7 +68,7 @@ class OptionMenuDescriptor : MenuDescriptor native mIndent = 0; mDontDim = 0; } - + //============================================================================= // // @@ -106,6 +109,9 @@ class OptionMenu : Menu mParentMenu = parent; mDesc = desc; DontDim = desc.mDontDim; + DontBlur = desc.mDontBlur; + AnimatedTransition = desc.mAnimatedTransition; + Animated = desc.mAnimated; let itemCount = mDesc.mItems.size(); if (itemCount > 0) @@ -133,7 +139,7 @@ class OptionMenu : Menu } } - + //============================================================================= // // @@ -149,7 +155,7 @@ class OptionMenu : Menu } return NULL; } - + //============================================================================= // @@ -193,7 +199,7 @@ class OptionMenu : Menu mDesc.mScrollPos += 2; VisBottom += 2; } - else + else if (VisBottom < mDesc.mItems.Size()-1) { mDesc.mScrollPos++; VisBottom++; @@ -201,6 +207,30 @@ class OptionMenu : Menu } return true; } + else if (ev.type == UIEvent.Type_Char) + { + int key = String.CharLower(ev.keyChar); + int itemsNumber = mDesc.mItems.Size(); + int direction = ev.IsAlt ? -1 : 1; + for (int i = 0; i < itemsNumber; ++i) + { + int index = (mDesc.mSelectedItem + direction * (i + 1) + itemsNumber) % itemsNumber; + if (!mDesc.mItems[index].Selectable()) continue; + String label = StringTable.Localize(mDesc.mItems[index].mLabel); + int firstLabelCharacter = String.CharLower(label.GetNextCodePoint(0)); + if (firstLabelCharacter == key) + { + mDesc.mSelectedItem = index; + break; + } + } + if (mDesc.mSelectedItem <= mDesc.mScrollTop + mDesc.mScrollPos + || mDesc.mSelectedItem > VisBottom) + { + int pagesize = VisBottom - mDesc.mScrollPos - mDesc.mScrollTop; + mDesc.mScrollPos = clamp(mDesc.mSelectedItem - mDesc.mScrollTop - 1, 0, mDesc.mItems.size() - pagesize - 1); + } + } return Super.OnUIEvent(ev); } @@ -260,7 +290,7 @@ class OptionMenu : Menu do { ++mDesc.mSelectedItem; - + if (CanScrollDown && mDesc.mSelectedItem == VisBottom) { mDesc.mScrollPos++; @@ -356,7 +386,7 @@ class OptionMenu : Menu return true; } - + //============================================================================= // // @@ -393,7 +423,7 @@ class OptionMenu : Menu return Super.MouseEvent(type, x, y); } - + //============================================================================= // // @@ -408,7 +438,7 @@ class OptionMenu : Menu mDesc.mItems[i].Ticker(); } } - + //============================================================================= // // @@ -509,12 +539,12 @@ class OptionMenu : Menu { mFocusControl = OptionMenuItem(fc); } - + override bool CheckFocus(MenuItemBase fc) { return mFocusControl == fc; } - + override void ReleaseFocus() { mFocusControl = NULL; diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs index 7ece14176..4733d5b3b 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs @@ -36,7 +36,7 @@ class OptionMenuItem : MenuItemBase { String mLabel; bool mCentered; - + protected void Init(String label, String command, bool center = false) { Super.Init(0, 0, command); @@ -48,11 +48,11 @@ class OptionMenuItem : MenuItemBase { Menu.DrawOptionText(x, y, color, text, grayed); } - + protected int drawLabel(int indent, int y, int color, bool grayed = false) { String label = Stringtable.Localize(mLabel); - + int x; int w = Menu.OptionWidth(label) * CleanXfac_1; if (!mCentered) x = indent - w; @@ -66,24 +66,24 @@ class OptionMenuItem : MenuItemBase Menu.DrawOptionText(indent + CursorSpace(), y, color, text, grayed); } - + int CursorSpace() { return (14 * CleanXfac_1); } - + override bool Selectable() { return true; } - + override int GetIndent() { if (mCentered) return 0; if (screen.GetWidth() < 640) return screen.GetWidth() / 2; return Menu.OptionWidth(Stringtable.Localize(mLabel)); } - + override bool MouseEvent(int type, int x, int y) { if (Selectable() && type == Menu.MOUSE_Release) @@ -147,7 +147,7 @@ class OptionMenuItemLabeledSubmenu : OptionMenuItemSubmenu override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); - + String text = mLabelCVar.GetString(); if (text.Length() == 0) text = Stringtable.Localize("$notset"); drawValue(indent, y, OptionMenuSettings.mFontColorValue, text); @@ -166,7 +166,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu private String ccmd; // do not allow access to this from the outside. bool mCloseOnSelect; private bool mUnsafe; - + OptionMenuItemCommand Init(String label, Name command, bool centered = false, bool closeonselect = false) { Super.Init(label, command, 0, centered); @@ -255,7 +255,7 @@ class OptionMenuItemOptionBase : OptionMenuItem 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) @@ -288,11 +288,11 @@ class OptionMenuItemOptionBase : OptionMenuItem { return 0; } - + virtual void SetSelection(int Selection) { } - + //============================================================================= override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { @@ -304,7 +304,7 @@ class OptionMenuItemOptionBase : OptionMenuItem int Selection = GetSelection(); String text = StringTable.Localize(OptionValues.GetText(mValues, Selection)); - if (text.Length() == 0) text = "Unknown"; + if (text.Length() == 0) text = StringTable.Localize("$TXT_UNKNOWN"); drawValue(indent, y, OptionMenuSettings.mFontColorValue, text, isGrayed()); return indent; } @@ -338,7 +338,7 @@ class OptionMenuItemOptionBase : OptionMenuItem } return true; } - + virtual bool isGrayed() { return mGrayCheck != null && !mGrayCheck.GetInt(); @@ -542,7 +542,7 @@ class OptionMenuItemControlBase : OptionMenuItem } return false; } - + void SendKey(int key) { mInput = key; @@ -717,7 +717,7 @@ class OptionMenuSliderBase : OptionMenuItem { return 0; } - + virtual void SetSliderValue(double val) { } @@ -862,7 +862,7 @@ class OptionMenuSliderBase : OptionMenuItem class OptionMenuItemSlider : OptionMenuSliderBase { CVar mCVar; - + OptionMenuItemSlider Init(String label, Name command, double min, double max, double step, int showval = 1, CVar graycheck = NULL) { Super.Init(label, min, max, step, showval, command, graycheck); @@ -941,11 +941,11 @@ class OptionMenuItemColorPicker : OptionMenuItem if (mCVar != null) { Menu.MenuSound("menu/choose"); - + // This code is a bit complicated because it should allow subclassing the // colorpicker menu. // New color pickers must inherit from the internal one to work here. - + let desc = MenuDescriptor.GetDescriptor('Colorpickermenu'); if (desc != NULL && (desc.mClass == null || desc.mClass is "ColorPickerMenu")) { @@ -1042,7 +1042,7 @@ class OptionMenuFieldBase : OptionMenuItem class OptionMenuItemTextField : OptionMenuFieldBase { TextEnterMenu mEnter; - + OptionMenuItemTextField Init (String label, Name command, CVar graycheck = null) { Super.Init(label, command, graycheck); @@ -1175,7 +1175,7 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider String TextZero; String TextNegOne; int mClickVal; - + OptionMenuItemScaleSlider Init(String label, Name command, double min, double max, double step, String zero, String negone = "") { Super.Init(label, command, min, max, step, 0); @@ -1204,7 +1204,7 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider } return indent; } - + override bool MouseEvent(int type, int x, int y) { int value = int(GetSliderValue()); @@ -1214,11 +1214,11 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider mClickVal = value; if (value <= 0) return false; return Super.MouseEvent(type, x, y); - + case Menu.MOUSE_Move: if (mClickVal <= 0) return false; return Super.MouseEvent(type, x, y); - + case Menu.MOUSE_Release: if (mClickVal <= 0) { @@ -1231,7 +1231,7 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider } return false; } - + } //============================================================================= diff --git a/wadsrc/static/zscript/engine/ui/menu/reverbedit.zs b/wadsrc/static/zscript/engine/ui/menu/reverbedit.zs index 65fa5158e..282fce55d 100644 --- a/wadsrc/static/zscript/engine/ui/menu/reverbedit.zs +++ b/wadsrc/static/zscript/engine/ui/menu/reverbedit.zs @@ -15,14 +15,14 @@ class ReverbEdit : OptionMenu super.Init(parent, desc); OnReturn(); } - + override void OnReturn() { string env; int id; - + [env, id] = GetSelectedEnvironment(); - + let li = GetItem('EvironmentName'); if (li != NULL) { @@ -126,7 +126,7 @@ class OptionMenuItemReverbSelect : OptionMenuItemSubMenu return self; } - + override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { int x = drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor); @@ -164,7 +164,7 @@ class OptionMenuItemReverbOption : OptionMenuItemOptionBase { return int(ReverbEdit.GetValue(mValIndex)); } - + override void SetSelection(int Selection) { ReverbEdit.SetValue(mValIndex, Selection); @@ -182,7 +182,7 @@ class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase int mValIndex; String mEditValue; TextEnterMenu mEnter; - + OptionMenuItemSliderReverbEditOption Init(String label, double min, double max, double step, int showval, int valindex) { Super.Init(label, min, max, step, showval); @@ -190,7 +190,7 @@ class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase mEnter = null; return self; } - + override double GetSliderValue() { @@ -201,7 +201,7 @@ class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase { ReverbEdit.SetValue(mValIndex, val); } - + override bool Selectable() { return !ReverbEdit.GrayCheck(); @@ -228,7 +228,7 @@ class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase } return indent; } - + override bool MenuEvent (int mkey, bool fromcontroller) { if (mkey == Menu.MKEY_Enter) @@ -253,6 +253,6 @@ class OptionMenuItemSliderReverbEditOption : OptionMenuSliderBase return Super.MenuEvent(mkey, fromcontroller); } - + } diff --git a/wadsrc/static/zscript/engine/ui/menu/textentermenu.zs b/wadsrc/static/zscript/engine/ui/menu/textentermenu.zs index 6fc7abe02..9a83deb50 100644 --- a/wadsrc/static/zscript/engine/ui/menu/textentermenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/textentermenu.zs @@ -38,7 +38,7 @@ class TextEnterMenu : Menu { const INPUTGRID_WIDTH = 13; const INPUTGRID_HEIGHT = 5; - + const Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-=.,!?@'\":;[]()<>^#$%&*/_ \b"; String mEnterString; @@ -50,7 +50,7 @@ class TextEnterMenu : Menu int CursorSize; bool AllowColors; Font displayFont; - + //============================================================================= // // @@ -106,13 +106,13 @@ class TextEnterMenu : Menu { return mEnterString; } - + override bool TranslateKeyboardEvents() { return mInputGridOkay; } - - + + //============================================================================= // // @@ -303,7 +303,7 @@ class TextEnterMenu : Menu return false; } - + //============================================================================= // // @@ -375,5 +375,5 @@ class TextEnterMenu : Menu } Super.Drawer(); } - + } diff --git a/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs b/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs index 86f93773c..b00af3fde 100644 --- a/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs +++ b/wadsrc/static/zscript/engine/ui/statusbar/statusbarcore.zs @@ -23,22 +23,22 @@ class StatusBarCore native ui DI_MIRROR = 0x1000, // flip the texture horizontally, like a mirror DI_ITEM_RELCENTER = 0x2000, DI_MIRRORY = 0x40000000, - + DI_SCREEN_AUTO = 0, // decide based on given offsets. DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect - + DI_SCREEN_TOP = DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VCENTER = 0x8000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_BOTTOM = 0x10000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VOFFSET = 0x18000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_VMASK = 0x18000 | DI_SCREEN_MANUAL_ALIGN, - + DI_SCREEN_LEFT = DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HCENTER = 0x20000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_RIGHT = 0x40000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HOFFSET = 0x60000 | DI_SCREEN_MANUAL_ALIGN, DI_SCREEN_HMASK = 0x60000 | DI_SCREEN_MANUAL_ALIGN, - + DI_SCREEN_LEFT_TOP = DI_SCREEN_TOP | DI_SCREEN_LEFT, DI_SCREEN_RIGHT_TOP = DI_SCREEN_TOP | DI_SCREEN_RIGHT, DI_SCREEN_LEFT_BOTTOM = DI_SCREEN_BOTTOM | DI_SCREEN_LEFT, @@ -49,21 +49,21 @@ class StatusBarCore native ui DI_SCREEN_CENTER_TOP = DI_SCREEN_TOP | DI_SCREEN_HCENTER, DI_SCREEN_CENTER_BOTTOM = DI_SCREEN_BOTTOM | DI_SCREEN_HCENTER, DI_SCREEN_OFFSETS = DI_SCREEN_HOFFSET | DI_SCREEN_VOFFSET, - + DI_ITEM_AUTO = 0, // equivalent with bottom center, which is the default alignment. - + DI_ITEM_TOP = 0x80000, DI_ITEM_VCENTER = 0x100000, DI_ITEM_BOTTOM = 0, // this is the default vertical alignment DI_ITEM_VOFFSET = 0x180000, DI_ITEM_VMASK = 0x180000, - + DI_ITEM_LEFT = 0x200000, DI_ITEM_HCENTER = 0, // this is the default horizontal alignment DI_ITEM_RIGHT = 0x400000, DI_ITEM_HOFFSET = 0x600000, DI_ITEM_HMASK = 0x600000, - + DI_ITEM_LEFT_TOP = DI_ITEM_TOP|DI_ITEM_LEFT, DI_ITEM_RIGHT_TOP = DI_ITEM_TOP|DI_ITEM_RIGHT, DI_ITEM_LEFT_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_LEFT, @@ -71,7 +71,7 @@ class StatusBarCore native ui DI_ITEM_CENTER = DI_ITEM_VCENTER|DI_ITEM_HCENTER, DI_ITEM_CENTER_BOTTOM = DI_ITEM_BOTTOM|DI_ITEM_HCENTER, DI_ITEM_OFFSETS = DI_ITEM_HOFFSET|DI_ITEM_VOFFSET, - + DI_TEXT_ALIGN_LEFT = 0, DI_TEXT_ALIGN_RIGHT = 0x800000, DI_TEXT_ALIGN_CENTER = 0x1000000, @@ -94,7 +94,7 @@ class StatusBarCore native ui FNF_WHENNOTZERO = 0x1, FNF_FILLZEROS = 0x2, } - + // These are block properties for the drawers. A child class can set them to have a block of items use the same settings. native double Alpha; native Vector2 drawOffset; // can be set by subclasses to offset drawing operations @@ -118,17 +118,17 @@ class StatusBarCore native ui native double, double, double, double TransformRect(double x, double y, double w, double h, int flags = 0); native void Fill(Color col, double x, double y, double w, double h, int flags = 0); native void SetClipRect(double x, double y, double w, double h, int flags = 0); - + native void SetSize(int height, int vwidth, int vheight, int hwidth = -1, int hheight = -1); native Vector2 GetHUDScale(); native void BeginStatusBar(bool forceScaled = false, int resW = -1, int resH = -1, int rel = -1); native void BeginHUD(double Alpha = 1., bool forcescaled = false, int resW = -1, int resH = -1); - + void ClearClipRect() { screen.ClearClipRect(); } - + //============================================================================ // // Returns how much the status bar's graphics extend into the view @@ -137,7 +137,7 @@ class StatusBarCore native ui // by the element requesting this information. // //============================================================================ - + virtual int GetProtrusion(double scaleratio) const { return 0; @@ -156,7 +156,7 @@ class LinearValueInterpolator : Object { int mCurrentValue; int mMaxChange; - + static LinearValueInterpolator Create(int startval, int maxchange) { let v = new("LinearValueInterpolator"); @@ -164,12 +164,12 @@ class LinearValueInterpolator : Object v.mMaxChange = maxchange; return v; } - + void Reset(int value) { mCurrentValue = value; } - + // This must be called periodically in the status bar's Tick function. // Do not call this in the Draw function because that may skip some frames! void Update(int destvalue) @@ -183,7 +183,7 @@ class LinearValueInterpolator : Object mCurrentValue = min(destvalue, mCurrentValue + mMaxChange); } } - + // This must be called in the draw function to retrieve the value for output. int GetValue() { @@ -197,8 +197,8 @@ class DynamicValueInterpolator : Object int mMinChange; int mMaxChange; double mChangeFactor; - - + + static DynamicValueInterpolator Create(int startval, double changefactor, int minchange, int maxchange) { let v = new("DynamicValueInterpolator"); @@ -208,12 +208,12 @@ class DynamicValueInterpolator : Object v.mChangeFactor = changefactor; return v; } - + void Reset(int value) { mCurrentValue = value; } - + // This must be called periodically in the status bar's Tick function. // Do not call this in the Draw function because that may skip some frames! void Update(int destvalue) @@ -228,7 +228,7 @@ class DynamicValueInterpolator : Object mCurrentValue = min(destvalue, mCurrentValue + diff); } } - + // This must be called in the draw function to retrieve the value for output. int GetValue() { diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index 7492ea2b0..6da39d39f 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -124,6 +124,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) {} // @@ -148,4 +149,5 @@ 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); + 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 97ba5b637..e88343ec2 100644 --- a/wadsrc/static/zscript/level_compatibility.zs +++ b/wadsrc/static/zscript/level_compatibility.zs @@ -964,6 +964,14 @@ class LevelCompatibility : LevelPostProcessor break; } + case 'FAA0550BE9923B3A3332B4F7DB897A4A': // heretic.wad e2m7 + { + // missing texture + TextureID looserck = TexMan.CheckForTexture("LOOSERCK", TexMan.Type_Wall); + SetWallTextureID( 629, Line.back, Side.top, looserck); + break; + } + case 'CA3773ED313E8899311F3DD0CA195A68': // heretic.wad e3m6 { // Quartz flask outside of map @@ -987,6 +995,13 @@ class LevelCompatibility : LevelPostProcessor break; } + case '30D1480A6D4F3A3153739D4CCF659C4E': // heretic.wad E4M8 + { + // multiplayer teleporter prevents exit on cooperative + SetThingFlags(78,MTF_DEATHMATCH); + break; + } + case '6CDA2721AA1076F063557CF89D88E92B': // hexen.wad map08 { // Amulet of warding accidentally shifted outside of map @@ -2136,6 +2151,13 @@ class LevelCompatibility : LevelPostProcessor SetLineFlags(6842, 0, Line.ML_BLOCKING); break; } + + case '50E394239FF64264950D11883E933553': // 1024.wad map05 + { + // Change duplicate player 2 start to player 3 start + SetThingEdNum(59, 3); + break; + } } } } diff --git a/wadsrc/static/zscript/level_postprocessor.zs b/wadsrc/static/zscript/level_postprocessor.zs index 93ee8343d..930b17531 100644 --- a/wadsrc/static/zscript/level_postprocessor.zs +++ b/wadsrc/static/zscript/level_postprocessor.zs @@ -12,6 +12,7 @@ class LevelPostProcessor native play protected native void ClearLineIDs(int line); protected native void AddLineID(int line, int tag); protected native void OffsetSectorPlane(int sector, int plane, double offset); + protected native void SetSectorPlane(int sector, int plane, vector3 normal, double d); const SKILLS_ALL = 31; const MODES_ALL = MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; @@ -47,6 +48,9 @@ class LevelPostProcessor native play protected native void SetThingStringArgument(uint thing, Name value); protected native void SetVertex(uint vertex, double x, double y); + protected native double, bool GetVertexZ(uint vertex, int plane); + protected native void SetVertexZ(uint vertex, int plane, double z); + protected native void RemoveVertexZ(uint vertex, int plane); protected native void SetLineVertexes(uint Line, uint v1, uint v2); protected native void FlipLineSideRefs(uint Line); protected native void SetLineSectorRef(uint line, uint side, uint sector); diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index f0cfce1c0..e7f3044ff 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -28,11 +28,52 @@ struct SectorPortal native play native Actor mSkybox; }; +struct LinePortal native play +{ + enum EType + { + PORTT_VISUAL, + PORTT_TELEPORT, + PORTT_INTERACTIVE, + PORTT_LINKED, + PORTT_LINKEDEE // Eternity compatible definition which uses only one line ID and a different anchor type to link to. + }; + + enum EFlags + { + PORTF_VISIBLE = 1, + PORTF_PASSABLE = 2, + PORTF_SOUNDTRAVERSE = 4, + PORTF_INTERACTIVE = 8, + PORTF_POLYOBJ = 16, + + PORTF_TYPETELEPORT = PORTF_VISIBLE | PORTF_PASSABLE | PORTF_SOUNDTRAVERSE, + PORTF_TYPEINTERACTIVE = PORTF_VISIBLE | PORTF_PASSABLE | PORTF_SOUNDTRAVERSE | PORTF_INTERACTIVE, + }; + + enum EAlignment + { + PORG_ABSOLUTE, // does not align at all. z-ccoordinates must match. + PORG_FLOOR, + 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; +} struct Vertex native play { native readonly Vector2 p; - native clearscope int Index(); + native clearscope int Index() const; } struct Side native play @@ -77,44 +118,44 @@ struct Side native play native int16 Light; native uint16 Flags; - native TextureID GetTexture(int which); + native clearscope TextureID GetTexture(int which) const; native void SetTexture(int which, TextureID tex); native void SetTextureXOffset(int which, double offset); - native double GetTextureXOffset(int which); + native clearscope double GetTextureXOffset(int which) const; native void AddTextureXOffset(int which, double delta); native void SetTextureYOffset(int which, double offset); - native double GetTextureYOffset(int which); + native clearscope double GetTextureYOffset(int which) const; native void AddTextureYOffset(int which, double delta); native void SetTextureXScale(int which, double scale); - native double GetTextureXScale(int which); + native clearscope double GetTextureXScale(int which) const; native void MultiplyTextureXScale(int which, double delta); native void SetTextureYScale(int which, double scale); - native double GetTextureYScale(int which); + native clearscope double GetTextureYScale(int which) const; native void MultiplyTextureYScale(int which, double delta); - native int GetTextureFlags(int tier); + native clearscope int GetTextureFlags(int tier) const; native void ChangeTextureFlags(int tier, int And, int Or); native void SetSpecialColor(int tier, int position, Color scolor, bool useowncolor = true); - native Color GetAdditiveColor(int tier); + native clearscope Color GetAdditiveColor(int tier) const; native void SetAdditiveColor(int tier, Color color); native void EnableAdditiveColor(int tier, bool enable); native void SetColorization(int tier, Name cname); //native DInterpolation *SetInterpolation(int position); //native void StopInterpolation(int position); - native clearscope Vertex V1(); - native clearscope Vertex V2(); + native clearscope Vertex V1() const; + native clearscope Vertex V2() const; - native clearscope int Index(); + native clearscope int Index() const; - int GetUDMFInt(Name nm) + clearscope int GetUDMFInt(Name nm) const { return Level.GetUDMFInt(LevelLocals.UDMF_Side, Index(), nm); } - double GetUDMFFloat(Name nm) + clearscope double GetUDMFFloat(Name nm) const { return Level.GetUDMFFloat(LevelLocals.UDMF_Side, Index(), nm); } - String GetUDMFString(Name nm) + clearscope String GetUDMFString(Name nm) const { return Level.GetUDMFString(LevelLocals.UDMF_Side, Index(), nm); } @@ -186,28 +227,32 @@ struct Line native play native readonly int health; native readonly int healthgroup; - native bool isLinePortal(); - native bool isVisualPortal(); - native Line getPortalDestination(); - native int getPortalAlignment(); - native clearscope int Index(); + native clearscope bool isLinePortal() const; + native clearscope bool isVisualPortal() const; + native clearscope Line getPortalDestination() const; + native clearscope int getPortalFlags() const; + native clearscope int getPortalAlignment() const; + native clearscope int getPortalType() const; + native clearscope Vector2 getPortalDisplacement() const; + native clearscope double getPortalAngleDiff() const; + 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); - int GetUDMFInt(Name nm) + clearscope int GetUDMFInt(Name nm) const { return Level.GetUDMFInt(LevelLocals.UDMF_Line, Index(), nm); } - double GetUDMFFloat(Name nm) + clearscope double GetUDMFFloat(Name nm) const { return Level.GetUDMFFloat(LevelLocals.UDMF_Line, Index(), nm); } - String GetUDMFString(Name nm) + clearscope String GetUDMFString(Name nm) const { return Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm); } - native clearscope int GetHealth(); + native clearscope int GetHealth() const; native void SetHealth(int newhealth); } @@ -217,15 +262,15 @@ struct SecPlane native play native double D; native double negiC; - native bool isSlope() const; - native int PointOnSide(Vector3 pos) const; + native clearscope bool isSlope() const; + native clearscope int PointOnSide(Vector3 pos) const; native clearscope double ZatPoint (Vector2 v) const; - native double ZatPointDist(Vector2 v, double dist) const; - native bool isEqual(Secplane other) const; + native clearscope double ZatPointDist(Vector2 v, double dist) const; + native clearscope bool isEqual(Secplane other) const; native void ChangeHeight(double hdiff); - native double GetChangedHeight(double hdiff) const; - native double HeightDiff(double oldd, double newd = 1e37) const; - native double PointToDist(Vector2 xy, double z) const; + 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; } struct F3DFloor native play @@ -275,7 +320,7 @@ struct F3DFloor native play native readonly int alpha; - native TextureID GetTexture(int pos); + native clearscope TextureID GetTexture(int pos) const; } // This encapsulates all info Doom's original 'special' field contained - for saving and transferring. @@ -428,15 +473,15 @@ struct Sector native play native readonly int sectornum; - native clearscope int Index(); + native clearscope int Index() const; - native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); - native double, Sector, F3DFloor NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0); + native clearscope double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0) const; + native clearscope double, Sector, F3DFloor NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0) const; - native F3DFloor Get3DFloor(int index); - native int Get3DFloorCount(); - native Sector GetAttached(int index); - native int GetAttachedCount(); + native clearscope F3DFloor Get3DFloor(int index) const; + native clearscope int Get3DFloorCount() const; + native clearscope Sector GetAttached(int index) const; + native clearscope int GetAttachedCount() const; native void RemoveForceField(); deprecated("3.8", "Use Level.PointInSector instead") static clearscope Sector PointInSector(Vector2 pt) @@ -444,109 +489,110 @@ struct Sector native play return level.PointInSector(pt); } - native bool PlaneMoving(int pos); - native int GetFloorLight(); - native int GetCeilingLight(); - native Sector GetHeightSec(); + native clearscope bool PlaneMoving(int pos) const; + native clearscope int GetFloorLight() const; + native clearscope int GetCeilingLight() const; + native clearscope Sector GetHeightSec() const; native void TransferSpecial(Sector model); - native void GetSpecial(out SecSpecial spec); + native clearscope void GetSpecial(out SecSpecial spec) const; native void SetSpecial( SecSpecial spec); - native int GetTerrain(int pos); + native clearscope int GetTerrain(int pos) const; + native clearscope TerrainDef GetFloorTerrain(int pos) const; // Gets the terraindef from floor/ceiling (see EPlane const). native void CheckPortalPlane(int plane); - native double, Sector HighestCeilingAt(Vector2 a); - native double, Sector LowestFloorAt(Vector2 a); - native double, double GetFriction(int plane); + native clearscope double, Sector HighestCeilingAt(Vector2 a) const; + native clearscope double, Sector LowestFloorAt(Vector2 a) const; + native clearscope double, double GetFriction(int plane) const; native void SetXOffset(int pos, double o); native void AddXOffset(int pos, double o); - native double GetXOffset(int pos); + native clearscope double GetXOffset(int pos) const; native void SetYOffset(int pos, double o); native void AddYOffset(int pos, double o); - native double GetYOffset(int pos, bool addbase = true); + native clearscope double GetYOffset(int pos, bool addbase = true) const; native void SetXScale(int pos, double o); - native double GetXScale(int pos); + native clearscope double GetXScale(int pos) const; native void SetYScale(int pos, double o); - native double GetYScale(int pos); + native clearscope double GetYScale(int pos) const; native void SetAngle(int pos, double o); - native double GetAngle(int pos, bool addbase = true); + native clearscope double GetAngle(int pos, bool addbase = true) const; native void SetBase(int pos, double y, double o); native void SetAlpha(int pos, double o); - native double GetAlpha(int pos); - native int GetFlags(int pos); - native int GetVisFlags(int pos); + native clearscope double GetAlpha(int pos) const; + native clearscope int GetFlags(int pos) const; + native clearscope int GetVisFlags(int pos) const; native void ChangeFlags(int pos, int And, int Or); - native int GetPlaneLight(int pos); + native clearscope int GetPlaneLight(int pos) const; native void SetPlaneLight(int pos, int level); native void SetColor(color c, int desat = 0); native void SetFade(color c); native void SetFogDensity(int dens); - native double GetGlowHeight(int pos); - native color GetGlowColor(int pos); + native clearscope double GetGlowHeight(int pos) const; + native clearscope color GetGlowColor(int pos) const; native void SetGlowHeight(int pos, double height); native void SetGlowColor(int pos, color color); native void SetSpecialColor(int pos, color color); native void SetAdditiveColor(int pos, Color color); native void SetColorization(int tier, Name cname); - native TextureID GetTexture(int pos); + native clearscope TextureID GetTexture(int pos) const; native void SetTexture(int pos, TextureID tex, bool floorclip = true); - native double GetPlaneTexZ(int pos); + native clearscope double GetPlaneTexZ(int pos) const; native void SetPlaneTexZ(int pos, double val, bool dirtify = false); // This mainly gets used by init code. The only place where it must set the vertex to dirty is the interpolation code. native void ChangeLightLevel(int newval); native void SetLightLevel(int newval); - native int GetLightLevel(); + native clearscope int GetLightLevel() const; native void AdjustFloorClip(); - native bool IsLinked(Sector other, bool ceiling); + native clearscope bool IsLinked(Sector other, bool ceiling) const; - native bool PortalBlocksView(int plane); - native bool PortalBlocksSight(int plane); - native bool PortalBlocksMovement(int plane); - native bool PortalBlocksSound(int plane); - native bool PortalIsLinked(int plane); + native clearscope bool PortalBlocksView(int plane) const; + native clearscope bool PortalBlocksSight(int plane) const; + native clearscope bool PortalBlocksMovement(int plane) const; + native clearscope bool PortalBlocksSound(int plane) const; + native clearscope bool PortalIsLinked(int plane) const; native void ClearPortal(int plane); - native double GetPortalPlaneZ(int plane); - native Vector2 GetPortalDisplacement(int plane); - native int GetPortalType(int plane); - native int GetOppositePortalGroup(int plane); - native double CenterFloor(); - native double CenterCeiling(); + native clearscope double GetPortalPlaneZ(int plane) const; + native clearscope Vector2 GetPortalDisplacement(int plane) const; + native clearscope int GetPortalType(int plane) const; + native clearscope int GetOppositePortalGroup(int plane) const; + native clearscope double CenterFloor() const; + native clearscope double CenterCeiling() const; native int MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush, bool instant = false); native int MoveCeiling(double speed, double dest, int crush, int direction, bool hexencrush); - native Sector NextSpecialSector(int type, Sector prev); - native double, Vertex FindLowestFloorSurrounding(); - native double, Vertex FindHighestFloorSurrounding(); - native double, Vertex FindNextHighestFloor(); - native double, Vertex FindNextLowestFloor(); - native double, Vertex FindLowestCeilingSurrounding(); - native double, Vertex FindHighestCeilingSurrounding(); - native double, Vertex FindNextLowestCeiling(); - native double, Vertex FindNextHighestCeiling(); + native clearscope Sector NextSpecialSector(int type, Sector prev) const; + native clearscope double, Vertex FindLowestFloorSurrounding() const; + native clearscope double, Vertex FindHighestFloorSurrounding() const; + native clearscope double, Vertex FindNextHighestFloor() const; + native clearscope double, Vertex FindNextLowestFloor() const; + native clearscope double, Vertex FindLowestCeilingSurrounding() const; + native clearscope double, Vertex FindHighestCeilingSurrounding() const; + native clearscope double, Vertex FindNextLowestCeiling() const; + native clearscope double, Vertex FindNextHighestCeiling() const; - native double FindShortestTextureAround(); - native double FindShortestUpperAround(); - native Sector FindModelFloorSector(double floordestheight); - native Sector FindModelCeilingSector(double floordestheight); - native int FindMinSurroundingLight(int max); - native double, Vertex FindLowestCeilingPoint(); - native double, Vertex FindHighestFloorPoint(); + native clearscope double FindShortestTextureAround() const; + native clearscope double FindShortestUpperAround() const; + native clearscope Sector FindModelFloorSector(double floordestheight) const; + native clearscope Sector FindModelCeilingSector(double floordestheight) const; + native clearscope int FindMinSurroundingLight(int max) const; + native clearscope double, Vertex FindLowestCeilingPoint() const; + native clearscope double, Vertex FindHighestFloorPoint() const; native void SetEnvironment(String env); native void SetEnvironmentID(int envnum); native SeqNode StartSoundSequenceID (int chan, int sequence, int type, int modenum, bool nostop = false); native SeqNode StartSoundSequence (int chan, Name seqname, int modenum); - native SeqNode CheckSoundSequence (int chan); + native clearscope SeqNode CheckSoundSequence (int chan) const; native void StopSoundSequence(int chan); - native bool IsMakingLoopingSound (); + native clearscope bool IsMakingLoopingSound () const; - bool isSecret() + clearscope bool isSecret() const { return !!(Flags & SECF_SECRET); } - bool wasSecret() + clearscope bool wasSecret() const { return !!(Flags & SECF_WASSECRET); } @@ -556,15 +602,15 @@ struct Sector native play Flags &= ~SECF_SECRET; } - int GetUDMFInt(Name nm) + clearscope int GetUDMFInt(Name nm) const { return Level.GetUDMFInt(LevelLocals.UDMF_Sector, Index(), nm); } - double GetUDMFFloat(Name nm) + clearscope double GetUDMFFloat(Name nm) const { return Level.GetUDMFFloat(LevelLocals.UDMF_Sector, Index(), nm); } - String GetUDMFString(Name nm) + clearscope String GetUDMFString(Name nm) const { return Level.GetUDMFString(LevelLocals.UDMF_Sector, Index(), nm); } @@ -598,7 +644,7 @@ struct Sector native play } - native clearscope int GetHealth(SectorPart part); + native clearscope int GetHealth(SectorPart part) const; native void SetHealth(SectorPart part, int newhealth); } diff --git a/wadsrc/static/zscript/ui/intermission.zs b/wadsrc/static/zscript/ui/intermission.zs new file mode 100644 index 000000000..657be98ba --- /dev/null +++ b/wadsrc/static/zscript/ui/intermission.zs @@ -0,0 +1,61 @@ + + +class IntermissionController native ui +{ + // This is mostly a black box to the native intermission code. + // May be scriptified later, but right now we do not need it. + + native void Start(); + native bool Responder(InputEvent ev); + native bool Ticker(); + native void Drawer(); + native bool NextPage(); +} + +// Wrapper to play the native intermissions within a screen job. +class IntermissionScreenJob : ScreenJob +{ + IntermissionController controller; + + ScreenJob Init(IntermissionController ctrl, bool allowwipe) + { + Super.Init(); + if (allowwipe && wipetype != 0) flags = wipetype << ScreenJob.transition_shift; + controller = ctrl; + return self; + } + + override void Start() { controller.Start(); } + override bool OnEvent(InputEvent evt) { return controller.Responder(evt); } + override void OnTick() { if (!controller.Ticker()) jobstate = finished; } + override void Draw(double smoothratio) { controller.Drawer(); } + + override void OnDestroy() + { + if (controller) + controller.Destroy(); + Super.OnDestroy(); + } +} + + +class DoomCutscenes ui +{ + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + static void BuildMapTransition(ScreenJobRunner runner, IntermissionController inter, StatusScreen status) + { + if (status) + { + runner.Append(status); + } + if (inter) + { + runner.Append(new("IntermissionScreenJob").Init(inter, status != null)); + } + } +} diff --git a/wadsrc/static/zscript/ui/menu/conversationmenu.zs b/wadsrc/static/zscript/ui/menu/conversationmenu.zs index a849269bc..1b1d3c011 100644 --- a/wadsrc/static/zscript/ui/menu/conversationmenu.zs +++ b/wadsrc/static/zscript/ui/menu/conversationmenu.zs @@ -497,14 +497,13 @@ class ConversationMenu : Menu double sx = (x - 160.0) * CleanXfac + (screen.GetWidth() * 0.5); double sy = (y - 100.0) * CleanYfac + (screen.GetHeight() * 0.5); - ypositions.Push(sy); - screen.DrawText(displayFont, Font.CR_GREEN, sx / fontScale, sy / fontScale, mResponseLines[i], DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight); if (i == mResponses[response]) { String tbuf; + ypositions.Push(sy); response++; tbuf = String.Format("%d.", response); x = 50 - displayFont.StringWidth(tbuf); diff --git a/wadsrc/static/zscript/ui/menu/doommenus.zs b/wadsrc/static/zscript/ui/menu/doommenus.zs index 969437a8b..9affca2bc 100644 --- a/wadsrc/static/zscript/ui/menu/doommenus.zs +++ b/wadsrc/static/zscript/ui/menu/doommenus.zs @@ -4,7 +4,7 @@ class GameplayMenu : OptionMenu { Super.Drawer(); - String s = String.Format("dmflags = %d dmflags2 = %d", dmflags, dmflags2); + String s = String.Format("dmflags = %d dmflags2 = %d dmflags3 = %d", dmflags, dmflags2, dmflags3); screen.DrawText (OptionFont(), OptionMenuSettings.mFontColorValue, (screen.GetWidth() - OptionWidth (s) * CleanXfac_1) / 2, 35 * CleanXfac_1, s, DTA_CleanNoMove_1, true); diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen.zs b/wadsrc/static/zscript/ui/statscreen/statscreen.zs index fe46b7f6a..500185ee0 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen.zs @@ -1,6 +1,6 @@ // Note that the status screen needs to run in 'play' scope! -class InterBackground native play version("2.5") +class InterBackground native ui version("2.5") { native static InterBackground Create(wbstartstruct wbst); native virtual bool LoadBackground(bool isenterpic); @@ -9,7 +9,7 @@ class InterBackground native play version("2.5") } // This is obsolete. Hopefully this was never used... -struct PatchInfo play version("2.5") +struct PatchInfo ui version("2.5") { Font mFont; deprecated("3.8") TextureID mPatch; @@ -39,7 +39,7 @@ struct PatchInfo play version("2.5") }; -class StatusScreen abstract play version("2.5") +class StatusScreen : ScreenJob abstract version("2.5") { enum EValues { @@ -105,7 +105,7 @@ class StatusScreen abstract play version("2.5") float shadowalpha; PatchInfo mapname; - PatchInfo finished; + PatchInfo finishedp; PatchInfo entering; PatchInfo content; PatchInfo author; @@ -334,7 +334,7 @@ class StatusScreen abstract play version("2.5") if (!TexMan.OkForLocalization(finishedPatch, "$WI_FINISHED")) { - disp += finished.mFont.GetMaxAscender("$WI_FINISHED"); + disp += finishedp.mFont.GetMaxAscender("$WI_FINISHED"); } } else @@ -349,10 +349,10 @@ class StatusScreen abstract play version("2.5") // draw "Finished!" int statsy = multiplayer? NG_STATSY : SP_STATSY * scaleFactorY; - if (y < (statsy - finished.mFont.GetHeight()*3/4) * scaleFactorY) + if (y < (statsy - finishedp.mFont.GetHeight()*3/4) * scaleFactorY) { // don't draw 'finished' if the level name is too tall - y = DrawPatchOrText(y, finished, finishedPatch, "$WI_FINISHED"); + y = DrawPatchOrText(y, finishedp, finishedPatch, "$WI_FINISHED"); } return y; } @@ -681,7 +681,6 @@ class StatusScreen abstract play version("2.5") if (cnt == 0) { End(); - Level.WorldDone(); } } @@ -696,8 +695,7 @@ class StatusScreen abstract play version("2.5") if (wbs.next == "") { // Last map in episode - there is no next location! - End(); - Level.WorldDone(); + jobstate = finished; return; } @@ -787,7 +785,7 @@ class StatusScreen abstract play version("2.5") // ==================================================================== - // checkForAccelerate + // // Purpose: See if the player has hit either the attack or use key // or mouse button. If so we set acceleratestage to 1 and // all those display routines above jump right to the end. @@ -796,25 +794,24 @@ class StatusScreen abstract play version("2.5") // // ==================================================================== - protected void checkForAccelerate(void) + override bool OnEvent(InputEvent evt) { - int i; - - // check for button presses to skip delays - for (i = 0; i < MAXPLAYERS; i++) + if (evt.type == InputEvent.Type_KeyDown) { - PlayerInfo player = players[i]; - if (playeringame[i]) - { - if ((player.cmd.buttons ^ player.oldbuttons) && - ((player.cmd.buttons & player.oldbuttons) == player.oldbuttons) && player.Bot == NULL) - { - acceleratestage = 1; - playerready[i] = true; - } - player.oldbuttons = player.buttons; - } + accelerateStage = 1; + return true; } + return false; + } + + void nextStage() + { + accelerateStage = 1; + } + + // this one is no longer used, but still needed for old content referencing them. + deprecated("4.8") void checkForAccelerate() + { } // ==================================================================== @@ -833,11 +830,11 @@ class StatusScreen abstract play version("2.5") //==================================================================== // - // + // Two stage interface to allow redefining this class as a screen job // //==================================================================== - virtual void Ticker(void) + protected virtual void Ticker() { // counter for general background animation bcnt++; @@ -847,7 +844,6 @@ class StatusScreen abstract play version("2.5") StartMusic(); } - checkForAccelerate(); bg.updateAnimatedBack(); switch (CurState) @@ -865,18 +861,23 @@ class StatusScreen abstract play version("2.5") break; case LeavingIntermission: - // Hush, GCC. break; } } + override void OnTick() + { + Ticker(); + if (CurState == StatusScreen.LeavingIntermission) jobstate = finished; + } + //==================================================================== // // // //==================================================================== - virtual void Drawer (void) + protected virtual void Drawer() { switch (CurState) { @@ -897,6 +898,11 @@ class StatusScreen abstract play version("2.5") } } + override void Draw(double smoothratio) + { + Drawer(); + } + //==================================================================== // // @@ -924,7 +930,7 @@ class StatusScreen abstract play version("2.5") } entering.Init(gameinfo.mStatscreenEnteringFont); - finished.Init(gameinfo.mStatscreenFinishedFont); + finishedp.Init(gameinfo.mStatscreenFinishedFont); mapname.Init(gameinfo.mStatscreenMapNameFont); content.Init(gameinfo.mStatscreenContentFont); author.Init(gameinfo.mStatscreenAuthorFont); @@ -955,7 +961,6 @@ class StatusScreen abstract play version("2.5") scaleFactorY = CleanYfac; } - protected virtual void initStats() {} protected virtual void updateStats() {} protected virtual void drawStats() {} diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen_coop.zs b/wadsrc/static/zscript/ui/statscreen/statscreen_coop.zs index 47941066a..73b397c07 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen_coop.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen_coop.zs @@ -216,16 +216,8 @@ class CoopStatusScreen : StatusScreen } else if (ng_state == 12) { - int i; - for (i = 0; i < MAXPLAYERS; i++) - { - // If the player is in the game and not ready, stop checking - if (playeringame[i] && players[i].Bot == NULL && !playerready[i]) - break; - } - // All players are ready; proceed. - if ((i == MAXPLAYERS && acceleratestage) || autoskip) + if ((acceleratestage) || autoskip) { PlaySound("intermission/pastcoopstats"); initShowNextLoc(); @@ -311,7 +303,7 @@ class CoopStatusScreen : StatusScreen screen.Dim(player.GetDisplayColor(), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight); - if (playerready[i] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion + //if (playerready[i] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion screen.DrawTexture(readyico, true, x - (readysize.Y * CleanXfac), y, DTA_CleanNoMove, true); Color thiscolor = GetRowColor(player, i == consoleplayer); diff --git a/wadsrc/static/zscript/ui/statscreen/statscreen_dm.zs b/wadsrc/static/zscript/ui/statscreen/statscreen_dm.zs index 49ae54ed3..e768b9db2 100644 --- a/wadsrc/static/zscript/ui/statscreen/statscreen_dm.zs +++ b/wadsrc/static/zscript/ui/statscreen/statscreen_dm.zs @@ -124,16 +124,8 @@ class DeathmatchStatusScreen : StatusScreen } else if (ng_state == 6) { - int i; - for (i = 0; i < MAXPLAYERS; i++) - { - // If the player is in the game and not ready, stop checking - if (playeringame[i] && players[i].Bot == NULL && !playerready[i]) - break; - } - // All players are ready; proceed. - if ((i == MAXPLAYERS && acceleratestage) || doautoskip) + if ((acceleratestage) || doautoskip) { PlaySound("intermission/pastdmstats"); initShowNextLoc(); @@ -207,7 +199,7 @@ class DeathmatchStatusScreen : StatusScreen screen.Dim(player.GetDisplayColor(), 0.8, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight); - if (playerready[pnum] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion + //if (playerready[pnum] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion screen.DrawTexture(readyico, true, x - (readysize.X * CleanXfac), y, DTA_CleanNoMove, true); let thiscolor = GetRowColor(player, pnum == consoleplayer); @@ -247,4 +239,4 @@ class DeathmatchStatusScreen : StatusScreen String leveltime = Stringtable.Localize("$SCORE_LVLTIME") .. ": " .. String.Format("%02i:%02i:%02i", hours, minutes, seconds); drawTextScaled(displayFont, x, y, leveltime, FontScale, textcolor); } -} \ No newline at end of file +} diff --git a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs index deaedf553..69939da27 100644 --- a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs +++ b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs @@ -204,6 +204,18 @@ class AltHud ui ? String.Format("%i/%i/%i ", CPlayer.killcount, Level.killed_monsters, Level.total_monsters) : String.Format("%i/%i ", Level.killed_monsters, Level.total_monsters)); } + + if (hud_showtimestat) + { + String s; + let seconds = Thinker.Tics2Seconds(level.time); + if (seconds >= 3600) + s = String.Format("%02i:%02i:%02i", seconds / 3600, (seconds % 3600) / 60, seconds % 60); + else + s = String.Format("%02i:%02i", seconds / 60, seconds % 60); + DrawStatLine(x, y, "T:", s); + } + } } @@ -706,9 +718,10 @@ class AltHud ui // //--------------------------------------------------------------------------- - void DrawCoordinateEntry(int xpos, int ypos, String coordstr) + void DrawCoordinateEntry(int xpos, int ypos, String coordstr, Font fnt = nullptr) { - screen.DrawText(SmallFont, hudcolor_xyco, xpos, ypos, coordstr, + if (fnt == nullptr) fnt = SmallFont; + screen.DrawText(fnt, hudcolor_xyco, xpos, ypos, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); } @@ -717,7 +730,8 @@ class AltHud ui { Vector3 pos; String coordstr; - int h = SmallFont.GetHeight(); + let fnt = generic_ui ? NewSmallFont : SmallFont; + int h = fnt.GetHeight(); let mo = CPlayer.mo; if (!map_point_coordinates || !automapactive) @@ -730,7 +744,7 @@ class AltHud ui pos.z = Level.PointInSector(pos.xy).floorplane.ZatPoint(pos.xy); } - int xpos = hudwidth - SmallFont.StringWidth("X: -00000")-6; + int xpos = hudwidth - fnt.StringWidth("X: -00000")-6; int ypos = 18; if (withmapname) @@ -749,20 +763,20 @@ class AltHud ui ypos += 2 * hh + h; } - DrawCoordinateEntry(xpos, ypos, String.Format("X: %.0f", pos.X)); + DrawCoordinateEntry(xpos, ypos, String.Format("X: %.0f", pos.X), fnt); ypos += h; - DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", pos.Y)); + DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", pos.Y), fnt); ypos += h; - DrawCoordinateEntry(xpos, ypos, String.Format("Z: %.0f", pos.Z)); + DrawCoordinateEntry(xpos, ypos, String.Format("Z: %.0f", pos.Z), fnt); ypos += h; if (hud_showangles) { - DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", Actor.Normalize180(mo.Angle))); + DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", Actor.Normalize180(mo.Angle)), fnt); ypos += h; - DrawCoordinateEntry(xpos, ypos, String.Format("P: %.0f", Actor.Normalize180(mo.Pitch))); + DrawCoordinateEntry(xpos, ypos, String.Format("P: %.0f", Actor.Normalize180(mo.Pitch)), fnt); ypos += h; - DrawCoordinateEntry(xpos, ypos, String.Format("R: %.0f", Actor.Normalize180(mo.Roll))); + DrawCoordinateEntry(xpos, ypos, String.Format("R: %.0f", Actor.Normalize180(mo.Roll)), fnt); } } @@ -961,9 +975,31 @@ class AltHud ui let amstr = Level.FormatMapName(hudcolor_titl); font = generic_ui? NewSmallFont : SmallFont.CanPrint(amstr)? SmallFont : OriginalSmallFont; - screen.DrawText(font, Font.CR_BRICK, 2, hudheight - fonth - 1, amstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); + bottom = hudheight - fonth - 1; + + screen.DrawText(font, Font.CR_BRICK, 2, bottom, amstr, + DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); + + if (am_showcluster && (Level.clusterflags & Level.CLUSTER_HUB)) + { + let text = Level.GetClusterName(); + if (text != "") + { + bottom -= fonth; + screen.DrawText(font, Font.CR_ORANGE, 2, bottom, text, + DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); + } + } + if (am_showepisode) + { + let text = Level.GetEpisodeName(); + if (text != "") + { + bottom -= fonth; + screen.DrawText(font, Font.CR_RED, 2, bottom, text, + DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); + } + } DrawCoordinates(CPlayer, false); } diff --git a/wadsrc_extra/static/filter/chex.chex3/language.csv b/wadsrc_extra/static/filter/chex.chex3/language.csv index e94a52a2e..7ad2e3d6b 100644 --- a/wadsrc_extra/static/filter/chex.chex3/language.csv +++ b/wadsrc_extra/static/filter/chex.chex3/language.csv @@ -2,7 +2,7 @@ default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs Picked up a blue flemkey.,GOTBLUEFLEM,Flem = phlegm,,,Sebrán modrý slizoklíč.,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.,Zebrano niebieski flemowy klucz,Pegou uma flemchave azul.,,Ai ridicat flemcheia albastră.,Получен синий флемключ., Picked up a yellow flemkey.,GOTYELLOWFLEM,,,,Sebrán žlutý slizoklíč.,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.,Zebrano żółty flemowy klucz,Pegou uma flemchave amarela.,,Ai ridicat flemcheia galbenă.,Получен жёлтый флемключ., Picked up a red flemkey.,GOTREDFLEM,,,,Sebrán červený slizoklíč.,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.,Zebrano czerwony flemowy klucz,Pegou uma flemchave vermelha.,,Ai ridicat flemcheia roșie.,Получен красный флемключ., -Found Ultra Goggles,GOTGOGGLES,,,,Nalezeny ultrabrýle.,Ultrasichtbrille gefunden,,Trovis Plejajn Okulvitrojn.,Ultra Gafas encontradas,,Löysit ultralasit,Ultra-lunettes récupérées.,Ultraszemüveg felvéve.,,ウルトラゴーグル をみつけた,울트라 고글 사용.,Ultraroggles gevonden,Znaleziono Ultra Gogle,Achou um Ultra Óculos.,,Ai găsit Ultra Ochelarii,Получены Ультра-очки, +Found Ultra Goggles,GOTGOGGLES,,,,Nalezeny ultrabrýle.,Ultrasichtbrille gefunden,,Trovis Plejajn Okulvitrojn.,Ultra Gafas encontradas,,Löysit ultralasit,Ultra-lunettes récupérées.,Ultraszemüveg felvéve.,,ウルトラゴーグル をみつけた,울트라 고글 사용.,Ultraroggles gevonden,Znaleziono Ultra Gogle,Achou um Ultra Óculos.,,Ai găsit Ultra Ochelarii,Получены ультра-очки, You need a blue key to activate this object,PD_BLUECO,,,,Potřebuješ modrý klíč pro aktivaci tohoto objektu,"Du brauchst einen blauen Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas bluan ŝlosilon por aktivigi tion 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.,"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,Для активации нужен синий ключ,Треба вам плави кључ да бисте активирали овај предмет You need a red key to activate this object,PD_REDCO,,,,Potřebuješ červený klíč pro aktivaci tohoto objektu,"Du brauchst einen roten Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas ruĝan ŝlosilon por aktivigi tion 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.,"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,Для активации нужен красный ключ,Треба вам црвени кључ да бисте активирали овај предмет You need a yellow key to activate this object,PD_YELLOWCO,,,,Potřebuješ žlutý klíč pro aktivaci tohoto objektu,"Du brauchst einen gelben Schlüssel, um dieses Objekt zu aktivieren.",,Vi bezonas flavan ŝlosilon por aktivigi tion 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.,"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,Для активации нужен жёлтый ключ,Треба вам жути кључ да бисте активирали овај предмет @@ -13,7 +13,7 @@ Picked up a zorcher.,PICKUP_PISTOL_DROPPED,,,,Sebrán bzukr.,Zorcher genommen.,, Zorch and keys added,STSTR_KFAADDED,,,,Bzukr a klíče přidány,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,Dodano amunicję Zorch i klucze,Zorch e chaves adicionadas,,Zorcher și chei adăugate,Зорч и ключи получены, E1M1: Landing Zone,HUSTR_E1M1,,,,E1M1: Přistávací zóna,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: Strefa Lądowania,E1M1: Zona de Pouso,,E1M1: Zona de Aterizare,E1M1: Зона высадки, E1M2: Storage Facility,HUSTR_E1M2,,,,E1M2: Skladiště,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: Magazyn,E1M2: Depósito,,E1M2: Depozitul,E1M2: Хранилище, -E1M3: Laboratory,HUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Labor,,E1M3: Laboratorio,E1M3: Laboratorio,,E1M3: Laboratorio,E1M3: Laboratoire,E1M3: Laboratórium,E1M3: Laboratorio,E1M3: ラボラトリー,E1M3: 연구소,E1M3: Laboratorium,E1M3: Laboratorium Eksperymentalne,E1M3: Laboratório de Experimentos,,E1M3: Laboratorul,E1M3: Лаборатория, +E1M3: Laboratory,HUSTR_E1M3,,,,E1M3: Testovací laboratoř,E1M3: Labor,,E1M3: Laboratorio,E1M3: Laboratorio,,E1M3: Laboratorio,E1M3: Laboratoire,E1M3: Laboratórium,E1M3: Laboratorio,E1M3: ラボラトリー,E1M3: 연구소,E1M3: Laboratorium,E1M3: Laboratorium,E1M3: Laboratório de Experimentos,,E1M3: Laboratorul,E1M3: Лаборатория, E1M4: Arboretum,HUSTR_E1M4,,,,,,,E1M4: Arbejo,E1M4: Arboreto,,,E1M4: Arboretum,E1M4: Arborétum,E1M4: Arboreto,E1M4: じゅもく園,E1M4: 수목원,,E1M4: Arboretum,E1M4: Arvoredo,,E1M4: Arboretum,E1M4: Дендрарий, E1M5: Caverns of Bazoik,HUSTR_E1M5,,,,E1M5: Bazoikské jeskyně,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: Jaskinie Bazoik,E1M5: Cavernas de Bazoik,,E1M5: Cavernele lui Bazoik,E1M5: Пещеры Базоика, E2M1: Spaceport,HUSTR_E2M1,,,,E2M1: Kosmodrom,E2M1: Raumhafen,,E2M1: Kosmo-haveno,E2M1: Puerto Espacial,,E2M1: Avaruussatama,E2M1: Spatioport,E2M1: Űrkikötő,E2M1: Spazioporto,E2M1: スペースポート,E2M1: 우주공항,E2M1: Ruimtehaven,E2M1: Port Kosmiczny,E2M1: Espaçoporto,,E2M1: Portul Spațial,E2M1: Космодром, @@ -25,7 +25,7 @@ E3M1: Central Command,HUSTR_E3M1,,,,E3M1: Centrální velení,E3M1: Kommandozent 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: Организация Объединённых Хлопьев, E3M3: Villa Chex,HUSTR_E3M3,,,,,,,E3M3: Vilao Chex,,,,E3M3: Villa Chex,,,E3M3: チェックスのべっそう,E3M3: 책스 주택,,E3M3: Willa Chex,E3M3: Villa 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: Провинциальный парк, -E3M5: Meteor Spaceship,HUSTR_E3M5,,,,E3M5: Meteorová vesmírná loď,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: Statek Kosmiczny ""Meteor""",E3M5: Espaçonave Meteoro,,E3M5: Nava Spațială Meteor,E3M5: Космический корабль “Метеор”, +E3M5: Meteor Spaceship,HUSTR_E3M5,,,,E3M5: Meteorová vesmírná loď,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: Statek Kosmiczny ""Meteor""",E3M5: Espaçonave Meteoro,,E3M5: Nava Spațială Meteor,E3M5: Космический корабль «Метеор», Commonus,CC_ZOMBIE,,,,Obecnýs,,,Oftmukulo,,,,,Általánusz,,コモンズ,커머누스,,Pospolitus,,,Comun,Обыкновеннус, Bipedicus,CC_SHOTGUN,,,,Dvojnožus,,,Dupiedmukulo,,,,,Kétlábusz,,バイピディクス,바이피디쿠스,,,,,Biped,Двуножка, Bipedicus with Armor,CC_IMP,,,,Dvojnožus s brněním,Bipedicus mit Panzerung,,Kirasa Dupiedmukulo,Bipedicus con Armadura,,Panssaroitu bipedicus,Bipedicus avec Armure,Páncélozott kétlábusz,Bipedicus corazzato,アーマードバイピディクス,정예 바이피디쿠스,Bipedicus met harnas,Opancerzony Bipedicus,Bipedicus de Armadura,,Biped cu Armură,Бронированная двуножка, @@ -47,7 +47,7 @@ You need a yellow flemkey to open this door,PD_YELLOWF,,,,Potřebuješ žlutý s %o was hit by inter-dimensional slime!,OB_POWERSTRAND,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%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 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 was hit by inter-dimensional slime!,OB_KILLEDSELF,,,,%o byl@[ao_cs] zasažen@[ao_cs] mezidimenzionálním slizem!,%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 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 was boogered by a stridicus.,OB_STRIDICUS,,,,%o dostal@[ao_cs] holuby od běhakem.,%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 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 was gooed by a flem mine.,OB_FLEMMINE,,,,%o byl@[ao_cs] zablácen@[ao_cs] sliznou minou.,%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 è stata colpita da una bomba a flem.,%o はフレムマインに ヒドいめにあった。,%o 는(은) 플렘 지뢰에 의해 점액 범벅이 됐습니다.,%o werd door een Flemmijn getreiterd.,"%o został@[ao_pl] zabrejowan@[adj_pl] przez flemową minę. +%o was gooed by a flem mine.,OB_FLEMMINE,,,,%o byl@[ao_cs] zablácen@[ao_cs] sliznou minou.,%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 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 was slimed by a super cycloptis.,OB_SUPERCYCLOPTIS,,,,%o byl@[ao_cs] osliznut@[ao_cs] superkykloptem.,%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 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 was defeated by a Maximus.,OB_MAXIMUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Maximem.,%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 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 проиграл Максимусу., @@ -55,7 +55,7 @@ You need a yellow flemkey to open this door,PD_YELLOWF,,,,Potřebuješ žlutý s %o was slimed by a Quadrumpus.,OB_QUADRUMPUS,,,,%o byl@[ao_cs] zahleněn@[ao_cs] Čtyřzadkem.,%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 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 was defeated by the Flembomination.,OB_FLEMBOMINATION,,,,%o byl@[ao_cs] poražen@[ao_cs] Slizavností.,%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 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 was defeated by Lord Snotfolus.,OB_SNOTFOLUS,,,,%o byl@[ao_cs] poražen@[ao_cs] Lordem Hlenfujem.,%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 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 was hit by %k's propulsor.,OB_MPR_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráče %k.,%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 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 was hit by %k's propulsor.,OB_MPR_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráče %k.,%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 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 was lazzed by %k.,OB_MPBFG_SPLASH,,,,%o byl@[ao_cs] odlazován@[ao_cs] hráčem %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 został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%k a folosit dispozitivul LAZ pe %o.,Игрок %o получил заряд из «ЗБР» игрока %k., "After sending the monstrous Flembrane back to his own dimension, you free the @@ -114,7 +114,7 @@ de vuelta a su dimensión, liberas a los rehenes. ¡Pero los flemoides están por todas partes! Tú y los rehenes escapais hacia tu nave. Los flemoides cubren de -lodo tu nave, pero escapas en órbita por +babas tu nave, pero escapas en órbita por los pelos. Durante el regreso eres felicitad@[ao_esp] por tu valiente rescate, pero mandas una advertencia... @@ -179,20 +179,20 @@ azonban figyelmeztetsz mindenkit: nem utoljára láttuk a slejmoidokat. Sajnos igazad lett. Amint megérkeztél, szembesülsz azzal, hogy a slejmoidok valahogy hazáig követtek. Készülj fel a terrorra Chexvárosban, jön a Chex Quest 2!","Dopo aver rispedito il mostruoso Flembrane -nella sua dimensione, si liberano i prigionieri. +nella sua dimensione, puoi liberare i prigionieri. Eppure i flemoidi sono ovunque! Tu e i -prigionieri fare una pausa per la vostra -astronave. I flemoidi melma la vostra nave, -ma si fuggire di poco in orbita. -Durante il ritorno ci si congratula per -l'audace salvataggio, ma si emette un +prigionieri vi avviate per la tua astronave. +I flemoidi coprono di melma la tua astronave, +ma riuscite per poco a scappare in orbita. +Dopo il vostro ritorno vieni congratulato per +l'audace salvataggio, ma comunicate un avvertimento... -Non abbiamo visto l'ultimo dei Flemoidi. +Troveremo ancora i Flemoidi... -Purtroppo hai ragione. Infatti, al vostro -ritorno a casa, vi accorgerete che le -flotte vi hanno in qualche modo seguito qui. -Preparatevi per +Purtroppo hai ragione. Infatti, al tuo +ritorno a casa, ti accorgi che le loro +flotte ti hanno in qualche modo seguito qui. +Preparati per Chex Quest 2: Terrore a Chex City!","巨大なフレムブレンを元の次元に送り ほりょを解放した。 けれども、フレモイドはまだまだいる! フレモイドは 君の宇宙船を スライムまみれにしたため、 @@ -366,8 +366,8 @@ cereales ricos en nutrientes no ha disminuido. ¡Han reunido todas sus fuerzas, abierto un gigantesco túnel interdimensional en el espacio y ahora -una gran bola de lodo se dirige derecha -al planeta de los cereales! +una gran bola de baba se dirige hacia +el planeta de los cereales! Prepárate para Chex Quest 3: ¡Invasión!",,"Zorchaat jäljelle jääneet viemäreihin @@ -413,9 +413,9 @@ mit sem csökkent. Összegyűlt erőik gigantikus interdimenzionális rést ütöttek az űrben, és most egy óriási trutyilabda száguld egyenesen a gabonapelyhek bolygója felé! -Készülj fel az invázióra a Chex Quest 3-ban!","Hai zorch il restante flemoidi che si erano +Készülj fel az invázióra a Chex Quest 3-ban!","Hai neutralizzato restante flemoidi che si erano riuniti nelle fogne. Chex City è stata -salvata. Sembra che la minaccia Flemoid è +salvata. Sembra che la minaccia Flemoid sia finalmente finita. Dieci anni passano in pace e prosperità. @@ -428,8 +428,7 @@ spaccatura interdimensionale nello spazio e ora una grande palla di melma è diretta direttamente verso il pianeta dei cereali! Preparati per -Chex Quest 3: Invasione! -","君は 下水道に集まっていたフレモイドを +Chex Quest 3: Invasione!","君は 下水道に集まっていたフレモイドを ぶっとばして、チェックス シティーを守った。 フレモイドの きょういはようやく なくなったようだ。 @@ -514,10 +513,10 @@ planeta cerealelor! Pregătește-te pentru Chex Quest 3: Invazia!","С помощью Зорчера, ты освободил@[ao_rus] канализацию от оставшихся флемоидов. Город Chex спасён. Казалось, что с -угрозой Флемоидов наконец-то покончено. +угрозой флемоидов наконец-то покончено. Десять лет прошли в мире и процветании. -Но Флемоиды не были побеждены, им всё +Но флемоиды не были побеждены, им всё ещё хотелось править измерением полезных и питательных хлопьев. Они собрали все силы и открыли @@ -621,18 +620,16 @@ dimenziójába. De ha mégis visszatérnek, te készen állsz majd! -","Con un ultimo colpo, hai zorch Lord Snotfolus -torna alla sua dimensione! contro tutte -le probabilità che hai sventato -l'invasione con una sola mano! +","Con un ultimo colpo, hai neutralizzato Lord +Snotfolus, che ritorna alla sua dimensione! +Contro tutte le probabilità hai sventato +l'invasione tutto da solo! -Speri davvero che i flemoidi hanno +Speri davvero che i flemoidi abbiano finalmente imparato la lezione e non -torneranno mai più alla dimensione dei cereali. +torneranno mai più nella dimensione dei cereali. -Ma se lo sai che sarai pronto per loro! - -","さいごのいちげきで、ロード スノフォールスを元の次元に +Ma se lo faranno, sai che sarai pronto per loro!","さいごのいちげきで、ロード スノフォールスを元の次元に もどした。君一人で全てのオーズのしゅうげきを 阻止した! 君は フレモイド達のことを みんなに教え、再び diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp new file mode 100644 index 000000000..ec5879e85 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/010A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/010A.lmp new file mode 100644 index 000000000..1e951e746 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/010A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp new file mode 100644 index 000000000..593e1a6d9 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp new file mode 100644 index 000000000..a1d8302f1 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/011E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/011E.lmp new file mode 100644 index 000000000..83e4b77ca Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/011E.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp new file mode 100644 index 000000000..b1e8d2607 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0122.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0122.lmp new file mode 100644 index 000000000..7305bbc68 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0122.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0126.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0126.lmp new file mode 100644 index 000000000..264532468 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0126.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/012A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/012A.lmp new file mode 100644 index 000000000..760fb438a Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/012A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp new file mode 100644 index 000000000..9fb95b3fb Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013B.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013B.lmp new file mode 100644 index 000000000..8f6137574 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013B.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013D.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013D.lmp new file mode 100644 index 000000000..892a6b034 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/013D.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp new file mode 100644 index 000000000..80e105523 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp new file mode 100644 index 000000000..195a8da66 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0172.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0172.lmp new file mode 100644 index 000000000..0f3898b3e Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0172.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0174.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0174.lmp new file mode 100644 index 000000000..a25e7a369 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0174.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp new file mode 100644 index 000000000..4443deed6 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp new file mode 100644 index 000000000..9a4901d0b Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp new file mode 100644 index 000000000..c4fed22fb Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp new file mode 100644 index 000000000..f1c3ff3dc Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C0.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C0.lmp index 27fe843b1..a4e06caa8 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C0.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C0.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C1.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C1.lmp index fb2bb63c0..a3d165896 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C1.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C1.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C2.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C2.lmp index 82e78ce86..c1157da60 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C2.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C2.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C3.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C3.lmp index 8a6752b13..2d47965d7 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C3.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C3.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C4.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C4.lmp index 63df556b7..db8142bcb 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C4.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C4.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C5.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C5.lmp index fb2bb63c0..3dc94ef4e 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C5.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C5.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C8.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C8.lmp index 1a5025b11..91947b7f9 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C8.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C8.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C9.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C9.lmp index 8c7ac3652..32af88857 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C9.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00C9.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CA.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CA.lmp index ef965c4a3..7fad909b0 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CA.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CA.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CB.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CB.lmp index c21bac1b5..3e63a67c1 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CB.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CB.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CC.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CC.lmp index 18fe3d2b9..11ff1511b 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CC.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CC.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CD.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CD.lmp index 9b5645ab8..0171d4e6b 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CD.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CD.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp index 574bd7f85..30e2b0d3b 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp index df13e960a..bf0359c31 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D1.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D1.lmp index dffc67522..7eb9f80f2 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D1.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D1.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D2.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D2.lmp index 90796119c..4d0011457 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D2.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D2.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D3.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D3.lmp index 55ff8b5a7..f804135ac 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D3.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D3.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D4.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D4.lmp index c07704002..6ee0aafd1 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D4.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D4.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D5.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D5.lmp index b2143f1b4..794004991 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D5.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D5.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D6.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D6.lmp index 738ad156e..31d4dc1cb 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D6.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D6.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D9.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D9.lmp index 7b4089f54..862d01742 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D9.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00D9.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DA.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DA.lmp index 63bbf679a..11e694203 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DA.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DA.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DB.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DB.lmp index fe75e412b..2d9aaddd6 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DB.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DB.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DC.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DC.lmp index 60534ab2a..21c1f43b4 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DC.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DC.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DD.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DD.lmp index 9dea90348..28ede22bc 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DD.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00DD.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0100.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0100.lmp index e7c8e33e7..c8833c412 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0100.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0100.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0102.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0102.lmp index 999e2b95a..cb2ed1c0f 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0102.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0102.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0106.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0106.lmp index b1451f6ff..d7d715cd4 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0106.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0106.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0108.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0108.lmp index 86bf6f332..2bea57c4b 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0108.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0108.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010A.lmp new file mode 100644 index 000000000..49e905578 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010C.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010C.lmp index 3f5e45b52..4f7dbf927 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010C.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010C.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010E.lmp index 8ee4f7c5e..f92d5a0ad 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010E.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/010E.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0112.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0112.lmp index ccd193567..4e7c1fe38 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0112.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0112.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0114.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0114.lmp index 38e34f098..8f190e6d2 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0114.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0114.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0116.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0116.lmp new file mode 100644 index 000000000..635e3cf72 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0116.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011A.lmp index 103542342..099d7ff45 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011A.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011C.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011C.lmp index e41e832a2..f134fdb5a 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011C.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011C.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011E.lmp new file mode 100644 index 000000000..aa4af38b8 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/011E.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0120.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0120.lmp new file mode 100644 index 000000000..16cd7f6e7 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0120.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp new file mode 100644 index 000000000..057c1ef0f Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0124.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0124.lmp index 6d2878763..78039dd5c 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0124.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0124.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012A.lmp new file mode 100644 index 000000000..0eaa06e06 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp new file mode 100644 index 000000000..c4a7effd7 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0134.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0134.lmp index d00f8ec8b..c12a87524 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0134.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0134.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp new file mode 100644 index 000000000..ae3589e31 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.lmp new file mode 100644 index 000000000..eb90e1069 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.lmp new file mode 100644 index 000000000..17fccdc69 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0143.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0143.lmp index 02d47abfe..933540fa5 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0143.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0143.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0147.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0147.lmp index 0a14fba58..5d9d4bbb4 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0147.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0147.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0150.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0150.lmp index bdcf8ee3b..0b48dea30 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0150.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0150.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0154.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0154.lmp index 697477bc1..03c641101 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0154.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0154.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0158.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0158.lmp index 10e9de414..b42175e63 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0158.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0158.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015A.lmp index d27766577..ee9fe1768 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015A.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015C.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015C.lmp index a41a7af1b..af52cd062 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015C.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/015C.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0160.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0160.lmp index 30bd7979c..8d720b612 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0160.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0160.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0164.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0164.lmp index f1b03f98e..6cb69d60b 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0164.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0164.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016A.lmp new file mode 100644 index 000000000..e1a092515 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016A.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016C.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016C.lmp index fb43845b1..a986db5ba 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016C.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016C.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016E.lmp index 7557f1a8c..0e3a5cc70 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016E.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/016E.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0170.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0170.lmp index f0dbe3dce..04e3a0131 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0170.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0170.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp new file mode 100644 index 000000000..54b92066e Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0174.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0174.lmp new file mode 100644 index 000000000..96dfa9c0c Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0174.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0176.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0176.lmp new file mode 100644 index 000000000..10e05edb8 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0176.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0178.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0178.lmp index cfaf87157..1f2b949f3 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0178.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0178.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0179.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0179.lmp index 7482f0618..f1a92ba69 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0179.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0179.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017B.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017B.lmp index 49b3050cd..cc9d2f978 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017B.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017B.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017D.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017D.lmp index 13f4fba43..c0037b473 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017D.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/017D.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AA.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AA.lmp deleted file mode 100644 index df13e960a..000000000 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AA.lmp and /dev/null differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AB.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AB.lmp deleted file mode 100644 index cfaf87157..000000000 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/03AB.lmp and /dev/null differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0401.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0401.lmp deleted file mode 100644 index c21bac1b5..000000000 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0401.lmp and /dev/null differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..fd61ad553 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp index 30f1c79d8..2f5ee22b7 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp index 950f91656..c48e80d4f 100644 Binary files a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..d7c9420ae Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E80.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E80.lmp new file mode 100644 index 000000000..7b014bdb1 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E80.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E82.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E82.lmp new file mode 100644 index 000000000..7acbe05fb Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1E82.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1EF2.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1EF2.lmp new file mode 100644 index 000000000..a0336a5f8 Binary files /dev/null and b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/1EF2.lmp differ diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/font.inf b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/font.inf new file mode 100644 index 000000000..b3c8f4978 --- /dev/null +++ b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/font.inf @@ -0,0 +1,2 @@ +FontHeight 9 + diff --git a/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0404.lmp b/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0404.lmp new file mode 100644 index 000000000..7a1a21014 Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0490.lmp b/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0490.lmp new file mode 100644 index 000000000..5a7d5477e Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/bigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp new file mode 100644 index 000000000..5a41b45e3 Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..f175981b4 Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..5b12eba74 Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp new file mode 100644 index 000000000..c9b6cf5af Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp new file mode 100644 index 000000000..b3bf1609d Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp differ diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2026.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2026.lmp new file mode 100644 index 000000000..c3a5a8198 Binary files /dev/null and b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2026.lmp differ diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0404.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0404.lmp new file mode 100644 index 000000000..622e15ea5 Binary files /dev/null and b/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0490.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0490.lmp new file mode 100644 index 000000000..171c645c3 Binary files /dev/null and b/wadsrc_extra/static/filter/game-heretic/fonts/defbigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..af549dd86 Binary files /dev/null and b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..945b1c6bd Binary files /dev/null and b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0404.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0404.lmp new file mode 100644 index 000000000..ea11cc4cc Binary files /dev/null and b/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0490.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0490.lmp new file mode 100644 index 000000000..0cf9b98f0 Binary files /dev/null and b/wadsrc_extra/static/filter/game-hexen/fonts/defbigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..cec6e1596 Binary files /dev/null and b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..16033384e Binary files /dev/null and b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0404.lmp b/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0404.lmp new file mode 100644 index 000000000..ad5074e95 Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0490.lmp b/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0490.lmp new file mode 100644 index 000000000..ff7b9d708 Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/bigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0403.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0403.lmp new file mode 100644 index 000000000..18bf0a3bc Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0403.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..dd130d30e Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..994885686 Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0403.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0403.lmp new file mode 100644 index 000000000..0729bc6df Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0403.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0404.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0404.lmp new file mode 100644 index 000000000..8d7d53364 Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0404.lmp differ diff --git a/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0490.lmp b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0490.lmp new file mode 100644 index 000000000..0d726dbf2 Binary files /dev/null and b/wadsrc_extra/static/filter/game-strife/fonts/defsmallfont2/0490.lmp differ 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 7c4359e4a..ff8f14f81 100644 --- a/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv +++ b/wadsrc_extra/static/filter/hacx.hacx1/after_iwad/language.csv @@ -12,15 +12,15 @@ Real hackers never jack out of the action.,QUITMSG4,,,,Skuteční hackeři nikdy malkonektiĝi el la 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.,Prawdziwi hakerzy nigdy nie uciekają z akcji.,Hackers de verdade nunca vazam da ação!,,Adevărații hackeri nu fug de acțiune.,Настоящие хакеры не пытаются улизнуть с поля боя., C'mon! You haven't seen the best part yet!,QUITMSG5,,,,No tak! Ještě jsi neviděl to nejlepší!,Komm schon. Du hast das Beste noch gar nicht gesehen!,,Venu! Vi ne ankoraŭ vidis la plej bonan parton!,¡Venga! ¡Aún no has visto 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!,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ă!,"Да ладно, ты ещё не видел самое крутое!", "Give up now, and cyberspace is toast!",QUITMSG6,,,,Vzdej se a s kyberprostorem je konec!,Wenn du jetzt aufgibst ist der Cyberspace am Ende.,,"Se vi ĉesas nun, tiam retumejo estos detruiĝita!",¡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!","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!","Если ты сейчас сдашься, киберпространству конец!", -"GENIE sends its best regards, scumbag!",QUITMSG7,,,,"GENIE posílá své pozdravy, hajzle!","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 manda i suoi\nmigliori saluti, bastardo!",GENIEがベストの挨拶を送るぜ、カス野郎!,어이 등신! 지니에서 안부를 전해 달라더군.,"GENIE doet je de groeten, klootzak!","GENIE przysyła pozdrowienia, łajzo!","GENIE manda lembranças, seu lixo!",,"GENIE își transmite condoleanțele, ticălosule!","Наилучшие пожелания от ДЖИННа, ублюдок!", -"Hmm. So much for being a hero, Hacker.",QUITMSG8,,,,"Hmm. To by bylo pro hrdinství, Hackeře.","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. Così tanto per essere un eroe, Hacker.",うーん。英雄とはこの程度だったのか、ハッカー。,영웅이 될 그릇은 아닌 거 같군. 안 그래? 해커 형씨.,"Hmm. Tot zover de held, 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.","Хм-м. Вот тебе и герой, Хакер!", +"GENIE sends its best regards, scumbag!",QUITMSG7,,,,"GENIE posílá své pozdravy, hajzle!","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 przysyła pozdrowienia, łajzo!","GENIE manda lembranças, seu lixo!",,"GENIE își transmite condoleanțele, ticălosule!","Наилучшие пожелания от ДЖИННа, ублюдок!", +"Hmm. So much for being a hero, Hacker.",QUITMSG8,,,,"Hmm. To by bylo pro hrdinství, Hackeře.","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. Tak wiele by być bohaterem, Hakerze.","Hmm. Não é tão herói assim, pelo visto.",,"Hmm. Asta a fost cu eroismele, Hacker.","Хм-м. Вот тебе и герой, хакер!", What? You'd rather go back to the pen?,QUITMSG9,,,,Co? Radši by ses vrátil do basy?,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?,Co? Wolisz wrócić do więzienia?,O quê? Prefere voltar pro xilindró?,,Ce? Vrei să te întorci la captivitate?,Что? Ты хочешь вернуться в неволю?, Shoulda taken the blue pill.,QUITMSG10,,,,Měl sis vzít modrou pilulku.,Du hättest die blaue Pille nehmen sollen...,,Devintu 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.,Trzeba było wziąć niebieską pigułkę.,Devia ter tomado a pílula azul.,,Trebuia să iei pastila albastră.,Надо было принять синюю таблетку., The name of the game ain't Twitch n' Run!,QUITMSG11,,,,V názvu hry není napsané „uteč“!,"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!,"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!,Эта игра называется не «Дрожи и прячься»!, "No worries. Saving the world can wait, right?",QUITMSG12,,,,"Žádný problém. Záchrana světa může počkat, ne?","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?","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?","Не парься. Спасение мира подождёт, ведь так?", Guess it's time to make like the 'net and split!,QUITMSG13,,,,"Hádám, že je čas vypojit server!","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!,"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!", -"Don't go off and forget about HacX, now!",QUITMSG14,,,,Ať tě nenapadne odejít a zapomenout na 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 dimenticati di HacX, ora!",HacXを忘れんじゃねえぞ、な!,부디 나가지 말고 HacX를 잊지 말아줘!,"Ga niet af en vergeet HacX niet, nu!","Nie wyłączaj i nie zapominaj o HacX, teraz!","Não vai se esquecer do HacX, hein!",,Nu pleca și uita de HacX!,"Только посмей уйти и забыть про HacX, ты!", -%o deleted %hself from the universe.,OB_SUICIDE,,,,%o se smazal@[ao_cs] z vesmíru.,%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 usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a sters pe sine din univers.,%o стёр себя с лица Вселенной., +"Don't go off and forget about HacX, now!",QUITMSG14,,,,Ať tě nenapadne odejít a zapomenout na 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!","Nie wyłączaj i nie zapominaj o HacX, teraz!","Não vai se esquecer do HacX, hein!",,Nu pleca și uita de HacX!,"Только посмей уйти и забыть про HacX, ты!", +%o deleted %hself from the universe.,OB_SUICIDE,,,,%o se smazal@[ao_cs] z vesmíru.,%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 usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a sters pe sine din univers.,%o стёр себя с лица вселенной., %o formed a crater the size of Kansas.,OB_FALLING,,,,%o utvořil@[ao_cs] kráter velikosti Kansasu.,%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 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 became a human pancake.,OB_CRUSH,,,,%o se změnil@[ao_cs] v lidskou palačinku.,%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 stał@[ao_pl] się ludzkim plackiem.,%o virou uma panqueca humana.,,%o a devenit o clătită umană.,Игрока %o сплющило в лепешку., %o tried to jack out.,OB_EXIT,,,,%o se pokusil@[ao_cs] prchnout.,%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 chciał@[ao_pl] się wydostać.,%o tentou se desconectar.,,%o a încercat să o taie.,%o хотел улизнуть., @@ -34,82 +34,80 @@ Guess it's time to make like the 'net and split!,QUITMSG13,,,,"Hádám, že je %o deleted %hself from the universe.,OB_KILLEDSELF,,,,%o se smazal@[ao_cs] z vesmíru.,%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 usun@[irreg_2_pl] się ze świata.,%o se deletou deste universo.,,%o s-a șters pe sine din univers.,%o стёр@[irreg_2_rus] себя с лица Вселенной., %o is no longer the dominant species.,OB_THUG,,,,%o už není vládnoucím živočichem.,%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 nie jest już dominującym gatunkiem.,%o não é mais a espécie dominante.,,%o nu mai e specia dominantă.,%o больше не доминантная форма жизни., %o plugged in to the wrong machine.,OB_ANDROID,,,,%o se zapojil@[ao_cs] ke špatnému stroji.,%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 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 got %hself a monster of a cyber-jockey-derriere-kicking.,OB_MONSTRUCT,,,,%o dostal@[ao_cs] šíleně kybernakopáno.,%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 ho avuto un mostruoso calcio cibernetico mancato.,%o は己に サイバー-ジョッキー-デリエレ-キッキング を取り入れた。,%o 은(는) 저 괴물의 슈퍼-울트라-캡쑝-파워를 맛봤다.,%o kreeg een monsterlijke cybertrap in @[zijn_haar_nl] kont.,%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 получил@[ao_rus] поджопника от кибер-диджея., -%o got ICEd.,OB_ICE,,,,%o byl@[ao_cs] zmražen@[ao_cs] ICEm.,%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 è stato ghiacciato.,%o は冷えた。,%o 은(는) 지독하게 물어뜯겼다.,%o was IJS'd.,%o został@[ao_pl] zamrożon@[adj_pl].,%o foi peg@[ao_ptb] por um ICE. AI SE ferrou!,,%o a ÎNGHEȚat.,%o вляпал@[refl_rus] в ЛЁД., -%o feels a little buzzed.,OB_BUZZER,,,,%o dostal@[ao_cs] malou pecku.,%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 si sente solleticato un po '.,%o は少し賑やかになった。,%o 은(는) 짜릿하게 찔렸다.,%o voelt een beetje gezoemd.,%o poczuł@[ao_pl] brzęczenie.,%o se sente meio chocad@[ao_ptb].,,%o se simte puțin șocat.,%o л@[irreg_3_rus] спать в компании вертолётиков., -%o uncovers a rather shocking development.,OB_STEALTH,,,,%o odhalil@[ao_cs] šokující informace.,%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 ha fatto una scoperta scioccante.,%o はかなり衝撃的な開発を発見した。,%o 은(는) 비밀리에 만들어진 병기를 발견했다.,%o ontdekt een nogal schokkende ontwikkeling.,%o odkrywa coś szokującego.,%o descobre uma revelação chocante.,,%o dezvăluie o schimbare șocantă.,%o встретил@[ao_rus] довольно серьёзный поворот событий., -%o was erased from cyberspace.,OB_DMAN,,,,%o byl@[ao_cs] vymazán@[ao_cs] z kyberprostoru.,%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 è stato eliminato dal cyberspazio.,%o はサイバースペースに消去された。,%o 은(는) 영구차단을 당했다.,%o werd gewist uit 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 gave %hself a glass jaw.,OB_GLASS,,,,%o si přidělal@[ao_cs] skleněnou čelist.,%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 ha un mento di vetro.,%o は自身にグラスジョーを取り付けた。,%o 은(는) 유리창을 깨고 등장하는 액션 배우가 아니였다.,%o gaf zichzelf een glazen kaak.,%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's life membership was terminated.,OB_MANIAC,,,,%o@[psn_cs] členství v klubu živých bylo přerušeno.,%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.,,L'appartenenza di %o alla vita è finita.,%o のメンバーシップ生活は終幕した。,%o 의 계정은 영원히 삭제되었다.,%o's levenslange lidmaatschap werd beëindigd.,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 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 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.,,%o è morto in un modo inimmaginabile.,%o は計算外の乱数で死んだ。,%o 은(는) 의미불명의 이유로 잠수를 타게 되었다.,%o stierf op een of andere willekeurige manier die ik me niet kan voorstellen.,"%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 внезапно умер@[irreg_2_rus] по непостижимой для меня причине., -%o was fried by a femme fatale freak.,OB_TERMIN,,,,%o byl@[ao_cs] usmažen@[ao_cs] šílenou femme fatale.,%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 è stato fritto da una femme fatale.,%o はファム ファタル フリークに揚げられた。,%o 은(는) 미인계에 발을 들였다.,%o werd gebakken door een 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 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 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 è arrivato troppo vicino all'altro sesso.,%o は少し異性に成り果てた。,%o 의 남자다운 자존심은 쪼그라들었다.,%o kwam een beetje in de buurt van het andere geslacht.,%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 почти сблизил@[refl_rus] с противоположным полом., -%o said goodbye to an old friend.,OB_REPLI,,,,%o řekl@[ao_cs] sbohem starému příteli.,%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 ha detto addio a un vecchio amico.,%o は古い友人に別れを告げた。,%o 은(는) 오랜 친구와 작별인사를 했다.,%o nam afscheid van een oude vriendin.,%o pożegnał@[ao_pl] się ze starym znajomym.,%o disse adeus a um velho amigo.,,%o a spus adio unui vechi prieten.,%o распрощал@[refl_rus] со старым другом., -%o was stabbed in the back by an old friend.,OB_REPLIHIT,,,,%o byl@[ao_cs] bodnuta do zad starým přítelem.,%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 è stato pugnalato alla schiena da un vecchio amico.,%o は古い友人に背中を刺された。,%o 은(는) 오랜 친구에게 배신을 당했다.,%o werd in de rug gestoken door een oude vriend.,%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 получил@[ao_rus] нож в спину от старого друга., -%o was weeded out by natural selection.,OB_PHAGE,,,,%o byl@[ao_cs] vyčištěna přirozeným výběrem.,%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.,,%o cadde vittima della selezione naturale.,%o は自然淘汰によって除草された。,%o 은(는) 약육강식을 지금까진 모르고 있었다.,%o werd door natuurlijke selectie weggehaald.,%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 был@[ao_rus] отсеян@[ao_rus] естественным отбором., -%o couldn't escape a thorny death.,OB_THORN,,,,%o nemohl@[ao_cs] utéct bodlavé smrti.,%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.,,%o non poteva sfuggire a una morte spinosa.,%o は棘のある死から逃げられなかった。,%o 은(는) 따가운 죽음을 피할 수 없었다.,%o kon niet ontsnappen aan een netelige dood.,%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 took a sumo punch to the groin.,OB_SUMATIC,,,,%o dostal@[ao_cs] sumo ránu pod pás.,%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 ha ricevuto un soffio su un punto sensibile.,%o は股座にスモウ ハリテを食らった。,%o 은(는) 가랑이 사이에 정권을 찔렀다.,%o nam een sumo punch in de lies.,%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 отхватил@[ao_rus] удар в пах от сумоиста., -%o didn't get %p three wishes.,OB_GENIE,,,,%o nedostal@[ao_cs] svá tři přání.,%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 non ha soddisfatto i suoi tre desideri.,%o は %p に三願を望まなかった。,%o 은(는) 세 가지 소원을 빌 수 없었다.,%o kreeg niet drie wensen.,%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 tried to pet a mine.,OB_MINE,,,,%o se pokusil@[ao_cs] pohladit minu.,"%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 ha provato ad accarezzare una mina.,%o は地雷を愛撫しようとした。,%o 은(는) 기뢰와 친구가 되고 싶었다.,%o probeerde een mijn te aaien.,%o próbował@[ao_pl] pogłaskać minę.,%o tentou fazer carinho numa mina.,,%o a încercat să mângâie o mină.,%o хотел@[ao_rus] погладить мину., -%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 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 ha un calcio in faccia.,%o の顔に %k のブルースリーキックを当てた。,%o 은(는) %k 의 거침없는 하이킥을 받았다.,%o nam %k's Bruce Lee fu-kick in het gezicht.,%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 отхватил@[ao_rus] от игрока %k удар в лицо, достойный Брюса Ли.", -%o fell apart via %k's shocking revelation.,OB_MPREZNATOR,,,,%o se rozpadl@[ao_cs] šokujícím odhalením hráče %k.,%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.,,%o ricevette una scioccante rivelazione da %k.,%o は %k の衝撃的な啓示によりバラバラになった。,%o 은(는) %k 이(가) 선사한 전기 찜질을 맛봤다.,%o viel uit elkaar via %k's schokkende onthulling.,%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 шокирован@[ao_rus] откровениями %k., -%o took a double-dose of %k's punishment.,OB_MPXPISTOL,,,,%o dostal@[ao_cs] dvojitou dávku potrestání hráče %k.,%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 ha ottenuto una doppia dose della punizione di %k.,%o は %k の懲罰を二度受けた。,%o 은(는) %k 의 2총신 사격을 받았다.,%o nam een dubbele dosis van %k's straf.,%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 принял@[ao_rus] двойную дозу возмездия от %k., -%o was shut down by %k's shock-stick.,OB_MPTAZER,,,,%o byl@[ao_cs] vypnut@[ao_cs] šokádou hráče %k.,%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 è stato spento dalla bacchetta di %k.,%o は %k のショックスティックでシャットダウンした。,%o 은(는) %k 의 무력행사에 아예 포기했다.,%o werd uitgeschakeld door %k's schokstick.,%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 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 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.,,%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 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 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 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 è stato perforato da %k in stile gangsta.,%o はギャングの様な %k に蜂の巣にされた。,%o 은(는) %k 이(가) 선사한 갱스터 스타일 난사를 막지 못했다.,"%o werd vol gaten geboord met %k, in gangsta-stijl.",%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 ate %k's photon bomb.,OB_MPZOOKA,,,,%o sežral@[ao_cs] fotonovou bombu hráče %k.,%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 ha preso la bomba fotonica di %k.,%o は %k のフォトンボムを食らった。,%o 은(는) %k 의 광자탄을 봤는데도 피하지 못했다.,%o at %o %k's fotonbom.,%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 съел@[ao_rus] фотонную бомбу %k., -%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 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 è stato elaborato da %k in un mucchio di fotoni.,%o は %k によって蛍光灯にされた。,%o 은(는) %k 의 광자력을 탐냈다. 죽기 전까지는.,%o werd gereduceerd tot een nette stapel fotonen met %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 был@[ao_rus] разложен@[ao_rus] игроком %k в аккуратную кучку фотонов., -%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 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.,,%o è stato ridotto all'antimateria da %k,%o は %k のにより反物質に変換された。,%o 은(는) %k 의 반물질의 힘에 의해 소멸되었다.,%o werd gereduceerd tot antimaterie met %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 был@[ao_rus] разложен@[ao_rus] игроком %k до антиматерии., -%o swallowed %k's nuke.,OB_MPNUKE,,,,%o spolkl@[ao_cs] atomovku hráče %k.,%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 soffocò sul missile nucleare di %k.,%o は %k の核を飲み干した。,%o 은(는) %k 덕분에 하늘을 뚫을 버섯구름이 되었다.,%o geslikt %o nuke %k's nuke.,%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 проглотил@[ao_rus] ядерный заряд %k., -%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 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 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 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 was turned inside-out by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] obrácen@[ao_cs] naruby hráčem %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.,,%o fu fatto a pezzi da %k,%o は %k に裏返しにされた。,%o 은(는) %k 에 의해 자신이 분해되는 꼴을 못 봤다.,%o werd binnenstebuiten gekeerd met %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's atomic structure was split apart.,OB_MONTELEFRAG,,,,Struktura atomů hráče %o se rozpadla.,%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.,,La struttura atomica di %o fu distrutta.,%o の原子構造は分解された。,%o 의 원자 마디마디가 흩어졌다.,De atoomstructuur van %o werd gesplitst.,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 spontaneously expired.,OB_DEFAULT,,,,%o samovolně vypršel@[ao_cs].,%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 ha smesso spontaneamente di esistere.,%o の有効期限が自発的に切れた,%o 은(는) 파란만장하게 사라졌다.,%o is spontaan verlopen.,%o spontanicznie umarł@[ao_pl].,%o pereceu expontâneamente.,,%o a expirat în mod spontan.,Время игрока %o неожиданно вышло., -You grab a NUKER! Suck on this!,GOTNUKER,,,,Sebral@[ao_cs] jsi ATOMOVKÁTOR! Pojď na to!,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!,,Prendi un NUKER! Succhia su questo!,NUEKR を奪った! 覚悟しろ!,누커 획득! 한바탕 쓸어볼까!,Je pakt een NUKER! Zuig hier maar aan!,Podniosłeś ATOMÓWKĘ! Ssijcie to!,Você pegou um NUKER! Chupa essa manga!,,Ai ridicat Lansatorul Nuclear! Ia de-aici!,Заполучен ЯДЕРНЫЙ ГРАНАТОМЁТ! Отсосите!, -You got an UZI!!,GOTUZI,,,,Získal@[ao_cs] jsi UZI!,UZI genommen!,,Vi prenis UZI!!,¡¡Has obtenido una UZI!!,,Sait UZIn!!,Vous chopez un UZI!,,Hai un UZI !!,UZI をゲットした!!,우지 기관단총 획득!,Je hebt een UZI!!,Zdobyłeś UZI!!,Você pegou uma UZI!!,,Ai ridicat un UZI!!,Заполучен УЗИ!, -A HOIG Reznator - FRY some butt,GOTREZNATOR,,,,HOIG Reznátor - pár jich upeč,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!",,Un Reignator HOIG - friggere un po 'di carne,HOIGレジネイター - ぶっ潰してやれ,HOIG 전자무력기 획득! 전기 통구이를 만들자고!,Een HOIG Reznator - FRY sommige kont,Reznator HOIG - skop trochę tyłków,Um Reznador HOIG - Hora de fritar,,Un Rezonator HOIG - Arde-i!,ХОЙГ Резнатор, -You got a Photon 'Zooka!,GOTPHOTONZOOKA,,,,Sebral@[ao_cs] jsi Fotonovou bazuku!,Photonen-'zooka genommen!,,Vi prenis Fotonbazukon!,¡Has obtenido un Bazooka de Fotones!,,Sait fotonisingon!,Vous récupérez un Bazooka Photonique!,,Hai un cannone Photon!,フォトン'ゾーカ をゲットした!,광자 바주카 획득!,Je hebt een Photon 'Zooka!,Zdobyłeś Fotonozukę!,Você pegou uma Bazuca de Fótons!,,Ai ridicat o Bazooka Fotonică!,Заполучена Фотон-базука!, -You carry a Big Stick!,GOTBIGSTICK,,,,Nosíš velkou bouchačku!,Du trägst einen langen Stock.,,Vi portas grandan bastonon!,¡Llevas un Gran Palo!,,Kannat isoa keppiä!,Vous avez un gros bâton!,,Porti un grosso bastone!,ビッグスティック を手に取った!,반물질 봉 획득!,Je draagt een Big Stick!,Podnosisz Wielką Pałkę!,Você pegou um Grande Bastão!,,Ai ridicat un Băț Lung!,Заполучена Длинная палка!, -You got a Tazer!!,GOTTAZER,,,,Získal@[ao_cs] jsi tazer!,Tazer genommen!,,Vi prenis Elektropafilon!!,¡¡Has obtenido un Taser!!,,Sait etälamauttimen!!,Vous trouvez un Taser!,,Hai un Taser !!,テイザー をゲットした!,테이져 획득!,Je hebt een Tazer!!,Zdobyłeś Tazer!!,Você pegou um Tazer!!,,Ai ridicat un Taser!!,"Заполучен Тазер! -", -You grab a Cryogun! FREEZE!,GOTCRYOGUN,,,,Sebral@[ao_cs] jsi krypušku! ANI SE NEHNI!,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!,,Prendi un Cryogun! CONGELARE!,クライォガン を奪った! フリーズ!,크라이로건 획득! 그대로 멈춰라!,Je pakt een Cryogun! FREEZE!,Podniosłeś Zamrażarkę! STAĆ!,Você pegou uma Cryogun! FICA FRIO AÍ!,,Ai ridicat o Crio-armă! ÎNGHEAȚĂ!,Заполучена Замораживающая пушка! НИ С МЕСТА!, -You grab some rounds!,GOTROUNDS,,,,Sebral@[ao_cs] jsi nějaké náboje!,Munition genommen.,,Vi prenis kuglojn!,¡Has pillado unas balas!,¡Has recogido unas balas!,Kahmaiset patruunoita!,Vous prenez des balles!,,Prendi delle munizioni!,幾つかのラウンド を奪った!,권총 탄약을 주웠다!,Je pakt wat rondes!,Podniosłeś trochę naboi!,Você pegou munição!,,Ai ridicat niște muniție!,Заполучена обойма патронов!, -You grab a case of rounds!,GOTROUNDSCASE,,,,Sebral@[ao_cs] jsi krabici nábojů!,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!,,Prendi un caso di munizioni!,ケースのラウンド を奪った!,권총 탄약 상자를 주웠다!,Je pakt een kist met rondes!,Podniosłeś skrzynkę naboi!,Você pegou uma caixa de munição!,,Ai ridicat un cartuș de muniție!,Заполучена коробка патронов!, -You grab a Torpedo!,GOTTORPEDO,"Was ""grap"" for some reason.",,,Sebral@[ao_cs] jsi torpédo!,Torpedo genommen.,,Vi prenis Torpedon!,¡Has pillado un torpedo!,¡Has recogido un torpedo!,Kahmaiset torpedon!,Vous prenez une torpille!,,Prendi un siluro!,トルペード を奪った!,광자탄을 주웠다!,Je pakt een Torpedo!,Podniosłeś Torpedę!,Você pegou um Torpedo!,,Ai ridicat o Torpilă!,Заполучена торпеда!, -You grab a case of Torpedos!,GOTTORPEDOS,,,,Sebral@[ao_cs] jsi krabici torpéd!,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!,,Prendi un caso di siluri!,トルペードのケース を奪った!,광자탄 무더기를 주웠다!,Je pakt een kist Torpedo's!,Podniosłeś skrzynkę Torped!,Você pegou uma caixa de Torpedos!,,Ai ridicat o cutie de Torpile!,Заполучен ящик торпед!, -You grab a molecule module!,GOTMOLECULES,,,,Sebral@[ao_cs] jsi molekulový modul!,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!,,Prendi un modulo molecolare!,モーレキュールモヂュール を奪った!,분자 모듈을 주웠다!,Je pakt een molecuulmodule!,Podniosłeś molekularny moduł!,Você pegou um módulo molecular!,,Ai ridicat un modul molecular!,Заполучен молекулярный модуль!, -You grab a tank full of molecules!,GOTMOLECULESTANK,,,,Sebral@[ao_cs] jsi sud plný molekul!,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!,,Prendi un serbatoio pieno di molecole!,タンク満タンのモーレキュール を奪った!,분자 탱크를 주웠다!,Je pakt een tank vol met moleculen!,Podniosłeś zbiornik pełen molekuł!,Você pegou um tanque cheio de moléculas!,,Ai ridicat un rezervor plin cu molecule!,Заполучен контейнер с молекулами!, -You grab some Cartridges!,GOTCARTRIDGES,,,,Sebral@[ao_cs] jsi nějaké kazety!,Magazin genommen.,,Vi prenis iom da kartoĉoj!,¡Has pillado unos cartuchos!,¡Has recogido unos cartuchos!,Kahmaiset kasetteja!,Vous prenez des cartouches!,,Prendi alcune cartucce!,残弾のカートリッジ を奪った!,카트리지 한 줌을 주웠다!,Je pakt een paar patronen!,Podniosłeś trochę pocisków!,Você pegou alguns Carregadores!,,Ai ridicat niște Cartușe!,Заполучены картриджи!, -You grab a case of Cartridges!,GOTCARTRIDGESCASE,,,,Sebral@[ao_cs] jsi krabici kazet!,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!,,Prendi un caso di cartucce!,カートリッジケース を奪った!,카트리지 박스를 주웠다!,Je pakt een kist patronen!,Podniosłeś skrzynkę pocisków!,Você pegou uma caixa de Carregadores!,,Ai ridicat o cutie de Cartușe!,Заполучен ящик картриджей!, -You grab a Valise stuffed with goods!,GOTVALISE,,,,Sebral@[ao_cs] jsi kufr plný munice!,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!,,Prendi una Valigia piena di merci!,代物を詰めたバリス を奪った!,탄약이 든 서류 가방을 주웠다!,Je pakt een Valise gevuld met goederen!,Podniosłeś Walizkę z wieloma dobrami!,Você pegou uma Mala cheia de equipamento!,,Ai ridicat o Valiză plină cu bunătăți!,Заполучена полная сумка боеприпасов!, -Force Field!,GOTFORCEFIELD,,,,Silové pole!,Kraftfeld!,,Fortkampo!,¡Campo de fuerza!,,Voimakenttä!,Champ de force!,,Campo di forza!,フォースフィールド!,방어막!,Krachtveld!,Pole Siłowe!,Campo de Força!,,Câmp de Forță!,Силовое поле!, +%o got %hself a monster of a cyber-jockey-derriere-kicking.,OB_MONSTRUCT,,,,%o dostal@[ao_cs] šíleně kybernakopáno.,%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 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 получил@[ao_rus] поджопника от кибер-диджея., +%o got ICEd.,OB_ICE,,,,%o byl@[ao_cs] zmražen@[ao_cs] ICEm.,%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 został@[ao_pl] zamrożon@[adj_pl].,%o foi peg@[ao_ptb] por um ICE. AI SE ferrou!,,%o a ÎNGHEȚat.,%o вляпал@[refl_rus] в ЛЁД., +%o feels a little buzzed.,OB_BUZZER,,,,%o dostal@[ao_cs] malou pecku.,%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 poczuł@[ao_pl] brzęczenie.,%o se sente meio chocad@[ao_ptb].,,%o se simte puțin șocat.,%o л@[irreg_3_rus] спать в компании вертолётиков., +%o uncovers a rather shocking development.,OB_STEALTH,,,,%o odhalil@[ao_cs] šokující informace.,%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 odkrywa coś szokującego.,%o descobre uma revelação chocante.,,%o dezvăluie o schimbare șocantă.,%o встретил@[ao_rus] довольно серьёзный поворот событий., +%o was erased from cyberspace.,OB_DMAN,,,,%o byl@[ao_cs] vymazán@[ao_cs] z kyberprostoru.,%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 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 gave %hself a glass jaw.,OB_GLASS,,,,%o si přidělal@[ao_cs] skleněnou čelist.,%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 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's life membership was terminated.,OB_MANIAC,,,,%o@[psn_cs] členství v klubu živých bylo přerušeno.,%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.,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 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 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 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 внезапно умер@[irreg_2_rus] по непостижимой для меня причине., +%o was fried by a femme fatale freak.,OB_TERMIN,,,,%o byl@[ao_cs] usmažen@[ao_cs] šílenou femme fatale.,%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 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 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 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 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 почти сблизил@[refl_rus] с противоположным полом., +%o said goodbye to an old friend.,OB_REPLI,,,,%o řekl@[ao_cs] sbohem starému příteli.,%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 pożegnał@[ao_pl] się ze starym znajomym.,%o disse adeus a um velho amigo.,,%o a spus adio unui vechi prieten.,%o распрощал@[refl_rus] со старым другом., +%o was stabbed in the back by an old friend.,OB_REPLIHIT,,,,%o byl@[ao_cs] bodnuta do zad starým přítelem.,%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 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 получил@[ao_rus] нож в спину от старого друга., +%o was weeded out by natural selection.,OB_PHAGE,,,,%o byl@[ao_cs] vyčištěna přirozeným výběrem.,%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 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 был@[ao_rus] отсеян@[ao_rus] естественным отбором., +%o couldn't escape a thorny death.,OB_THORN,,,,%o nemohl@[ao_cs] utéct bodlavé smrti.,%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 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 took a sumo punch to the groin.,OB_SUMATIC,,,,%o dostal@[ao_cs] sumo ránu pod pás.,%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 dostał@[ao_pl] cios sumo w pachwinę.,%o tomou um golpe de sumô na virilha.,,%o a primit un pumn sumo în vintre.,%o отхватил@[ao_rus] удар в пах от сумоиста., +%o didn't get %p three wishes.,OB_GENIE,,,,%o nedostal@[ao_cs] svá tři přání.,%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 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 tried to pet a mine.,OB_MINE,,,,%o se pokusil@[ao_cs] pohladit minu.,"%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óbował@[ao_pl] pogłaskać minę.,%o tentou fazer carinho numa mina.,,%o a încercat să mângâie o mină.,%o хотел@[ao_rus] погладить мину., +%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 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 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 отхватил@[ao_rus] от игрока %k удар в лицо, достойный Брюса Ли.", +%o fell apart via %k's shocking revelation.,OB_MPREZNATOR,,,,%o se rozpadl@[ao_cs] šokujícím odhalením hráče %k.,%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 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 шокирован@[ao_rus] откровениями %k., +%o took a double-dose of %k's punishment.,OB_MPXPISTOL,,,,%o dostal@[ao_cs] dvojitou dávku potrestání hráče %k.,%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 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 принял@[ao_rus] двойную дозу возмездия от %k., +%o was shut down by %k's shock-stick.,OB_MPTAZER,,,,%o byl@[ao_cs] vypnut@[ao_cs] šokádou hráče %k.,%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 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 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 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 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 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 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 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 ate %k's photon bomb.,OB_MPZOOKA,,,,%o sežral@[ao_cs] fotonovou bombu hráče %k.,%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 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 съел@[ao_rus] фотонную бомбу %k., +%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 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 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 был@[ao_rus] разложен@[ao_rus] игроком %k в аккуратную кучку фотонов., +%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 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 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 был@[ao_rus] разложен@[ao_rus] игроком %k до антиматерии., +%o swallowed %k's nuke.,OB_MPNUKE,,,,%o spolkl@[ao_cs] atomovku hráče %k.,%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 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 проглотил@[ao_rus] ядерный заряд %k., +%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 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 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 was turned inside-out by %k.,OB_MPTELEFRAG,,,,%o byl@[ao_cs] obrácen@[ao_cs] naruby hráčem %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 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's atomic structure was split apart.,OB_MONTELEFRAG,,,,Struktura atomů hráče %o se rozpadla.,%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.,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 spontaneously expired.,OB_DEFAULT,,,,%o samovolně vypršel@[ao_cs].,%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 spontanicznie umarł@[ao_pl].,%o pereceu expontâneamente.,,%o a expirat în mod spontan.,Время игрока %o неожиданно вышло., +You grab a NUKER! Suck on this!,GOTNUKER,,,,Sebral@[ao_cs] jsi ATOMOVKÁTOR! Pojď na to!,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!,Podniosłeś ATOMÓWKĘ! Ssijcie to!,Você pegou um NUKER! Chupa essa manga!,,Ai ridicat Lansatorul Nuclear! Ia de-aici!,Заполучен ЯДЕРНЫЙ ГРАНАТОМЁТ! Отсосите!, +You got an UZI!!,GOTUZI,,,,Získal@[ao_cs] jsi 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!!,Zdobyłeś UZI!!,Você pegou uma UZI!!,,Ai ridicat un UZI!!,Заполучен УЗИ!, +A HOIG Reznator - FRY some butt,GOTREZNATOR,,,,HOIG Reznátor - pár jich upeč,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,Reznator HOIG - skop trochę tyłków,Um Reznador HOIG - Hora de fritar,,Un Rezonator HOIG - Arde-i!,ХОЙГ Резнатор, +You got a Photon 'Zooka!,GOTPHOTONZOOKA,,,,Sebral@[ao_cs] jsi Fotonovou bazuku!,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!,Zdobyłeś Fotonozukę!,Você pegou uma Bazuca de Fótons!,,Ai ridicat o Bazooka Fotonică!,Заполучена фотон-базука!, +You carry a Big Stick!,GOTBIGSTICK,,,,Nosíš velkou bouchačku!,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!,Podnosisz Wielką Pałkę!,Você pegou um Grande Bastão!,,Ai ridicat un Băț Lung!,Заполучена длинная палка!, +You got a Tazer!!,GOTTAZER,,,,Získal@[ao_cs] jsi 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!!,Zdobyłeś Tazer!!,Você pegou um Tazer!!,,Ai ridicat un Taser!!,Заполучен тазер!, +You grab a Cryogun! FREEZE!,GOTCRYOGUN,,,,Sebral@[ao_cs] jsi krypušku! ANI SE NEHNI!,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!,Podniosłeś Zamrażarkę! STAĆ!,Você pegou uma Cryogun! FICA FRIO AÍ!,,Ai ridicat o Crio-armă! ÎNGHEAȚĂ!,Заполучена замораживающая пушка! НИ С МЕСТА!, +You grab some rounds!,GOTROUNDS,,,,Sebral@[ao_cs] jsi nějaké náboje!,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!,Podniosłeś trochę naboi!,Você pegou munição!,,Ai ridicat niște muniție!,Заполучена обойма патронов!, +You grab a case of rounds!,GOTROUNDSCASE,,,,Sebral@[ao_cs] jsi krabici nábojů!,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!,Podniosłeś skrzynkę naboi!,Você pegou uma caixa de munição!,,Ai ridicat un cartuș de muniție!,Заполучена коробка патронов!, +You grab a Torpedo!,GOTTORPEDO,"Was ""grap"" for some reason.",,,Sebral@[ao_cs] jsi torpédo!,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!,Podniosłeś Torpedę!,Você pegou um Torpedo!,,Ai ridicat o Torpilă!,Заполучена торпеда!, +You grab a case of Torpedos!,GOTTORPEDOS,,,,Sebral@[ao_cs] jsi krabici torpéd!,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!,Podniosłeś skrzynkę Torped!,Você pegou uma caixa de Torpedos!,,Ai ridicat o cutie de Torpile!,Заполучен ящик торпед!, +You grab a molecule module!,GOTMOLECULES,,,,Sebral@[ao_cs] jsi molekulový modul!,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!,Podniosłeś molekularny moduł!,Você pegou um módulo molecular!,,Ai ridicat un modul molecular!,Заполучен молекулярный модуль!, +You grab a tank full of molecules!,GOTMOLECULESTANK,,,,Sebral@[ao_cs] jsi sud plný molekul!,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!,Podniosłeś zbiornik pełen molekuł!,Você pegou um tanque cheio de moléculas!,,Ai ridicat un rezervor plin cu molecule!,Заполучен контейнер с молекулами!, +You grab some Cartridges!,GOTCARTRIDGES,,,,Sebral@[ao_cs] jsi nějaké kazety!,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!,Podniosłeś trochę pocisków!,Você pegou alguns Carregadores!,,Ai ridicat niște Cartușe!,Заполучены картриджи!, +You grab a case of Cartridges!,GOTCARTRIDGESCASE,,,,Sebral@[ao_cs] jsi krabici kazet!,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!,Podniosłeś skrzynkę pocisków!,Você pegou uma caixa de Carregadores!,,Ai ridicat o cutie de Cartușe!,Заполучен ящик картриджей!, +You grab a Valise stuffed with goods!,GOTVALISE,,,,Sebral@[ao_cs] jsi kufr plný munice!,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!,Podniosłeś Walizkę z wieloma dobrami!,Você pegou uma Mala cheia de equipamento!,,Ai ridicat o Valiză plină cu bunătăți!,Заполучена полная сумка боеприпасов!, +Force Field!,GOTFORCEFIELD,,,,Silové pole!,Kraftfeld!,,Fortkampo!,¡Campo de fuerza!,,Voimakenttä!,Champ de force!,Erőtér!,Campo di forza!,フォースフィールド!,방어막!,Krachtveld!,Pole Siłowe!,Campo de Força!,,Câmp de Forță!,Силовое поле!, 007Microtel,GOTMICROTEL,,,,,,,007 Microtel!,Microtel 007,,,007 Microtel,,,007マイクロテル,007마이크로텔 근력 향상 칩!,,,,,Microtel 007,Микрочип 007, -You are EnK Blind!,GOTENKBLIND,,,,Jsi EnK-slep@[adj_cs]!,Du bist EnK-blind!,,Vi estas ENK-Blinda,¡Tienes Ceguera EnK!,,Olet EnK-sokea!,Vous êtes aveugle à l'EnK!,,Sei EnK-cieco!,EnKブラインドみてえだ!,EnK 투명 위장 장치!,Jij bent EnK Blind!,Jesteś oślepiony przez EnK!,Você está vendado por EnK!,,Acum ești nedetectabil pentru Enk!,"У тебя EnK-видимость! -", -Vulcan rubber Boots!,GOTRUBBERBOOTS,,,,Gumové boty!,Gummistiefel!,,Vulkanaj Kauŭĉukaj Botoj!,¡Botas de goma vulcanizada!,,Vulkanoidut kumisaappaat!,Bottes en caoutchouc vulcanisé!,,Stivali di gomma vulcanica!,バルカンラバーブーツ!,벌컨 방화 부츠!,Vulcan rubber Laarzen!,Gumowe Buty Vulcan!,Botas Vulcanizadas!,,Bocanci din cauciuc Vulcan!,Резиновые сапоги!, -SI Array mapping!,GOTSIARRAY,,,,Mapa pole SI!,SI-Feld Karte!,,SI-matric-mapado!,¡Mapeado de Tabla SI!,,SI-kenttäkartta!,Carte du tableau SI!,,Mappatura di array SI!,SIアーレイ マッピング!,Si 어레이 지도!,,Mapa Pola SI!,Mapeamento por Campo de SI!,,Hartă SI compilată!,Составлена карта SI-массива!, -Infrared Visor!,GOTINFRARED,,,,Infračervené brýle!,Infrarotbrille!,,Transruĝa Viziero!,¡Visor infrarrojo!,,Infrapunavisiiri!,Viseur infrarouge!,,Visore a infrarossi!,赤外線バイザー!,적외선 바이져!,Infrarood vizier!,Wizjer na Podczerwień!,Visor Infravermelho!,,Vedere Infraroșie!,Инфракрасный визор!, -"Breathe deep, Inhaler!",GOTINHALER,,,,"Pořádně se nadechni, inhalátor!","Atme tief, Inhalierer!",,"Spiru profunde, inhalo!","¡Un inhalador, inspira fuerte!",,"Hengitä syvään, inhalaattori!","Respire, inhaleur!",,"Respirare profondamente, inalatore!",深呼吸だ、インヘイラー!,각성제를 주웠다. 잘 들이마셔!,"Adem diep in, inhalator!",Weź głęboki wdech! Inhalator!,Inalador! Respira fundo!,,"Inspiră adânc, Inhalatorule!",Ингалятор! Вдыхай глубже!, -A dose of Hydergine from a Hypo saves you!,GOTHYPONEED,,,,Jsi zachráněn@[ao_cs] dávkou Hyderginu z Hypa!,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!,,Una dose di Hydergine di un Hypo ti salva!,ハイポで ヒデルギン をキメた!,하이포의 하이데르진이 당신을 살렸다!,Een dosis Hydergine van een Hypo redt je!,Dawka Hyderginy z Hypo ratuje cię!,Uma dose de hidergina do Hypo para te salvar!,,O doză de Hidrogine dintr-o seringă te salvează!,Доза Редергина из шприца спасла тебя!, -You grab a Hypo!,GOTHYPO,,,,Sebral@[ao_cs] jsi Hypo!,Hypo!,,Vi prenis Injektilon!,¡Has pillado una jeringa hipodérmica!,,Kahmaiset piikin!,Vous prenez une seringue!,,Prendi un Hypo!,ハイポ を奪った!,하이포를 주웠다!,Je pakt een Hypo!,Podniosłeś Hypo!,Você pegou um Hypo!,,Ai ridicat o Seringă!,Заполучен шприц!, -You found a KeyCard!,GOTKEYCARD,,,,Nalezl@[ao_cs] jsi přístupovou kartu!,Schlüsselkarte gefunden!,,Vi trovis Ŝlosilkarton!,¡Has encontrado una Tarjeta Llave!,,Löysit avainkortin!,Vous trouvez une clé magnétique!,,Hai trovato una chiave magnetica!,キーカードを見つけた!,키 카드를 찾았다!,U heeft een sleutelkaart gevonden!,Znalazłeś Kartę Dostępu!,Você achou um Cartão de Passe!,,Ai găsit un Card-Cheie!,Найдена ключ-карта!, -You found a C-Key!,GOTCKEY,,,,Nalezl@[ao_cs] jsi kyberklíč!,C-Schlüssel gefunden!,,Vi trovis C-Ŝlosilon!,¡Has encontrado una Llave-C!,,Löysit C-avaimen!,Vous trouvez une C-Clé!,,Hai trovato una chiave C!,C-keyを見つけた!,C-키를 찾았다!,Je hebt een C-sleutel gevonden!,Znalazłeś Klucz C!,Você achou uma Chave-C!,,Ai găsit o Cheie-C!,Найден C-образный ключ!, -You found a Password!,GOTPASSWORD,,,,Nalezl@[ao_cs] jsi heslo!,Passwort gefunden!,,Vi trovis Pasvorton!,¡Has encontrado una Contraseña!,,Löysit salasanan!,Vous trouvez un mot de passe!,,Hai trovato una parola d'ordine!,パスワードを見つけた!,암호를 찾았다!,U heeft een wachtwoord gevonden!,Znalazłeś Hasło!,Você achou uma Senha!,,Ai găsit o Parolă!,Найден пароль!, -You found a blue Z-Key!,GOTBLUEZKEY,,,,Nalezl@[ao_cs] jsi modrý Z-klíč!,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!,,Hai trovato una chiave Z blu!,ブルー Z-Key を見つけた!,청색 Z-키를 찾았다!,Je hebt een blauwe Z-sleutel gevonden!,Znalazłeś niebieski Klucz Z!,Você achou uma Chave-Z azul!,,Ai găsit o Z-Cheie albastră!,Найден синий Z-образный ключ!, -You found a yellow Z-Key!,GOTYELWZKEY,,,,Nalezl@[ao_cs] jsi žlutý Z-klíč!,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!,,Hai trovato una chiave Z gialla!,イエローZ-Key を見つけた!,황색 Z-키를 찾았다!,Je hebt een gele Z-sleutel gevonden!,Znalazłeś żółty Klucz Z!,Você achou uma Chave-Z amarela!,,Ai găsit o Z-Cheie galbenă!,Найден жёлтый Z-образный ключ!, -You found a red Z-Key!,GOTREDZKEY,,,,Nalezl@[ao_cs] jsi červený Z-klíč!,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!,,Hai trovato una chiave Z rossa!,レッド Z-Key を見つけた!,적색 Z-키를 찾았다!,Je hebt een rode Z-sleutel gevonden!,Znalazłeś czerwony Klucz Z!,Você achou uma Chave-Z vermelha!,,Ai găsit o Z-Cheie roșie!,Найден красный Z-образный ключ!, -Body Armor!,GOTBODYARMOR,,,,Brnění!,Körperpanzerung!,,Kiraso!,¡Armadura!,,Suojavarustus!,Armure!,,Giubbotti antiproiettile!,ボディーアーマー!,강화복!,Kogelvrije vesten!,Pancerz!,Colete a Prova de Balas!,,Armură de Corp!,Бронежилет!, +You are EnK Blind!,GOTENKBLIND,,,,Jsi EnK-slep@[adj_cs]!,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!,Jesteś oślepiony przez EnK!,Você está vendado por EnK!,,Acum ești nedetectabil pentru Enk!,У тебя EnK-видимость!, +Vulcan rubber Boots!,GOTRUBBERBOOTS,,,,Gumové boty!,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!,Gumowe Buty Vulcan!,Botas Vulcanizadas!,,Bocanci din cauciuc Vulcan!,Резиновые сапоги!, +SI Array mapping!,GOTSIARRAY,,,,Mapa pole SI!,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 어레이 지도!,,Mapa Pola SI!,Mapeamento por Campo de SI!,,Hartă SI compilată!,Составлена карта SI-массива!, +Infrared Visor!,GOTINFRARED,,,,Infračervené brýle!,Infrarotbrille!,,Transruĝa Viziero!,¡Visor infrarrojo!,,Infrapunavisiiri!,Viseur infrarouge!,Infravörös Sisak!,Visore a infrarossi!,赤外線バイザー!,적외선 바이져!,Infrarood vizier!,Wizjer na Podczerwień!,Visor Infravermelho!,,Vedere Infraroșie!,Инфракрасный визор!, +"Breathe deep, Inhaler!",GOTINHALER,,,,"Pořádně se nadechni, inhalátor!","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!",Weź głęboki wdech! Inhalator!,Inalador! Respira fundo!,,"Inspiră adânc, Inhalatorule!",Ингалятор! Вдыхай глубже!, +A dose of Hydergine from a Hypo saves you!,GOTHYPONEED,,,,Jsi zachráněn@[ao_cs] dávkou Hyderginu z Hypa!,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!,Dawka Hyderginy z Hypo ratuje cię!,Uma dose de hidergina do Hypo para te salvar!,,O doză de Hidrogine dintr-o seringă te salvează!,Доза Редергина из шприца спасла тебя!, +You grab a Hypo!,GOTHYPO,,,,Sebral@[ao_cs] jsi 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!,Podniosłeś Hypo!,Você pegou um Hypo!,,Ai ridicat o Seringă!,Заполучен шприц!, +You found a KeyCard!,GOTKEYCARD,,,,Nalezl@[ao_cs] jsi přístupovou kartu!,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!,Znalazłeś Kartę Dostępu!,Você achou um Cartão de Passe!,,Ai găsit un Card-Cheie!,Найдена ключ-карта!, +You found a C-Key!,GOTCKEY,,,,Nalezl@[ao_cs] jsi kyberklíč!,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!,Znalazłeś Klucz C!,Você achou uma Chave-C!,,Ai găsit o Cheie-C!,Найден C-образный ключ!, +You found a Password!,GOTPASSWORD,,,,Nalezl@[ao_cs] jsi heslo!,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!,Znalazłeś Hasło!,Você achou uma Senha!,,Ai găsit o Parolă!,Найден пароль!, +You found a blue Z-Key!,GOTBLUEZKEY,,,,Nalezl@[ao_cs] jsi modrý Z-klíč!,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!,Znalazłeś niebieski Klucz Z!,Você achou uma Chave-Z azul!,,Ai găsit o Z-Cheie albastră!,Найден синий Z-образный ключ!, +You found a yellow Z-Key!,GOTYELWZKEY,,,,Nalezl@[ao_cs] jsi žlutý Z-klíč!,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!,Znalazłeś żółty Klucz Z!,Você achou uma Chave-Z amarela!,,Ai găsit o Z-Cheie galbenă!,Найден жёлтый Z-образный ключ!, +You found a red Z-Key!,GOTREDZKEY,,,,Nalezl@[ao_cs] jsi červený Z-klíč!,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!,Znalazłeś czerwony Klucz Z!,Você achou uma Chave-Z vermelha!,,Ai găsit o Z-Cheie roșie!,Найден красный Z-образный ключ!, +Body Armor!,GOTBODYARMOR,,,,Brnění!,Körperpanzerung!,,Kiraso!,¡Armadura!,,Suojavarustus!,Armure!,Testpáncél!,Giubbotti antiproiettile!,ボディーアーマー!,강화복!,Kogelvrije vesten!,Pancerz!,Colete a Prova de Balas!,,Armură de Corp!,Бронежилет!, Centrophenoxine,GOTCENTROPHENOXINE,,,,Centrofenoxin,,,Centrofenoksino!,¡Centrofenoxina!,,Sentrofenoksiinia,Centrophenoxine!,,,セントロフェノキシン!,메클로페녹세이트!,,Centrofenoxina,Centrofenoxina,,Centrofenoxine,Центрофеноксин, -You grab a Kevlar vest!,GOTKEVLARVEST,,,,Sebral@[ao_cs] jsi kevlarovou vestu!,Kevlarweste!,,Vi prenis kevlaran veŝton!,¡Has pillado un traje de Kevlar!,¡Has recogido un traje de Kevlar!,Kahmaiset Kevlar-liivit!,Veste en Kevlar!,,Prendi una maglia di kevlar!,ケブラーベスト を奪った!,방탄복을 주웠다!,Pak een Kevlar vest!,Podniosłeś kamizelkę kuloodporną!,Você pegou um Colete de Kevlar!,,Ai ridicat o vestă din Kevlar!,Заполучен кевларовый жилет!, -You grab Super Kevlar vest!,GOTSKEVLARVEST,,,,Sebral@[ao_cs] jsi superkevlarovou vestu!,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!,,Prendi una maglia super kevlar!,スーパーケブラーベスト を奪った!,중 방탄복을 주웠다!,Je pakt een Super Kevlar vest!,Podniosłeś superkamizelkę kuloodporną!,Você pegou um Super Colete de Kevlar!,,Ai ridicat o Super Vestă din Kevlar!,Заполучен усиленный кевларовый жилет!, -You grab a MicroKit!,GOTMICROKIT,,,,Sebral@[ao_cs] jsi mikrosadu!,MicroKit genommen!,,Vi prenis Kompleteton!,¡Has pillado un MicroKit!,¡Has recogido un MicroKit!,Kahmaiset Microkitin!,Microkit!,,Prendi un MicroKit!,マイクロキット を奪った!,마이크로킷을 주웠다!,Je pakt een MicroKit!,Podniosłeś MikroZestaw!,Você pegou um MicroKit!,,Ai ridicat un MicroKit!,Заполучена мини-аптечка!, -You grab a Dampener!,GOTDAMPENER,,,,Sebral@[ao_cs] jsi tlumič!,Dämpfer genommen!,,Vi prenis Dampilon!,¡Has pillado un Amortiguador!,¡Has recogido un Amortiguador!,Kahmaiset vaimentimen!,Amortisseur!,,Prendi un antivento!,ダンプナー を奪った!,완충 장치를 주웠다!,Je pakt een Demper!,Podniosłeś Tłumik!,Você pegou um Amortecedor!,,Ai ridicat un Amortizor!,Заполучен глушитель!, -You need a C-Key to access this item!,PD_CKEY,,,,K přístupu potřebuješ kyberklíč!,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!,,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!,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-образный ключ!", -You need a KeyCard to access this item!,PD_KEYCARD,,,,K přístupu potřebuješ přístupovou kartu!,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!,,Hai bisogno di una chiave magnetica per accedere a questo oggetto!,アクセスには キーカード が必要だ!,키 카드가 있어야 작동이 가능하다!,U heeft een sleutelkaart nodig om toegang te krijgen tot dit item!,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!,"Нет доступа, нужен ключ-карта!", -You need a Password to access this item!,PD_PASSWORD,,,,K přístupu potřebuješ heslo!,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!,,Hai bisogno di una parola d'ordine per accedere a questo oggetto!,アクセスには パスワード が必要だ!,암호를 입력해야 작동이 가능하다!,Je hebt een wachtwoord nodig om toegang te krijgen tot dit item!,Potrzebujesz Hasła by uruchomić ten przedmiot!,Você precisa de uma Senha para acessar!,,Ai nevoie de Parolă pentru a accesa acest obiect!,"Нет доступа, нужен пароль!", -You need a Blue Z-Key to make this work,PD_BLUEZKEY,,,,Tohle bude fungovat jen s modrým Z-klíčem.,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.,,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.,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-образный ключ!", -You need a Red Z-Key to make this work!,PD_REDZKEY,,,,Tohle bude fungovat jen s červeným Z-klíčem.,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.,,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!,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-образный ключ!", -You need a Yellow Z-Key to make this work!,PD_YELWZKEY,,,,Tohle bude fungovat jen se žlutým Z-klíčem.,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.,,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!,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-образный ключ!", +You grab a Kevlar vest!,GOTKEVLARVEST,,,,Sebral@[ao_cs] jsi kevlarovou vestu!,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!,Podniosłeś kamizelkę kuloodporną!,Você pegou um Colete de Kevlar!,,Ai ridicat o vestă din Kevlar!,Заполучен кевларовый жилет!, +You grab Super Kevlar vest!,GOTSKEVLARVEST,,,,Sebral@[ao_cs] jsi superkevlarovou vestu!,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!,Podniosłeś superkamizelkę kuloodporną!,Você pegou um Super Colete de Kevlar!,,Ai ridicat o Super Vestă din Kevlar!,Заполучен усиленный кевларовый жилет!, +You grab a MicroKit!,GOTMICROKIT,,,,Sebral@[ao_cs] jsi mikrosadu!,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!,Podniosłeś MikroZestaw!,Você pegou um MicroKit!,,Ai ridicat un MicroKit!,Заполучена мини-аптечка!, +You grab a Dampener!,GOTDAMPENER,,,,Sebral@[ao_cs] jsi tlumič!,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!,Podniosłeś Tłumik!,Você pegou um Amortecedor!,,Ai ridicat un Amortizor!,Заполучен глушитель!, +You need a C-Key to access this item!,PD_CKEY,,,,K přístupu potřebuješ kyberklíč!,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!,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-образный ключ!", +You need a KeyCard to access this item!,PD_KEYCARD,,,,K přístupu potřebuješ přístupovou kartu!,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!,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!,"Нет доступа, нужен ключ-карта!", +You need a Password to access this item!,PD_PASSWORD,,,,K přístupu potřebuješ heslo!,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!,Potrzebujesz Hasła by uruchomić ten przedmiot!,Você precisa de uma Senha para acessar!,,Ai nevoie de Parolă pentru a accesa acest obiect!,"Нет доступа, нужен пароль!", +You need a Blue Z-Key to make this work,PD_BLUEZKEY,,,,Tohle bude fungovat jen s modrým Z-klíčem.,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.,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-образный ключ!", +You need a Red Z-Key to make this work!,PD_REDZKEY,,,,Tohle bude fungovat jen s červeným Z-klíčem.,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!,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-образный ключ!", +You need a Yellow Z-Key to make this work!,PD_YELWZKEY,,,,Tohle bude fungovat jen se žlutým Z-klíčem.,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!,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-образный ключ!", "Twenty mill in gold doesn't seem worth all this aggravation, does it, hacker? Makes the pen look like a freakin' picnic! @@ -220,9 +218,15 @@ piraté auparavant était comme ça! Il faut que vous trouvez le prochain terminal, traversez le cyberespace, découpez du mutant et barrez-vous -d'ici!",,"Venti mulini d'oro non sembra valere tutto -questo peggioramento, vero, hacker? -Fa sembrare la penna come un +d'ici!","Húsz milka nem ér meg ennyi bosszankodás, ugye hekker? A cella ehhez képest egy francos piknik! + +Baromi ocsmány bio-mutációk és embertársaid úgy lógnak le a mennyezetről, mintha csak a hentesnél lennénk. + +Mi az ördög ez a GENIE? Semmilyen más számítógépre nem hasonlít amit hekkelni próbáltál! + +Jobban jársz ha megkeresed a következő terminált, végig rombolsz a kibertéren mutánsokat gázolva, és minél előbb itt hagyod Dodge-ot!","Venti milioni in oro non sembra valere tutta +questa esasperazione , vero, hacker? +Fa sembrare la prigione come un cavolo di picnic! Le enormi bio-mutazioni e i tuoi @@ -237,7 +241,6 @@ Faresti meglio a trovare il terminale successivo, a fare un giro nel c-spazio, a tagliare a dadi qualche culo mutante, e ad uscire da Dodge! - ","20ミリの金塊にこの重大な事態の価値を見出せない、 それとも、ハッカーの仕業か? 幻覚のピクニックってワケでもねえ! @@ -453,26 +456,33 @@ Des fluides neuraux humains alimentent ces insectes! Pas de surprise que le coin est désert. Retournez au sous-comité -et faites gaffe à vous!",,"Dove sono tutte le persone?! -Parigi è una città fantasma, a meno -che non si consideri mutante -bug cittadini eccezionali. +et faites gaffe à vous!","Hol vannak az emberek? -Hai colpito resistenza sanguinosa. -Amico, questi insetti possono combattere! -Fortunatamente per voi non sono le +Párizs egy szellemváros, kivétel ha a mutáns óriás bogarakat nem vesszük számba mint mintapolgár. + +Komoly ellenállásba ütköztél. Ezek a bogarak aztán tudnak harcolni! Szerencsédre nem a legélesebb kések a fiókban. + +Szerencsére meg sikerült kerítened az információkat, amit az albizottság akart...és igen piszkos! + +Kiszívják ezek a dögök az emberek gerincvelejét! Nem is csoda, hogy a szomszédság igen megritkult. Jelezz vissza az albizottságnak, és vigyázz magadra...","Dove sono tutte le persone?! +Parigi è una città fantasma, a meno +che non si considerino questi +mutanti come cittadini eccezionali. + +Hai trovato resistenza feroce. +Amico, questi mutanti sanno combattere! +Fortunatamente per te non sono le luci dei portici più brillanti del blocco. -Ma hai ottenuto un po' dell'informatica -che il sottocomitato vuole. Ed è brutto! +Ma hai ottenuto un po' delle informazioni +che il sottocomitato vuole. E sono brutte! I fluidi neurali umani alimentano -questi insetti! Non c'è da stupirsi -che il quartiere sia sempre più rado. -Segnala al sottocomitato. +questi mutanti! Non c'è da stupirsi +che il quartiere sia sempre più spopolato. +Riporta al sottocomitato. -E guardatevi le spalle ... -","皆何処に行った?! +E guardati le spalle ...","皆何処に行った?! パリはゴーストタウンと化した、突然変異したバグ共が 未解決なまま自分以外の住民はいなくなった。 @@ -587,8 +597,7 @@ universe you'll find its mutant butt! And the gold? Hell, this is for free. -.....(to be continued)..... -",X3TEXT,,,,"Civilizace, tak jak ji známe, je pryč. +.....(to be continued).....",X3TEXT,,,,"Civilizace, tak jak ji známe, je pryč. Nada. Nilch. Bez přátel, bez rodiny. Bez lidí. @@ -664,19 +673,29 @@ le cul! Ca va en chier! Oh, et l'Or? Non, ça, c'est gratuit... -... A suivre!",,"Civiltà come lo sapevi che è nada! +... A suivre!","A civilizáció mint olyan már nem létezik! + +Se barátok, se család. Nincs több ember. Legalábbis nem normális emberek. + +Csak egy dolog van hátra...GENIE! Már olyan zabos vagy, hogy ha a világ végére is kell mened érte, akkor is megkeresed és végzel vele. + +És az arany? A fenébe is, ingyen van. + +.....(folytatjuk).....","La civiltà come la conoscevi è nada! Nessun amico, nessuna famiglia. Niente più persone. Non persone normali, comunque. Solo una cosa è rimasta...GENIE! -E se dovete andare alla fine -dell'universo troverete il suo +E se dovessi andare alla fine +dell'universo troveresti il suo culo mutante! Perché ora sei incazzato! -E l'oro? Diavolo, questo è gratis... -","俺の知っている文明は崩壊した! +E l'oro? Al diavolo, questo è gratis... + + +.....(continua).....","俺の知っている文明は崩壊した! 友も。家族も。住民も。まともなヤツは何もかも 消え失せた。 @@ -751,7 +770,7 @@ Iar aurul? La naiba cu el, asta e din partea casei. Осталось только одно существо. ДЖИНН! Ты надерёшь зад этому уроду, даже если -придётся дойти до края Вселенной. Теперь +придётся дойти до края вселенной. Теперь это личное! Что насчёт золота? К чёрту, это не ради @@ -821,13 +840,18 @@ Vous ne pouvez pas contacter le sous-comité. Cela signifie qu'il est compromis. -Vous.. êtes seul.",,"Sei vivo! +Vous.. êtes seul.","Még életben vagy! + +Mik voltak az esélyeid hekkerem?! Még a csapból is a bogarak folynak. + +Nem tudod elérni az albizottságot, ami azt jelenti hogy kompromittálódtak. + +Már...csak Te maradtál.","Sei vivo! Quali sono queste probabilità, hacker?! -Perché strisciano di insetti. +Perché i mutanti sono ovunque Non puoi raggiungere il sottocomitato, Il che significa che è stato compromesso. -Tu... sei solo. -","俺は生きている! +Tu... sei solo.","俺は生きている! 何か勝ち目はあるか、ハッカー?! バグ共がそこいらを蠢いている。 @@ -876,7 +900,7 @@ a fost compromis. Ești... singur.","Ты выжил! -Какая теперь разница, Хакер? Это место +Какая теперь разница, хакер? Это место просто кишит багами. Ты не можешь связаться с подкомитетом. @@ -887,50 +911,50 @@ Ești... singur.","Ты выжил! ", ,,,,,,,,,,,,,,,,,,,,,,, GenEmp Corp.,TXT_HACXMAP01,,,,Sídlo GenEmp,,,Korporacio GenEmp,,,GenEmp-yhtiö,,,,GenEmpコーポ,ZONE 1: 진엠프 주식회사 본부,,,,,Corporația GenEmp,Корпорация ГенИмп, -Tunnel Town,TXT_HACXMAP02,,,,Tunelové město,Tunnelstadt,,Tunelo Urbeto,Pueblo Túnel,,Tunnelikaupunki,Ville Tunnel,,Città del tunnel,トンネル タウン,ZONE 2: 터널 도시,Tunnelstad,Miasto Tuneli,Cidade Túnel,,Orașul Subteran,Подземный город, -Lava Annex,TXT_HACXMAP03,,,,Lávová přístavba,Lavaanbau,,Lafa Anekso,Anexo de Lava,,Laavalaajennus,Annexe de Lave,,Annesso di lava,ラバ アネックス,ZONE 3: 용암 속 건물,Lava Bijlage,Aneks Lawy,Anexo de Lava,,Anexa de Lavă,Лавовая электростанция, -Alcatraz,TXT_HACXMAP04,,,,,,,Alkatrazo,,,,,,,アルカトラズ,ZONE 4: 알카트라즈,,,,,,Алькатрас, -Cyber Circus,TXT_HACXMAP05,,,,Kybercirkus,Cyberzirkus,,Cibernetika Cirko,Circo Cibernético,,Kybersirkus,,,Circo Cyber,サイバーサークル,ZONE 5: 사이버 서커스,,Cyber Cyrk,Circo Cibernético,,Circ Cibernetic,Кибер-Цирк, +Tunnel Town,TXT_HACXMAP02,,,,Tunelové město,Tunnelstadt,,Tunelo Urbeto,Pueblo Túnel,,Tunnelikaupunki,Ville Tunnel,Kanális Község,Città del tunnel,トンネル タウン,ZONE 2: 터널 도시,Tunnelstad,Miasto Tuneli,Cidade Túnel,,Orașul Subteran,Подземный город, +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,Aneks Lawy,Anexo de Lava,,Anexa de Lavă,Лавовая электростанция, +Alcatraz,TXT_HACXMAP04,,,,,,,Alkatrazo,,,,,Alkatraz,,アルカトラズ,ZONE 4: 알카트라즈,,,,,,Алькатрас, +Cyber Circus,TXT_HACXMAP05,,,,Kybercirkus,Cyberzirkus,,Cibernetika Cirko,Circo Cibernético,,Kybersirkus,,Kiber Cirkusz,Circo Cyber,サイバーサークル,ZONE 5: 사이버 서커스,,Cyber Cyrk,Circo Cibernético,,Circ Cibernetic,Киберцирк, Digi-Ota,TXT_HACXMAP06,,,,,,,,,,,,,,デジ - オータ,ZONE 6: 디지-오타,,,,,,Диджитал-Ота, -The Great Wall,TXT_HACXMAP07,,,,Velká zeď,Die große Mauer,,La Grandega Muro,La Gran Muralla,,Suuri muuri,La grande Muraille,,Il grande muro,ザ - グレート ウォール,ZONE 7: 만리장성,De grote muur,Wielka Ściana,A Grande Muralha,,Marele Zid,Великая стена, -Garden of Delights,TXT_HACXMAP08,,,,Zahrada rozkoše,Lustgarten,,Ĝardeno de Ĝuoj,Jardin de las Delicias,,Nautintojen puutarha,Jardin de Délices,,Giardino delle delizie,ガーデン オブ デライト,ZONE 8: 쾌락의 정원,Tuin van lekkernijen,Ogród Zachwytu,Jardim dos Prazeres,,Grădina Plăcerilor,Сад наслаждений, -Hidden Fortress,TXT_HACXMAP09,,,,Skrytá pevnost,Versteckte Festung,,Kaŝita Fortreso,Fortaleza Oculta,,Salainen linnoitus,Forteresse Secrète,,Fortezza nascosta,ヒドゥン フォートレス,ZONE 9: 숨겨진 요새,Verborgen Vesting,Ukryta Forteca,Fortaleza Oculta,,Fortăreața Ascunsă,Скрытая крепость, -Anarchist Dream,TXT_HACXMAP10,,,,Anarchistův sen,Anarchistentraum,,Anarkia Sonĝo,Sueño Anarquista,,Anarkistin unelma,Rève d'Anarchiste,,Sogno anarchico,アナーキスト ドリーム,ZONE 10: 아나키스트의 꿈,Anarchistische droom,Sen Anarchisty,Sonho Anarquista,,Vis Anarhist,Анархистская утопия, +The Great Wall,TXT_HACXMAP07,,,,Velká zeď,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,Wielka Ściana,A Grande Muralha,,Marele Zid,Великая стена, +Garden of Delights,TXT_HACXMAP08,,,,Zahrada rozkoše,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,Ogród Zachwytu,Jardim dos Prazeres,,Grădina Plăcerilor,Сад наслаждений, +Hidden Fortress,TXT_HACXMAP09,,,,Skrytá pevnost,Versteckte Festung,,Kaŝita Fortreso,Fortaleza Oculta,,Salainen linnoitus,Forteresse Secrète,Eltitkolt Erőd,Fortezza nascosta,ヒドゥン フォートレス,ZONE 9: 숨겨진 요새,Verborgen Vesting,Ukryta Forteca,Fortaleza Oculta,,Fortăreața Ascunsă,Скрытая крепость, +Anarchist Dream,TXT_HACXMAP10,,,,Anarchistův sen,Anarchistentraum,,Anarkia Sonĝo,Sueño Anarquista,,Anarkistin unelma,Rève d'Anarchiste,Anarchista Álom,Sogno anarchico,アナーキスト ドリーム,ZONE 10: 아나키스트의 꿈,Anarchistische droom,Sen Anarchisty,Sonho Anarquista,,Vis Anarhist,Анархистская утопия, 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,,,ゴシック ガントレット,ZONE 12: 고딕풍 결투장,,Gotycka Rękawica,Punição Gótika,,Mănușa Gotică,Готическая перчатка, -The Sewers,TXT_HACXMAP13,,,,Kanály,Die Kanäle,,La Kanaloj,Las Alcantarillas,,Viemärit,Les Egouts,,Le fogne,ザ・サワー,ZONE 13: 하수 처리장,De Riolen,Ścieki,Os Esgotos,,Canale,Канализация, -Trode Wars,TXT_HACXMAP14,,,,Válka elektrod,Elektrodenkrieg,,Milito de Elektrodoj,Guerra de Electrodos,,Trodisodat,Guerre des Trodes,,Guerra degli elettrodi,トレード ウォーズ,ZONE 14: 전격의 전쟁,Trode oorlogen,Wojna Elektrod,Guerra de Eletrodos,,Război cu Electrozi,Торговые войны, -Twilight of Enk's,TXT_HACXMAP15,,,,Soumrak EnKu,Zwielicht von EnK,,Krespusko de EnK-oj,Crepúsculo de los Enk,,EnKin illankoitto,Crépuscule des Enk's,,Crepuscolo di Enk,Enkタチ ノ トワイライト,ZONE 15: 전자황혼,Schemering van Enk's,Zmierzch Enk,Crepúsculo de Enk's,,Amurgul lui Enk,Сумерки EnK, +Gothik Gauntlet,TXT_HACXMAP12,,,,Gotický trest,,,Gotika Spaliro,Guantelete Gótiko,,Goottinen kujanjuoksu,Gantelet Gothik,Gótikus Vesszőfutás,,ゴシック ガントレット,ZONE 12: 고딕풍 결투장,,Gotycka Rękawica,Punição Gótika,,Mănușa Gotică,Готическая перчатка, +The Sewers,TXT_HACXMAP13,,,,Kanály,Die Kanäle,,La Kanaloj,Las Alcantarillas,,Viemärit,Les Egouts,A Kanális,Le fogne,ザ・サワー,ZONE 13: 하수 처리장,De Riolen,Ścieki,Os Esgotos,,Canale,Канализация, +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,Wojna Elektrod,Guerra de Eletrodos,,Război cu Electrozi,Торговые войны, +Twilight of Enk's,TXT_HACXMAP15,,,,Soumrak EnKu,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,Zmierzch Enk,Crepúsculo de Enk's,,Amurgul lui Enk,Сумерки EnK, 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,Многоликий Сайбэкс, -River of Blood,TXT_HACXMAP17,,,,Řeka krve,Blutfluss,,Rivero de Sango,Río de Sangre,,Verivirta,Rivière de Sang,,Fiume di sangue,リバー オブ ブラッド,ZONE 17: 학살의 강,Rivier van bloed,Rzeka Krwi,Rio de Sangue,,Râu de Sânge,Река крови, +River of Blood,TXT_HACXMAP17,,,,Řeka krve,Blutfluss,,Rivero de Sango,Río de Sangre,,Verivirta,Rivière de Sang,Vérfolyó,Fiume di sangue,リバー オブ ブラッド,ZONE 17: 학살의 강,Rivier van bloed,Rzeka Krwi,Rio de Sangue,,Râu de Sânge,Река крови, Bizarro,TXT_HACXMAP18,,,,Bizár,,,,,,,,,,ビザロ,ZONE 18: 요상한 곳,,,,,,Бизарро, -The War Rooms,TXT_HACXMAP19,,,,Válečné kabinety,Kriegsräume,,La Militĉambroj,Las Salas de Guerra,,Sotahuoneet,La Salle des Commandes,,Le stanze della guerra,ザ・ウォー ルーム,ZONE 19: 전략 회의실,De oorlogskamers,Pokoje Wojny,As Salas de Comando,,Camerele de Control,Генеральный штаб, -Intruder Alert!,TXT_HACXMAP20,,,,"Pozor, vetřelec!",Eindringlingsalarm!,,Alarmo pri Entrudanto!,¡Alerta de Intruso!,,Murtohälytys!,"Alerte, Intrus!",,Allarme intruso!,シンニュウシャ アリ!,ZONE 20: 칩입자 경보!,Inbreker alarm!,Alarm Intruz!,Alerta de Intruso!,,Alertă Intrus!,Тревога! Нарушитель!, -Desiccant Room,TXT_HACXMAP31,,,,Sušící místnost,Trocknungsraum,,Ĉambro de Elsekigo,Sala del Desecante,,Kuivatesali,Salle du Desiccant,,Stanza disseccante,ダスキン ルーム,ZONE 31: 건조한 곳,Drogende kamer,Śluza Osuszająca,Sala do Dessecante,,Camera Desicanților,Сушильная комната, +The War Rooms,TXT_HACXMAP19,,,,Válečné kabinety,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,Pokoje Wojny,As Salas de Comando,,Camerele de Control,Генеральный штаб, +Intruder Alert!,TXT_HACXMAP20,,,,"Pozor, vetřelec!",Eindringlingsalarm!,,Alarmo pri Entrudanto!,¡Alerta de Intruso!,,Murtohälytys!,"Alerte, Intrus!",Betolakodó Riadó!,Allarme intruso!,シンニュウシャ アリ!,ZONE 20: 칩입자 경보!,Inbreker alarm!,Alarm Intruz!,Alerta de Intruso!,,Alertă Intrus!,Тревога! Нарушитель!, +Desiccant Room,TXT_HACXMAP31,,,,Sušící místnost,Trocknungsraum,,Ĉambro de Elsekigo,Sala del Desecante,,Kuivatesali,Salle du Desiccant,Szárító Szoba,Stanza disseccante,ダスキン ルーム,ZONE 31: 건조한 곳,Drogende kamer,Śluza Osuszająca,Sala do Dessecante,,Camera Desicanților,Сушильная комната, "Now Arriving At... -",STSTR_CLEV,,,,Příjezd do...,Angekommen bei...,,Nun Ĝisirante...,Ahora llegando a...,,Seuraavana...,On arrive maintenant à:,,Arrivando a...,今到着した...,이동하는 중...,Nu we aankomen bij....,Wchodzisz do...,Agora chegando em ...,,Acum Sosiți La...,Переходим на..., -...gonna fry your ass!,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,...ti upeče prdel!,...ich brate deinen Arsch!,,...fritos vian pugon!,... ¡voy a freirte el trasero!,,...kärtsää takalistosi!,...C'est l'heure de botter du cul!,,....ti friggerà il culo!,...ケツまくれ!,... 지져버리겠어!,...gaat je kont bakken!,...skopię ci dupę!,...vou fritar teu rabo!,,...te voi prăji!,...поджарит твою задницу!, +",STSTR_CLEV,,,,Příjezd do...,Angekommen bei...,,Nun Ĝisirante...,Ahora llegando a...,,Seuraavana...,On arrive maintenant à:,Következő állomás...,Arrivando a...,今到着した...,이동하는 중...,Nu we aankomen bij....,Wchodzisz do...,Agora chegando em ...,,Acum Sosiți La...,Переходим на..., +...gonna fry your ass!,STSTR_CHOPPERS,"Printed when entering the idchoppers cheat, which gives the player a chainsaw",,,...ti upeče prdel!,...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!,...skopię ci dupę!,...vou fritar teu rabo!,,...te voi prăji!,...поджарит твою задницу!, "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, 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のどれだ?","무적, 광전사, 투명, 보호복, 지도, 아니면 바이저?",,"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).","нерањ., снага, невидљ., радиј., мапа или ноћ. визор" -Let's Get Serious!,STSTR_BEHOLDX,,,,Teď je to vážné!,Es wird ernst!,,Ni Serioziĝu!,¡Vamos en Serio!,,Otetaanpa tosissaan!,Passons aux choses sérieuses!,,Prendiamoci sul serio!,マジになったぜ!,철들 때다!,Laten we serieus worden!,Bądźmy Poważni!,Agora a Coisa Fica Séria!,,Să Devenim Serioși!,А теперь серьёзно!, -Cyberslicer Mode ON,STSTR_NCON,,,,Režim kybersekače ZAP,Cyberschnetzelmodus AN,,Cibernetika Tranĉila Reĝimo AKTIVA,Modo Cibercorte ACTIVADO,,Kyberviipaloijatila PÄÄLLÄ,,,Modalità Cyberslicer ATTIVADA,サイバースライサーモード オン,전자마귀 모드 ON,Cyberslicer-modus AAN,Tryb Cybercięcia WŁĄCZONY,Cibercortador ATIVADO,,Modul Cibertăietor ACTIVAT,Режим кибер-резака вкл., -Cyberslicer Mode OFF,STSTR_NCOFF,,,,Režim kybersekače VYP,Cyberschnetzelmodus AUS,,Cibernetika Tranĉila Reĝimo NEAKTIVA,Modo Cibercorte DESACTIVADO,,Kyberviipaloijatila POIS PÄÄLTÄ,,,Modalità Cyberslicer DISATTIVADA,サイバースライサーモード オフ,전자마귀 모드 OFF,Cyberslicer-modus UIT,Tryb Cybercięcia WYŁĄCZONY,Cibercortador DESATIVADO,,Modul Cibertăietor DEZACTIVAT,Режим кибер-резака откл., +Let's Get Serious!,STSTR_BEHOLDX,,,,Teď je to vážné!,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!,Bądźmy Poważni!,Agora a Coisa Fica Séria!,,Să Devenim Serioși!,А теперь серьёзно!, +Cyberslicer Mode ON,STSTR_NCON,,,,Režim kybersekače ZAP,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,Tryb Cybercięcia WŁĄCZONY,Cibercortador ATIVADO,,Modul Cibertăietor ACTIVAT,Режим кибер-резака включён., +Cyberslicer Mode OFF,STSTR_NCOFF,,,,Režim kybersekače VYP,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,Tryb Cybercięcia WYŁĄCZONY,Cibercortador DESATIVADO,,Modul Cibertăietor DEZACTIVAT,Режим кибер-резака отключён., Selection: Impossible ,STSTR_NOMUS,,,,Nemožný výběr,Falsche Auswahl,,Elekto: Malebla,Selección impossible,,Valinta ei mahdollinen,Séléction Impossible!,Lehetetlen Kiválasztás,Selezione impossibile,選択: 不可能,선택 불가능,Selectie: Onmogelijk,Niemożliwy wybór,Seleção: Impossível,,Selectare: Imposibilă,Выбор: Невозможен,НЕМОГУЋИ ИЗБОР "Pump Up The Volume -",STSTR_MUS,Should probably not be translated...,,,Zesil to!,,,,,,Nuppi kaakkoon,,,,音量を上げろよ,볼륨을 올려라!,,Podkręć Audio,"Som na Caixa, DJ!",,Mărește Volumul,Подкрутите громкость, -INIT-Twitch n'Kill Mode,STSTR_KFAADDED,,,,Inicializuji režim Twitch and Kill,Initiiere Twitch'n Kill-Modus,,INIC-Modo de Tiku kaj Buĉu,INIT-Modo Tirar a Matar,,INIT-Nykäise ja nylje -tila,,,Iniziare Twitch n'Kill Mode,INIT-Twitch n'Killモード,때리고 죽이는 모드 ON,,Inicjacja Trybu Drżenia I Zabijania,Inicializando Modo Chumbo Grosso,,INIT-Modul Click-și-Elimină,ИНИЦ: режим Кликай-И-Убивай, -"So be it, Hacker.",STSTR_FAADDED,,,,"Budiž, Hackeře.","So sei es, Hacker.",,"Tiel estu, Kodrompisto.","Que así sea, Hacker.",,"Olkoon niin, hakkeri.","Qu'il en soit ainsi, hacker.",,"Cosi' sia, Hacker.",好きにしろ、ハッカー。,"마음대로 해, 해커 양반.","Het zij zo, Hacker.","Niech tak będzie, Hakerze.","Que assim seja, Hacker.",,"Așa să fie, Hacker.","Да будет так, Хакер.", -Cyberpotence Mode ON,STSTR_DQDON,,,,Režim kybermoci ZAP,Cyberpotenzmodus AN,,Cibernetikpova Reĝimo AKTIVA,Modo Ciberpotencia ACTIVADO,,Kyberpotenssitila PÄÄLLÄ,,,Modo Cyberpotenza ATTIVADA,サイバーポテンスモード オン,전지전능 모드 ON,Cyberpotentiemodus AAN,Tryb Cyberpotencji WŁĄCZONY,Ciberpotência ATIVADA,,Ciberpotență ACTIVATĂ,Режим Кибер-улучшения вкл., -Cyberpotence Mode OFF,STSTR_DQDOFF,,,,Režim kybermoci VYP,Cyberpotenzmodus AUS,,Cibernetikpova Reĝimo NEAKTIVA,Modo Ciberpotencia DESACTIVADO,,Kyberpotenssitila POIS PÄÄLTÄ,,,Modo Cyberpotenza DISATTIVADA,サイバーポテンスモード オフ,전지전능 모드 OFF,Cyberpotentiemodus UIT,Tryb Cyberpotencji WYŁĄCZONY,Ciberpotência DESATIVADA,,Ciberpotență DEZACTIVATĂ,Режим Кибер-улучшения откл., -Tracking ON,AMSTR_FOLLOWON,,,,Sledování ZAP,Verfolgung AN,,Spurdado AKTIVA,Seguimiento ACTIVADO,,Seuranta PÄÄLLÄ,,,Mappa scorribile DISATTIVATA,トラッキング オン,추적 모드 ON,Tracking AAN,Namierzanie WŁĄCZONE,Seguimento ATIVADO,,Urmărire ACTIVATĂ,Сопровождение вкл., -Tracking OFF,AMSTR_FOLLOWOFF,,,,Sledování VYP,Verfolgung AUS,,Spurdado NEAKTIVA,Seguimiento DESACTIVADO,,Seuranta POIS PÄÄLTÄ,,,Mappa scorribile ATTIVATA,トラッキング オフ,추적 모드 OFF,Tracking UIT,Namierzanie WYŁĄCZONE,Seguimento DESATIVADO,,Urmărire DEZACTIVATĂ,Сопровождение откл., -- press Y to run away! -,DOSY,,,,- stiskni Y pro útěk! -,- drücke Y um wegzurennen -,,- premu Y por forkuri! -,- ¡pulsa Y para escapar! - ,,- Paina Y paetaksesi! -,-Appuie sur Y pour t'échapper!-,,- premere Y per scappare! -,-Y でトンズラだ!-,- 달아날려먼 Y 키를 눌러! -,- druk op Y om weg te lopen! -,- wciśnij Y by uciec! -,- Aperte Y para fugir! -,- Carrega Y para fugir! -,- apasă Y pentru a fugi! -,"- нажми «Y», чтобы сбежать! -", +",STSTR_MUS,Should probably not be translated...,,,Zesil to!,,,,,,Nuppi kaakkoon,,Csavard Fel a Szőnyeget,,音量を上げろよ,볼륨을 올려라!,,Podkręć Audio,"Som na Caixa, DJ!",,Mărește Volumul,Подкрутите громкость, +INIT-Twitch n'Kill Mode,STSTR_KFAADDED,,,,Inicializuji režim Twitch and Kill,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,,Inicjacja Trybu Drżenia I Zabijania,Inicializando Modo Chumbo Grosso,,INIT-Modul Click-și-Elimină,ИНИЦ: режим «Дрожи и убивай», +"So be it, Hacker.",STSTR_FAADDED,,,,"Budiž, Hackeře.","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.","Niech tak będzie, Hakerze.","Que assim seja, Hacker.",,"Așa să fie, Hacker.","Да будет так, хакер.", +Cyberpotence Mode ON,STSTR_DQDON,,,,Režim kybermoci ZAP,Cyberpotenzmodus AN,,Cibernetikpova Reĝimo AKTIVA,Modo Ciberpotencia ACTIVADO,,Kyberpotenssitila PÄÄLLÄ,,Kibererő Mód BE,Modo Cyberpotenza ATTIVADA,サイバーポテンスモード オン,전지전능 모드 ON,Cyberpotentiemodus AAN,Tryb Cyberpotencji WŁĄCZONY,Ciberpotência ATIVADA,,Ciberpotență ACTIVATĂ,Режим кибер-улучшения включён., +Cyberpotence Mode OFF,STSTR_DQDOFF,,,,Režim kybermoci VYP,Cyberpotenzmodus AUS,,Cibernetikpova Reĝimo NEAKTIVA,Modo Ciberpotencia DESACTIVADO,,Kyberpotenssitila POIS PÄÄLTÄ,,Kibererő Mód KI,Modo Cyberpotenza DISATTIVADA,サイバーポテンスモード オフ,전지전능 모드 OFF,Cyberpotentiemodus UIT,Tryb Cyberpotencji WYŁĄCZONY,Ciberpotência DESATIVADA,,Ciberpotență DEZACTIVATĂ,Режим кибер-улучшения отключён., +Tracking ON,AMSTR_FOLLOWON,,,,Sledování ZAP,Verfolgung AN,,Spurdado AKTIVA,Seguimiento ACTIVADO,,Seuranta PÄÄLLÄ,,Követés BE,Mappa scorribile DISATTIVATA,トラッキング オン,추적 모드 ON,Tracking AAN,Namierzanie WŁĄCZONE,Seguimento ATIVADO,,Urmărire ACTIVATĂ,Сопровождение включено., +Tracking OFF,AMSTR_FOLLOWOFF,,,,Sledování VYP,Verfolgung AUS,,Spurdado NEAKTIVA,Seguimiento DESACTIVADO,,Seuranta POIS PÄÄLTÄ,,Követés KI,Mappa scorribile ATTIVATA,トラッキング オフ,추적 모드 OFF,Tracking UIT,Namierzanie WYŁĄCZONE,Seguimento DESATIVADO,,Urmărire DEZACTIVATĂ,Сопровождение отключено., +- press Y to run away! -,DOSY,,,,- stiskni Y pro útě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! -,- wciśnij Y by uciec! -,- Aperte Y para fugir! -,- Carrega Y para fugir! -,- apasă Y pentru a fugi! -,"- нажми «Y», чтобы сбежать! -", "Are you insane or maladjusted? Well? Yes or No!",ENDGAME,,,,"Jsi blb@[adj_cs] nebo jen naveden@[adj_cs]? Tak? Jo nebo ne?","Bist du verrückt oder mies gelaunt? Also? Ja oer Nein?",,"Ĉu vi estas freneza aŭ misagordita? Ĉu? Jes aŭ Ne!?","¿Estás loc@[ao_esp] o descolocad@[ao_esp]? ¿Y bien? ¿Sí o No?",,"Oletko hullu tai häiriintynyt? -No? Y tai N!",Vous êtes fou où malajusté? Eh bien? Oui où non?,,"Sei pazzo o disadattato? +No? Y tai N!",Vous êtes fou où malajusté? Eh bien? Oui où non?,"Őrült vagy, vagy csak simán rosszul vagy összerakva? Nos? Igen vagy Nem!","Sei pazzo o disadattato? Allora? Sì o no!","お前はイカれた社会不適合者だろ? あぁ?イエスかノーか言え!","부적응은 안 하겠지? 그렇겠지? 자신 있으면 선택해!","Ben je gek of onaangepast? @@ -957,7 +981,9 @@ tätä taitotasoa, hakkeri! Paina Y kuollaksesi. ","Vous êtes sûr? Vous n'arriverez pas à tenir le coup, hacker! -Appuyez sur Y pour mourir.",,"Sei sicura? Non puoi gestire +Appuyez sur Y pour mourir.","Biztos vagy benne? Nem hinném hogy elbírsz ezzel a fokozattal hekker. + +Nyomj Y-t a halálhoz.","Sei sicuro? Non puoi gestire questa abilità, hacker! Premere Y per morire. ","本気か? @@ -1124,17 +1150,17 @@ Apasă Y sau N.","Загрузить файл Thug,CC_THUG,,,,Pobuda,Scherge,,Perfortuloj,Matón,,Roisto,Brute,Bandatag,Tazza,チンピラ,서그,Schurk,Zbir,Bandido,,Bandit,Головорез, Android,CC_ANDROID,,,,,,,Androido,Androide,,Androidi,Androïde,,,アンドロイド,안드로이드,Androïde,Android,Andróide,,,Андроид, ICE,CC_ICE,,,,,,,,,,,,,,アイス,아이스,,,,,,ЛЁД, -Buzzer,CC_BUZZER,,,,Bzučák,Summer,,Zumilo,Zumbador,,Surisija,,,Cicalino,ブザー,버저,Zoemer,Brzęczyk,,,Dronă,Летун, +Buzzer,CC_BUZZER,,,,Bzučák,Summer,,Zumilo,Zumbador,,Surisija,,Sokkoló,Cicalino,ブザー,버저,Zoemer,Brzęczyk,,,Dronă,Летун, D-Man,CC_DMAN,,,,,,,D-Vir',,,D-mies,,,,D-Man,디-맨,,,,,,Д-Мэн, -Phage,CC_PHAGE,,,,Fág,,,Faĝo,Fago,,Fagi,,,Fago,ファージ,페이지,Faag,Fag,Fago,,Mâncător,Пожиратель, -Monstruct,CC_MONSTRUCT,,,,Monstrukce,Monstrukt,,Monstrukto,,,Keinohirviö,,,Mostrutto,モンストラクト,몬스트럭트,Monstructie,Monstrukt,,,,Монструкт, -Mecha Maniac,CC_MECH,,,,Mechamaniak,,,Mekanika Frenezulo,Meca-Maníaco,,Mechamaanikko,Mécha-maniaque,,Mecha Maniaco,メカマニア,메카 메니악,Mecha Maniak,Mechaniczny Maniak,Meca-Maníaco,,Meca-Maniac,Механоман, +Phage,CC_PHAGE,,,,Fág,,,Faĝo,Fago,,Fagi,,Fekély,Fago,ファージ,페이지,Faag,Fag,Fago,,Mâncător,Пожиратель, +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,Механоман, Terminatrix,CC_TERMI,,,,,,,,,,,,,,ターミネイトリクス,터미네트릭스,,,,,,Терминатриса, -Thorn Thing,CC_THORN,,,,Bodlák,Dornending,,Dorna Aĵo,Cosa Espinosa,,Okaolio,Truc épineux,,,ソーンツィン,쏜 씽,Doornding,Cierniowe Coś,Coisa Espinhosa,,Spinos,Тернистая тварь, +Thorn Thing,CC_THORN,,,,Bodlák,Dornending,,Dorna Aĵo,Cosa Espinosa,,Okaolio,Truc épineux,Tövis Úrnő,,ソーンツィン,쏜 씽,Doornding,Cierniowe Coś,Coisa Espinhosa,,Spinos,Тернистая тварь, 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!",Bitte schieß nicht!,,Bonvolu ne pafi!,¡Por favor no dispares!,,"Pyydän, älä ammu!","Pitié, ne tirez pas!",,"Ti prego, non sparare!",撃たないでくれ!,쏘지 마세요!,"Niet schieten, alsjeblieft!",Proszę nie strzelaj!,"Por favor, não atire!",,Te rog nu trage!,"Не стреляй, пожалуйста!", -"Aargh, I need health!",SKILL_EASY,,,,Potřebuju zdraví!,Ich brauche Gesundheit!,,"Aargh, mi bezonas sanon!","¡Aargh, necesito salud!",,"Aargh, tarvitsen terveyttä!","Aargh, des soins!",,"Aargh, ho bisogno di salute!",キメてくれ!,체력이 필요해!,"Aargh, ik heb gezondheid nodig!","Ałć, potrzebuję apteczki!","Aargh, preciso de saúde!",,"Aarș, am nevoie de un medic!","А-а-ргх, аптечку!", -Let's rip them apart!,SKILL_NORMAL,,,,Rozsekejme je na kusy!,Lass uns sie zerfetzen!,,Ni disŝiru ilin!,¡Rompámoslos en pedazos!,,Revitään ne kappaleiksi!,J'en fais de la bouillie!,,Facciamoli a pezzi!,ばらまいてやれ!,갈기갈기 찢어버려!,Laten we ze uit elkaar scheuren!,Czas ich rozerwać!,Vamos despedaçá-los!,,Să-i facem zob!,Разорвём их на куски!, -I am immortal!,SKILL_HARD,,,,Jsem nesmrtelný!,Ich bin unsterblich!,,Mi estas senmorta!,¡Soy inmortal!,,Olen kuolemation!,Je suis immortel!,,Sono immortale!,とっととくたばれ!,난 무적이다!,Ik ben onsterfelijk!,Jestem nieśmiertelny!,Eu sou imortal!,,Sunt nemuritor!,Я бессмертен!, -Insanity!,SKILL_NIGHTMARE,,,,Šílenství!,Wahnsinn!,,Frenezo!,¡Locura!,,Mielettömyys!,Folie!,,Follia!,イカれてやがる!,코드명: 광기!,Waanzin!,Szaleństwo!,Insanidade!,,Demență!,Безумие!, \ No newline at end of file +Please don't shoot!,SKILL_BABY,,,,"Nestřílej, prosím!",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!",Proszę nie strzelaj!,"Por favor, não atire!",,Te rog nu trage!,"Не стреляй, пожалуйста!", +"Aargh, I need health!",SKILL_EASY,,,,Potřebuju zdraví!,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!","Ałć, potrzebuję apteczki!","Aargh, preciso de saúde!",,"Aarș, am nevoie de un medic!","А-а-ргх, аптечку!", +Let's rip them apart!,SKILL_NORMAL,,,,Rozsekejme je na kusy!,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!,Czas ich rozerwać!,Vamos despedaçá-los!,,Să-i facem zob!,Разорвём их на куски!, +I am immortal!,SKILL_HARD,,,,Jsem nesmrtelný!,Ich bin unsterblich!,,Mi estas senmorta!,¡Soy inmortal!,,Olen kuolemation!,Je suis immortel!,Halhatatlan vagyok!,Sono immortale!,とっととくたばれ!,난 무적이다!,Ik ben onsterfelijk!,Jestem nieśmiertelny!,Eu sou imortal!,,Sunt nemuritor!,Я бессмертен!, +Insanity!,SKILL_NIGHTMARE,,,,Šílenství!,Wahnsinn!,,Frenezo!,¡Locura!,,Mielettömyys!,Folie!,Téboly!,Follia!,イカれてやがる!,코드명: 광기!,Waanzin!,Szaleństwo!,Insanidade!,,Demență!,Безумие!, \ No newline at end of file diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0403.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0403.lmp new file mode 100644 index 000000000..857efd6fd Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0403.lmp differ diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0404.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0404.lmp new file mode 100644 index 000000000..071b831bc Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0490.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0490.lmp new file mode 100644 index 000000000..c1dc8133a Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/bigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0403.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0403.lmp new file mode 100644 index 000000000..f961b1354 Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0403.lmp differ diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..b4264c336 Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..d4c050513 Binary files /dev/null and b/wadsrc_extra/static/filter/hacx.hacx1/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/decaldef.txt b/wadsrc_extra/static/filter/harmony/decaldef.txt index 44abfe5e4..83fb0117f 100644 --- a/wadsrc_extra/static/filter/harmony/decaldef.txt +++ b/wadsrc_extra/static/filter/harmony/decaldef.txt @@ -388,7 +388,7 @@ generator Beastling BulletChip generator Follower BulletChip generator Soldier BulletChip generator WalkingPhage2 BulletChip -generator Echida BulletChip +generator Echidna BulletChip generator PhageNeutron ArachnotronScorch generator GrenadeExplosion CacoScorch diff --git a/wadsrc_extra/static/filter/harmony/decorate.txt b/wadsrc_extra/static/filter/harmony/decorate.txt index db173e8d8..3b3102b1f 100644 --- a/wadsrc_extra/static/filter/harmony/decorate.txt +++ b/wadsrc_extra/static/filter/harmony/decorate.txt @@ -548,7 +548,7 @@ actor Mine replaces LostSoul } } -actor Echida replaces SpiderMastermind +actor Echidna replaces SpiderMastermind { scale 0.33 health 5000 diff --git a/wadsrc_extra/static/filter/harmony/endoom.bin b/wadsrc_extra/static/filter/harmony/endoom.bin new file mode 100644 index 000000000..62f2b00ba Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/endoom.bin differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/bigfont/0403.lmp b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0403.lmp new file mode 100644 index 000000000..b0f2e3ab6 Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0403.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/bigfont/0404.raw b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0404.raw new file mode 100644 index 000000000..e010cb6cc Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0404.raw differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/bigfont/0490.lmp b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0490.lmp new file mode 100644 index 000000000..0353569ef Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/bigfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0403.lmp b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0403.lmp new file mode 100644 index 000000000..6ce99ca21 Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0403.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0404.lmp new file mode 100644 index 000000000..a26b8009c Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0404.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0490.lmp new file mode 100644 index 000000000..9fcdd23ca Binary files /dev/null and b/wadsrc_extra/static/filter/harmony/fonts/defsmallfont/0490.lmp differ diff --git a/wadsrc_extra/static/filter/harmony/language.csv b/wadsrc_extra/static/filter/harmony/language.csv index caa5640f7..4a04fa7cb 100644 --- a/wadsrc_extra/static/filter/harmony/language.csv +++ b/wadsrc_extra/static/filter/harmony/language.csv @@ -28,7 +28,7 @@ Requires the YELLOW key,PD_YELLOWK,,,,Vyžaduje ŽLUTÝ klíč,Benötigt den GEL Requires the PURPLE key,PD_REDK,,,,Vyžaduje FIALOVÝ klíč,Benötigt den VIOLETTEN Schlüssel,,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,Wymaga FIOLETOWEGO klucza,Você precisa da chave ROXA,,Necesită cheia MOV,Требуется ФИОЛЕТОВЫЙ ключ, Picked up armor.,GOTARMOR,,,Picked up armour.,Sebráno brnění.,Panzer genommen.,,Prenis kirason.,Recogiste la armadura.,,Panssari poimittu.,Armure récupérée.,Vért felvéve,Raccolto un'armatura.,アーマー ニュウシュ,획득: 전투복.,Je hebt een harnas opgehaald.,Zebrano pancerz.,Pegou uma armadura.,,Ai ridicat Armura.,Получена броня.,Покупили сте панцир. Picked up Combat Armor.,GOTMEGA,,,Picked up Combat Armour.,Sebráno bojové brnění.,Super-Panzer genommen.,,Prenis Batalkirason.,Recogiste la 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.,Zebrano pancerz bojowy.,Pegou uma Armadura de Combate.,,Ai ridicat Armura de Luptă.,Получена боевая броня., -Superhealth,GOTMSPHERE,,,,Superzdraví,Super-Gesundheit,,Supersano,Supersalud,,Superterveys,Super-Santé,Szuperéleterő,Super salute,スーパー ヘルス,사용: 체력강화 버섯.,,Superzdrowie,Supersaúde,,Supersănătate,Суперздоровье, +Superhealth,GOTMSPHERE,,,,Superzdraví,Super-Gesundheit,,Supersano,Supersalud,,Superterveys,Super-Santé,Szuperéleterő,Super salute,スーパー ヘルス,사용: 체력강화 버섯.,,Superzdrowie,Superssaúde,,Supersănătate,Суперздоровье, Obtained the GREEN keycard.,GOTBLUECARD,,,,Sebrána ZELENÁ karta.,GRÜNE Schlüsselkarte erhalten,,Akiris la VERDAN ŝlosilkarton.,Obtenida 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,Zdobyto ZIELONĄ kartę.,Pegou o cartão de passe VERDE.,,Ai achiziționat cardul VERDE.,Получена ЗЕЛЁНАЯ ключ-карта., Obtained the YELLOW keycard.,GOTYELWCARD,,,,Sebrána ŽLUTÁ karta.,GELBE Schlüsselkarte erhalten,,Akiris la FLAVAN ŝlosilkarton.,Obtenida 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,Zdobyto ŻÓŁTĄ kartę.,Pegou o cartão de passe AMARELO.,,Ai achiziționat cardul GALBEN.,Получена ЖЁЛТАЯ ключ-карта., Obtained the PURPLE keycard.,GOTREDCARD,,,,Sebrána FIALOVÁ karta.,VIOLETTE Schlüsselkarte erhalten,,Akiris la PURPURO ŝlosilkarton.,Obtenida 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,Zdobyto FIOLETOWĄ kartę.,Pegou o cartão de passe ROXO.,,Ai achiziționat cardul MOV.,Получена ФИОЛЕТОВАЯ ключ-карта., @@ -45,12 +45,12 @@ Acquired: Grenades.,GOTROCKBOX,,,,Ziskány granáty.,Erhalten: Granaten,,Akiris: Acquired: box of shotgun shells.,GOTSHELLBOX,,,,Získána krabice broků.,Erhalten: Schrotpatronen,,Akiris: Skatolon da kartoĉoj.,Adquirido: 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.,Zdobyto: pudełko loftek do strzelby.,Pegou uma caixa de cartuchos de espingarda.,,Achiziționat: Cutie de muniție pentru pușcă.,Получена: Коробка патронов для дробовика., Acquired: ammo backpack.,GOTBACKPACK,,,,Ziskán batoh s municí.,Erhalten: Munitionsrucksack,,Akiris: Tornistron da municioj.,Adquirido: Mochila de municiones.,,Saatu: ammusreppu.,Acquis: Sac de munitions.,Megszerezve: lőszeres hátizsák,Acquisito: zaino munizioni.,シュトク: バックパック,획득: 탄약 가방.,Verworven: munitie rugzak.,Zdobyto: plecak z amunicją.,Pegou uma mochila de munição.,,Achiziționat: Raniță.,Получен: Ранец для боеприпасов., Acquired: Grenade.,GOTBFG9000,,,,Získán granát.,Erhalten: Granate,,Akiris: Grenadon.,Adquirido: Granada.,,Saatu: kranaatti.,Acquis: Grenade.,Megszerezve: Gránát.,Acquisito: Granata.,シュトク: グレネード,획득: 세열탄.,Verworven: Granaat.,Zdobyto: Granat.,Pegou uma granada.,,Achiziționat: Grenadă.,Получена: Граната., -Acquired: Minigun.,GOTCHAINGUN,,,,Získán kulomet.,Erhalten: Minigun,,Akiris: Maŝinpafilon.,Adquirido: Ametralladora.,,Saatu: minigun.,Acquis: Minigun.,Megszerezve: Gépfegyver.,Acquisito: Minigun.,シュトク: ミニガン,획득: 회전포.,Verworven: Minigun.,Zdobyto: Minigun.,Pegou uma metralhadora giratória.,,Achiziționat: Minimitralieră.,Получен: Миниган., +Acquired: Minigun.,GOTCHAINGUN,,,,Získán kulomet.,Erhalten: Minigun,,Akiris: Maŝinpafilon.,Adquirido: Ametralladora.,,Saatu: minigun.,Acquis: Minigun.,Megszerezve: Gépfegyver.,Acquisito: Minigun.,シュトク: ミニガン,획득: 회전포.,Verworven: Minigun.,Zdobyto: Minigun.,Pegou uma metralhadora giratória.,,Achiziționat: Minimitralieră.,Получен: Пулемёт., Acquired: Grenade launcher.,GOTLAUNCHER,,,,Získán granátomet.,Erhalten: Granatwerfer,,Akiris: Grenadlanĉilon.,Adquirido: Lanzagranadas.,,Saatu: kranaatinheitin.,Acquis: Lance-Grenades,Megszerezve: Gránátvető,Acquisito: Lanciagranate.,シュトク: グレネードランチャー,획득: 세열탄 추진기.,Verworven: Granaatwerper.,Zdobyto: Wyrzutnię granatów.,Pegou um lança-granadas.,,Achiziționat: Lansator de grenade.,Получен: Гранатомёт., Entropy thrower!,GOTPLASMA,,,,Vrhač entropie!,Entropiewerfer,,Entropi-ĵetilon!,¡Lanzador de Entropía!,,Entropianheitin!,Acquis: Lanceur d'Entropie!,Entrópiavető!,Lancia entropia!,エントロピースロワー!,획득: 엔트로피 방사기!,Entropiewerper!,Miotacz Entropii!,Lançador de entropia!,,Aruncător entropic!,Энтропиемёт!, Acquired: Shotgun.,GOTSHOTGUN,,,,Získána brokovnice.,Erhalten: Schrotflinte,,Akiris: Ĉaspafilon.,Adquirido: Escopeta.,,Saatu: haulikko.,Acquis: Fusil à pompe.,Megszerezve: Sörétes puska,Acquisito: Fucile.,シュトク: ショットガン,획득: 산탄총.,Verworven: Shotgun.,Zdobyto: Strzelbę.,Pegou uma espingarda.,,Achiziționat: Pușcă.,Получен: Дробовик., -God Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,Gott-Modus AN,,Dio-Reĝimo AKTIVA,Modo Dios ACTIVADO,,Kuolemattomuustila PÄÄLLÄ,Mode invulnérable ON,Isten mód BE,Modo Dio ATTIVADA,ゴッドモード オン,무적 치트: ON,God Modus AAN,Tryb Boga WŁĄCZONY,Modo Deus LIGADO,,Modul Invincibil PORNIT,Режим Бога вкл., -God Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,Gott-Modus AUS,,Dio-Reĝimo NEAKTIVA,Modo Dios DESACTIVADO,,Kuolemattomuustila POIS PÄÄLTÄ,Mode invulnérable OFF,Isten mód KI,Modo Dio DISATTIVADA,ゴッドモード オフ,무적 치트: OFF,God Modus UIT,Tryb Boga WYŁĄCZONY,Modo Deus DESLIGADO,,Modul Invincibil OPRIT,Режим Бога откл., +God Mode ON,STSTR_DQDON,,,,Nesmrtelnost ZAP,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,Tryb Boga WŁĄCZONY,Modo Deus LIGADO,,Modul Invincibil PORNIT,Режим Бога включён., +God Mode OFF,STSTR_DQDOFF,,,,Nesmrtelnost VYP,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,Tryb Boga WYŁĄCZONY,Modo Deus DESLIGADO,,Modul Invincibil OPRIT,Режим Бога отключён., All weapons/ ammo/ keys,STSTR_KFAADDED,,,,Všechny zbraně/munice/klíče,"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,Wszystkie bronie/amunicja/klucze,Todas as armas/munição/chaves,,Toate armele/muniție/chei,Всё оружие/боеприпасы/ключи, All weapons and ammo,STSTR_FAADDED,,,,Všechny zbraně a munice,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,Wszystkie bronie i amunicja,Todas as armas e munição completa,,Toate armele și muniție,Всё оружие и боеприпасы, Abduction,TXT_HARMMAP01,,,,Únos,Entführung,,Forkapto,Abducción,,Sieppaus,Enlèvement,Elrablás,Il rapimento,アブダクション,유괴,Ontvoering,Porwanie,Sequestro,,Răpire,Похищение, @@ -60,7 +60,7 @@ Megalapolis,TXT_HARMMAP04,,,,Megalopole,Megalopolis,,Megtropolo,Megalópolis,,Me The Hospital,TXT_HARMMAP05,,,,Nemocnice,Das Hospital,,La Malsanulejo,El Hospital,,Sairaala,L'Hôpital,Kórház,L'ospedale,ホスピタル,병동,Het ziekenhuis,Szpital,O Hospital,,Spitalul,Больница, The Weapons Factory,TXT_HARMMAP06,,,,Továrna na zbraně,Die Waffenfabrik,,La Arm-fabrikejo,La Fábrica de Armas,,Asetehdas,L'Usine d'Armes,Fegyvergyár,La fabbrica di armi,ウェポンファクトリー,무기 공장,De Wapenfabriek,Fabryka Broni,A Fábrica de Armamentos,,Fabrica de Arme,Оружейный завод, The Underwater Lab,TXT_HARMMAP07,,,,Podvodní laboratoř,Das Unterwasserlabor,,La Subakva Labotorio,El Laboratorio Submarino,,Vedenalainen laboratorio,Le Laboratoire Sous-marin,Vízalatti labor,Il laboratorio subacqueo,アンダーウォーターラボ,해저 연구소,Het onderwaterlaboratorium,Podwodne Laboratorium,O Laboratório Submarino,,Laboratorul Subacvatic,Подводная лаборатория, -Airstrip One,TXT_HARMMAP08,,,,Přistávací dráha jedna,Flugplatz Eins,,Surteriĝejo Numero Unu,Pista de Aterrizaje Uno,,Kiitorata Yksi,Piste D'Atterrisage Un,1-es kifutó,Pista di atterraggio Uno,エアーシップ ワン,활주로 1호,Vliegveld Een,Lądowisko Numer Jeden,Base Aérea Um,,Pista Unu,Взлётная полоса №1, +Airstrip One,TXT_HARMMAP08,,,,Přistávací dráha jedna,Flugplatz Eins,,Surteriĝejo Numero Unu,Pista de Aterrizaje Uno,,Kiitorata Yksi,Piste D'Atterrisage Un,1-es kifutó,Pista Uno,エアーシップ ワン,활주로 1호,Vliegveld Een,Lądowisko Numer Jeden,Base Aérea Um,,Pista Unu,Взлётная полоса №1, The Launch Base,TXT_HARMMAP09,,,,Vzletová základna,Die Startbasis,,La Lanĉbazo,La Base de Despegue,,Laukaisutukikohta,La Base de Lancement,Kilövő Állomás,La base di lancio,ランチャーベース,발진기지,De lanceerbasis,Baza Startowa,A Base de Lançamento,,Baza de Lansare,Пусковая площадка, The Radioactive Zone,TXT_HARMMAP10,,,,Radioaktivní zóna,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,Radioaktywna Strefa,A Zona Radioativa,,Zona Radioactivă,Заражённая зона, Echidna,TXT_HARMMAP11,,,,,,,Ekidno,,,Nokkasiili,,Hangyászsün,,エキドナ,에키드나,,,Equidna,,,Ехидна, @@ -199,23 +199,22 @@ Ezek a szörnyek minden bizonnyal meglelték a módját, hogy ezzé a borzasztó = V É G E =","Ti senti male allo stomaco... Guardando in faccia alla regina mutante... -Quella cosa... Quello era... +Quella cosa... Quella era... La tua amica... Amira! Quei mostri devono aver trovato il modo di mutarla e trasformarla in questa -orrenda creatura per portare i loro figli. +orrenda creatura per generare i loro figli. -- sospiro - +*sospiro* -Ti riunisci... -Pagheranno per farti uccidere la tuo amica... +Ti ricomponi... +Pagheranno per averti farti uccidere la tua amica... -""L'inferno non ha furia come una donna disprezzata!"" +""L'inferno non ha furia come una donna oltraggiata!"" = L A F I N E = - -","貴方はミュータントの女王の顔を見た時 + ","貴方はミュータントの女王の顔を見た時 気分が凄まじく悪くなった... その顔は... 見覚えがあった... 私の親友... アミラ! @@ -257,23 +256,23 @@ vermoorden door je vriend... ""De hel heeft geen woede zoals een vrouw die wordt geminacht!"" - = EINDE =","Czujesz się niedobrze... -Patrząc na twarz królowej mutantów... -Ale rzecz w tym, że... to była kiedyś... + = EINDE =","Jest ci niedobrze... +Patrzysz królowej mutantów prosto w twarz... +Ta maszkara... to tak naprawdę... Twoja przyjaciółka... Amira! Te potwory znalazły sposób, aby ją zmutować i zamienić ją w tą ohydną poczwarę, by mogły się rozmnażać. -Ehh... +Ech... Bierzesz się w garść... Zapłacą za to, że musiałaś zabić swoją przyjaciółkę... -""Nawet piekło nie może być tak wściekłe -jak zlekceważnona kobieta!"" +""Nawet piekło nie powstrzyma +zlekceważnonej kobiety!"" =K O N I E C=","Você sente vontade de vomitar... Vendo o rosto da rainha mutante... @@ -334,10 +333,10 @@ Te aduni... ", ,WI_FINISHED,This text is deliberately empty,,,,,,,,,,,,,,,,,,,,, Loading,WI_ENTERING,Yellow needs retranslation,,,Načítá se,Lade,,Ŝargante,Cargando,,Ladattavana,Chargement,Betöltés,Caricamento,ローディング,불러오는 중,Laden van,Ładowanie,Carregando,,Se încarcă,Загрузка уровня, -Very Easy,SKILL_BABY,,,,Velmi snadné,Sehr einfach,,Tre Facila,Muy facil,,Erittäin helppo,Trés facile,Nagyon könnyű,Molto facile,ベリーイージー,아주 쉬움,Zeer gemakkelijk,Bardzo Łatwy,Muito facil,,Foarte Ușor,Очень лёгкий, -Easy,SKILL_EASY,,,,Snadný,Einfach,,Facila,Facil,,Helppo,Facile,Könnyű,Facile,イージー,쉬움,Gemakkelijk,Łatwy,Fácil,,Ușor,Лёгкий, -Medium,SKILL_NORMAL,,,,Střední,Mittel,,Meza,Medio,,Keskivaikea,Moyen,Normál,Medio,ミディアム,중간,Middel,Średni,Médio,,Mediu,Средний, -Hard,SKILL_HARD,,,,Obtížný,Schwer,,Malfacila,Difícil,,Vaikea,Difficile,Nehéz,Difficile,ハード,어려움,Moeilijk,Trudny,Difícil,,Greu,Тяжёлый, -Very Hard,SKILL_NIGHTMARE,,,,Velmi obtížné,Sehr schwer,,Tre Malfacila,Muy difícil,,Erittäin vaikea,Très difficile,Nagyon nehéz,Molto difficile,ベリーハード,아주 어려윰,Zeer moeilijk,Bardzo Trudny,Muito difícil,,Foarte Greu,Очень тяжёлый, +Very Easy,SKILL_BABY,,,,Velmi snadné,Sehr einfach,,Tre Facila,Muy facil,,Erittäin helppo,Trés facile,Nagyon könnyű,Molto facile,ベリーイージー,아주 쉬움,Zeer gemakkelijk,Bardzo Łatwy,Muito fácil,,Foarte Ușor,Очень легко, +Easy,SKILL_EASY,,,,Snadný,Einfach,,Facila,Facil,,Helppo,Facile,Könnyű,Facile,イージー,쉬움,Gemakkelijk,Łatwy,Fácil,,Ușor,Легко, +Medium,SKILL_NORMAL,,,,Střední,Mittel,,Meza,Medio,,Keskivaikea,Moyen,Normál,Medio,ミディアム,중간,Middel,Średni,Médio,,Mediu,Средне, +Hard,SKILL_HARD,,,,Obtížný,Schwer,,Malfacila,Difícil,,Vaikea,Difficile,Nehéz,Difficile,ハード,어려움,Moeilijk,Trudny,Difícil,,Greu,Тяжело, +Very Hard,SKILL_NIGHTMARE,,,,Velmi obtížné,Sehr schwer,,Tre Malfacila,Muy difícil,,Erittäin vaikea,Très difficile,Nagyon nehéz,Molto difficile,ベリーハード,아주 어려윰,Zeer moeilijk,Bardzo Trudny,Muito difícil,,Foarte Greu,Очень тяжело, Thanks for playing,HARMQUITMSG,,,,Díky za hraní,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,Dziękuję za grę,Obrigado por jogar,,Mulțumim că ai jucat,"Спасибо, что сыграли в Harmony", -Harmony,TXT_D2E1,,,,,,,Harmonio,,,Harmonia,,Harmónia,,,,,Harmonia,,,,, \ No newline at end of file +Harmony,TXT_D2E1,,,,,,,Harmonio,,,Harmonia,,Harmónia,,,,,Harmonia,Harmony,,,Harmony, \ No newline at end of file diff --git a/wadsrc_extra/static/filter/harmony/mapinfo.txt b/wadsrc_extra/static/filter/harmony/mapinfo.txt index 059469773..4c534ff3a 100644 --- a/wadsrc_extra/static/filter/harmony/mapinfo.txt +++ b/wadsrc_extra/static/filter/harmony/mapinfo.txt @@ -193,5 +193,5 @@ clusterdef 1 // exittext, background flat is DEM1_1 and music is titletrack flat = DEM1_1 music = "d_dm2ttl" - exittext = "CLUSTEREXIT1" + exittext = lookup, "CLUSTEREXIT1" } diff --git a/wadsrc_extra/static/language.csv b/wadsrc_extra/static/language.csv index 763df68c9..2ac74baaf 100644 --- a/wadsrc_extra/static/language.csv +++ b/wadsrc_extra/static/language.csv @@ -9,7 +9,7 @@ Proverbs 5:11",,,Tvé tělo pozřeto,Dein Leib verzehrt,Η Σάρκα σου θ Hell On Earth,TXT_D2E1,,,,Peklo na zemi,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,Piekło na Ziemi,Inferno na Terra,,Iadul pe Pământ,Ад на Земле,Пакао на Земљи No Rest for the Living,TXT_D2E2,"References ""No rest for the wicked"" in Isaiah 48:22",,,Nemajíť živí pokoje,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,Brak Wytchnienia Dla Żywych,Não Há Descanso Para os Vivos,,Cei vii Fără de Odihnă,Не будет покоя живым,Нема одмора живима The Plutonia Experiment,TXT_PLUT_EP,,,,Experiment Plutonia,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,Eksperyment Plutonia,O Experimento Plutonia,A Experiência Plutonia,Experimentul Plutonia,Эксперимент «Плутония»,Експеримент Плутонија -TNT: Evilution,TXT_TNT_EP,,,,TNT: Zlovoluce,,ΤΝΤ: Κακοξέλιξη,TNT: Mavalucio,TNT: Maligvolución,,TNT: Paholuutio,,,TNT: Malvoluzione,TNT:邪神化,TNT: 이블루션,Tnt: Evilutie,TNT: Ewolucja Zła,TNT: Malvolução,,TNT: Diavoluția,TNT: Дьяволюция,TNT: Ђаволуција +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,,,,,,,,,,,,,,,,,,,,, @@ -25,11 +25,11 @@ E1M9: Military Base,HUSTR_E1M9,,,,E1M9: Vojenská základna,E1M9: Militärbasis, E1M10: Sewers,HUSTR_E1M10,,,,E1M10: Kanály,E1M10: Kanalisation,,E1M10: Kloakoj,E1M10: Las Alcantarillas,,E1M10: Viemärit,E1M10: Egouts,E1M10: Kanálisok,E1M10: Le Fogne,E1M10: 下水道,E1M10: 하수구,E1M10: De Rioleringen,E1M10: Ścieki,E1M10: Os Esgotos,,E1M10: Canalizarea,E1M10: Канализация,E1M10: Канализација E2M1: Deimos Anomaly,HUSTR_E2M1,,,,E2M1: Deimosská anomálie,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: Anomalia Deimosa,E2M1: Anomalia de Deimos,,E2M1: Anomalia Deimos,E2M1: Аномалия Деймоса,E2M1: Аномалија на Дејмосу E2M2: Containment Area,HUSTR_E2M2,,,,E2M2: Skladiště,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: Obszar Zastrzeżony,E2M2: Area de Contenção,E2M2: Área de Confinamento,E2M2: Zona de Izolare,E2M2: Складские помещения,E2M2: Складишта -E2M3: Refinery,HUSTR_E2M3,,,,E2M3: Rafinerie,E2M3: Raffinerie,E2Χ3: Διυλιστήριο,E2M3: Refinejo,E2M3: Refinería,,E2M3: Jalostamo,E2M3: Raffinerie,E2M3: Finomító,E2M3: Raffineria,E2M3: 精製所,E2M3: 정제소,E2M3: Raffinaderij,E2M3: Rafineria,E2M3: Refinaria,,E2M3: Rafinărie,E2M3: Очистные сооружения,E2M3: Рафинерија +E2M3: Refinery,HUSTR_E2M3,,,,E2M3: Rafinerie,E2M3: Raffinerie,E2Χ3: Διυλιστήριο,E2M3: Rafinejo,E2M3: Refinería,,E2M3: Jalostamo,E2M3: Raffinerie,E2M3: Finomító,E2M3: Raffineria,E2M3: 精製所,E2M3: 정제소,E2M3: Raffinaderij,E2M3: Rafineria,E2M3: Refinaria,,E2M3: Rafinărie,E2M3: Очистные сооружения,E2M3: Рафинерија E2M4: Deimos Lab,HUSTR_E2M4,,,,E2M4: Deimosská laboratoř,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: Laboratoria Deimosa,E2M4: Laboratório de Deimos,,E2M4: Laboratorul Deimos,E2M4: Лаборатория на Деймосе,E2M4: Лабораторија на Дејмосу E2M5: Command Center,HUSTR_E2M5,,,,E2M5: Řídící středisko,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: Centrum Dowodzenia,E2M5: Centro de Comando,,E2M5: Centru de Comandă,E2M5: Командный центр,E2M5: Командни центар E2M6: Halls of the Damned,HUSTR_E2M6,,,,E2M6: Chodby zatracených,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: Korytarze Przeklętych,E2M6: Salões dos Condenados,,E2M6: Camerele Blestemaților,E2M6: Залы проклятых,E2M6: Дворана проклетих -E2M7: Spawning Vats,HUSTR_E2M7,,,,E2M7: Plodné kádě,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: Kadzie Reprodukcyjne,E2M7: Cubas de Desova,,E2M7: Cuve de Reproducere,E2M7: Нерестилище,E2M7: Размножавалиште +E2M7: Spawning Vats,HUSTR_E2M7,,,,E2M7: Plodné kádě,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: Kadzie Reprodukcyjne,E2M7: Tanques de Criação,,E2M7: Cuve de Reproducere,E2M7: Нерестилище,E2M7: Размножавалиште E2M8: Tower of Babel,HUSTR_E2M8,,,,E2M8: Babylonská věž,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: Wieża Babel,E2M8: Torre de Babel,,E2M8: Turnul Babel,E2M8: Вавилонская башня,E2M8: Вавилонска кула E2M9: Fortress of Mystery,HUSTR_E2M9,,,,E2M9: Pevnost záhad,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: Forteca Tajemnic,E2M9: Fortaleza do Mistério,,E2M9: Fortăreața Misterelor,E2M9: Крепость тайн,E2M9: Тврђава тајни E3M1: Hell Keep,HUSTR_E3M1,,,,E3M1: Pekelná tvrz,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: Twierdza Piekieł,E3M1: Torre do Inferno,,E3M1: Fortul Iadului,E3M1: Крепость Ада,E3M1: Тврђава пакла @@ -51,118 +51,118 @@ E4M7: And Hell Followed,HUSTR_E4M7,Revelation 6:8,,,E4M7: A peklo šlo za ním,E E4M8: Unto The Cruel,HUSTR_E4M8,Proverbs 5:9,,,E4M8: Ukrutníku odevzdáš,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: Kto Nie Zna Litości,E4M8: Aos Cruéis,E4M8: Entregue a Cruéis,E4M8: Unuia Fără de Milă,E4M8: К мучителю,E4M8: Немилостивоме E4M9: Fear,HUSTR_E4M9,,,,E4M9: Strach,E4M9: Angst,E4Χ9: Τρόμος,E4M9: Timo,E4M9: Miedo,,E4M9: Pelko,E4M9: Terreur,E4M9: Félelem,E4M9: Paura,E4M9: 恐怖,E4M9: 공포,E4M9: Angst,E4M9: Strach,E4M9: Medo,,E4M9: Frica,E4M9: Страх,E4M9: Страх ,,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: Eingangshalle,Επίπεδο 1: Είσοδος,Nivelo 1: Enirejo,Nivel 1: Entrada,,Taso 1: Eteiskäytävä,NIVEAU 1: Hall D'Entrée,Bejárat,Level 1: Ingresso,Level 1: 入口,레벨 1: 초입,Level 1: Ingang,Level 1: Wejście,Fase 1: Entrada,Nível 1: Entrada,Nivelul 1: Intrarea,Level 1: Вход,Level 1: Улаз -Level 2: Underhalls,HUSTR_2,,,,Level 2: Podzemí,Level 2: Kellergewölbe,,Nivelo 2: Subtervojoj,Nivel 2: Salones subterráneos,,Taso 2: Maanalaiset käytävät,NIVEAU 2: Souterrains,Alagutak,Level 2: Sotterranei,Level 2: 下水道,레벨 2: 지하수로,Level 2: Onderhallen,Level 2: Podziemia,Fase 2: Subterrâneo,Nível 2: Subterrâneo,Nivelul 2: Pasaje subterane,Level 2: Подземные ходы,Level 2: Подземни ходници -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: Spießrutenlauf,,Nivelo 3: La Spaliro,Nivel 3: El Guantelete,,Taso 3: Kujanjuoksu,NIVEAU 3: Parcours du Combatant,Vesszőfutás,Level 3: Le fustigazioni,Level 3: ガントレット,레벨 3: 건틀릿,Level 3: De gantlet,Level 3: Praszczęta,Fase 3: A Punição,Nível 3: A Punição,Nivelul 3: Stroiul,Level 3: Вызов брошен,Level 3: Казна -Level 4: The Focus,HUSTR_4,,,,Level 4: Ohnisko,Level 4: Der Fokus,,Nivelo 4: La Fokuso,Nivel 4: El Foco,,Taso 4: Polttopiste,NIVEAU 4: Le Focus,A középpont,Level 4: L'Epicentro,Level 4: フォーカス,레벨 4: 초점,Level 4: De focus,Level 4: Skupisko,Fase 4: O Foco,Nível 4: O Foco,Nivelul 4: Focarul,Level 4: Средоточие,Level 4: Средиште -Level 5: The Waste Tunnels,HUSTR_5,,,,Level 5: Odpadní tunely,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,Szennyvízalagutak,Level 5: I Tunnel dei Rifiuti,Level 5: 廃棄トンネル,레벨 5: 하수도,Level 5: De afvaltunnels,Level 5: Kanały,Fase 5: Os Túneis de Dejetos,Nível 5: Os Túneis de Dejetos,Nivelul 5: Tuneluri pentru deșeuri,Level 5: Сточные туннели,Level 5: Отпадни тунели -Level 6: The Crusher,HUSTR_6,,,,Level 6: Drtička,Level 6: Die Presse,Επίπεδο 6: Ο Συνθλιπτής,Nivelo 6: La Dispistilo,Nivel 6: La Trituradora,,Taso 6: Murskaaja,NIVEAU 6: Le Broyeur,A zúzda,Level 6: La Pressa,Level 6: クラッシャー,레벨 6: 분쇄기,Level 6: De maalmachine,Level 6: Zgniatarka,Fase 6: O Esmagador,Nível 6: O Esmagador,Nivelul 6: Zdrobitorul,Level 6: Пресс,Level 6: Разбијач -Level 7: Dead Simple,HUSTR_7,,,,Level 7: Smrtelně prosté,Level 7: Tödlich einfach,Επίπεδο 7: Πανεύκολο,Nivelo 7: Morte Simpla,Nivel 7: Simplemente Muerto,,Taso 7: Kuolettavan yksinkertainen,NIVEAU 7: Mortellement Simple,Halálegyszerű,Level 7: Morte Pura,Level 7: 死ぬほど単純,레벨 7: 죽여주는 단순함,Level 7: Dodelijk eenvoudig,Level 7: Śmiertelnie Proste,Fase 7: Mortalmente Simples,Nível 7: Simplesmente Mortal,Nivelul 7: Mortal de simplu,Level 7: Смертельно просто,Level 7: Смртно једноставно -Level 8: Tricks and Traps,HUSTR_8,,,,Level 8: Lesti a léčky,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,Cselek és csapdák,Level 8: Trucchi e Trappole,Level 8: 悪戯と罠,레벨 8: 속임수와 함정들,Level 8: Trucs en vallen,Level 8: Sztuczki i Pułapki,Fase 8: Truques e Armadilhas,Nível 8: Truques e Armadilhas,Nivelul 9: Surprize și capcane,Level 8: Уловки и ловушки,Level 8: Замке и смицалице -Level 9: The Pit,HUSTR_9,,,,Level 9: Jáma,Level 9: Die Grube,Επίπεδο 9: Λάκκος,Nivelo 9: La Fosaĵo,Nivel 9: El Pozo,,Taso 9: Monttu,NIVEAU 9: La Fosse,A gödör,Level 9: Il Pozzo,Level 9: 大穴,레벨 9: 구덩이,Level 9: De groeve,Level 9: Dół,Fase 9: O Fosso,Nível 9: O Fosso,Nivelul 9: Groapa,Level 9: Яма,Level 9: Јама -Level 10: Refueling Base,HUSTR_10,,,,Level 10: Tankovací základna,Level 10: Treibstoffbunker,Επίπεδο 10: Βάση Ανεφοδιασμού,Nivelo 10: Refuelbazo,Nivel 10: Base de Reabastecimiento,,Taso 10: Tankkausasema,NIVEAU 10: Base de Ravitaillement,Tankolóállomás,Level 10: Base di Rifornimento,Level 10: 補給基地,레벨 10: 연료 충전소,Level 10: Tankstation,Level 10: Stacja Tankowania,Fase 10: Base de Reabastecimento,Nível 10: Base de Reabastecimento,Nivelul 10: Baza de alimentare,Level 10: Заправочная база,Level 10: Бензинска база +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: 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,Level 1: Wejście,Fase 1: Entrada,Nível 1: Entrada,Nivelul 1: Intrarea,Уровень 1: Вход,Level 1: Улаз +Level 2: Underhalls,HUSTR_2,,,,Level 2: Podzemí,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,Level 2: Podziemia,Fase 2: Subterrâneo,Nível 2: Subterrâneo,Nivelul 2: Pasaje subterane,Уровень 2: Подземные ходы,Level 2: Подземни ходници +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: 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,Level 3: Praszczęta,Fase 3: A Punição,Nível 3: A Punição,Nivelul 3: Stroiul,Уровень 3: Вызов брошен,Level 3: Казна +Level 4: The Focus,HUSTR_4,,,,Level 4: Ohnisko,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,Level 4: Skupisko,Fase 4: O Foco,Nível 4: O Foco,Nivelul 4: Focarul,Уровень 4: Средоточие,Level 4: Средиште +Level 5: The Waste Tunnels,HUSTR_5,,,,Level 5: Odpadní tunely,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,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: Отпадни тунели +Level 6: The Crusher,HUSTR_6,,,,Level 6: Drtička,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,Level 6: Zgniatarka,Fase 6: O Esmagador,Nível 6: O Esmagador,Nivelul 6: Zdrobitorul,Уровень 6: Пресс,Level 6: Разбијач +Level 7: Dead Simple,HUSTR_7,,,,Level 7: Smrtelně prosté,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,Level 7: Śmiertelnie Proste,Fase 7: Mortalmente Simples,Nível 7: Simplesmente Mortal,Nivelul 7: Mortal de simplu,Уровень 7: Смертельно просто,Level 7: Смртно једноставно +Level 8: Tricks and Traps,HUSTR_8,,,,Level 8: Lesti a léčky,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,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: Замке и смицалице +Level 9: The Pit,HUSTR_9,,,,Level 9: Jáma,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,Level 9: Dół,Fase 9: O Fosso,Nível 9: O Fosso,Nivelul 9: Groapa,Уровень 9: Яма,Level 9: Јама +Level 10: Refueling Base,HUSTR_10,,,,Level 10: Tankovací základna,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,Level 10: Stacja Tankowania,Fase 10: Base de Reabastecimento,Nível 10: Base de Reabastecimento,Nivelul 10: Baza de alimentare,Уровень 10: Заправочная база,Level 10: Бензинска база Level 11: 'O' of Destruction!,HUSTR_11,"Alternative title: -Circle of Death ",,,Level 11: Kruh smrti,Level 11: 'O' der Zerstörung!,Επίπεδο 11: Ο Κύκλος της Καταστροφής,Nivelo 11: 'O' de Detruo!,Nivel 11: 'O' de Destrucción,,Taso 11: Hävityksen 'O',NIVEAU 11: Le Cercle de la Mort!,A pusztulás köre,Level 11: Il Cerchio della Morte,Level 11: 破滅の'O'!,레벨 11: 파괴의 고리,Level 11: 'O' van vernietiging!,Level 11: Krąg Śmierci,Fase 11: Círculo da Morte,Nível 11: Círculo da Morte,Nivelul 11: Cercul distrugerii,Level 11: Круг разрушения!,Level 11: Круг уништења -Level 12: The Factory,HUSTR_12,,,,Level 12: Továrna,Level 12: Die Fabrik,Επίπεδο 12: To Εργοστάσιο,Nivelo 12: La Fabrikejo,Nivel 12: La Fábrica,,Taso 12: Tehdas,NIVEAU 12: L'Usine,A gyár,Level 12: La Fabbrica,Level 12: 工場,레벨 12: 공장,Level 12: De fabriek,Level 12: Fabryka,Fase 12: A Fábrica,Nível 12: A Fábrica,Nivelul 12: Fabrica,Level 12: Фабрика,Level 12: Фабрика -Level 13: Downtown,HUSTR_13,,,,Level 13: Centrum,Level 13: Stadtzentrum,Επίπεδο 13: Κέντρο,Nivelo 13: Urbocentro,Nivel 13: Centro de la Ciudad,,Taso 13: Keskikaupunki,NIVEAU 13: Centre-Ville,Belváros,Level 13: Periferia,Level 13: 市内,레벨 13: 번화가,Level 13: De binnenstad,Level 13: Śródmieście,Fase 13: Centro Urbano,Nível 13: Centro Urbano,Nivelul 13: Centru urban,Level 13: Деловой район,Level 13: Центар града -Level 14: The Inmost Dens,HUSTR_14,,,,Level 14: Nejhlubší doupata,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,A legmélyebb rejtekek,Level 14: Gli Antri Profondi,Level 14: 最深巣窟,레벨 14: 깊숙한 동굴들,Level 14: De binnenste gebouwen,Level 14: Najgłębsze Nory,Fase 14: Os Antros Profundos,Nível 14: Os Antros Profundos,Nivelul 14: Cele mai intime bârloguri,Level 14: Глубочайшие логовища,Level 14: Најдубље јазбине -Level 15: Industrial Zone,HUSTR_15,,,,Level 15: Průmyslová zóna,Level 15: Industriegebiet,Επίπεδο 15: Βιομηχανική Ζώνη,Nivelo 15: Industria Zono,Nivel 15: Zona Industrial,,Taso 15: Teollisuusalue,NIVEAU 15: Zone Industrielle,Ipari zóna,Level 15: Zona Industriale,Level 15: 工業地帯,레벨 15: 공업 지대,Level 15: Industriegebied,Level 15: Strefa Przemysłowa,Fase 15: Zona Industrial,Nível 15: Zona Industrial,Nivelul 15: Zona industrială,Level 15: Промышленная зона,Level 15: Индустријска зона -Level 16: Suburbs,HUSTR_16,,,,Level 16: Předměstí,Level 16: Vororte,Επίπεδο 16: Προάστια,Nivelo 16: Antaŭurboj,Nivel 16: Suburbios,,Taso 16: Lähiö,NIVEAU 16: Banlieue,Külváros,Level 16: Sobborghi,Level 16: 郊外,레벨 16: 교외,Level 16: Buitenwijken,Level 16: Przedmieścia,Fase 16: Subúrbios,Nível 16: Subúrbios,Nivelul 16: Suburbii,Level 16: Пригород,Level 16: Предграђе -Level 17: Tenements,HUSTR_17,,,,Level 17: Sídliště,Level 17: Wohnbezirk,Επίπεδο 17: Καταλύματα,Nivelo 17: Loĝejoj,Nivel 17: Viviendas,,Taso 17: Vuokratalot,NIVEAU 17: Immeubles,Bérházak,Level 17: Possedimenti,Level 17: 安アパート,레벨 17: 공동주택,Level 17: Huurwoningen,Level 17: Kamienice,Fase 17: Habitações,Nível 17: Habitações,Nivelul 17: Proprietăți,Level 17: Владения,Level 17: Станови -Level 18: The Courtyard,HUSTR_18,,,,Level 18: Nádvoří,Level 18: Der Innenhof,Επίπεδο 18: Η Αυλή,Nivelo 18: La Korto,Nivel 18: El Patio,,Taso 18: Esipiha,NIVEAU 18: La Cour,Az udvar,Level 18: Il cortile,Level 18: 中庭,레벨 18: 중정,Level 18: De binnenplaats,Level 18: Dziedziniec,Fase 18: O Átrio,Nível 18: O Átrio,Nivelul 18: Curtea,Level 18: Внутренний двор,Level 18: Двориште -Level 19: The Citadel,HUSTR_19,,,,Level 19: Citadela,Level 19: Die Zizadelle,Επίπεδο 19: Το Κάστρο,Nivelo 19: La Citadelo,Nivel 19: La Ciudadela,,Taso 19: Linnoitus,NIVEAU 19: La Citadelle,Fellegvár,Level 19: La cittadella,Level 19: 要塞,레벨 19: 성채,Level 19: De citadel,Level 19: Cytadela,Fase 19: A Cidadela,Nível 19: A Cidadela,Nivelul 19: Cetatea,Level 19: Цитадель,Level 19: Цитадела -Level 20: Gotcha!,HUSTR_20,,,,Level 20: Mám tě!,Level 20: Erwischt!,Επίπεδο 20: Σ'έπιασα!,Nivelo 20: Kaptis Vin!,Nivel 20: ¡Te Pillé!,,Taso 20: Sainpas sinut!,NIVEAU 20: Je t'ai eu!,Megvagy!,Level 20: Preso!,Level 20: 捉らえた!,레벨 20: 잡았다!,Level 20: Ik heb je!,Level 20: Mam Cię!,Fase 20: Te Peguei!,Nível 20: Apanhei-te!,Nivelul 20: Te-am prins!,Level 20: Попался!,Level 20: Имају те! -Level 21: Nirvana,HUSTR_21,,,,Level 21: Nirvána,,Επίπεδο 21: Νιρβάνα,Nivelo 21: Nirvano,Nivel 21: Nirvana,,,NIVEAU 21: Nirvana,Nirvána,Level 21: Nirvana,Level 21: 涅槃,레벨 21: 열반,,Level 21: Nirvana,Fase 21: Nirvana,Nível 21: Nirvana,Nivelul 21: Nirvana,Level 21: Нирвана,Level 21: Нирвана -Level 22: The Catacombs,HUSTR_22,,,,Level 22: Katakomby,Level 22: Katakomben,Επίπεδο 22: Οι Κατακόμβες,Nivelo 22: La Katakomboj,Nivel 22: Las Catacumbas,,Taso 22: Katakombit,NIVEAU 22: Les Catacombes,A katakombák,Level 22: Le Catacombe,Level 22: 地下悪霊墓所,레벨 22: 지하 묘지,Level 22: De catacomben,Level 22: Katakumby,Fase 22: As Catacumbas,Nível 22: Os Calabouços,Nivelul 22: Catacombe,Level 22: Катакомбы,Level 22: Катакомбе -Level 23: Barrels O' Fun,HUSTR_23,,,,Level 23: Barely srandy,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,Mókás hordók,Level 23: Barili da Sballo,Level 23: 戯れのバレル,레벨 23: 신나는 폭발통들,Level 23: Grappige vaten,Level 23: Beczki Śmiechu,Fase 23: Barris de Diversão,Nível 23: Barris de Diversão,Nivelul 23: Butoaiele veseliei,Level 23: Бочки веселья,Level 23: Бачве забаве -Level 24: The Chasm,HUSTR_24,,,,Level 24: Rokle,Level 24: Die Kluft,Επίπεδο 24: Το Χάσμα,Nivelo 24: La Fendego,Nivel 24: El Desfiladero,,Taso 24: Rotko,NIVEAU 24: Le Gouffre,A szakadék,Level 24: L'Abisso,Level 24: 裂け目,레벨 24: 협곡,Level 24: De afgrond,Level 24: Przepaść,Fase 24: O Abismo,Nível 24: O Abismo,Nivelul 24: Hăul,Level 24: Пропасть,Level 24: Провалија -Level 25: Bloodfalls,HUSTR_25,,,,Level 25: Krvopády,Level 25: Blutfälle,Επίπεδο 25: Καταρράκτες Αίματος,Nivelo 25: Sangfaloj,Nivel 25: Cataratas de Sangre,,Taso 25: Veriputoukset,NIVEAU 25: Chutes de Sang,Véresések,Level 25: Cascate di Sangue,Level 25: 血の滝,레벨 25: 혈폭포,Level 25: Bloeddruppels,Level 25: Wodospad Krwi,Fase 25: Cataratas de Sangue,Nível 25: Cascatas de Sangue,Nivelul 25: Cascade de sânge,Level 25: Кровопады,Level 25: Крвопади -Level 26: The Abandoned Mines,HUSTR_26,,,,Level 26: Opuštěné doly,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,Az elhagyatott bányák,Level 26: Le Miniere Abbandonate,Level 26: 廃鉱山,레벨 26: 버려진 광산,Level 26: De verlaten mijnen,Level 26: Opuszczone Kopalnie,Fase 26: As Minas Abandonadas,Nível 26: As Minas Abandonadas,Nivelul 26: Minele părăsite,Level 26: Заброшенные шахты,Level 26: Напуштени рудници -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,A szörnyek háza,Level 27: Casa dei Mostri,Level 27: モンスターマンション,레벨 27: 괴물 콘도,,Level 27: Apartament Potworów,Fase 27: Mansão dos Monstros,Nível 27: Condomínio Monstruoso,Nivelul 27: Casa monștrilor,Level 27: Жилище монстров,Level 27: Боравишта монструма -Level 28: The Spirit World,HUSTR_28,,,,Level 28: Onen svět,Level 28: Die Geisterwelt,Επίπεδο 28: Ο Κόσμος των Πνευμάτων,Nivelo 28: La Animo-Mondo,Nivel 28: El Mundo Espiritual,,Taso 28: Henkimaailma,NIVEAU 28: Le Monde Spirituel,A lelkek világa,Level 28: Il Mondo dello Spirito,Level 28: 悪霊の世界,레벨 28: 영령의 세계,Level 28: De geestenwereld,Level 28: Świat Dusz,Fase 28: O Mundo Espiritual,Nível 28: O Mundo Espiritual,Nivelul 28: Lumea duhurilor,Level 28: Мир духов,Level 28: Духовни свет -Level 29: The Living End,HUSTR_29,,,,Level 29: Živoucí konec,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,Az élő Végzet,Level 29: La Fine Imminente,Level 29: 極限の存在,레벨 29: 최종점,Level 29: Het levende einde,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,Level 29: Конец всего живого,Level 29: Крај живота -Level 30: Icon of Sin,HUSTR_30,,,,Level 30: Ikona hříchu,Level 30: Symbol der Sünde,Επίπεδο 30: Σύμβολο της Αμαρτίας,Nivelo 30: Ikono de Peko,Nivel 30: Ícono del Pecado,,Taso 30: Synnin ikoni,NIVEAU 30: L'Icône du Péché,A megtestesült bűn,Level 30: Icona del Peccato,Level 30: 罪の聖像,레벨 30: 죄악의 상징,Level 30: Pictogram van de zonde,Level 30: Ikona Grzechu,Fase 30: Ícone do Pecado,Nível 30: Ícone do Pecado,Nivelul 30: Icoana păcatelor,Level 30: Икона греха,Level 30: Икона греха -Level 31: Wolfenstein,HUSTR_31,,,,,,,Nivelo 31: Wolfenstein,Nivel 31: Wolfenstein,,,,Wolfenstein,Level 31: Wolfenstein,Level 31: ウルフェンシュタイン,레벨 31: 울펜슈타인,,Level 31: Wolfenstein,Fase 31: Wolfenstein,Nível 31: Wolfenstein,Nivelul 31: Wolfenstein,Level 31: Вольфенштайн,Level 31: Волфенштајн -Level 32: Grosse,HUSTR_32,,,,,,,Nivelo 32: Grosse,Nivel 32: Grosse,,,,Grosse,Level 32: Grosse,Level 32: グローシュ,레벨 32: 그로세,,Level 32: Grosse,Fase 32: Grosse,Nível 32: Grosse,Nivelul 32: Grosse,Level 32: Гросс,Level 32: Гроссе -Level 31: IDKFA,HUSTR_31B,,,,,,,Nivelo 31: IDKFA,Nivel 31: IDKFA,,,NIVEAU 31: IDKFQ,IDKFA,Level 31: IDKFA,Level 31: IDKFA,레벨 31: IDKFA,,Level 31: IDKFA,Fase 31: IDKFA,Nível 31: IDKFA,Nivelul 31: IDKFA,Level 31: IDKFA, -Level 32: Keen,HUSTR_32B,,,,,,,Nivelo 32: Keen,Nivel 32: Keen,,,,Keen,Level 32: Keen,Level 32: キーン,레벨 32: 킨,,Level 32: Keen,Fase 32: Keen,Nível 32: Keen,Nivelul 32: Keen,Level 32: Кин,Level 32: Кин -Level 33: Betray,HUSTR_33,,,,Level 33: Zraď,Level 33: Verrat,,Nivelo 33: Perfido,Nivel 33: Traición,,Taso 33: Petä,NIVEAU 33: Trahison,Árulás,Level 33: Tradimento ,Level 33: 裏切り,레벨 33: 배반,Level 33: Verraad,Level 33: Zdrada,Fase 33: Traição,Nível 33: Traição,Nivelul 33: Trădare,Level 33: Предательство,Level 33: Издаја +Circle of Death ",,,Level 11: Kruh smrti,Level 11: 'O' der Zerstörung!,Επίπεδο 11: Ο Κύκλος της Καταστροφής,Nivelo 11: 'O' de Detruo!,Nivel 11: 'O' de Destrucción,,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!,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: Круг уништења +Level 12: The Factory,HUSTR_12,,,,Level 12: Továrna,Level 12: Die Fabrik,Επίπεδο 12: To Εργοστάσιο,Nivelo 12: La Fabrikejo,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,Level 12: Fabryka,Fase 12: A Fábrica,Nível 12: A Fábrica,Nivelul 12: Fabrica,Уровень 12: Фабрика,Level 12: Фабрика +Level 13: Downtown,HUSTR_13,,,,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,Level 13: Śródmieście,Fase 13: Centro Urbano,Nível 13: Centro Urbano,Nivelul 13: Centru urban,Уровень 13: Деловой район,Level 13: Центар града +Level 14: The Inmost Dens,HUSTR_14,,,,Level 14: Nejhlubší doupata,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,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: Најдубље јазбине +Level 15: Industrial Zone,HUSTR_15,,,,Level 15: Průmyslová zóna,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,Level 15: Strefa Przemysłowa,Fase 15: Zona Industrial,Nível 15: Zona Industrial,Nivelul 15: Zona industrială,Уровень 15: Промышленная зона,Level 15: Индустријска зона +Level 16: Suburbs,HUSTR_16,,,,Level 16: Předměstí,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,Level 16: Przedmieścia,Fase 16: Subúrbios,Nível 16: Subúrbios,Nivelul 16: Suburbi,Уровень 16: Пригород,Level 16: Предграђе +Level 17: Tenements,HUSTR_17,,,,Level 17: Sídliště,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,Level 17: Kamienice,Fase 17: Habitações,Nível 17: Habitações,Nivelul 17: Proprietăți,Уровень 17: Владения,Level 17: Станови +Level 18: The Courtyard,HUSTR_18,,,,Level 18: Nádvoří,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,Level 18: Dziedziniec,Fase 18: O Átrio,Nível 18: O Átrio,Nivelul 18: Curtea,Уровень 18: Внутренний двор,Level 18: Двориште +Level 19: The Citadel,HUSTR_19,,,,Level 19: Citadela,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,Level 19: Cytadela,Fase 19: A Cidadela,Nível 19: A Cidadela,Nivelul 19: Cetatea,Уровень 19: Цитадель,Level 19: Цитадела +Level 20: Gotcha!,HUSTR_20,,,,Level 20: Mám tě!,Level 20: Erwischt!,Επίπεδο 20: Σ'έπιασα!,Nivelo 20: Kaptis Vin!,Nivel 20: ¡Te Pillé!,,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!,Level 20: Mam Cię!,Fase 20: Te Peguei!,Nível 20: Apanhei-te!,Nivelul 20: Te-am prins!,Уровень 20: Попался!,Level 20: Имају те! +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: Нирвана +Level 22: The Catacombs,HUSTR_22,,,,Level 22: Katakomby,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,Level 22: Katakumby,Fase 22: As Catacumbas,Nível 22: Os Calabouços,Nivelul 22: Catacombe,Уровень 22: Катакомбы,Level 22: Катакомбе +Level 23: Barrels O' Fun,HUSTR_23,,,,Level 23: Barely srandy,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,Level 23: Beczki Śmiechu,Fase 23: Barris de Diversão,Nível 23: Barris de Diversão,Nivelul 23: Butoaiele veseliei,Уровень 23: Бочки веселья,Level 23: Бачве забаве +Level 24: The Chasm,HUSTR_24,,,,Level 24: Rokle,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,Level 24: Przepaść,Fase 24: O Abismo,Nível 24: O Abismo,Nivelul 24: Hăul,Уровень 24: Пропасть,Level 24: Провалија +Level 25: Bloodfalls,HUSTR_25,,,,Level 25: Krvopády,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,Level 25: Wodospad Krwi,Fase 25: Cataratas de Sangue,Nível 25: Cascatas de Sangue,Nivelul 25: Cascade de sânge,Уровень 25: Кровопады,Level 25: Крвопади +Level 26: The Abandoned Mines,HUSTR_26,,,,Level 26: Opuštěné doly,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,Level 26: Opuszczone Kopalnie,Fase 26: As Minas Abandonadas,Nível 26: As Minas Abandonadas,Nivelul 26: Minele părăsite,Уровень 26: Заброшенные шахты,Level 26: Напуштени рудници +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: 괴물 콘도,,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: Боравишта монструма +Level 28: The Spirit World,HUSTR_28,,,,Level 28: Onen svět,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,Level 28: Świat Dusz,Fase 28: O Mundo Espiritual,Nível 28: O Mundo Espiritual,Nivelul 28: Lumea duhurilor,Уровень 28: Мир духов,Level 28: Духовни свет +Level 29: The Living End,HUSTR_29,,,,Level 29: Živoucí konec,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,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: Крај живота +Level 30: Icon of Sin,HUSTR_30,,,,Level 30: Ikona hříchu,Level 30: Symbol der Sünde,Επίπεδο 30: Σύμβολο της Αμαρτίας,Nivelo 30: Ikono de Peko,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,Level 30: Ikona Grzechu,Fase 30: Ícone do Pecado,Nível 30: Ícone do Pecado,Nivelul 30: Icoana păcatelor,Уровень 30: Икона греха,Level 30: Икона греха +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: Волфенштајн +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: Гроссе +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, +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: Кин +Level 33: Betray,HUSTR_33,,,,Level 33: Zraď,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,Level 33: Zdrada,Fase 33: Traição,Nível 33: Traição,Nivelul 33: Trădare,Уровень 33: Предательство,Level 33: Издаја ,,No Rest For The Living,,,,,,,,,,,,,,,,,,,,, -Level 1: The Earth Base,NHUSTR_1,,,,Level 1: Pozemská základna,Level 1: Die Erd-Basis,,Nivelo 1: La Tera Bazo,Nivel 1: La Base Terrestre,,Taso 1: Maatukikohta,NIVEAU 1: La Base Terrienne,A földi bázis,Level 1: La Base Terrestre ,Level 1: 地球基地,레벨 1: 지구 기지,Level 1: De basis van de aarde,Level 1: Ziemska Baza,Fase 1: A Base Terrestre,Nível 1: A Base Terrestre,Nivelul 1: Baza terestră,Level 1: База на земле,Level 1: Земаљска база -Level 2: The Pain Labs,NHUSTR_2,,,,Level 2: Laboratoře bolesti,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,A kínok laboratóriuma,Level 2: I Laboratori del Dolore,Level 2: 生物工学実験室,레벨 2: 고통의 연구소,Level 2: De pijnlaboratoria,Level 2: Laboratoria Bólu,Fase 2: Os Laboratórios da Dor,Nível 2: Os Laboratórios da Dor,Nivelul 2: Laboratoarele durerii,Level 2: Лаборатории боли,Level 2: Лабораторије патње -Level 3: Canyon of The Dead,NHUSTR_3,,,,Level 3: Kaňon mrtvých,Level 3: Schlucht der Toten,,Nivelo 3: Kanjono de La Mortitaj,Nivel 3: Cañón de los Muertos,,Taso 3: Kalmankanjoni,NIVEAU 3: Canyon des Morts,A holtak szurdoka,Level 3: Il Canyon dei Morti,Level 3: 死の渓谷,레벨 3: 죽음의 계곡,Level 3: Canyon van de doden,Level 3: Kanion Umarłych,Fase 3: Desfiladeiro dos Mortos,Nível 3: Desfiladeiro dos Mortos,Nivelul 3: Canionul morților,Level 3: Каньон мертвецов,Level 3: Кањон мртваца -Level 4: Hell Mountain,NHUSTR_4,,,,Level 4: Pekelná hora,Level 4: Höllenberg,,Nivelo 4: Monto de Infero,Nivel 4: Montaña Infernal,,Taso 4: Hornanvuori,NIVEAU 4: Montagne Infernale,Pokol-hegy,Level 4: Promontorio Infernale ,Level 4: 地獄山脈,레벨 4: 지옥의 산,Level 4: Helleberg,Level 4: Piekielna Góra,Fase 4: Montanha Infernal,Nível 4: Montanha Infernal,Nivelul 4: Muntele infernal,Level 4: Адская гора,Level 4: Планина пакла -Level 5: Vivisection,NHUSTR_5,,,,Level 5: Vivisekce,Level 5: Vivisektion,,Nivelo 5: Vivisekcio,Nivel 5: Vivisección,,Taso 5: Vivisektio,NIVEAU 5: Vivisection,Élveboncolás,Level 5: Vivisezione ,Level 5: 生体解剖,레벨 5: 생체 해부,Level 5: Vivisectie,Level 5: Wiwisekcja,Fase 5: Vivissecção,Nível 5: Vivissecção,Nivelul 5: Vivisecție,Level 5: Вивисекция,Level 5: Вивисекција -Level 6: Inferno of Blood,NHUSTR_6,,,,Level 6: Krvavé inferno,Level 6: Blutiges Inferno,,Nivelo 6: Brulego de Sango,Nivel 6: Hoguera de Sangre,,Taso 6: Veri-inferno,NIVEAU 6: Enfer Sanglant,Véres alvilág,Level 6: Inferno di Sangue ,Level 6: 血のインフェルノ,레벨 6: 연옥의 피,Level 6: Bloederige inferno,Level 6: Piekło Krwi,Fase 6: Inferno de Sangue,Nível 6: Inferno de Sangue,Nivelul 6: Infern sângeriu,Level 6: Кровавая преисподняя,Level 6: Ватре крви -Level 7: Baron's Banquet,NHUSTR_7,,,,Level 7: Baronova hostina,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,A báró bankettje,Level 7: Il Banchetto del Barone ,Level 7: バロンの晩餐,레벨 7: 남작의 연회,Level 7: Baron's banket,Level 7: Bankiet Barona,Fase 7: Banquete do Barão,Nível 7: Banquete do Barão,Nivelul 7: Banchetul baronilor,Level 7: Банкет у барона,Level 7: Баронова Гозба -Level 8: Tomb of Malevolence,NHUSTR_8,,,,Level 8: Hrobka zlovolnosti,Level 8: Feindselige Gruft,,Nivelo 8: Tombo de Malbonvolo,Nivel 8: Tumba de Malevolencia,,Taso 8: Pahantahdon hauta,NIVEAU 8: Tombe Maléfique,A Rosszindulat sírja,Level 8: Tomba della Malevolenza,Level 8: 悪意の墓,레벨 8: 증오의 무덤,Level 8: Graf van kwaadwilligheid,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,Level 8: Гробница злобы,Level 8: Гроб злобе -Level 9: March of The Demons,NHUSTR_9,,,,Level 9: Pochod démonů,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,A démonok felvonulása,Level 9: La Marcia dei Demoni ,Level 9: デーモンの行進,레벨 9: 악마들의 행진,Level 9: Maart van de demonen,Level 9: Marsz Demonów,Fase 9: Marcha dos Demônios,Nível 9: Marcha dos Demônios,Nivelul 9: Marșul demonilor,Level 9: Шествие демонов,Level 9: Марш демона +Level 1: The Earth Base,NHUSTR_1,,,,Level 1: Pozemská základna,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,Level 1: Ziemska Baza,Fase 1: A Base Terrestre,Nível 1: A Base Terrestre,Nivelul 1: Baza terestră,Уровень 1: База на земле,Level 1: Земаљска база +Level 2: The Pain Labs,NHUSTR_2,,,,Level 2: Laboratoře bolesti,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,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: Лабораторије патње +Level 3: Canyon of The Dead,NHUSTR_3,,,,Level 3: Kaňon mrtvých,Level 3: Schlucht der Toten,,Nivelo 3: Kanjono de La Mortitaj,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,Level 3: Kanion Umarłych,Fase 3: Desfiladeiro dos Mortos,Nível 3: Desfiladeiro dos Mortos,Nivelul 3: Canionul morților,Уровень 3: Каньон мертвецов,Level 3: Кањон мртваца +Level 4: Hell Mountain,NHUSTR_4,,,,Level 4: Pekelná hora,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,Level 4: Piekielna Góra,Fase 4: Montanha Infernal,Nível 4: Montanha Infernal,Nivelul 4: Muntele infernal,Уровень 4: Адская гора,Level 4: Планина пакла +Level 5: Vivisection,NHUSTR_5,,,,Level 5: Vivisekce,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,Level 5: Wiwisekcja,Fase 5: Vivissecção,Nível 5: Vivissecção,Nivelul 5: Vivisecție,Уровень 5: Вивисекция,Level 5: Вивисекција +Level 6: Inferno of Blood,NHUSTR_6,,,,Level 6: Krvavé 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,Level 6: Piekło Krwi,Fase 6: Inferno de Sangue,Nível 6: Inferno de Sangue,Nivelul 6: Infern sângeriu,Уровень 6: Кровавая преисподняя,Level 6: Ватре крви +Level 7: Baron's Banquet,NHUSTR_7,,,,Level 7: Baronova hostina,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,Level 7: Bankiet Barona,Fase 7: Banquete do Barão,Nível 7: Banquete do Barão,Nivelul 7: Banchetul baronilor,Уровень 7: Банкет у барона,Level 7: Баронова Гозба +Level 8: Tomb of Malevolence,NHUSTR_8,,,,Level 8: Hrobka zlovolnosti,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,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: Гроб злобе +Level 9: March of The Demons,NHUSTR_9,,,,Level 9: Pochod démonů,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,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: Марш демона ,,Plutonia,,,,,,,,,,,,,,,,,,,,, -Level 1: Congo,PHUSTR_1,,,,Level 1: Kongo,Level 1: Kongo,,Nivelo 1: Kongo,Nivel 1: Congo,,Taso 1: Kongo,NIVEAU 1: Congo,Kongó,Level 1: Congo,Level 1: コンゴ川,레벨 1: 콩고,Level 1: Kongo,Level 1: Kongo,Fase 1: Congo,Nível 1: Congo,Nivelul 1: Congo,Level 1: Конго,Level 1: Конго -Level 2: Well of Souls,PHUSTR_2,,,,Level 2: Studna duší,Level 2: Seelenbrunnen,,Nivelo 2: Puto de Animoj,Nivel 2: Pozo de las Almas,,Taso 2: Sielujen lähde,NIVEAU 2: Puits des Ames,A lelkek kútja,Level 2: Pozzo delle Anime,Level 2: 魂の井戸,레벨 2: 영혼의 우물,Level 2: Bron van zielen,Level 2: Studnia Dusz,Fase 2: Poço das Almas,Nível 2: Poço de Almas,Nivelul 2: Fântâna sufletelor,Level 2: Колодец душ,Level 2: Бунар душа -Level 3: Aztec,PHUSTR_3,,,,Level 3: Azték,Level 3: Aztekisch,,Nivelo 3: Azteko,Nivel 3: Azteca,,Taso 3: Asteekki,NIVEAU 3: Aztèque,Azték,Level 3: Aztec,Level 3: アステカ,레벨 3: 아즈텍,Level 3: Azteken,Level 3: Aztek,Fase 3: Asteca,Nível 3: Asteca,Nivelul 3: Aztec,Level 3: Ацтек,Level 3: Астек -Level 4: Caged,PHUSTR_4,,,,Level 4: V kleci,Level 4: Eingesperrt,,Nivelo 4: Enkaĝigita,Nivel 4: Enjaulado,,Taso 4: Häkissä,NIVEAU 4: Enfermé,Ketrecbe zárva,Level 4: Ingabbiato,Level 4: 檻の中,레벨 4: 갇히다,Level 4: Gekooid,Level 4: W Klatce,Fase 4: Na Jaula,Nível 4: Na Jaula,Nivelul 4: Încarcerat,Level 4: В клетке,Level 4: Заробљен -Level 5: Ghost Town,PHUSTR_5,,,,Level 5: Město duchů,Level 5: Geisterstadt,,Nivelo 5: Fantomurbeto,Nivel 5: Pueblo Fantasma,,Taso 5: Aavekaupunki,NIVEAU 5: Ville Fantôme,Szellemváros,Level 5: Città Fantasma,Level 5: ゴーストタウン,레벨 5: 유령 도시,Level 5: Spookstad,Level 5: Miasto Duchów,Fase 5: Cidade Fantasma,Nível 5: Cidade Fantasma,Nivelul 5: Orașul fantomă,Level 5: Город-призрак,Level 5: Град духова -Level 6: Baron's Lair,PHUSTR_6,,,,Level 6: Baronovo doupě,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,A báró rejteke,Level 6: Tana del Barone,Level 6: バロンの隠れ家,레벨 6: 남작의 은신처,Level 6: Baron's kamp,Level 6: Legowisko Barona,Fase 6: Covil do Barão,Nível 6: Covil do Barão,Nivelul 6: Claustrul Baronului,Level 6: Обитель барона,Level 6: Баронова јазбина -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,A foglyok udvara,Level 7: Cortile della Prigione,Level 7: 囚われの庭,레벨 7: 포획마당,Level 7: Omheining,Level 7: Dziedziniec Więzienny,Fase 7: Campo de Concentração,Nível 7: Campo de Concentração,Nivelul 7: Capcana curții,Level 7: Двор-ловушка,Level 7: Замчиште -Level 8: Realm,PHUSTR_8,,,,Level 8: Říše,Level 8: Bereich,,Nivelo 8: Regno,Nivel 8: Reino,,Taso 8: Valtapiiri,NIVEAU 8: Royaume,Birodalom,Level 8: Regno,Level 8: 領地,레벨 8: 왕국,Level 8: Rijk,Level 8: Królestwo,Fase 8: Reino,Nível 8: Reino,Nivelul 8: Tărâm,Level 8: Царство,Level 8: Царство -Level 9: Abattoire,PHUSTR_9,,,,Level 9: Jatka,Level 9: Schlachthaus,,Nivelo 9: Buĉejo,Nivel 9: Matadero,,Taso 9: Teurastamo,NIVEAU 9: Abattoir,Vágóhíd,Level 9: Mattatoio,Level 9: 屠殺場,레벨 9: 도축장,Level 9: Abattoir,Level 9: Rzeźnia,Fase 9: Matadouro,Nível 9: Matadouro,Nivelul 9: Abator,Level 9: Скотобойня,Level 9: Кланица -Level 10: Onslaught,PHUSTR_10,,,,Level 10: Nájezd,Level 10: Angriff,,Nivelo 10: Buĉado,Nivel 10: Arremetida,,Taso 10: Ryntäys,NIVEAU 10: Assaut,Támadás,Level 10: Assalto,Level 10: 猛襲,레벨 10: 맹공격,Level 10: Aanval,Level 10: Szturm,Fase 10: Investida,Nível 10: Investida,Nivelul 10: Năvala,Level 10: Натиск,Level 10: Јуриш -Level 11: Hunted,PHUSTR_11,,,,Level 11: Loven,Level 11: Gehetzt,,Nivelo 11: Ĉasata,Nivel 11: Cazado,,Taso 11: Metsästetty,NIVEAU 11: Traque,Üldözve,Level 11: Braccato,Level 11: 逃走,레벨 11: 사냥당함,Level 11: Gejaagd,Level 11: Nawiedzony,Fase 11: Perseguição,Nível 11: Perseguição,Nivelul 11: Vânătoarea,Level 11: Преследуемый,Level 11: Уловљен -Level 12: Speed,PHUSTR_12,,,,Level 12: Rychlost,Level 12: Tempo,,Nivelo 12: Rapido,Nivel 12: Velocidad,,Taso 12: Vauhti,NIVEAU 12: Vitesse,Iram,Level 12: Velocità,Level 12: スピード,레벨 12: 스피드,Level 12: Haast,Level 12: Pęd,Fase 12: Velocidade,Nível 12: Velocidade,Nivelul 12: Viteză,Level 12: Скорость,Level 12: Брзина -Level 13: The Crypt,PHUSTR_13,,,,Level 13: Krypta,Level 13: Die Gruft,,Nivelo 13: La Kripto,Nivel 13: La Cripta,,Taso 13: Krypta,NIVEAU 13: La Crypte,A kripta,Level 13: La Cripta,Level 13: 地下聖堂,레벨 13: 봉안당,Level 13: De crypte,Level 13: Krypta,Fase 13: A Cripta,Nível 13: A Cripta,Nivelul 13: Cripta,Level 13: Склеп,Level 13: Гробница -Level 14: Genesis,PHUSTR_14,,,,,,,Nivelo 14: Genezo,Nivel 14: Génesis,,Taso 14: Luominen,NIVEAU 14: Genèse,Teremtés,Level 14: Genesi,Level 14: 創世記,레벨 14: 창세기,,Level 14: Geneza,Fase 14: Gênese,Nível 14: Gênese,Nivelul 14: Geneza,Level 14: Зарождение,Level 14: Постанак -Level 15: The Twilight,PHUSTR_15,,,,Level 15: Soumrak,Level 15: Zwielicht,,Nivelo 15: La Krepusko,Nivel 15: El Ocaso,,Taso 15: Hämärä,NIVEAU 15: Le Crépuscule,Alkonyat,Level 15: Il crepuscolo,Level 15: 黄昏,레벨 15: 황혼,Level 15: De schemering,Level 15: Zmierzch,Fase 15: O Crepúsculo,Nível 15: O Crepúsculo,Nivelul 15: Amurgul,Level 15: Сумерки,Level 15: Сумрак -Level 16: The Omen,PHUSTR_16,,,,Level 16: Znamení,Level 16: Das Omen,,Nivelo 16: La Aŭguro,Nivel 16: El Presagio,,Taso 16: Enne,NIVEAU 16: Le Présage,Ómen,Level 16: Il presagio,Level 16: 予兆,레벨 16: 징조,Level 16: De omen,Level 16: Omen,Fase 16: O Presságio,Nível 16: O Presságio,Nivelul 16: Prevestirea,Level 16: Предзнаменование,Level 16: Знамење -Level 17: Compound,PHUSTR_17,,,,Level 17: Ústav,Level 17: Anlage,,Nivelo 17: Konstruaĵaro,Nivel 17: Complejo,,Taso 17: Laitos,NIVEAU 17: Installation,Létesítmény,Level 17: Recinto,Level 17: 調合,레벨 17: 복합체,Level 17: Faciliteit,Level 17: Mieszanka,Fase 17: Complexo,Nível 17: Complexo,Nivelul 17: Complexul,Level 17: Комплекс,Level 17: Једињење -Level 18: Neurosphere,PHUSTR_18,,,,Level 18: Neurosféra,Level 18: Neurosphäre,,Nivelo 18: Neŭrosfero,Nivel 18: Neuroesfera,,Taso 18: Neurosfääri,NIVEAU 18: Neurosphère,Neuroszféra,Level 18: Neurosfera,Level 18: ニューロスフィア,레벨 18: 뉴로스피어,Level 18: Neurosferen,Level 18: Neurosfera,Fase 18: Neurosfera,Nível 18: Neurosfera,Nivelul 18: Neurosferă,Level 18: Нейросфера,Level 18: Неуросфера -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: NMIGO,,Taso 19: VHLLNN,NIVEAU 19: NMI,LNSG,Level 19: NMIC,Level 19: 野郎,레벨 19: NOM,,Level 19: WRG,Fase 19: N-MIGO,Nível 19: N-MIGO,Nivelul 19: INMIC,Level 19: В.Р.А.Г.,Level 19: Н.Е.П.Р. -Level 20: The Death Domain,PHUSTR_20,,,,Level 20: Panství smrti,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,A holtak birtoka,Level 20: Il Dominio della Morte,Level 20: 死の領域,레벨 20: 죽음의 영역,Level 20: Het domein van de dood,Level 20: Domena Śmierci,Fase 20: O Domínio da Morte,Nível 20: O Domínio da Morte,Nivelul 20: Domeniul morții,Level 20: Владения смерти,Level 20: Подручије смрти -Level 21: Slayer,PHUSTR_21,,,,Level 21: Zabiják,Level 21: Töter,,Nivelo 21: Mortigisto,Nivel 21: Descuatizador,,Taso 21: Tappaja,NIVEAU 21: Pourfendeur,Halálosztó,Level 21: Uccisore,Level 21: スレイヤー,레벨 21: 슬레이어,Level 21: Doder,Level 21: Pogromca,Fase 21: Matador,Nível 21: Matador,Nivelul 21: Ucigător,Level 21: Палач,Level 21: Убица -Level 22: Impossible Mission,PHUSTR_22,,,,Level 22: Nemožná mise,Level 22: Unmögliche Mission,,Nivelo 22: Malebla Misio,Nivel 22: Misión Imposible,,Taso 22: Mahdoton tehtävä,NIVEAU 22: Mission Impossible,Lehetetlen küldetés,Level 22: Missione Impossibile,Level 22: 不可能な任務,레벨 22: 임파서블 미션,Level 22: Onmogelijke missie,Level 22: Niemożliwa Misja,Fase 22: Missão Impossível,Nível 22: Missão Impossível,Nivelul 22: Misiune imposibilă,Level 22: Невыполнимое задание,Level 22: Немогућа мисија -Level 23: Tombstone,PHUSTR_23,,,,Level 23: Náhrobek,Level 23: Grabstein,,Nivelo 23: Tombŝtono,Nivel 23: Lápida,,Taso 23: Hautakivi,NIVEAU 23: Pierre Tombale,Sírkő,Level 23: Pietra Tombale,Level 23: 墓石,레벨 23: 묘비,Level 23: Grafsteen,Level 23: Nagrobek,Fase 23: Lápide,Nível 23: Lápide,Nivelul 23: Piatra de mormânt,Level 23: Надгробие,Level 23: Надгробни споменик -Level 24: The Final Frontier,PHUSTR_24,,,,Level 24: Poslední hranice,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,A végső határ,Level 24: La Frontiera Finale,Level 24: 最後のフロンティア,레벨 24: 최후의 개척지,Level 24: De eindgrens,Level 24: Ostateczna Granica,Fase 24: A Fronteira Final,Nível 24: A Fronteira Final,Nivelul 24: Ultima frontieră,Level 24: Последний рубеж,Level 24: Коначна граница -Level 25: The Temple of Darkness,PHUSTR_25,,,,Level 25: Chrám temna,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,A sötétség temploma,Level 25: Il Tempio dell'Oscurità,Level 25: 暗黒の神殿,레벨 25: 어둠의 신전,Level 25: De tempel van de duisternis,Level 25: Świątynia Mroku,Fase 25: O Templo da Escuridão,Nível 25: O Templo da Escuridão,Nivelul 25: Templul tenebros,Level 25: Храм тьмы,Level 25: Храм таме -Level 26: Bunker,PHUSTR_26,,,,Level 26: Bunkr,Level 26: Bunker,,Nivelo 26: Bunkro,Nivel 26: Búnker,,Taso 26: Bunkkeri,NIVEAU 26: Bunker,Bunker,Level 26: Bunker,Level 26: バンカー,레벨 26: 방공호,,Level 26: Bunkier,Fase 26: Casamata,Nível 26: Bunker,Nivelul 26: Buncăr,Level 26: Бункер,Level 26: Бункер -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,Antikrisztus,Level 27: Anticristo,Level 27: アンチキリスト,레벨 27: 적그리스도,Level 27: Antichrist,Level 27: Antychryst,Fase 27: Anticristo,Nível 27: Anticristo,Nivelul 27: Antihrist,Level 27: Антихрист,Level 27: Антихрист -Level 28: The Sewers,PHUSTR_28,,,,Level 28: Kanály,Level 28: Kanäle,,Nivelo 28: La Kanalo,Nivel 28: Las Alcantarillas,,Taso 28: Viemärit,NIVEAU 28: Les Egouts,A csatornák,Level 28: Le Fogne,Level 28: 下水道,레벨 28: 하수구,Level 28: De rioleringen,Level 28: Ścieki,Fase 28: Os Esgotos,Nível 28: Os Esgotos,Nivelul 28: Canalizarea,Level 28: Канализация,Level 28: Канализација -Level 29: Odyssey of Noises,PHUSTR_29,,,,Level 29: Odysea křiku,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,A zajok bolyongása,Level 29: Odissea di Rumori,Level 29: オデッセイのノイズ,레벨 29: 속삭임의 여정,Level 29: Odyssee van geluiden,Level 29: Odyseja Wrzawy,Fase 29: Odisséia de Ruidos,Nível 29: Odisséia de Ruidos,Nivelul 29: Odiseea zgomotelor,Level 29: Одиссея шумов,Level 29: Одисеја шумова -Level 30: The Gateway of Hell,PHUSTR_30,,,,Level 30: Brána pekla,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,Átjáró a pokolba,Level 30: La Porta dell'Inferno,Level 30: 地獄の関門,레벨 30: 지옥의 차원문,Level 30: De poort van de hel,Level 30: Brama Piekieł,Fase 30: O Portão do Inferno,Nível 30: O Portão do Inferno,Nivelul 30: Poarta spre infern,Level 30: Врата ада,Level 30: Пролаз пакла -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,Kiberodú,Level 31: Cybergabbia,Level 31: サイバーの巣,레벨 31: 사이버소굴,,Level 31: Cybernora,Fase 31: Ciberantro,Nível 31: Ciberantro,Nivelul 31: Cibervizuină,Level 31: Киберлогово,Level 31: Сајбер-јазбина -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 Adelante!,Taso 32: Iske kii,NIVEAU 32: Go 2 It,Menj oda!,Level 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,Level 32: П0лный вп3ред,Level 32: Иди ка њему +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,Level 1: Kongo,Fase 1: Congo,Nível 1: Congo,Nivelul 1: Congo,Уровень 1: Конго,Level 1: Конго +Level 2: Well of Souls,PHUSTR_2,,,,Level 2: Studna duší,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,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: Бунар душа +Level 3: Aztec,PHUSTR_3,,,,Level 3: Azték,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,Level 3: Aztek,Fase 3: Asteca,Nível 3: Asteca,Nivelul 3: Aztec,Уровень 3: Ацтек,Level 3: Астек +Level 4: Caged,PHUSTR_4,,,,Level 4: V kleci,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,Level 4: W Klatce,Fase 4: Na Jaula,Nível 4: Na Jaula,Nivelul 4: Încarcerat,Уровень 4: В клетке,Level 4: Заробљен +Level 5: Ghost Town,PHUSTR_5,,,,Level 5: Město duchů,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,Level 5: Miasto Duchów,Fase 5: Cidade Fantasma,Nível 5: Cidade Fantasma,Nivelul 5: Orașul fantomă,Уровень 5: Город-призрак,Level 5: Град духова +Level 6: Baron's Lair,PHUSTR_6,,,,Level 6: Baronovo doupě,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,Level 6: Legowisko Barona,Fase 6: Covil do Barão,Nível 6: Covil do Barão,Nivelul 6: Claustrul Baronului,Уровень 6: Обитель барона,Level 6: Баронова јазбина +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,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: Замчиште +Level 8: Realm,PHUSTR_8,,,,Level 8: Říše,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,Level 8: Królestwo,Fase 8: Reino,Nível 8: Reino,Nivelul 8: Tărâm,Уровень 8: Царство,Level 8: Царство +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,Level 9: Rzeźnia,Fase 9: Matadouro,Nível 9: Matadouro,Nivelul 9: Abator,Уровень 9: Скотобойня,Level 9: Кланица +Level 10: Onslaught,PHUSTR_10,,,,Level 10: Nájezd,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,Level 10: Szturm,Fase 10: Investida,Nível 10: Investida,Nivelul 10: Năvala,Уровень 10: Натиск,Level 10: Јуриш +Level 11: Hunted,PHUSTR_11,,,,Level 11: Loven,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,Level 11: Nawiedzony,Fase 11: Perseguição,Nível 11: Perseguição,Nivelul 11: Vânătoarea,Уровень 11: Преследуемый,Level 11: Уловљен +Level 12: Speed,PHUSTR_12,,,,Level 12: Rychlost,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,Level 12: Pęd,Fase 12: Velocidade,Nível 12: Velocidade,Nivelul 12: Viteză,Уровень 12: Скорость,Level 12: Брзина +Level 13: The Crypt,PHUSTR_13,,,,Level 13: Krypta,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,Level 13: Krypta,Fase 13: A Cripta,Nível 13: A Cripta,Nivelul 13: Cripta,Уровень 13: Склеп,Level 13: Гробница +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: Постанак +Level 15: The Twilight,PHUSTR_15,,,,Level 15: Soumrak,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,Level 15: Zmierzch,Fase 15: O Crepúsculo,Nível 15: O Crepúsculo,Nivelul 15: Amurgul,Уровень 15: Сумерки,Level 15: Сумрак +Level 16: The Omen,PHUSTR_16,,,,Level 16: Znamení,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,Level 16: Omen,Fase 16: O Presságio,Nível 16: O Presságio,Nivelul 16: Prevestirea,Уровень 16: Предзнаменование,Level 16: Знамење +Level 17: Compound,PHUSTR_17,,,,Level 17: Ústav,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,Level 17: Mieszanka,Fase 17: Complexo,Nível 17: Complexo,Nivelul 17: Complexul,Уровень 17: Комплекс,Level 17: Једињење +Level 18: Neurosphere,PHUSTR_18,,,,Level 18: Neurosféra,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,Level 18: Neurosfera,Fase 18: Neurosfera,Nível 18: Neurosfera,Nivelul 18: Neurosferă,Уровень 18: Нейросфера,Level 18: Неуросфера +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: NMIGO,,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: Н.Е.П.Р. +Level 20: The Death Domain,PHUSTR_20,,,,Level 20: Panství smrti,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,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: Подручије смрти +Level 21: Slayer,PHUSTR_21,,,,Level 21: Zabiják,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,Level 21: Pogromca,Fase 21: Matador,Nível 21: Matador,Nivelul 21: Ucigător,Уровень 21: Палач,Level 21: Убица +Level 22: Impossible Mission,PHUSTR_22,,,,Level 22: Nemožná mise,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,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: Немогућа мисија +Level 23: Tombstone,PHUSTR_23,,,,Level 23: Náhrobek,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,Level 23: Nagrobek,Fase 23: Lápide,Nível 23: Lápide,Nivelul 23: Piatra de mormânt,Уровень 23: Надгробие,Level 23: Надгробни споменик +Level 24: The Final Frontier,PHUSTR_24,,,,Level 24: Poslední hranice,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,Level 24: Ostateczna Granica,Fase 24: A Fronteira Final,Nível 24: A Fronteira Final,Nivelul 24: Ultima frontieră,Уровень 24: Последний рубеж,Level 24: Коначна граница +Level 25: The Temple of Darkness,PHUSTR_25,,,,Level 25: Chrám temna,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,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: Храм таме +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: Бункер +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,Level 27: Antychryst,Fase 27: Anticristo,Nível 27: Anticristo,Nivelul 27: Antihrist,Уровень 27: Антихрист,Level 27: Антихрист +Level 28: The Sewers,PHUSTR_28,,,,Level 28: Kanály,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,Level 28: Ścieki,Fase 28: Os Esgotos,Nível 28: Os Esgotos,Nivelul 28: Canalizarea,Уровень 28: Канализация,Level 28: Канализација +Level 29: Odyssey of Noises,PHUSTR_29,,,,Level 29: Odysea křiku,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,Level 29: Odyseja Wrzawy,Fase 29: Odisséia de Ruidos,Nível 29: Odisséia de Ruidos,Nivelul 29: Odiseea zgomotelor,Уровень 29: Одиссея шумов,Level 29: Одисеја шумова +Level 30: The Gateway of Hell,PHUSTR_30,,,,Level 30: Brána pekla,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,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: Пролаз пакла +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: Сајбер-јазбина +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 Adelante!,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: Иди ка њему ,,TNT: Evilution,,,,,,,,,,,,,,,,,,,,, -Level 1: System Control,THUSTR_1,,,,Level 1: Administrace,Level 1: Systemkontrolle,,Nivelo 1: Sistema Kontrolo,Nivel 1: Control del Sistema,,Taso 1: Järjestelmäohjaamo,NIVEAU 1: Système de Contrôle,Rendszervezérlő,Level 1: Controllo del Sistema,Level 1: 制御システム,레벨 1: 시스템 제어시설,Level 1: Systeemcontrole,Level 1: Kontrola Systemu,Fase 1: Controle do Sistema,Nível 1: Controlo de Sistema,Nivelul 1: Control sisteme,Level 1: Центр управления системой,Level 1: Контролна система -Level 2: Human BBQ,THUSTR_2,,,,Level 2: Člověčí grilovačka,Level 2: Menschliches Barbecue,,Nivelo 2: Homo-Kradrostado,Nivel 2: Barbacoa Humana,,Taso 2: Ihmisgrilli,NIVEAU 2: Barbecue Humain,Emberi grill,Level 2: Barbecue Umano,Level 2: 人肉晩餐会,레벨 2: 인간 바비큐,Level 2: Menselijke BBQ,Level 2: Ludzki Grill,Fase 2: Churrasco Humano,Nível 2: Churrasco Humano,Nivelul 2: Oameni la grătar,Level 2: Барбекю из человечины,Level 2: Људски роштиљ -Level 3: Power Control,THUSTR_3,,,,Level 3: Napájecí vedení,Level 3: Energiekontrolle,,Nivelo 3: Energia Kontrolo,Nivel 3: Control de Energía,,Taso 3: Voimalan ohjaamo,NIVEAU 3: Contrôle Energétique,Energiavezérlő,Level 3: Centrale Energetica,Level 3: 制御室,레벨 3: 전력 통제소,Level 3: Machtscontrole,Level 3: Kontrola Zasilania,Fase 3: Controle de Energia,Nível 3: Controlo Energético,Nivelul 3: Uzina,Level 3: Центр управления питанием,Level 3: Контролна моћ -Level 4: Wormhole,THUSTR_4,,,,Level 4: Červí díra,Level 4: Wurmloch,,Nivelo 4: Vermtruo,Nivel 4: Agujero de Gusano,,Taso 4: Madonreikä,NIVEAU 4: Trou de Ver,Féreglyuk,Level 4: Wormhole,Level 4: 虫喰い穴,레벨 4: 웜홀,Level 4: Wormgat,Level 4: Tunel,Fase 4: Buraco de Minhoca,Nível 4: Buraco de Minhoca,Nivelul 4: Gaura de vierme,Level 4: Червоточина,Level 4: Црвоточина -Level 5: Hanger,THUSTR_5,,,,Level 5: Hangár,Level 5: Hangar,,Nivelo 5: Hangaro,Nivel 5: Hangar,Nivel 5: Colgador,Taso 5: Lentoalushalli,NIVEAU 5: Hangar,Horog,Level 5: Gancio,Level 5: 格納庫,레벨 5: 격납고,Level 5: Hangar,Level 5: Hangar,Fase 5: Hangar,Nível 5: Hangar,Nivelul 5: Hangar,Level 5: Онгар,Level 5: Вешалица -Level 6: Open Season,THUSTR_6,,,,Level 6: Lovecká sezóna,Level 6: Jagdsaison,,Nivelo 6: Ĉasosezono,Nivel 6: Temporada Abierta,,Taso 6: Avoin sesonki,NIVEAU 6: La Chasse Est Ouverte,Vadászszezon,Level 6: Stagione Aperta,Level 6: 狩猟解禁,레벨 6: 사냥철,Level 6: Open seizoen,Level 6: Otwarty Sezon,Fase 6: Temporada Aberta,Nível 6: Época Aberta,Nivelul 6: Sezon deschis,Level 6: Сезон охоты,Level 6: Отворена сезона -Level 7: Prison,THUSTR_7,,,,Level 7: Vězení,Level 7: Gefängnis,,Nivelo 7: Malliberejo,Nivel 7: Prisión,,Taso 7: Vankila,NIVEAU 7: Prison,Börtön,Level 7: Prigione,Level 7: 監獄,레벨 7: 감옥,Level 7: Gevangenis,Level 7: Więzienie,Fase 7: Prisão,Nível 7: Prisão,Nivelul 7: Închisoare,Level 7: Тюрьма,Level 7: Затвор -Level 8: Metal,THUSTR_8,,,,Level 8: Kov,Level 8: Metall,,Nivelo 8: Metalo,Nivel 8: Metal,,Taso 8: Metalli,NIVEAU 8: Métal,Fém,Level 8: Metallo,Level 8: メタル,레벨 8: 강철,Level 8: Metaal,Level 8: Metal,Fase 8: Metal,Nível 8: Metal,Nivelul 8: Metal,Level 8: Металл,Level 8: Метал -Level 9: Stronghold,THUSTR_9,,,,Level 9: Pevnost,Level 9: Festung,,Nivelo 9: Fuorto,Nivel 9: Fortaleza,,Taso 9: Linnake,NIVEAU 9: Forteresse,Erőd,Level 9: Fortezza,Level 9: 牙城,레벨 9: 요새,Level 9: Vesting,Level 9: Warownia,Fase 9: Fortaleza,Nível 9: Fortaleza,Nivelul 9: Bastion,Level 9: Твердыня,Level 9: Упориште -Level 10: Redemption,THUSTR_10,,,,Level 10: Vykoupení,Level 10: Erlösung,,Nivelo 10: Elaĉeto,Nivel 10: Redención,,Taso 10: Lunastus,NIVEAU 10: Rédemption,Megváltás,Level 10: Redenzione,Level 10: 償還,레벨 10: 구원,Level 10: Aflossing,Level 10: Odkupienie,Fase 10: Redenção,Nível 10: Redenção,Nivelul 10: Răscumpărare,Level 10: Искупление,Level 10: Искупљење -Level 11: Storage Facility,THUSTR_11,,,,Level 11: Skladiště,Level 11: Lagerstätte,,Nivelo 11: Stokejo,Nivel 11: Complejo de Almacenes,,Taso 11: Varastolaitos,NIVEAU 11: Complexe de Stockage,Raktárépület,Level 11: Impianto di Stoccaggio,Level 11: 貯蔵施設,레벨 11: 저장소,Level 11: Opslagfaciliteit,Level 11: Magazyn,Fase 11: Centro de Armazenamento,Nível 11: Centro de Armazenamento,Nivelul 11: Stația de depozitare,Level 11: Склад,Level 11: Складиште -Level 12: Crater,THUSTR_12,,,,Level 12: Kráter,Level 12: Krater,,Nivelo 12: Kratero,Nivel 12: Cráter,,Taso 12: Kraateri,NIVEAU 12: Cratère,Kráter,Level 12: Cratere,Level 12: 火口,레벨 12: 분화구,Level 12: Krater,Level 12: Krater,Fase 12: Cratera,Nível 12: Cratera,Nivelul 12: Crater,Level 12: Кратер,Level 12: Кратер -Level 13: Nukage Processing,THUSTR_13,,,,Level 13: Jaderné zpracování,Level 13: Nuklearverarbeitung,,Nivelo 13: Nukleaĵo-Traktejo,Nivel 13: Procesamiento de Residuos Nucleares,,Taso 13: Ydinjätekäsittely,NIVEAU 13: Traitement Nucléaire,Atomhulladék-feldolgozó,Level 13: Trattamento Nucleare,Level 13: 核廃棄物加工所,레벨 13: 폐기물 처리소,Level 13: Nucleaire verwerking,Level 13: Przetwórstwo Jądrowe,Fase 13: Processamento Nuclear,Nível 13: Processamento Nuclear,Nivelul 13: Prelucrarea deșeurilor nucleare,Level 13: Переработка ядерных отходов,Level 13: Прерада нуклеарног отпада -Level 14: Steel Works,THUSTR_14,,,,Level 14: Ocelárna,Level 14: Stahlwerk,,Nivelo 14: Ŝtalejo,Nivel 14: Siderúrgica,,Taso 14: Terästehdas,NIVEAU 14: Aciérie,Acélművek,Level 14: Acciaieria,Level 14: 製鉄所,레벨 14: 제강소,Level 14: Staalfabrieken,Level 14: Huta,Fase 14: Siderúrgica,Nível 14: Siderúrgica,Nivelul 14: Oțelărie,Level 14: Сталелитейный завод,Level 14: Челичана -Level 15: Dead Zone,THUSTR_15,,,,Level 15: Mrtvá zóna,Level 15: Tote Zone,,Nivelo 15: Senvivzono,Nivel 15: Zona Muerta,,Taso 15: Kuollut alue,NIVEAU 15: Zone Morte,A holtak zónája,Level 15: Zona Morta,Level 15: 危険地帯,레벨 15: 사각지대,Level 15: Dode zone,Level 15: Martwa Strefa,Fase 15: Zona Morta,Nível 15: Zona Morta,Nivelul 15: Zona moartă,Level 15: Мёртвая зона,Level 15: Зона смрти -Level 16: Deepest Reaches,THUSTR_16,,,,Level 16: Nejhlubší sluje,Level 16: Tiefe,,Nivelo 16: Plejsubejo,Nivel 16: Recodos profundos,,Taso 16: Syvyydet,NIVEAU 16: Profondeurs,A legmélyebb pont,Level 16: Profondità,Level 16: 最深部,레벨 16: 깊숙한 강,Level 16: Diepste reiken,Level 16: Głębiny,Fase 16: Profundezas,Nível 16: Profundezas,Nivelul 16: În adâncuri,Level 16: Глубочайшие достижения,Level 16: Најдубља дубина -Level 17: Processing Area,THUSTR_17,,,,Level 17: Kombinát,Level 17: Verarbeitungsbereich,,Nivelo 17: Traktadareo,Nivel 17: Área de Procesamiento,,Taso 17: Käsittelyalue,NIVEAU 17: Zone de Traitement,Feldolgozó,Level 17: Area di Elaborazione,Level 17: 処理地帯,레벨 17: 처리 구역,Level 17: Verwerkingsgebied,Level 17: Strefa Przerobowa,Fase 17: Área de Processamento,Nível 17: Área de Processamento,Nivelul 17: Aria de procesare,Level 17: Зона обработки,Level 17: Подручје обраде -Level 18: Mill,THUSTR_18,,,,Level 18: Mlýn,Level 18: Mühle,,Nivelo 18: Muelejo,Nivel 18: Molino,,Taso 18: Mylly,NIVEAU 18: Fonderie,Malom,Level 18: Fonderia,Level 18: 製粉所,레벨 18: 제분소,Level 18: Molen,Level 18: Młyn,Fase 18: Moinho,Nível 18: Moinho,Nivelul 18: Moara,Level 18: Завод,Level 18: Млин -Level 19: Shipping/respawning,THUSTR_19,,,,Level 19: Přeprava,Level 19: Versandlager,,Nivelo 19: Ekspedo/Revivado,Nivel 19: Enviando/Reapareciendo,,Taso 19: Huolinta/Ylösnostatus,NIVEAU 19: Envoi/Réapparition,Szállítás/újraéledés,Level 19: Consegna/Respawn,Level 19: 出荷と再生成,레벨 19: 운송/리스폰 장소,Level 19: Verzendingscentrum,Level 19: Wysyłka/Reprodukcja,Fase 19: Expedição/reaparecimento,Nível 19: Expedição/reaparecimento,Nivelul 19: Livrare/reapariție,Level 19: Погрузка/отправка,Level 19: Отпремање/оживљавање -Level 20: Central Processing,THUSTR_20,,,,Level 20: Centrální zpracování,Level 20: Zentralverarbeitung,,Nivelo 20: Centra Eskpedado,Nivel 20: Procesamiento Central,,Taso 20: Käsittelykeskus,NIVEAU 20: Organisme Central,Központi feldolgozó,Level 20: Centrale di Elaborazione,Level 20: 中央処理所,레벨 20: 중앙 처리소,Level 20: Centrale verwerking,Level 20: Centralny Proces,Fase 20: Processamento Central,Nível 20: Processamento Central,Nivelul 20: Prelucrare centrală,Level 20: Центральный пункт обработки,Level 20: Централна обрада -Level 21: Administration Center,THUSTR_21,,,,Level 21: Administrativní centrum,Level 21: Verwaltungszentrum,,Nivelo 21: Administracia Centro,Nivel 21: Centro de Administración,,Taso 21: Keskushallinto,NIVEAU 21: Centre Administratif,Adminisztrációs központ,Level 21: Centro Amministrativo,Level 21: 行政センター,레벨 21: 관리 센터,Level 21: Administratief centrum,Level 21: Centrum Administracyjne,Fase 21: Centro de Administração,Nível 21: Centro de Administração,Nivelul 21: Centru administrativ,Level 21: Административный центр,Level 21: Административни центар -Level 22: Habitat,THUSTR_22,,,,,,,Nivelo 22: Habitato,Nivel 22: Hábitat,,Taso 22: Asuinpaikka,NIVEAU 22: Habitat,Élőhely,Level 22: Habitat,Level 22: 生息地,레벨 22: 서식지,,Level 22: Siedlisko,Fase 22: Habitat,Nível 22: Habitat,Nivelul 22: Habitat,Level 22: Обиталище,Level 22: Станиште -Level 23: Lunar Mining Project,THUSTR_23,,,,Level 23: Lunární těžební projekt,Level 23: Mondbergbauprojekt,,Nivelo 23: Luna Mino-Projekto,Nivel 23: Proyecto de Minería Lunar,,Taso 23: Kuukaivosprojekti,NIVEAU 23: Projet Minier Lunaire,Holdbánya-projekt,Level 23: Progetto Minerario Lunare,Level 23: 月面探鉱計画,레벨 23: 월석 채광 계획,Level 23: Maanmijnbouw project,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,Level 23: Лунный горный проект,Level 23: Пројекат лунарног рударства -Level 24: Quarry,THUSTR_24,,,,Level 24: Kamenolom,Level 24: Steinbruch,,Nivelo 24: Ŝtonejo,Nivel 24: Cantera,,Taso 24: Louhos,NIVEAU 24: Carrière,Kőbánya,Level 24: Caccia,Level 24: 採石場,레벨 24: 채석장,Level 24: Steengroeve,Level 24: Kamieniołom,Fase 24: Pedreira,Nível 24: Pedreira,Nivelul 24: Carieră,Level 24: Карьер,Level 24: Каменолом -Level 25: Baron's Den,THUSTR_25,,,,Level 25: Baronovo doupě,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,A báró odúja,Level 25: Antro del Barone,Level 25: バロンの巣窟,레벨 25: 남작의 소굴,Level 25: Het baron's gebouw,Level 25: Legowisko Barona,Fase 25: Covil do Barão,Nível 25: Covil do Barão,Nivelul 25: Cuibul Baronului,Level 25: Логово барона,Level 25: Баронова јазбина -Level 26: Ballistyx,THUSTR_26,,,,Level 26: Balistika,,,Nivelo 26: Balistikso,Nivel 26: Balístige,,Taso 26: Ballistyks,NIVEAU 26: Ballistyx,Ballisztüx,Level 26: Ballistige,Level 26: バリステュクス,레벨 26: 탄도스틱스,,Level 26: Balistyka,Fase 26: Ballistige,Nível 26: Ballistige,Nivelul 26: Ballistyx,Level 26: Баллистикс,Level 26: Билистичкикс -Level 27: Mount Pain,THUSTR_27,,,,Level 27: Hora bolesti,Level 27: Berg des Schmerzes,,Nivelo 27: Monto de Doloro,Nivel 27: Monte Dolor,,Taso 27: Tuskavuori,NIVEAU 27: Mont Souffrance,Szenvedés-hegy,Level 27: Monte del Dolore,Level 27: 苦しみの山,레벨 27: 등신같은 등산,Level 27: Pijn in de bergen,Level 27: Góra Bólu,Fase 27: Monte Dor,Nível 27: Monte Dor,Nivelul 27: Muntele Durerii,Level 27: Гора боль,Level 27: Планина боли -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?,Rosseb,Level 28: Grata,Level 28: 苛立ち,레벨 28: 젠장함,,Level 28: Do Diabła,Fase 28: Capeta,Nível 28: Inferno,Nivelul 28: Naiba,Level 28: Чертовщина,Level 28: Пакао -Level 29: River Styx,THUSTR_29,,,,Level 29: Řeka Styx,Level 29: Fluss Styx,,Nivelo 29: Rivero de Stikso,Nivel 29: Río Estige,,Taso 29: Styksjoki,NIVEAU 29: Fleuve Styx,A Sztüx folyó,Level 29: Fiume Stige,Level 29: 三途の川,레벨 29: 스틱스 강,Level 29: Rivier Styx,Level 29: Styks,Fase 29: Rio Estige,Nível 29: Rio Estige,Nivelul 29: Râul Styx,Level 29: Река стикс,Level 29: Река Стикс -Level 30: Last Call,THUSTR_30,,,,Level 30: Poslední mise,Level 30: Letzter Aufruf,,Nivelo 30: Fina Voko,Nivel 30: Última Llamada,,Taso 30: Viimeinen koollehuuto,NIVEAU 30: Dernier Appel,Utolsó esély,Level 30: Ultima Chiamata,Level 30: 最終指令,레벨 30: 최후의 호출,Level 30: Laatste oproep,Level 30: Ostatni Zew,Fase 30: Última Chamada,Nível 30: Última Chamada,Nivelul 30: Ultimul apel,Level 30: Последний вызов,Level 30: Последњи позив -Level 31: Pharaoh,THUSTR_31,,,,Level 31: Faraón,Level 31: Pharao,,Nivelo 31: Faraono,Nivel 31: Faraón,,Taso 31: Faarao,NIVEAU 31: Pharaon,Fáraó,Level 31: Faraone,Level 31: ファラオ,레벨 31: 파라오,Level 31: Farao,Level 31: Faraon,Fase 31: Faraó,Nível 31: Faraó,Nivelul 31: Faraon,Level 31: Фараон,Level 31: Фараон -Level 32: Caribbean,THUSTR_32,,,,Level 32: Karibik,Level 32: Karibik,,Nivelo 32: Karibio,Nivel 32: Caribeño,,Taso 32: Karibia,NIVEAU 32: Caraïbes,Karib-térség,Level 32: Caraibi,Level 32: カリビアン,레벨 32: 카리브해,Level 32: Caribisch,Level 32: Karaiby,Fase 32: Caribe,Nível 32: Caraíbas,Nivelul 32: Caraibe,Level 32: Карибы,Level 32: Кариби +Level 1: System Control,THUSTR_1,,,,Level 1: Administrace,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,Level 1: Kontrola Systemu,Fase 1: Controle do Sistema,Nível 1: Controlo de Sistema,Nivelul 1: Control sisteme,Уровень 1: Центр управления системой,Level 1: Контролна система +Level 2: Human BBQ,THUSTR_2,,,,Level 2: Člověčí grilovačka,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,Level 2: Ludzki Grill,Fase 2: Churrasco Humano,Nível 2: Churrasco Humano,Nivelul 2: Oameni la grătar,Уровень 2: Барбекю из человечины,Level 2: Људски роштиљ +Level 3: Power Control,THUSTR_3,,,,Level 3: Napájecí vedení,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,Level 3: Kontrola Zasilania,Fase 3: Controle de Energia,Nível 3: Controlo Energético,Nivelul 3: Uzina,Уровень 3: Центр управления питанием,Level 3: Контролна моћ +Level 4: Wormhole,THUSTR_4,,,,Level 4: Červí díra,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,Level 4: Tunel,Fase 4: Buraco de Minhoca,Nível 4: Buraco de Minhoca,Nivelul 4: Gaura de vierme,Уровень 4: Червоточина,Level 4: Црвоточина +Level 5: Hanger,THUSTR_5,,,,Level 5: Hangár,Level 5: Hangar,,Nivelo 5: Hangaro,Nivel 5: Hangar,Nivel 5: Colgador,Taso 5: Lentoalushalli,NIVEAU 5: Hangar,5. Pálya: Horog,Livello 5: Hanga,Level 5: 格納庫,레벨 5: 격납고,Level 5: Hangar,Level 5: Hangar,Fase 5: Hangar,Nível 5: Hangar,Nivelul 5: Hangar,Уровень 5: Онгар,Level 5: Вешалица +Level 6: Open Season,THUSTR_6,,,,Level 6: Lovecká sezóna,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,Level 6: Otwarty Sezon,Fase 6: Temporada Aberta,Nível 6: Época Aberta,Nivelul 6: Sezon deschis,Уровень 6: Сезон охоты,Level 6: Отворена сезона +Level 7: Prison,THUSTR_7,,,,Level 7: Vězení,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,Level 7: Więzienie,Fase 7: Prisão,Nível 7: Prisão,Nivelul 7: Închisoare,Уровень 7: Тюрьма,Level 7: Затвор +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,Level 8: Metal,Fase 8: Metal,Nível 8: Metal,Nivelul 8: Metal,Уровень 8: Металл,Level 8: Метал +Level 9: Stronghold,THUSTR_9,,,,Level 9: Pevnost,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,Level 9: Warownia,Fase 9: Fortaleza,Nível 9: Fortaleza,Nivelul 9: Bastion,Уровень 9: Твердыня,Level 9: Упориште +Level 10: Redemption,THUSTR_10,,,,Level 10: Vykoupení,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,Level 10: Odkupienie,Fase 10: Redenção,Nível 10: Redenção,Nivelul 10: Răscumpărare,Уровень 10: Искупление,Level 10: Искупљење +Level 11: Storage Facility,THUSTR_11,,,,Level 11: Skladiště,Level 11: Lagerstätte,,Nivelo 11: Stokejo,Nivel 11: Complejo de 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,Level 11: Magazyn,Fase 11: Centro de Armazenamento,Nível 11: Centro de Armazenamento,Nivelul 11: Stația de depozitare,Уровень 11: Склад,Level 11: Складиште +Level 12: Crater,THUSTR_12,,,,Level 12: Kráter,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,Level 12: Krater,Fase 12: Cratera,Nível 12: Cratera,Nivelul 12: Crater,Уровень 12: Кратер,Level 12: Кратер +Level 13: Nukage Processing,THUSTR_13,,,,Level 13: Jaderné zpracování,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,Level 13: Przetwórstwo Jądrowe,Fase 13: Processamento Nuclear,Nível 13: Processamento Nuclear,Nivelul 13: Prelucrarea deșeurilor nucleare,Уровень 13: Переработка ядерных отходов,Level 13: Прерада нуклеарног отпада +Level 14: Steel Works,THUSTR_14,,,,Level 14: Ocelárna,Level 14: Stahlwerk,,Nivelo 14: Ŝtalejo,Nivel 14: Siderúrgica,,Taso 14: Terästehdas,NIVEAU 14: Aciérie,14. Pálya: Acélművek,Livello 14: Acciaieria,Level 14: 製鉄所,레벨 14: 제강소,Level 14: Staalfabrieken,Level 14: Huta,Fase 14: Siderúrgica,Nível 14: Siderúrgica,Nivelul 14: Oțelărie,Уровень 14: Сталелитейный завод,Level 14: Челичана +Level 15: Dead Zone,THUSTR_15,,,,Level 15: Mrtvá zóna,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,Level 15: Martwa Strefa,Fase 15: Zona Morta,Nível 15: Zona Morta,Nivelul 15: Zona moartă,Уровень 15: Мёртвая зона,Level 15: Зона смрти +Level 16: Deepest Reaches,THUSTR_16,,,,Level 16: Nejhlubší sluje,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,Level 16: Głębiny,Fase 16: Profundezas,Nível 16: Profundezas,Nivelul 16: În adâncuri,Уровень 16: Глубочайшие достижения,Level 16: Најдубља дубина +Level 17: Processing Area,THUSTR_17,,,,Level 17: Kombinát,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,Level 17: Strefa Przerobowa,Fase 17: Área de Processamento,Nível 17: Área de Processamento,Nivelul 17: Aria de procesare,Уровень 17: Зона обработки,Level 17: Подручје обраде +Level 18: Mill,THUSTR_18,,,,Level 18: Mlýn,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,Level 18: Młyn,Fase 18: Moinho,Nível 18: Moinho,Nivelul 18: Moara,Уровень 18: Завод,Level 18: Млин +Level 19: Shipping/respawning,THUSTR_19,,,,Level 19: Přeprava,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,Level 19: Wysyłka/Reprodukcja,Fase 19: Expedição/reaparecimento,Nível 19: Expedição/reaparecimento,Nivelul 19: Livrare/reapariție,Уровень 19: Погрузка и отправка,Level 19: Отпремање/оживљавање +Level 20: Central Processing,THUSTR_20,,,,Level 20: Centrální zpracování,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,Level 20: Centralny Proces,Fase 20: Processamento Central,Nível 20: Processamento Central,Nivelul 20: Prelucrare centrală,Уровень 20: Центральный пункт обработки,Level 20: Централна обрада +Level 21: Administration Center,THUSTR_21,,,,Level 21: Administrativní centrum,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,Level 21: Centrum Administracyjne,Fase 21: Centro de Administração,Nível 21: Centro de Administração,Nivelul 21: Centru administrativ,Уровень 21: Административный центр,Level 21: Административни центар +Level 22: Habitat,THUSTR_22,,,,,,,Nivelo 22: Habitato,Nivel 22: Hábitat,,Taso 22: Asuinpaikka,NIVEAU 22: Habitat,22. Pálya: Élőhely,Livello 22: Habitat,Level 22: 生息地,레벨 22: 서식지,,Level 22: Siedlisko,Fase 22: Habitat,Nível 22: Habitat,Nivelul 22: Habitat,Уровень 22: Обиталище,Level 22: Станиште +Level 23: Lunar Mining Project,THUSTR_23,,,,Level 23: Lunární těžební projekt,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,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: Пројекат лунарног рударства +Level 24: Quarry,THUSTR_24,,,,Level 24: Kamenolom,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,Level 24: Kamieniołom,Fase 24: Pedreira,Nível 24: Pedreira,Nivelul 24: Carieră,Уровень 24: Карьер,Level 24: Каменолом +Level 25: Baron's Den,THUSTR_25,,,,Level 25: Baronovo doupě,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,Level 25: Legowisko Barona,Fase 25: Covil do Barão,Nível 25: Covil do Barão,Nivelul 25: Cuibul Baronului,Уровень 25: Логово барона,Level 25: Баронова јазбина +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: Билистичкикс +Level 27: Mount Pain,THUSTR_27,,,,Level 27: Hora bolesti,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,Level 27: Góra Bólu,Fase 27: Monte Dor,Nível 27: Monte Dor,Nivelul 27: Muntele Durerii,Уровень 27: Гора боль,Level 27: Планина боли +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: 젠장함,,Level 28: Do Diabła,Fase 28: Capeta,Nível 28: Inferno,Nivelul 28: Naiba,Уровень 28: Чертовщина,Level 28: Пакао +Level 29: River Styx,THUSTR_29,,,,Level 29: Řeka 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,Level 29: Styks,Fase 29: Rio Estige,Nível 29: Rio Estige,Nivelul 29: Râul Styx,Уровень 29: Река стикс,Level 29: Река Стикс +Level 30: Last Call,THUSTR_30,,,,Level 30: Poslední mise,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,Level 30: Ostatni Zew,Fase 30: Última Chamada,Nível 30: Última Chamada,Nivelul 30: Ultimul apel,Уровень 30: Последний вызов,Level 30: Последњи позив +Level 31: Pharaoh,THUSTR_31,,,,Level 31: Faraón,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,Level 31: Faraon,Fase 31: Faraó,Nível 31: Faraó,Nivelul 31: Faraon,Уровень 31: Фараон,Level 31: Фараон +Level 32: Caribbean,THUSTR_32,,,,Level 32: Karibik,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,Level 32: Karaiby,Fase 32: Caribe,Nível 32: Caraíbas,Nivelul 32: Caraibe,Уровень 32: Карибы,Level 32: Кариби ,,Heretic,,,,,,,,,,,,,,,,,,,,, The Docks,HHUSTR_E1M1,,,,Přístav,Die Docks,,La Havenoj,Los Muelles,,Satamat,Les Docks,A Kikötő,Il Molo,埠頭,항구,De dokken,Doki,As Docas,,Docul,Доки,Лука The Dungeons,HHUSTR_E1M2,,,,Žaláře,Die Kerker,,La Malliberejoj,Los Calabozos,,Tyrmät,Le Donjon,A Kazamaták,I Sotterranei,地下牢,지하감옥,De kerkers,Lochy,As Masmorras,,Temnița,Темницы,Тамнице @@ -174,7 +174,7 @@ The Crypts,HHUSTR_E1M7,,,,Krypty,Die Krypten,,La Kriptoj,Las Criptas,,Kryptat,La Hell's Maw,HHUSTR_E1M8,,,,Chřtán pekla,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,Paszcza Piekieł,A Boca do Inferno,,Gura iadului,Адская утроба,Паклено ждрело The Graveyard,HHUSTR_E1M9,,,,Hřbitov,Der Friedhof,,La Tombejo,El Cementerio,,Hautausmaa,Le Cimetière,A Temető,Il Cimitero,墓場,공동묘지,De begraafplaats,Cmentarz,O Cemitério,,Cimitirul,Кладбище,Гробље The Crater,HHUSTR_E2M1,,,,Kráter,Der Krater,,La Kratero,El Cráter,,Kraateri,Le Cratère,A Kráter,Il Cratere,噴火口,깊은 혈,De krater,Krater,A Cratera,,Craterul,Кратер,Кратер -The Lava Pits,HHUSTR_E2M2,,,,Lávové jámy,Die Lavagruben,,La Lafo-Fosaĵo,Las Canteras de Lava,,Laavamontut,Les Puits de Lave,A Lávagödrök,I Pozzi della Lava,溶岩の竪穴,용암 구덩이,De lavaputten,Szyb Lawy,Os Fossos de Lava,,Gropile cu lavă,Лавовые очаги,Понор лаве +The Lava Pits,HHUSTR_E2M2,,,,Lávové jámy,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,Szyb Lawy,Os Fossos de Lava,,Gropile cu lavă,Лавовые очаги,Понор лаве The River of Fire,HHUSTR_E2M3,,,,Ohnivá řeka,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,Rzeka Ognia,O Rio de Fogo,,Râul de foc,Река огня,Река од ватре The Ice Grotto,HHUSTR_E2M4,,,,Ledová grotta,Die Eisgrotte,,La Glacigroto,La Gruta de Hielo,,Jääluola,La Grotte de Glace,A Jégbarlang,La Grotta del Ghiaccio,氷の洞窟,얼음 동굴,De ijsgrot,Lodowa Grota,A Gruta de Gelo,,Grota de gheață,Ледяной грот,Ледена пећина The Catacombs,HHUSTR_E2M5,,,,Katakomby,Die Katakomben,,La Katakomboj,Las Catacumbas,,Katakombit,Les Catacombes,A Katakombák,Le Catacombe,地下墓所,태고의 무덤,De catacomben,Katakumby,As Catacumbas,Os Túmulos,Catacombele,Катакомбы,Катакомбе @@ -189,14 +189,14 @@ The Azure Fortress,HHUSTR_E3M4,,,,Azurová pevnost,Die himmelblaue Festung,,La L The Ophidian Lair,HHUSTR_E3M5,,,,Hadí doupě,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,Gniazdo Węży,A Cova dos Ofídios,,Cuibul ofidienilor,Логово офидианов,Змијска јазбина The Halls of Fear,HHUSTR_E3M6,,,,Chodby strachu,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,Korytarze Strachu,Os Salões do Medo,,Sălile groazei,Залы страха,Дворана страха The Chasm,HHUSTR_E3M7,,,,Propast,Der Abgrund,,La Fendego,El Abismo,,Rotko,Le Gouffre,A Szakadék,L'abisso,裂け目,깊은 골,De kloof,Przepaść,O Abismo,,Prăpastia,Пропасть,Понор лаве -D'Sparil's Keep,HHUSTR_E3M8,,,,D'Sparilova pevnost,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,Baszta D'Sparila,Fortaleza de D'Sparil,,Palatul lui D'sparil,Крепость Д'Спарила,Д'Спарилова кула +D'Sparil's Keep,HHUSTR_E3M8,,,,D'Sparilova pevnost,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,Baszta D'Sparila,Fortaleza de D'Sparil,,Palatul lui D'sparil,Крепость Д'Спарила,Д'Спарилова кула The Aquifer,HHUSTR_E3M9,,,,Zvodeň,Der Wasserspeicher,,La Akvigilo,El Acuífero,,Akviferi,L'Aquifère,A Víztorony,L'acquedotto,帯水層,대수층,Het water reservoir,Wodociąg,O Aquífero,,Galerii acvifere,Водоносный слой,Водоносник Catafalque,HHUSTR_E4M1,,,,Katafalk,Katafalk,,Katafalko,Catafalco,,Katafalkki,Le Catafalque,Ravatal,Catafalco,棺台,관대,Catafalk,Katafalk,Catafalco,,Catafalc,Катафалк,Одар Blockhouse,HHUSTR_E4M2,,,,Tvrzka,Blockhaus,,Blokhaŭso,Fortín,,Linnoitus,Le Fortin,Gerendaház,Blocco di Case,丸太小屋,특화점,Blokhuis,Blokhauz,O Forte,,Fort,Укрытие,Бункер Ambulatory,HHUSTR_E4M3,,,,Ochoz,Wandelgang,,Ĥorĉirkaŭirejo,Ambulatorio,,Kuorikäytävä,Le Déambulatoire,Kerengő,Ambulatorio,遊歩道,유보장,Kloostergang,Krużganek,Ambulatório,,Clinică,Монастырская галерея,Амбуланта Sepulcher,HHUSTR_E4M4,,,,Hrobka,Grabstätte,,Tombo,Sepulcro,,Hautakammio,Le Sépulcre,Síremlék,Sepolcro,埋葬所,매장소,Grafsteen,Grób,Sepulcro,,Sepulcru,Гробница,Гробница Great Stair,HHUSTR_E4M5,,,,Velké schody,Große Treppe,,Granda Ŝtuparo,Gran Escalera,,Suuret portaat,Le Grand Escalier,Nagy Lépcső,Grande Scala,大階段,특급 계단,Grote trap,Wielka Gwiazda,Grande Escada,,Scara cea mare,Великая лестница,Велики степеник -Halls of the Apostate,HHUSTR_E4M6,,,,Chodby odpadlictví,Halle des Abtrünnigen,,Haloj de la Apostato,Salas de los Apóstatas,,Luopioiden salit,Les Halls de l'Apôtre,A Hitehagyott Átjárója,Sale dell'Apostata,背教者の館,배교자의 회관,Zalen van de afvallige,Korytarze Odszczepieńca,Os Salões dos Apóstatas,,Sălile apostatului,Залы отступников,Дворана апостола +Halls of the Apostate,HHUSTR_E4M6,,,,Chodby odpadlictví,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,Korytarze Odszczepieńca,Os Salões dos Apóstatas,,Sălile apostatului,Залы отступников,Дворана апостола Ramparts of Perdition,HHUSTR_E4M7,,,,Náspy zatracení,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,Wał Potępienia,Muralhas da Perdição,,Meterezele pierzaniei,Твердыни погибели,Бедем пропасти Shattered Bridge,HHUSTR_E4M8,,,,Rozbitý most,Zerstörte Brücke,,Frakasita Ponto,Puente Destrozado,,Särkynyt silta,Le Pont effondré,Az Összeomlott Híd,Ponte Distrutto,崩落の橋,붕괴된 다리,Verbrijzelde brug,Zniszczony Most,Ponte Despedaçada,,Podul dărâmat,Разрушенный мост,Поломљен мост Mausoleum,HHUSTR_E4M9,,,,Mauzoleum,,,Maŭzoleo,Mausoleo,,Mausoleumi,Le Mausolée,Mauzóleum,Mausoleo,霊廟,대영묘,,Mauzoleum,Mausoléu,,Mausoleu,Мавзолей,Маузолеј @@ -208,44 +208,44 @@ Hydratyr,HHUSTR_E5M5,,,,Hydratýr,,,Akvotjr,Hydratyr,,,L'Hydratyr,Hidratáló,Hy Colonnade,HHUSTR_E5M6,,,,Kolonáda,Kolonnaden,,Kolonaro,Columnata,,Pylväikkö,La Colonnade,Kolonnád,Colonnato,柱廊,열주의 길,Zuilengalerij,Kolumnada,Colunata,,Colonadă,Колоннада,Колонада Foetid Manse,HHUSTR_E5M7,,,,Smrdutá vila,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,Cuchnąca Plebania,Mansão Fétida,,Conac Fetid,Зловонный особняк,Фетидна кућа Field of Judgement,HHUSTR_E5M8,,,,Soudná pole,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,Pole Sądu,Campo de Julgamento,,Câmpul de Judecată,Поле высшего суда,Чистилиште -Skein of D'sparil,HHUSTR_E5M9,,,,Hejno D'Sparilovo,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,Motek D'Sparila,Meada de D'Sparil,,Jurubița lui D'Sparil,Путаница Д'Спарила,Реке Д'Спарила +Skein of D'sparil,HHUSTR_E5M9,,,,Hejno D'Sparilovo,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,Motek D'Sparila,Meada de D'Sparil,,Jurubița lui D'Sparil,Путаница Д'Спарила,Реке Д'Спарила ,,Strife,,,,,,,,,,,,,,,,,,,,, AREA 1: Sanctuary,TXT_STRIFE_MAP01,,,,ZÓNA 1: Svatyně,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,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище, AREA 2: Town,TXT_STRIFE_MAP02,,,,ZÓNA 2: Město,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,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город, -AREA 3: Front Base,TXT_STRIFE_MAP03,,,,ZÓNA 3: Základna Fronty,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,Strefa 3: Baza Frontu,Área 3: Base da Frente,,ZONA 3: Baza Frontului,МЕСТНОСТЬ 3: База Сопротивления, +AREA 3: Front Base,TXT_STRIFE_MAP03,,,,ZÓNA 3: Základna Fronty,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,Strefa 3: Baza Frontu,Área 3: Base da Frente,,ZONA 3: Baza Frontului,МЕСТНОСТЬ 3: База сопротивления, AREA 4: Power Station,TXT_STRIFE_MAP04,,,,ZÓNA 4: Elektrárna,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,Strefa 4: Elektrownia,Área 4: Usina de Energia,Área 4: Central Energética,ZONA 4: Centrala,МЕСТНОСТЬ 4: Электростанция, AREA 5: Prison,TXT_STRIFE_MAP05,,,,ZÓNA 5: Vězení,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,Strefa 5: Więzienie,Área 5: Prisão,,ZONA 5: Închisoare,МЕСТНОСТЬ 5: Тюрьма, -AREA 6: Sewers,TXT_STRIFE_MAP06,,,,ZÓNA 6: Stoky,ZONE 6: Kanalisation,,AREO 6: Kloako,ÁREA 6: Alcantarillas,,ALUE 6: Viemärit,ZONE 6: Egouts,6. Terület: Szennyvízcsatornák,AREA 6: Fogne,エリア 6: 下水道,구역 6: 하수도,Zone 6: Riolering,Strefa 6: Kanały,Área 6: Esgoto,,ZONA 6: Canal,МЕСТНОСТЬ 6: Канализация, +AREA 6: Sewers,TXT_STRIFE_MAP06,,,,ZÓNA 6: Stoky,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,Strefa 6: Kanały,Área 6: Esgoto,,ZONA 6: Canal,МЕСТНОСТЬ 6: Канализация, AREA 7: Castle,TXT_STRIFE_MAP07,,,,ZÓNA 7: Hrad,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,Strefa 7: Zamek,Área 7: Castelo,,ZONA 7: Castel,МЕСТНОСТЬ 7: Замок, AREA 8: Audience Chamber,TXT_STRIFE_MAP08,,,,ZÓNA 8: Audienční sál,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,Strefa 8: Izba Audiencji,Área 8: Câmara de Audiências,,ZONA 8: Camera de audiențe,МЕСТНОСТЬ 8: Приёмная, -AREA 9: Castle: Programmer's Keep,TXT_STRIFE_MAP09,,,,ZÓNA 9: Hrad: Programátorovo doupě,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,Strefa 9: Zamek: Baszta Programisty,Área 9: Castelo: Torre do Programador,,ZONA 9: Castel: Cetatea programatorului,МЕСТНОСТЬ 9: Замок (Цитадель Программиста), -AREA 10: New Front Base,TXT_STRIFE_MAP10,,,,ZÓNA 10: Nová základna Fronty,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,Strefa 10: Nowa Baza Frontu,Área 10: Nova Base da Frente,,ZONA 10: Noua bază a Frontului,МЕСТНОСТЬ 10: Новая база Сопротивления, +AREA 9: Castle: Programmer's Keep,TXT_STRIFE_MAP09,,,,ZÓNA 9: Hrad: Programátorovo doupě,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,Strefa 9: Zamek: Baszta Programisty,Área 9: Castelo: Torre do Programador,,ZONA 9: Castel: Cetatea programatorului,МЕСТНОСТЬ 9: Замок (Цитадель программиста), +AREA 10: New Front Base,TXT_STRIFE_MAP10,,,,ZÓNA 10: Nová základna Fronty,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,Strefa 10: Nowa Baza Frontu,Área 10: Nova Base da Frente,,ZONA 10: Noua bază a Frontului,МЕСТНОСТЬ 10: Новая база сопротивления, AREA 11: Borderlands,TXT_STRIFE_MAP11,,,,ZÓNA 11: Pohraničí,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,Strefa 11: Pogranicze,Área 11: Fronteira,,ZONA 11: Frontiere,МЕСТНОСТЬ 11: Пограничье, AREA 12: The Temple of the Oracle,TXT_STRIFE_MAP12,,,,ZÓNA 12: Věštcův chrám,ZONE 12: Der Tempel des Orakels,,AREO 12: La Templo de La Oraklo,Á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,Strefa 12: Świątynia Wyroczni,Área 12: O Templo do Oráculo,,ZONA 12: Templul Oracolului,МЕСТНОСТЬ 12: Храм Оракула, AREA 13: Catacombs,TXT_STRIFE_MAP13,,,,ZÓNA 13: Katakomby,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,Strefa 13: Katakumby,Área 13: Catacumbas,Área 13: Túmulos,ZONA 13: Catacombe,МЕСТНОСТЬ 13: Катакомбы, AREA 14: Mines,TXT_STRIFE_MAP14,,,,ZÓNA 14: Doly,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,Strefa 14: Kopalnia,Área 14: Minas,,ZONA 14: Mine,МЕСТНОСТЬ 14: Шахты, -AREA 15: Fortress: Administration,TXT_STRIFE_MAP15,,,,ZÓNA 15: Pevnost: Administrace,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: Adminisztráció,AREA 15: Fortezza: Amministrazione,エリア 15: 要塞:管理室,구역 15: 요새: 중앙 관리소,Zone 15: Vesting: Administratieve organisatie,Strefa 15: Forteca: Administracja,Área 15: Fortaleza: Administração,,ZONA 15: Fortăreața: Administrația,МЕСТНОСТЬ 15: Крепость (Администрация), -AREA 16: Fortress: Bishop's Tower,TXT_STRIFE_MAP16,,,,ZÓNA 16: Pevnost: Biskupova věž,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,Strefa 16: Forteca: Wieża Biskupa,Área 16: Fortaleza: Torre do Bispo,,ZONA 16: Fortăreața: Turnul Episcopului,МЕСТНОСТЬ 16: Крепость (Башня Епископа), +AREA 15: Fortress: Administration,TXT_STRIFE_MAP15,,,,ZÓNA 15: Pevnost: Administrace,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,Strefa 15: Forteca: Administracja,Área 15: Fortaleza: Administração,,ZONA 15: Fortăreața: Administrația,МЕСТНОСТЬ 15: Крепость (Администрация), +AREA 16: Fortress: Bishop's Tower,TXT_STRIFE_MAP16,,,,ZÓNA 16: Pevnost: Biskupova věž,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,Strefa 16: Forteca: Wieża Biskupa,Área 16: Fortaleza: Torre do Bispo,,ZONA 16: Fortăreața: Turnul Episcopului,МЕСТНОСТЬ 16: Крепость (Башня епископа), AREA 17: Fortress: The Bailey,TXT_STRIFE_MAP17,,,,ZÓNA 17: Pevnost: Předhradí,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,Strefa 17: Forteca: Mur Obronny,Área 17: Fortaleza: O Pátio,,ZONA 17: Fortăreața: Curte,МЕСТНОСТЬ 17: Крепость (Двор), AREA 18: Fortress: Stores,TXT_STRIFE_MAP18,,,,ZÓNA 18: Pevnost: Sklady,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,Strefa 18: Forteca: Sklepy,Área 18: Fortaleza: Reservas,,ZONA 18: Fortăreața: Depozite,МЕСТНОСТЬ 18: Крепость (Склады), AREA 19: Fortress: Security Complex,TXT_STRIFE_MAP19,,,,ZÓNA 19: Pevnost: Bezpečnostní komplex,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,Strefa 19: Forteca: Kompleks Ochronny,Área 19: Fortaleza: Complexo de Segurança,,ZONA 19: Fortăreața: Complex de securitate,МЕСТНОСТЬ 19: Крепость (Охранный комплекс), AREA 20: Factory: Receiving,TXT_STRIFE_MAP20,,,,ZÓNA 20: Továrna: Příjem,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,Strefa 20: Fabryka: Odbiór,Área 20: Fábrica: Recebimento,,ZONA 20: Fabrica: Recepție,МЕСТНОСТЬ 20: Фабрика (Приём), AREA 21: Factory: Manufacturing,TXT_STRIFE_MAP21,,,,ZÓNA 21: Továrna: Výroba,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,Strefa 21: Fabryka: Przetwórstwo,Área 21: Fábrica: Manufatura,,ZONA 21: Fabrica: Procesare,МЕСТНОСТЬ 21: Фабрика (Обработка), -AREA 22: Factory: Forge,TXT_STRIFE_MAP22,,,,ZÓNA 22: Továrna: Kovárna,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,Strefa 22: Fabryka: Kuźnia,Área 22: Fábrica: Forja,,ZONA 22: Fabrica: Forja,МЕСТНОСТЬ 22: Фабрика (Кузня), +AREA 22: Factory: Forge,TXT_STRIFE_MAP22,,,,ZÓNA 22: Továrna: Slévárna,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,Strefa 22: Fabryka: Kuźnia,Área 22: Fábrica: Forja,,ZONA 22: Fabrica: Forja,МЕСТНОСТЬ 22: Фабрика (Кузня), AREA 23: Order Commons,TXT_STRIFE_MAP23,,,,ZÓNA 23: Náves Řádu,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,Strefa 23: Wikt Zakonu,Área 23: Câmara da Ordem,,ZONA 23: Decontare comenzi,МЕСТНОСТЬ 23: Поселение Ордена, AREA 24: Factory: Conversion Chapel,TXT_STRIFE_MAP24,,,,ZÓNA 24: Továrna: Kaple konverze,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,Strefa 24: Fabryka: Kaplica Przemiany,Área 24: Fábrica: Capela de Conversão,,ZONA 24: Fabrica: Capela de conversie,МЕСТНОСТЬ 24: Часовня обращения, AREA 25: Catacombs: Ruined Temple,TXT_STRIFE_MAP25,,,,ZÓNA 25: Katakomby: Zničený chrám,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,Strefa 25: Katakumby: Zrujnowana Świątynia,Área 25: Catacumbas: Templo Arruinado,Área 25: Túmulos: Templo Arruinado,ZONA 25: Catacombe: Templu în ruine,МЕСТНОСТЬ 25: Катакомбы (Руины храма), AREA 26: Proving Grounds,TXT_STRIFE_MAP26,,,,ZÓNA 26: Vojenský újezd,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,Strefa 26: Poligon Wojskowy,Área 26: Campo de Treinamento,Área 26: Campo de Treino,ZONA 26: Tabăra de instruire,МЕСТНОСТЬ 26: Испытательный полигон, AREA 27: The Lab,TXT_STRIFE_MAP27,,,,ZÓNA 27: Laboratoř,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,Strefa 27: Laboratorium,Área 27: O Laboratório,,ZONA 27: Laboratorul,МЕСТНОСТЬ 27: Лаборатория, AREA 28: Alien Ship,TXT_STRIFE_MAP28,,,,ZÓNA 28: Mimozemská loď,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,Strefa 28: Statek Obcych,Área 28: Nave Alienígena,,ZONA 28: Nava extraterestră,МЕСТНОСТЬ 28: Корабль пришельцев, -AREA 29: Entity's Lair,TXT_STRIFE_MAP29,,,,ZÓNA 29: Doupě Bytosti,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 Lény Búvóhelye,AREA 29: Tana dell'Entità,エリア 29: エンティティの隠れ家,구역 29: 엔티티의 소굴,Zone 29: Het nest van de entiteit,Strefa 29: Leże Bytu,Área 29: Covil da Entidade,,ZONA 29: Cuibul Entității,МЕСТНОСТЬ 29: Логово Сущности, -AREA 30: Abandoned Front Base,TXT_STRIFE_MAP30,,,,ZÓNA 30: Opuštěná základna Fronty,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,Strefa 30: Opuszczona Baza Frontu,Área 30: Base da Frente Abandonada,,ZONA 30: Baza abandonată a Frontului,МЕСТНОСТЬ 30: Заброшенная база Сопротивления, +AREA 29: Entity's Lair,TXT_STRIFE_MAP29,,,,ZÓNA 29: Doupě Bytosti,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,Strefa 29: Leże Bytu,Área 29: Covil da Entidade,,ZONA 29: Cuibul Entității,МЕСТНОСТЬ 29: Логово Сущности, +AREA 30: Abandoned Front Base,TXT_STRIFE_MAP30,,,,ZÓNA 30: Opuštěná základna Fronty,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,Strefa 30: Opuszczona Baza Frontu,Área 30: Base da Frente Abandonada,,ZONA 30: Baza abandonată a Frontului,МЕСТНОСТЬ 30: Заброшенная база сопротивления, AREA 31: Training Facility,TXT_STRIFE_MAP31,,,,ZÓNA 31: Výcvikové zařízení,ZONE 31: Trainingseinrichtung,,AREO 31: Trejnejo,ÁREA 31: Facilidad 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,Strefa 31: Centrum Szkoleniowe,Área 31: Instalação de Treinamento,,ZONA 31: Spațiul de antrenament,МЕСТНОСТЬ 31: Тренировочный корпус, AREA 1: Sanctuary,TXT_STRIFE_MAP32,,,,ZÓNA 1: Svatyně,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,Strefa 1: Sanktuarium,Área 1: Santuário,,ZONA 1: Sanctuar,МЕСТНОСТЬ 1: Святилище, AREA 2: Town,TXT_STRIFE_MAP33,,,,ZÓNA 2: Město,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,Strefa 2: Miasto,Área 2: Vila,,ZONA 2: Oraș,МЕСТНОСТЬ 2: Город, -AREA 3: Movement Base,TXT_STRIFE_MAP34,,,,ZÓNA 3: Rebelská základna,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,Strefa 3: Baza Ruchu Oporu,Área 3: Base do Movimento,,ZONA 3: Baza rezistenței,МЕСТНОСТЬ 3: База Сопротивления, +AREA 3: Movement Base,TXT_STRIFE_MAP34,,,,ZÓNA 3: Rebelská základna,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,Strefa 3: Baza Ruchu Oporu,Área 3: Base do Movimento,,ZONA 3: Baza rezistenței,МЕСТНОСТЬ 3: База сопротивления, AREA 35: Factory: Production,TXT_STRIFE_MAP35,,,,ZÓNA 35: Továrna: Produkce,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,Strefa 35: Fabryka: Produkcja,Área 35: Fábrica: Produção,,ZONA 35: Fabrica: Producție,МЕСТНОСТЬ 35: Фабрика (Производство), AREA 36: Castle Clash,TXT_STRIFE_MAP36,,,,ZÓNA 36: Střet na hradě,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,Strefa 36: Potyczka w Zamku,Área 36: Ataque ao Castelo,,ZONA 36: Bătălia castelului,МЕСТНОСТЬ 36: Битва в замке, AREA 37: Killing Grounds,TXT_STRIFE_MAP37,,,,ZÓNA 37: Popravčí zahrady,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,Strefa 37: Śmiercionośny Grunt,Área 37: Campo de Matança,,ZONA 37: Teren de ucis,МЕСТНОСТЬ 37: Секторы обстрела, @@ -256,7 +256,7 @@ Seven Portals,TXT_HEXEN_MAP02,,,,Sedmero portálů,Sieben Portale,,Sep Portaloj, Guardian of Ice,TXT_HEXEN_MAP03,,,,Strážce ledu,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,Strażnik Lodu,Guardião de Gelo,,Străjerul Gheții,Страж льда,Чувар леда Guardian of Fire,TXT_HEXEN_MAP04,,,,Strážce ohně,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,Strażnik Ognia,Guardião de Fogo,,Străjerul Focului,Страж огня,Чувар огња Guardian of Steel,TXT_HEXEN_MAP05,,,,Strážce oceli,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,Strażnik Stali,Guardião de Aço,,Străjerul Oțelului,Страж стали,Чувар челика -Bright Crucible,TXT_HEXEN_MAP06,,,,Světlý očistec,Glänzende Feuerprobe,,Luma Krisolo,Crisol de Luz,,Kirkas tulikoe,Creuset Radiant,Fényes Ketrec,Crogiolo Luminoso,光の坩堝,빛나는 고난,Heldere beproeving,Próba Światła,Crisol de Luz,,Creuzet Luminos,Испытание света,Испит светла +Bright Crucible,TXT_HEXEN_MAP06,,,,Světlý očistec,Glänzende Feuerprobe,,Luma Krisolo,Crisol de Luz,,Kirkas tulikoe,Creuset Radiant,Fényes Ketrec,Crogiolo Luminoso,光の坩堝,빛나는 고난,Heldere beproeving,Tygiel Światła,Crisol de Luz,,Creuzet Luminos,Испытание света,Испит светла Shadow Wood,TXT_HEXEN_MAP13,,,,Temný hvozd,Schattenwald,,Ombro-Arbareto,Bosque de la Sombra,,Varjosalo,Forêt des Ombres,Árnyék Erdő,Foresta Oscura,陰影樹,그림자 숲,Schaduwbos,Las Cieni,Floresta das Sombras,,Pădurea Umbrelor,Лес теней,Шума сенки 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,Болотная топь,Мочварна земља Caves of Circe,TXT_HEXEN_MAP09,,,,Kirčiny jeskyně,Circes Höhle,,Kavernoj de Circe,Cuevas de Circe,,Circeluolat,Caves de Circé,Körök Barlangja,Grotte di Circe,キルケーの洞窟,키르케의 동굴,Grotten van Circe,Jaskinie Kirke,Cavernas de Circe,,Peșterile lui Circe,Пещеры цирцеи,Киркине пећине @@ -279,18 +279,18 @@ Desolate Garden,TXT_HEXEN_MAP26,,,,Zpustošená zahrada,Verwildeter Garten,,Deze Necropolis,TXT_HEXEN_MAP35,,,,Nekropole,Nekropole,,Nekropolo,Necrópolis,,Nekropoli,Nécropole,Nekropolisz,Necropoli,ネクロポリス,망자의 도시,,Nekropolia,Necrópole,,Necropola,Некрополь,Некропола Zedek's Tomb,TXT_HEXEN_MAP36,,,,Zedekova hrobka,Zedeks Gruft,,Tombo de Zedek,Tumba de Zedek,,Sedekin hauta,Tombeau de Zedek,Zedek Sírja,Tomba di Zedek,ゼデクの墓,제닥의 무덤,Zedek's graf,Grobowiec Zedeka,Tumba de Zedek,Túmulo de Zedek,Mormântul lui Zedek,Гробница Зедека,Гробница Зедекова Menelkir's Tomb,TXT_HEXEN_MAP37,,,,Menelkirova hrobka,Menelkirs Gruft,,Tombo de Menelkir,Tumba de Menelkir,,Menelkirin hauta,Tombeau de Menelkir,Menelkir Sírja,Tomba di Menelkir,メネルキルの墓,메넬키어의 무덤,Menelkir's graf,Grobowiec Menelkira,Tumba de Menelkir,Túmulo de Menelkir,Mormântul lui Menelkir,Гробница Менелкира,Гробница Менелкирова -Traductus' Tomb,TXT_HEXEN_MAP38,,,,Traduktova hrobka,Traductus' Gruft,,Tombo de Traductus,Tumba de Traductus,,Traduktuksen hauta,Tombeau de Traductus,Traductus Sírja,Tomba di Traductus,トダクティスの墓,트라닥투스의 무덤,Traductus' graf,Grobowiec Traductusa,Tumba de Traductus,Túmulo de Traductus,Mormântul lui Traductus,Гробница Традактуса,Гробница Традуктусова +Traductus' Tomb,TXT_HEXEN_MAP38,,,,Traduktova hrobka,Traductus' Gruft,,Tombo de Traductus,Tumba de Traductus,,Traduktuksen hauta,Tombeau de Traductus,Traductus Sírja,Tomba di Traductus,トダクティスの墓,트라닥투스의 무덤,Traductus' graf,Grobowiec Traduktusa,Tumba de Traductus,Túmulo de Traductus,Mormântul lui Traductus,Гробница Традактуса,Гробница Традуктусова Vivarium,TXT_HEXEN_MAP39,,,,Vivárium,Vivarium,,Vivario,Vivario,,Vivaario,Vivarium,Vivárium,Vivario,ビバリウム,사육장,,Wiwarium,Viveiro,,Vivariu,Виварий,Виваријум Dark Crucible,TXT_HEXEN_MAP40,,,,Temný očistec,Dunkle Feuerprobe,,Malluma Krisolo,Crisol de Oscuridad,,Pimeä tulikoe,Creuset Sombre,Sötét Ketrec,Crogiolo Buio,"暗黒の坩堝 -",어두운 고난,Donkere beproeving,Próba Mroku,Crisol das Trevas,,Creuzet Întunecat,Испытание тьмы,Испит таме +",어두운 고난,Donkere beproeving,Tygiel Mroku,Crisol das Trevas,,Creuzet Întunecat,Испытание тьмы,Испит таме ,,Hexen Deathkings,,,,,,,,,,,,,,,,,,,,, Ruined Village,TXT_HEXDD_MAP41,,,,Zničená vesnice,Zerstörtes Dorf,,Ruiniga Vilaĝo,Pueblo en Ruinas,,Rauniokylä,Village en Ruines,Az Elpusztított Falu,Villagio in Rovine,廃村,파괴된 마을,Ruïneerd dorp,Zrujnowana Wioska,Aldeia Destruída,Aldeia em Ruinas,Sat ruinat,Разрушенная деревня,Уништено село Blight,TXT_HEXDD_MAP42,,,,Pohroma,Fäule,,Pesto,Decaimiento,,Turmelus,Peste,Penész,Peste,疫病,황폐화,Ziekte,Zaraza,Peste,,Cotropit,Упадок,Пошаст Sump,TXT_HEXDD_MAP43,,,,Žumpa,Sumpf,,Olekuvo,Pozo de Barro,,Likakaivo,Puisard,Tócsa,Pozzetto,汚水槽,웅덩이,Moeras,Studzienka,Poço de Lama,,Joampă,Грязеотстойник,Сливник Catacomb,TXT_HEXDD_MAP44,,,,Katakomby,Katakombe,,Katakombo,Catacumba,,Katakombi,Catacombe,Katakomba,Catacombe,カタコンベ,지하 묘실,Katacombe,Katakumba,Catacumba,,Catacombă,Катакомба,Катакомба -Badlands,TXT_HEXDD_MAP45,,,,Pustiny,Ödland,,Badlandoj,Páramos,,Autiomaa,Terres Sauvages,Terméketlen Föld,Terre Selvagge,不毛地帯,불모지,Woestijn,Nieurodzaj,Ermo,,Deșert,Бесплодные земли,Пустош +Badlands,TXT_HEXDD_MAP45,,,,Pustiny,Ödland,,Badlandoj,Páramos,,Autiomaa,Terres Sauvages,Terméketlen Föld,Terre Selvagge,不毛地帯,불모지,Woestijn,Pustkowia,Ermo,,Deșert,Бесплодные земли,Пустош 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,Брекенвуд,Папрат -Pyre,TXT_HEXDD_MAP47,,,,Hranice,Scheiterhaufen,,Kremaciejo,Pira Funeraria,,Rovio,Brasier,Máglya,Pira,火葬薪,화장,Brandstapel,Stos,Pira,,Rug,Погребальный костёр,Ломача +Pyre,TXT_HEXDD_MAP47,,,,Hranice,Scheiterhaufen,,Kremaciejo,Pira Funeraria,,Rovio,Brasier,Máglya,Pira,火葬薪,화장,Brandstapel,Ognisko,Pira,,Rug,Погребальный костёр,Ломача Constable's Gate,TXT_HEXDD_MAP48,,,,Konstáblova brána,Wachtor,,Pordego de Ĝendarmo,Puerta del Alguacil,,Konstaapelin portti,Portail du Constable,Csendőr Kapu,Porta del Conestabile,城守達の門,무관장의 문,Constable's poort,Brama Posterunkowego,Portão do Condestável,,Poarta ofițerului,Комендантские врата,Чиновникова капија Treasury,TXT_HEXDD_MAP49,,,,Pokladnice,Schatzkammer,,Trezorejo,Tesorería,,Rahasto,Trésorerie,Kincstár,Tesoreria,宝庫,국고,Schatkist,Skarbiec,Tesouraria,,Vistierie,Сокровищница,Трезор Market Place,TXT_HEXDD_MAP50,,,,Tržnice,Marktplatz,,Foirejo,Plaza del Mercado,,Markkinat,Place du Marché,Piactér,Piazza del Mercato,市場,시장,Markt,Rynek,Feira,,Piață,Рыночная площадь,Пијаца @@ -308,7 +308,7 @@ Transit,TXT_HEXDD_MAP33,,,,Převoz,,,Vojo,Sala de Espera,,Läpikulku,Transit,Tra 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,Nad I Pod,Sobre e Sob,,Mai sus și Mai jos,Выше и ниже,Изнад и испод Deathfog,TXT_HEXDD_MAP35,,,,Mha skonu,Todesnebel,,Mortnebulo,Niebla de Muerte,,Kuolonsumu,Brume Mortelle,Halálköd,Nebbia di Morte,死の霧,죽음의 안개,Dodenmist,Mgła Śmierci,Névoa da Morte,,Ceața morții,Туман смерти,Магла смрти Castle of Pain,TXT_HEXDD_MAP36,,,,Hrad bolesti,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,Zamek Bólu,Castelo da Dor,,Castelul durerii,Замок боли,Тврђава бола -Sewer Pit,TXT_HEXDD_MAP37,,,,Odpadní jáma,Kanalgrube,,Fekaĵputo,Pozo de Residuos,,Viemärimonttu,Trou d'Egout,Kanális,Fossa della Fogna,地下溝穴,하수도,Rioolput,Ściek,Fossa de Esgoto,,Groapa de scurgere,Сточная яма,Канализациона јама +Sewer Pit,TXT_HEXDD_MAP37,,,,Odpadní jáma,Kanalgrube,,Fekaĵputo,Pozo de Residuos,,Viemärimonttu,Trou d'Egout,Kanális akna,Fossa della Fogna,地下溝穴,하수도,Rioolput,Ściek,Fossa de Esgoto,,Groapa de scurgere,Сточная яма,Канализациона јама The Rose,TXT_HEXDD_MAP38,,,,Růže,Die Rose,,La Rozo,La Rosa,,Ruusu,La Rose,A Rózsa,La Rosa,薔薇,장밋빛,De roos,Róża,A Rosa,,Roza,Роза,Ружа ,,Intermission texts,,,,,,,,,,,,,,,,,,,,, "Once you beat the big badasses and @@ -364,8 +364,8 @@ vi estas kaptita sur La Bordoj de Infero. La sola eliro estas tra. Por daŭrigi la DOOM-sperton, ludu -""La Bordoj de Infero"" kaj ĝian -mirigan sekvon, ""Inferno""!","Una vez has vencido a los tremendos bastardos +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 @@ -375,7 +375,7 @@ y tu pasaje a casa? ¿Qué diablos es esto? 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 atravesarlo. +La única forma de salir es atravesarlo. Para continuar la experiencia de DOOM, juega Las Orillas del Infierno y su @@ -435,8 +435,7 @@ Az egyetlen kiút előre vezet. A DOOM élmény folytatásához játszd ""A pokol tornáca"" fejezetet, és annak -elképesztő folytatását, az ""Alvilág""-ot! -","Una volta che hai eliminato i cattivi e +elképesztő folytatását, az ""Alvilág""-ot!","Una volta che hai eliminato i cattivi e liberato la base lunare dovresti aver vinto, vero? Vero? Dove sono la tua ricca ricompensa e il biglietto per @@ -513,11 +512,11 @@ para casa? Não deveria acabar desse jeito! O cheiro é de carne podre, mas parece ser a base perdida de Deimos. Parece que você -está preso nas Margens do Inferno. +está preso nas Margens do Abismo. O único jeito de sair é através dela. Para continuar a experiência ""DOOM"", -jogue As Margens do Inferno e sua +jogue As Margens do Abismo e sua incrível sequência, Inferno!","Após derrotar as criaturas miseráveis e limpar a base lunar devias ter ganho, É, não é? Não é? Onde está a tua @@ -530,7 +529,7 @@ preso nas Margens do Inferno. O único maneira de sair é por aqui. Para continuar a experiência ""DOOM"", -jogue As Margens do Inferno e sua +jogue As Margens do Abismo e sua incrível sequência, Inferno!","Odată ce-i învingi pe ticăloși și cureți baza de pe Phobos, se presupune că ai câștigat, nu-i așa? Nu-i așa? Unde-ți sunt @@ -635,16 +634,16 @@ ke ili iam sciiĝis pri vi! Rapide, vi absejlas malsupren al la surfaco de Infero. Nun, ek al la fina ĉapitro de -DOOM! -- Inferno.","¡Lo hiciste! ¡El horrendo Ciberdemonio que +DOOM! -- Inferno.","¡Lo lograste! ¡El horrendo Ciberdemonio que regía la base lunar perdida de Deimos -ha sido asesinado y has triunfado! +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. -¡Deimos flota sobre el mismísimo infierno! +¡Deimos flota sobre el mismísimo Infierno! Nunca has oído de alguien escapar del -infierno, ¡pero harás que los bastardos +Infierno, ¡pero harás que los bastardos lamenten no haber escuchado sobre tí! Rápidamente, desciendes a rapel hacia la superficie del Infierno. @@ -899,19 +898,21 @@ ke neniu Inferido povintus veni tra la pordo kun vi...","El abominable demonio arácnido que orquestó la invasión de las bases lunares y causó innumerables muertes ha recibido una patada -en el trasero para siempre. +en el culo de una vez por todas. Una puerta oculta se abre y entonces entras. -Has demostrado ser demasiado rud@[ao_esp] para -el infierno para contener, y ahora el -infierno al final juega limpio -- ¡emerges +Has demostrado ser deamsiado dur@[ao_esp] para que el Infierno te contenga, y ahora el +Infierno al fin juega limpio -- ¡emerges desde la puerta para ver los campos verdes -de la Tierra! Hogar al fin. +de la Tierra! Por fin en casa. Te preguntas qué ha sucedido en la Tierra mientras combatías a la maldad desatada. Menos mal que ningún ser infernal ha podido -entrar a través de esa puerta contigo...",,"Hirvittävä hämähäkkipaholainen, joka juoni +entrar a través de esa puerta contigo... + + +",,"Hirvittävä hämähäkkipaholainen, joka juoni kuutukikohtien invaasion ja aiheutti niin paljon kuolemaa, on saanut kaikkien aikojen selkäsaunan. @@ -1654,7 +1655,7 @@ humanidad evacuar la Tierra y escapar de la pesadilla. Ahora tú eres el único ser humano que queda sobre la faz del planeta. Mutaciones caníbales, alienígenas -carnívoros, y espíritus malvados son tus +carnívoros, y espíritus malignos son tus únicos vecinos. Te sientas y esperas la muerte, content@[ao_esp] de haber salvado a tu especie. @@ -1738,20 +1739,20 @@ al genere umano di evacuare la terra e di fuggire dall'incubo. Ora sei il solo umano rimasto sulla faccia del pianeta. Mutazioni cannibali, alieni carnivori e -spiriti malvagi sono I tuoi soli vicini. +spiriti malvagi sono i tuoi soli vicini. Ti siedi e aspetti la morte, felice di aver salvato la tua specie. Proprio allora, il controllo della terra -rimanda un messaggio dallo spazio: ""I +trasmette un messaggio dallo spazio: ""I sensori hanno localizzato la fonte dell'invasione aliena. Se andrai lì -potrai forse bloccare il loro +forse potrai bloccare il loro ingresso. La base aliena è nel cuore della tua città natale, non lontano dallo spazioporto."" Lentamente e dolorosamente ti alzi -è ritorni alla battaglia.","勝利した!人類をこの世の地獄から脱出させ絶滅の悪夢から救ったのだ。 +e ritorni alla battaglia.","勝利した!人類をこの世の地獄から脱出させ絶滅の悪夢から救ったのだ。 そして自分が最後の地球人となった。 デーモンもとい人食いエイリアン、共食いミュータント、 くどい怨嗟のゴースト、そして死体だけが隣人だ。 @@ -2108,8 +2109,8 @@ desintegra y muere, sus miembros azotan el suelo devastando incontables kilómetros de suelo infernal. -Lo has hecho. La invasión se acabó. La tierra -está a salvo. El infierno es una ruina. Te +Lo has conseguido. La invasión ha terminado. La Tierra +ha sido salvada. El Infierno es una ruina. Te preguntas adónde irán los malos cuando mueran ahora. Secándote el sudor de la frente comienzas el largo camino de vuelta @@ -2146,7 +2147,7 @@ entreprenez le long chemin du retour. Reconstruire la Terre devrait être plus amusant que de la détruire.","A borzalmas ábrázata a legnagyobb démonnak amit valaha láttál összeomlik előtted, amikor -betömködted a rakétáidat a védtelen agyába. +betömködted a rakétáidat a kilátszódó agyába. A szörny összeroncsolodik és meghal, a végtagjai szanaszét repülnek a pokol felszínén. @@ -2332,11 +2333,10 @@ prisonnier des enfers ici...","Gratulálunk, megtaláltad a titkos pályát! Úgy tűnik, hogy ezt emberek építették, és nem démonok. Elgondolkodsz azon, hogy miféle lények tartózkodnak a pokol eme szegletében.","Congratulazioni, hai trovato il livello -degreto! Sembra essere stato edificato +segreto! Sembra essere stato edificato da umani più che da demoni. Ti chiedi chi siano gli abitanti di questo angolo -dell'inferno. -","おめでとう、君は隠しステージを発見した! +dell'inferno.","おめでとう、君は隠しステージを発見した! どうやらこの場所は悪魔ではなく、人間たちによって作られたようだ。 地獄の片隅には、どんな罪人がいるのだろうか?","축하한다. 당신은 비밀 레벨을 찾아냈다! 여기는 악마들보다는 인간들이 건설한 곳 같다. 그러나 당신은 구석에 있는 죄수들이 지옥에 있던 놈들임을 @@ -2442,7 +2442,7 @@ weiter, kämpfe weiter, töte weiter. Und ja, lebe auch weiter.",,"Vi ĝojaĉas super la vaporanta kadavro de La Gardinto. Per ĝia morto, vi eltiris La Akcelilon el la fetoraj krifoj de Infero. Vi ripozas kaj -ĉirkaŭrigardas la ĉambron. Damne! Devis esti +ĉirkaŭrigardas la ĉambron. Diable! Devis esti almenaŭ unu funkcia prototipo, sed vi ne vidas ĝin. La demonoj verŝajne prenis ĝin. @@ -2595,7 +2595,7 @@ Trebuie să găsești prototipul, altminteri toată munca ta se va duce de râpă. Continuă să te miști, continuă să lupți, continuă să omori. Ah, da, continuă și să trăiești, de asemenea.","Вы злорадствуете над дымящимися останками -стража. Убив его, вы вырвали акселератор +стража. Убив его, вы вырвали ускоритель из вонющих лап Преисподней. Вы вздыхаете с облегчением и осматриваете комнату. Чёрт! Здесь должен был остаться как минимум один @@ -2705,9 +2705,9 @@ stare să îți vină de hac, iar acum ai pus mâna pe prototipul Acceleratorului care va fi dezactivat în mod eficient și permanent curând. -Te pricepi la chestii de genul.","Даже лабиринт смертоносных Арч-вайлов не +Te pricepi la chestii de genul.","Даже лабиринт смертоносных архвилей не смог вас остановить, и вы добрались до -прототипа акселератора, сразу же +прототипа ускорителя, сразу же деактивировав его раз и навсегда. Это вы хорошо умеете.","Чак ни смртоносан арчвилов лавиринт @@ -2753,8 +2753,8 @@ vi konas iun pli mavan! Grimacante malice, vi kontrolas vian ilaron, kaj pretiĝas doni al la bastardo iom da Infero -de via farado mem!","Has golpeado y vapuleado tú camino al -corazón de la colmena diabólica. Es +de via farado mem!","Has golpeado y vapuleado abriéndote camino hacia +el corazón de la colmena diabólica. Es hora de una misión de búsqueda y destrucción, con el guardián del portal como objetivo, cuyos viles vástagos se @@ -2792,7 +2792,7 @@ Igen, ő rossz. De te tudod, hogy nála ki rosszabb! Gonosz vigyorral az arcodon ellenőrzöd a felszerelésed, és felkészülsz arra, hogy megmutasd a rohadéknak, hogy mi is az a pokol!","Ti sei aperto la via nel cuore del nido -dei demoni. è ora di una missione +dei demoni. È ora di una missione Cerca e Distruggi con obiettivo il Guardiano del cancello le cui malvage creature si riversano sulla Terra. Sì, @@ -3071,7 +3071,7 @@ difícil que tenemos. Esperemos que hayas guardado la partida con uno o dos niveles de anticipación. De lo contrario, prepárate a morir a placer. -Sólo para soldados profesionales.",,"Olet löytänyt toiseksi vaikeimman +Sólo para marines profesionales.",,"Olet löytänyt toiseksi vaikeimman tasoistamme. Toivottavasti sinulla on tallennettuna peli edelliseltä tai sitä edelliseltä tasolta. Jos ei, valmistaudu @@ -3125,7 +3125,7 @@ level we had ready for ya? Now you know. No one gets out alive.",P6TEXT,Plutonia before MAP32,,,"Určitě sis říkal@[ao_cs], CO byl ten nejtěžší level, který jsme pro tebe měli připravený? Teď už víš. -Ven se nikdo živ nedostane.","Du hast dich sicher gefragt, was denn nun +Ven se nikdo živý nedostane.","Du hast dich sicher gefragt, was denn nun der schwerste Level ist, nicht wahr? Jetzt weißt du es - niemand kommt hier lebend raus! @@ -3188,7 +3188,7 @@ laying around.",T1TEXT,TNT after MAP06,,,"Probojoval@[ao_cs] sis svou cestu skrz laboratoře. Zdá se, že to v UAC zase podělali. S takovou fluktuací zaměstnanců musí být pro chudáky z UAC těžké -najít si zdravotní pojištění... +najít si životní pojištění... V dáli leží vojenský komplex, ve kterém se to hemží nakaženými příšerami, @@ -3379,7 +3379,7 @@ verrückten Killer. Du wirst es ihnen nicht einfach machen.",,"Vi aŭdas la grincadon de amasa maŝinaro antaŭe. Vi certe esperas, ke ili ne fabrikas novajn inferidojn, sed vi pretas alezi tutan -brutaron, se vi bezonas. Ili eble planas +brutaron, se vi devas. Ili eble planas sangfestenon, sed vi sentas vin proksimume aĉa, kiel du mil frenezuloj pakitaj en unu rabian mortiganton. @@ -3567,7 +3567,7 @@ re proprio adesso. Più ci pensi e più diventi nervoso. Soppesando l'arma, un sorriso maligno si fa strada sul tuo volto. -è ora di prendere un pò di nomi.","前方に開けている景色は見飽きたものだ。 +È ora di fargliela vedere.","前方に開けている景色は見飽きたものだ。 臭いもよく知っている -- 煮えた排泄物のようなヤツ。 この場所は気に入らないし、気に入る予定もない。 考えれば考える程、気が滅入る。 @@ -3806,7 +3806,7 @@ of like King Tut's condo. Well, whatever's here can't be any worse than usual. Can it? Or maybe it's best to let sleeping gods lie..",T5TEXT,TNT before MAP31,,,"A co teď? Tohle vypadá úplně jinak. -Trochu jako sídlo krále Tuta. +Trochu jako sídlo krále Tutanchamona. Ať už je tu cokoliv, nemůže to být horší než obvykle. Nebo může? Možná je lepší nechat spící bohy odpočívat.","Was jetzt? Sieht ganz anders aus. Fast @@ -3823,7 +3823,7 @@ lasi dormantajn diojn kuŝi...","¿Y ahora qué? Esto se ve totalmente diferente. Se parece a la choza del rey Tut. Bueno, sea lo que sea no puede ser peor que los sitios -usuales. ¿O sí? O tal vez sería mejor +usuales. ¿O quizás sí? O tal vez sería mejor dejar dormir a los dioses que permanecen ahí...",,"Mitä nyt? Näyttää täysin erilaiselta. Vähän niin kuin Tutankhamonin lukaalilta. @@ -3923,7 +3923,7 @@ Infierno y por Dios que estás list@[ao_esp] para un descanso. Murmuras a tí mism@[ao_esp], tal vez alguien más debería ir a -patear traseros infernales la próxima +patear culos infernales la próxima vez. Más adelante se encuentra un pueblo tranquilo, con agua tranquila, construcciones pintorescas, y @@ -4137,8 +4137,8 @@ tra la kaĉo, kiun vi faris el lia vizaĝo. Ĉi tiu atrakcio estas fermita.","Otra vez se avecinan problemas en tu lugar de vacaciones favorito... -El Infierno. A un bruto ciberdemonio -se le ocurrió convertir el Infierno +El Infierno. Algún ciberdemonio mocoso +pensó que podría convertir el Infierno en su parque de atracciones personal, y hacer de la Tierra la taquilla. @@ -4147,7 +4147,7 @@ Bien, ese fenómeno de circo medio-robot no sabía quien vendría a la feria. No hay nada como una galería de tiro repleta de engendros -provenientes del infierno para ver +del averno para ver correr sangre a borbotones... Ahora las paredes del laberinto @@ -4158,7 +4158,7 @@ salen a duras penas por la mezcla de cables y carne que solía ser su rostro. -Esta atracción se ha cerrado. +Esta atracción está cerrada. ","Otra vez se avecinan problemas en tu lugar de vacaciones favorito... Demonios. A un ciberdemonio @@ -4411,20 +4411,20 @@ dass in einer sehr unfreundlichen Welt festsitzen wirst, aber hat jemals jemand behauptet, dass das Leben eines Ketzers einfach ist?",,"Per la detruo de la ferliĉoj kaj iliaj -servistoj, la revivantaj ceteraj estas -foriga el ĉi tiu ebeno de ekzisto. +servistoj, la revivantoj ceteraj estas +forigaj el ĉi tiu ebeno de ekzisto. -Tamen, tiuj estuloj devis veni de ie, +Tamen, tiuj estuloj devis veni el ie, kaj vi suspektas, ke la pordego fajra -de la faŭko de infero kondukas en +de la faŭko de infero malfermas en ilian dimension hejman. -Por certi, ke pli revivantaj (aŭ eĉ pli -malbona aĵoj) ne travenos, vi bezonas +Por certigi, ke pli revivantoj (aŭ eĉ pli +malbonaj aĵoj) ne travenos, vi devos fermi la faŭkon de infero ĉe la flanko alia. -Nature, tio signifas, ke vi eble estos -kaptita en mondo tre malamika, sed -neniu diris, ke esti herezulo estas facila! +Kompreneble, tio signifas, ke vi eble estos +kaptita en mondo tre malamika, sed neniu +iam diris, ke esti herezulo estis facila! ","Con la destrucción de los Liches de Hierro y sus lacayos, los últimos no-muertos son limpiados de este plano @@ -4491,22 +4491,22 @@ Annak érdekében hogy ne tudjon több élőhalott be kell rekesztened a pokol száját a túloldalról. Ez persze azt jelenti, hogy valószínű egy barátságtalan világban ragadhatsz -node ki mondta hogy ertneknek lenni könnyű?","con la distruzione degli iron lich +node ki mondta hogy ertneknek lenni könnyű?","Con la distruzione degli iron lich e dei loro servi, gli ultimi non- morti vengono rimossi da questo piano dell'esistenza. -quelle creature dovevano venire da +Quelle creature dovevano venire da qualche parte, pensi, e hai il sospetto che l'ardente portale delle fauci dell'inferno si apra sul loro posto di provenienza. -per assicurarti che altri non-morti +Per assicurarti che altri non-morti (o altro di peggio) non vi passino attraverso, devi sigillare la porta dell'inferno dall'altro lato. -certo, questo significa che rischi +Certo, questo significa che rischi di rimanere bloccato in un posto poco amichevole, ma chi ha detto che essere un eretico fosse facile!","アイアンリッチとその手下たちが滅ぼされたことにより、 @@ -4588,25 +4588,25 @@ mai oribile) nu trec prin ea, va trebui să închizi gura infernului de pe cealaltă parte. Firește că asta poate să însemne că vei rămâne blocat într-o lume extrem de neprimitoare, dar n-a spus nimeni că e ușor să -fii un eretic!","С уничтожением Железных Личей +fii un eretic!","С уничтожением железных личей и их приспешников, окрестные земли очистились от омерзительной нежити. Эта нежить, должна была как-то проникнуть -в наш мир, и у Вас есть подозрение, -что пылающий портал Утробы Ада ведет +в наш мир, и у вас есть подозрение, +что пылающий портал утробы Ада ведёт в их измерение. -Угроза исходит из Огненного Портала — +Угроза исходит из огненного портала — порождения Ада и чёрной магии могут изринуться из него. Ваша цель — сойти в Ад и запечатать проклятый портал. -Это смертельно опасное деяние, и Вы -рискуете навсегда увязнуть во Тьме. +Это смертельно опасное деяние, и вы +рискуете навсегда увязнуть во тьме. Но кто говорил, что путь истинного -Еретика лёгок и прост?","Са уништењем челичних личева и +еретика лёгок и прост?","Са уништењем челичних личева и његових пратиоца, последњи немртви су очишћени са равнице постојања. @@ -4676,19 +4676,19 @@ Seite dieser Tore? Die Krümmung einer riesigen Kuppel, dort wo der Himmel sein sollte, ist jedenfalls kein gutes Zeichen.",,"La bategtaŭroj potencaj montriĝis -tro malforta kontraŭ vi, kaj dum iliaj +tro malfortaj kontraŭ vi, kaj dum iliaj kadavroj vaporantaj falas sur la teron, -vi sentas kontenton malafablan, pro -ke ili estas detruita. +vi sentas kontenton malafablan, +ke ili estas detruitaj. -La pordegoj, kiojn ili gardis, malfermiĝas -en, kion espereble estas hejmo, sed -dum vi trapaŝas, ridado mokanta -resonas en viaj oreloj. +La pordegoj, kiujn ili gardis, malfermiĝas, +rivelante tion, kion espereble estas la vojo +hejmen, sed dum vi trapaŝas, ridado +mokanta resonas en viaj oreloj. -Ĉu forto alia kontrolis la bategtaŭrojn? +Ĉu forto alia regis la bategtaŭrojn? Ĉu estas eble eĉ pli estuloj hororaj tra -ĉi tiu pordego? La kupolo kristala vasta +ĉi tiu pordego? La balao de kupolo kristala supre, kie la ĉielo devas esti, certe ne estas antaŭsigno bona...","Los poderosos maulotauros han probado no ser un encuentro difícil para ti, y mientras @@ -4771,22 +4771,22 @@ egy gúnyos kacaj nyilall a füledbe. Talán egy másik erő irányította mindvégig a maulotaurokat? Létezne, hogy még ennél is borzasztóbb teremtmények várnak a kapu másik túloldalán? A tiszta égbolt helyett feléd -tornyosuló kristály kupola íve nem jelent semmi biztatót...","nemmeno i possenti maulotaur erano +tornyosuló kristály kupola íve nem jelent semmi biztatót...","Nemmeno i possenti Maulotauri erano alla tua altezza e mentre le loro carcasse fumanti cadono al suolo provi una feroce soddisfazione nell'averli distrutti. -i portali cui facevano la guardia +I portali cui facevano la guardia si sono aperti rivelando quella che -speri sia la via di casa. ma mentre -la attraversi, odi risa di scherno +speri sia la via di casa. Ma mentre +la attraversi, percepisci risa di scherno echeggiare nelle tue orecchie. -una qualche altra forza controllava -i maulotaur? che possano esserci +Una qualche altra forza controllava +i Maulotauri? Che possano esserci altri più spaventosi esseri oltre -questo portale? il baluginio di una +questo portale? Il baluginio di una volta cristallina là dove dovrebbe esserci il cielo non è certo un buon segno...","強靭と自負していたマウロタウロスは貴方に肩を並べるほど @@ -4870,20 +4870,20 @@ fie oare creaturi și mai oribile dincolo de acest portal? Un dom de cristal în locul unde trebuia să fie cerul cu siguranță nu e un semn bun...","Могучие Молотавры повержены. Их дымящиеся трупы падают, -разваливаясь на куски, к Вашим +разваливаясь на куски, к вашим ногам, и мрачное удовлетворение -наполняет Вас. +наполняет вас. Врата, которые они охраняли, открылись. Вы шагнули в них, думая, что вернётесь в родной мир, но лишь громкий, насмешливый хохот был -ответом на Вашу надежду. +ответом на вашу надежду. Чей это злобный хохот? Быть может это голос демонических сил, управляющих Молотаврами? Какие -чудовищные создания ожидают Вас +чудовищные создания ожидают вас за этими вратами? Не голубое небо родного мира над головой, а кристальный купол, — это плохой знак...","Моћни маулотаури су доказали да @@ -4970,7 +4970,7 @@ sorĉajn, kiuj tenis lian estulojn sur tion ĉi ebeno, dum iliaj kriegoj mortaj sonas super liaj kriegoj propraj de agonio. -Nun via ĵuro de venĝo estas veriga, do +Via ĵuro de venĝo verigita, vi eniras la portalon al vian mondon propran nur momentojn antaŭ la kupolo disfrakasiĝas en milionojn @@ -4978,12 +4978,12 @@ da pecoj Sed se la povo de D'Sparil estas eterne detruita, kial vi ne sentas sekura? Ĉu -estas ĉar la fina kriego tuj antaŭ lia -morto — tiu, kiu sonis, kiel malbeno? +estis pro la fina kriego tuj antaŭ lia +morto — tiu, kiu sonis kiel malbeno? Aŭ alvoko? Vi vere ne povas certi, sed ĝi eble estis nur kriego. -Tamen, kio pri la aliaj serpentrajdistoj?","La muerte de D'Sparil ha soltado +Tamen, kio pri la aliaj Serpentrajdistoj?","La muerte de D'Sparil ha soltado los vínculos mágicos que mantenían a sus criaturas en este plano, sus gritos moribundos abrumando sus @@ -5081,27 +5081,27 @@ Vagy egy megidézés? Nem lehetsz biztos benne, de reméled hogy csak egy egyszerű kiáltás volt. -Másfelől mi lesz majd a többi kígyólovaggal?","la morte di d'sparil ha spezzato i +Másfelől mi lesz majd a többi kígyólovaggal?","La morte di D'Sparil ha spezzato i magici legami che tenevano le sue creature in questa dimensione, e i loro lamenti di morte coprono le sue urla di agonia. -il tuo voto di vendetta è sciolto, +Il tuo voto di vendetta è sciolto, ed entri nel portale che conduce al tuo mondo pochi secondi prima che la cupola vada in mille pezzi. -ma se il potere di d'sparil è +Ma se il potere di D'Sparil è infranto per sempre, perchè non ti -senti al sicuro? è a causa del suo +senti al sicuro? È a causa del suo ultimo urlo prima di morire, quello -che suonava come una maledizione? o +che suonava come una maledizione? O un'invocazione? non puoi esserne certo, poteva essere solo un urlo. -ma allora, cosa ne è degli altri -serpent rider?","デ'スパリルの死によって魔法による従僕達は解放され +Ma allora, cosa ne è degli altri +Cavalcatori dei Serpenti?","デ'スパリルの死によって魔法による従僕達は解放され その風靡なる死の悲鳴に貴方は圧倒された。 復讐の誓いは成し遂げられ、元の世界へ戻るポータルを 通った瞬間、ドームが崩壊し数百万の破片と化した。 @@ -5201,7 +5201,7 @@ blestem? Sau o chemare? Nu poți fi tocmai sigur, dar e posibil să fii fost un simplu strigăt. Dar din nou, cu ceilalți Călăreți cum rămâne?","С гибелью Д'Спарила исчезла магия, -сохранявшая жизнь порождениям Тьмы. +сохранявшая жизнь порождениям тьмы. Стоны умирающих демонов заглушили вопль агонии самого Д'Спарила. @@ -5212,13 +5212,13 @@ Dar din nou, cu ceilalți Călăreți cum rămâne?","С гибелью Д'Сп ведущие в родной мир. Но и теперь, после гибели Д'Спарила, -душа Ваша не спокойна, и её +душа ваша не спокойна, и её одолевают плохие предчувствия. Не был ли проклятием его предсмертный крик? Или призывом тёмных сил? -И где таятся другие Змеиные -Всадники?","Смрт Д'Спарила је олабавила магичне +И где таятся другие змеиные +всадники?","Смрт Д'Спарила је олабавила магичне окове који су држали његова створења за ову равницу, њихови предсмртни врисци пренеражују његов плач у @@ -5308,16 +5308,17 @@ eniris la restaĵojn frakasitajn el landoj konkeritaj de D'Sparil. Vi venkis la finajn gardistojn de ĉi tiuj landoj, sed nun vi staras antaŭ la pordegoj inter vi kaj la -fuorto de D'Sparil. Antaŭ ĉi tiu momento, +fuorto de D'Sparil. Ĝis tiu ĉi momento, vi ne dubis, ke vi povus kontraŭi ĉion ajn, kioj vi eble trovos, sed preter ĉi tiu pordego estas la koro de mavo mem, kio invadis vian mondon. D'Sparil estas -mortinta, sed le truo, kie li naskiĝis, -restas. Nun vi bezonas eniri tiun truon, +mortinta, sed la truo, kie li naskiĝis, +restas. Nun vi devas eniri tiun truon, esperante trovi elirejon. Kaj ie, en la plej -malhela ejoj de la posedaĵo de D'Sparil, -liaj personaj gardistoj atendas vian venon...","Creíste que volverías a tu propio +malhela angulo de la posedaĵo de D'Sparil, +liaj gardistoj personaj atendas vian +alvenon...","Creíste que volverías a tu propio mundo después de que D'Sparil hubiera muerto, pero su acto final te ha desterrado hacia su propio @@ -5411,26 +5412,26 @@ D'Sparil ugyan meghalt, de a völgy ahol született továbbra is fennáll. Belépsz a völgybe annak reményében, hogy találsz egy kiutat. Valahol, ennek a birtoknak is a legsötétebb sarkában, a személyi testőrei várnak a revansra... -","pensavi di tornare nel tuo mondo -dopo la morte di d'sparil, ma il +","Pensavi di tornare nel tuo mondo +dopo la morte di D'Sparil, ma il il suo ultimo atto ti ha esiliato -in questo posto. sei quindi entrato +in questo posto. Sei quindi entrato nei resti infranti delle terre -conquistate da d'sparil. Ne hai poi +conquistate da D'Sparil. Ne hai poi abbattuto gli ultimi guardiani, ma ora ti trovi davanti ai cancelli -della fortezza di d'sparil. finora +della fortezza di D'Sparil. Fino ad ora non avevi avuto dubbi sulla tua abilità nel fronteggiare di tutto, ma oltre questo portale si trova il cuore del male che ha invaso -il tuo mondo. d'sparil sarà anche -morto, ma il pozzo dove è apparso -esiste ancora. devi entrare in quel +il tuo mondo. D'Sparil sarà anche +morto, ma il pozzo dal quale è apparso +esiste ancora. Devi entrare in quel pozzo nella speranza di trovare -un'uscita. e da qualche parte, +un'uscita. E da qualche parte, negli oscuri angoli del dominio -di d'sparil le sue guardie del +di D'Sparil le sue guardie del corpo aspettano il tuo arrivo...","貴方はデ'スパリルの死後、元の世界に戻れるはずだったが あの死に際の呪文により既に征服され破壊された古蹟へ 送られてしまった。先程その守護者を打ち倒し、次いで @@ -5518,18 +5519,18 @@ Poate că D'Sparil s-a dus, dar groapa în care s-a născut rămâne. Acum trebuie să intri în acea groapa în speranța că vei găsi și o cale de ieșire. Și undeva, în defensiva celui mai întunecat colț al locului, -proprii lui gardieni îți așteaptă sosirea ...","С гибелью Д'Спарила умерла и Ваша +proprii lui gardieni îți așteaptă sosirea ...","С гибелью Д'Спарила умерла и ваша надежда вернуться в родной мир. Своим предсмертным проклятьем -он отправил Вас в те немногие, +он отправил вас в те немногие, ещё оставшиеся подвластными ему земли. Вы разбили последних хранителей этих земель и стоите перед опустевшим замком Д'Спарила, оплотом его тёмных сил. -Само Сердце Зла растворило перед -Вами врата. И хотя Д'Спарил +Само сердце зла растворило перед +вами врата. И хотя Д'Спарил повержен, глубины, породившие его, стоят нерушимы. @@ -5538,7 +5539,7 @@ proprii lui gardieni îți așteaptă sosirea ...","С гибелью Д'Спа родной мир — отыскать вход в него в тёмных глубинах опустевшей вотчины Д'Спарила. Личные стражи мёртвого -господина уже дожидаются Вас...","Мислили сте да ћете се вратити +господина уже дожидаются вас...","Мислили сте да ћете се вратити сверту после Д'Спарилове смрти, али његов последњи кец у рукаву вас је прогнао у његов свет. Овде сте ушли у @@ -5590,7 +5591,7 @@ nějaké další nemyslitelné noční můře. Začínáš přemýšlet, jestli máš sílu pokračovat, jestliže na tebe nečeká nic, než smrt a utrpení. Co jiného ti zbývá, -když je vůle bojovat pryč? Mohl@[ao_cs] by +když vůle bojovat vyprchala? Mohl@[ao_cs] by ses přinutit kráčet dál v takovou beznaděj? Máš na to odvahu? @@ -5620,22 +5621,22 @@ dich mit offenen Augen deinem Schicksal stellen.",,"Dum la bategtaŭro fina blekas lian agonion, vi konscias, ke vi neniam estis tiom prokisme de via detruo -propra. Eĉ ne la batalo kun D'Sparil -kaj liaj disĉiploj estis tiom aflikta. -Vi malgaje rigardas la pordegon, +propra. Ne eĉ la batalo kun D'Sparil +kaj liaj disĉiploj estis tiom afliktaj. +Malgaje, vi rigardas la pordegon, kiu malfermiĝas antaŭ vi, scivolante -ĉu ĝi kondukas hejmen, aŭ ĉu ĝi -kondukas al iu teruro neprirevita. -Vi troviĝas scivolanta ĉu vi havas -forton pro daŭri plu, se nenio krom +ĉu ĝi gvidas hejmen, aŭ ĉu ĝi +gvidas al iu teruro neprirevita. +Vi troviĝas vin scivolanta ĉu vi havas +forton por daŭri plu, se nenio krom morto kaj doloro atendas vin. Sed -kion vi povas fari, se la volo batali +kion alian vi povas fari, se la volo batali estas for? Ĉu vi povas devigi vin daŭri -kontraŭ tia malespero? Ĉu vi havas -tiom bravecon? Vi vine trovis, ke vi -ne havas la povo por rezigni sen -batalo. Kun malfermitaj okuloj, -vi iras por renkonti vian destinon.","Mientras el último maulotauro brama +fronte al tia malespero? Ĉu vi havas +la kuraĝon? Vi trovas, fine, ke vi +ne havas la povo rezigni sen batalo. +Kun okuloj malfermegitaj, vi iras +por renkonti vian destinon.","Mientras el último maulotauro brama su muerte agonizante, te das cuenta que nunca has estado tan cerca de tu propia destrucción. Ni la pelea con @@ -5713,25 +5714,25 @@ hozzá a kellő bátorságod? A végén ráébredsz, hogy nem olyan fából faragtak aki harc nélkül feladja. Tágra nyílt szemekkel várod a -végzettel való találkát.","mentre l'ultimo maulotaur muggisce +végzettel való találkát.","Mentre l'ultimo Maulotauro muggisce agonizzante, comprendi che non eri mai stato così vicino alla tua -distruzione. nemmeno la lotta con -d'sparil e i suoi discepoli fu -così disperata. triste, guardi i +distruzione. Nemmeno la lotta con +D'Sparil e i suoi discepoli fu +così disperata. Cupo, guardi i cancelli che ti si aprono innanzi, chiedendoti se portino a casa o se conducano a un altro inimmaginabile -orrore. ti chiedi se avrai la forza +orrore. Ti chiedi se avrai la forza di andare avanti, se niente tranne dolore e morte ti attendano, ma che altro puoi fare se la forza di -combattere se ne va? puoi sforzarti +combattere se ne va? Puoi sforzarti di continuare, nonostante la disperazione? -ne hai il coraggio? decidi infine +Ne hai il coraggio? decidi infine che non è da te arrendersi senza -combattere. ad occhi aperti +combattere. Ad occhi aperti vai incontro al tuo destino.","最後のマウロタウロスが死際の咆哮を放った時、 貴方の所業が無謀ではないと証明された。 デ'スパリルとその従僕達との闘いでさえ @@ -5822,23 +5823,23 @@ să continui în ciuda disperării? Ai curajul necesar? fire. Cu privirea larg deschisă, te duci să-ți întâmpini destinul.","Наблюдая с мрачным отвращением предсмертную агонию последнего -сражённого Молотавра, Вы только +сражённого Молотавра, вы только теперь понимаете, что смерть ещё никогда не была так близка. Даже во время яростной битвы с самим Д'Спарилом и его тёмными слугами. С угрюмым отчаянием приближаетесь -Вы к открытым порталам. Слабая -надежда теплится в Вашей душе, — +вы к открытым порталам. Слабая +надежда теплится в вашей душе, — быть может за ними скрыта дорога домой, а не бездны чужих миров? -Отчаяние наделяет Вас мрачной +Отчаяние наделяет вас мрачной решимостью. Ничто не способно -остановить Вас, одна только — смерть. +остановить вас, одна только — смерть. Не сдавайтесь без боя, взгляните в -глаза своей судьбе. Знайте, если Вы +глаза своей судьбе. Знайте, если вы упали на самое дно, есть лишь один путь — наверх.","Са падом последњег минотаура у очајничку смрт, схватате да никад нисте @@ -5911,7 +5912,7 @@ du es dir wünschen könntest. Und dahinter, flackernd in der Ferne, scheinen die sich ständig verändernen Wände der Säulenhalle all -deinen Fortschritt zu verspotten.",,"Pasinde la sep portalojn, kiuj obturis +deinen Fortschritt zu verspotten.",,"Pasinte la sep portalojn, kiuj sigelis ĉi tion regionon, vi staras antaŭ vasta regno de severa sovaĝejo. Fajro, glacio, kaj ŝtelo provis vin. Tamen, pli grandaj @@ -6123,10 +6124,10 @@ ajunge să îți dorești acest lucru. Iar dincolo, strălucind în zare, zidurile veșnic schimbătoare ale hipostilei par să își bată joc de tine -la fiecare efort pe care îl faci.","Вы прошли Семь порталов, что +la fiecare efort pe care îl faci.","Вы прошли семь порталов, что властвовали над этими землями, и зловещая бескрайняя местность -простирается теперь перед Вами. +простирается теперь перед вами. Вас испытывали огонь, лёд и сталь, но впереди ожидают и более тяжкие испытания. Неведомые и коварные @@ -6136,14 +6137,14 @@ la fiecare efort pe care îl faci.","Вы прошли Семь порталов Бесплодные пустоши, гнилые болота и затхлые подземелья преграждают -Ваш путь, но ничто не сможет +ваш путь, но ничто не сможет изменить предначертанную судьбу, -хотите Вы того или нет. +хотите вы того или нет. И где-то далеко, в глубинах бесконечных гипостильных залов сами стены ожили, чтобы отяготить -каждый Ваш шаг.","Прошли сте Седам портала који су +каждый ваш шаг.","Прошли сте Седам портала који су владали над овим земљама, и сада се пред Вама простире злосутно, бескрајно подручје. @@ -6306,26 +6307,25 @@ lentről csak a holtak sikolyait hallani. Ahogy elindulsz megfagy a véred a démoni kántálás hallatán. A halálisten szerelmére! Miféle hely ez? Hogyan -fogsz kijutni innen?","La tua mente che ancora vacilla dai tuoi -incontri all'interno dell'ipostilo, devi -barcollare verso quella che speri sia una -via d'uscita. Le cose sembrano muoversi +fogsz kijutni innen?","La tua mente ancora vacilla dai tuoi +incontri all'interno dell'ipostilo, e barcolli +verso quella che speri sia una via d'uscita. +Le cose sembrano muoversi sempre più velocemente, la tua visione si confonde e comincia a svanire... -Quando il mondo crolla intorno a te, +Mentre il mondo crolla intorno a te, la luminosità di un teleportale ti inghiotte. Un lampo di luce, e poi -si sale stancamente ai piedi. +ti alzi faticosamente in piedi. -Si sta in cima ad una torre alta, e dal +Ti trovi in cima ad una torre alta, e dal basso arrivano le grida dei dannati. -Si fa un passo avanti, e immediatamente il -suono del canto demoniaco raffredda il sangue. +Fai un passo avanti, e immediatamente il +suono del canto demoniaco ti gela il sangue. Per tutti gli dei della morte! In che posto sei arrivato? Per tutti gli dei del dolore, -come troverai mai la tua via d'uscita? -","貴方は聳え立つ柱の間での遭遇に動揺したが +come troverai mai la tua via d'uscita?","貴方は聳え立つ柱の間での遭遇に動揺したが よろめきながら出口らしき所に向かった。 そして視界がぼやけ始め、物が目まぐるしく回り出す... 周りの世界が崩れ、転移門の光が貴方を飲み込んだ。 @@ -6610,10 +6610,10 @@ Valahol odabent várnak ellenlábasaid...","Le armi più potenti e gli artefatti degli antichi erano appena sufficienti per sconfiggere l'eresiarca e i suoi servi, -ma ora i loro resti di fallo giacciono -ai tuoi piedi. Raccogliendo l'ultima +ma ora i loro immondi resti giacciono +ai tuoi piedi. Con quel poco che rimane delle tue forze, ti prepari a entrare -nel portale che conduce dal santuario +nel portale che si trova nel santuario interno dell'eresiarca. Sopra di te, i bastioni di un immenso @@ -6716,14 +6716,14 @@ tine. Undeva în interior, dușmanii te așteaptă...","Сил могущест портал внутренних покоев обители Ересиарха. -Перед Вами величественный замок. +Перед вами величественный замок. Мрачные стены с тёмными бойницами окружают одинокую башню. Она высится за ними словно зловещий, безмолвный гигант. За смотровыми щелями дьявольского замка извиваются языки адского пламени, мелькают тени, -десятки злобных глаз смотрят на Вас +десятки злобных глаз смотрят на вас неотрывно из темноты. Притаившиеся враги уже ждут внутри...","Снага моћног оружја и чаролија @@ -6988,9 +6988,8 @@ tuo corpo avvolto nel fuoco mistico. Quando la tua visione si libera, ti ritrovi in piedi in una grande sala, piena di echi spettrali e ombre minacciose. -In lontananza è possibile e su di essa -l'unica fonte di luce in questo mondo. -","悲痛な叫びと共に貴方は別の世界に追いやられ +In lontananza vedi una pedana e su di essa +l'unica fonte di luce in questo mondo.","悲痛な叫びと共に貴方は別の世界に追いやられ 自分の体が神秘的な炎により癒されていった。 視界が戻ると、霊の威嚇する声と影が蔓延る壮観な広間に 立っていた。遠くには盛り上がった大皿が見え、 @@ -7029,17 +7028,17 @@ de foc mistic. Odată ce vederea redevine limpede, te regăsești stând într-o sală imensă, plină de ecouri fantomatice și umbre amenințătoare. În depărtare vezi un podium ridicat, și pe el, singura -sursă de lumină din această lume.","Внезапно Вас окутал огонь. -С воплем боли и страха Вы +sursă de lumină din această lume.","Внезапно вас окутал огонь. +С воплем боли и страха вы перемещаетесь в другой мир, и -каждая часть Вашего тела пронизана +каждая часть вашего тела пронизана мистическим пламенем. Видения отступили, взор снова ясен. Вы в огромном зале, наполненном призрачным эхом и грозными, неведомыми тенями. Одинокий свет струится с возвышения неподалёку -от Вас.","Одједном Вас окружи огањ. +от вас.","Одједном Вас окружи огањ. Уз врисак бола и страха премештате се у други свет, и сваки део Вашег тела је прожет @@ -7136,11 +7135,11 @@ la fonte del potere di Korax. Con questo, è possibile creare mondi ... O distruggerli. Con i diritti di battaglia e conquista è tuo, -e con le mani tremanti si raggiunge per afferrarlo. +e con le mani tremanti vai per afferrarlo. Forse, ora, un nuovo giocatore si unirà al gioco cosmico del potere. Come il pedone che viene promosso regina, all'improvviso -le stesse portate del tabellone +le stesse caselle della scacchiera sembrano essere alla tua portata.","カオススフィア、コラックスの魔力の源だ。 これを使えば世界を創造することが出来る...または破壊することも。 征服者の権利を得た貴方は震える手をそれに伸ばした。 @@ -7186,7 +7185,7 @@ tabla e în mâinile tale.","Это сфера хаоса, источник си Коракса. С её помощью можно создавать миры... или разрушать их. Дрогнувшей рукой вы берёте её. -Теперь она Ваша по праву силы. +Теперь она ваша по праву силы. Должно быть, новый игрок теперь вступит в космическую битву за @@ -7224,9 +7223,9 @@ puissants que vous encore, et qui peut prédire ce qu'ils feront pendant leur tour?","\nvannak ám nagyobb hatalmú játékosok is, és ki tudná előre a -következő lépésüket?","\nMa ci sono altri giocatori più potentidi te, +következő lépésüket?","""\nMa ci sono altri giocatori più potenti di te, e chi può conoscere le loro prossime mosse? -","\nしかし貴方より上手の挑戦者はいる、 +""","\nしかし貴方より上手の挑戦者はいる、 そして誰が彼らの一手を読めるだろうか?","\n하지만 분명 어딘가에 당신보다 강력한 도전자들이 있을 것이며, 그 누가 그들의 수를 짐작할 수 있겠는가?","\nmaar er zijn andere spelers machtiger dan jij, en wie kan hun volgende stappen @@ -7420,14 +7419,14 @@ mente da ciò che ti aspetta... ...e dimenticare cosa c'è dietro. In lontananza, gli aspri bastioni di un -grande complesso castellano sembrano -rendere il cielo in alto, e l'odore di -decadenza si diffonde dalle tombe -violate di morti non contesi. +grande complesso del castello +sembrano spezzare il cielo, e l'odore di +decadimento si diffonde dalle tombe +violate di innumerevoli morti. -Contare con attenzione ciò che poco -rimane dei vostri manufatti, cercate di -rassicurarvi che sarà sufficiente. +Dopo aver controllato ciò che poco +rimane dei tuoi manufatti, cerchi di +rassicurarti che sarà sufficiente. Dopo tutto, deve essere sufficiente, non è vero? @@ -7533,7 +7532,7 @@ Nu-i așa?","Отерев кровь с лица дрожащей рукой, ...и забыть ужас, оставшийся позади. -Вдали, в легкой дымке, виден +Вдали, в лёгкой дымке, виден величественный замок, подпирающий небо своими мрачными башнями. От разоренных могил веет зловонием @@ -7718,21 +7717,20 @@ halálról tanuskodnak... ...a szerencsésebbeknek.","Sicuramente le anime dei dannati abitano questo mondo, perché niente di giusto -o buono potrebbe sopravvivere a lungo. +o buono potrebbe sopravvivere a lungo qui. -Ma ciò che è passato prima non può +Ma ciò che hai passato prima non può che essere una pallida ombra di ciò -che impedisce il vostro passaggio ora: -la scura cittadella stessa. +che blocca il tuo passaggio ora: +la stessa Cittadella Oscura. -La cupa mole della cattedrale blocca -tutti gli scorci, ma frammentari, ma -ciò che si può vedere parla in -sibilanti sussurri di morte -fredda e persistente... +La cupa mole della cattedrale fa si che +solo scorci frammentari della cittadella +stessa si possano vedere, ma ciò che +tu puoi vedere parla insibilanti sussurri +di morte fredda e persistente... -...per i fortunati. -","この世界には地獄に堕とされた善人や親切であろう +...per i fortunati.","この世界には地獄に堕とされた善人や親切であろう 人々の魂が居着いている。 しかし通過する際には前方を遮る薄いもやでしかない @@ -7816,7 +7814,7 @@ slabă față de ceea ce îți blochează calea acum: Groasele blocuri ale catedralei stopează totul, mai puțin întrezăririle citadelei însăși, dar ceea ce poate fi văzut vorbesțe doar în șoapte siflante ale -lentei, recii morți... +lentei, reci morți... @@ -7824,9 +7822,9 @@ lentei, recii morți... мир, ибо ничто доброе и справедливое не может здесь выжить. -Страдания, пережитые Вами, — ничто, +Страдания, пережитые вами, — ничто, бледная тень тех испытаний, что ждут -в тёмной цитадели, стоящей на Вашем +в тёмной цитадели, стоящей на вашем пути. Силуэт тёмной цитадели едва виден за @@ -7951,17 +7949,16 @@ lépésed... ...szemek melyek mögött gonosz szándék lapul.","Ancora una volta ti ritrovi nella grande sala della sfera del caos, -come se non fosse passato alcun tempo +come se non fosse passato alcun istante da quando per l'ultima volta ti sei mosso tra queste ombre. Ma c'è qualcosa di diverso, un silenzio -dove un tempo si sussurrava dolcemente, +dove un tempo vi erano deboli sussurri, un senso di essere osservati da occhi nascosti... -...occhi che proteggono un intento malefico. -","貴方は今一度、あたかも最後の時が止まったままである +...occhi che proteggono un intento malefico.","貴方は今一度、あたかも最後の時が止まったままである カオススフィアの影の広間に立った。 しかしかつては柔らかい囁きによる静かな場所だったが @@ -8017,7 +8014,7 @@ ești urmărit de ochi ascunși... ...ochi care ascund intenții nefaste.","Вы вновь в зале сферы хаоса. Ничего Не изменилось здесь с последнего -Вашего посещения. время застыло. +вашего посещения. время застыло. И всё же... Тихий шёпот в темноте. Вы чувствуете, что невидимые @@ -8151,21 +8148,20 @@ megvédjen a sötétség erőitől, talán megszegni a gömbnek tett ígéreted. Mindazonáltal, sosem voltál olyan, aki -könnyen kihátrál a kihívás elől...","Una volta che avete afferrato la sfera -del caos, l'avete tenuta in mani tremanti. +könnyen kihátrál a kihívás elől...","Quando avevi afferrato precedentemente +la sfera del caos, l'avevi tenuta tremando. Ora le tue mani tremano con qualcosa di più che avarizia, e la paura si intreccia con la fame di potere. Se anche il potere della sfera -non è sufficiente a proteggervi dalla +non è sufficiente a proteggerti dalla le forze delle tenebre, forse è meglio lasciarla intatta, la sua promessa non mantenuta. Ma poi, non sei mai stato uno -che si è tirato indietro da una sfida... -","貴方はカオススフィアを掴む前に、一度震える手を握りしめた。 +che si tira indietro da una sfida...","貴方はカオススフィアを掴む前に、一度震える手を握りしめた。 今この手は貪欲に何かを超える権力を渇望している。 スフィアの魔力でさえ貴方を暗黒の軍勢から守護するのに 十分でないならば、恐らくそれに手を出さなければ、 @@ -8235,9 +8231,9 @@ neținută. Dar apoi, tu n-ai fost niciodată cineva care să se -dea înlături de la o provocare...","Когда-то Вы уже владели сферой +dea înlături de la o provocare...","Когда-то вы уже владели сферой хаоса и держали её в трепещущих -руках. Теперь Ваши руки дрожат не +руках. Теперь ваши руки дрожат не только от алчности, и чувство ужаса сливается с жаждой власти. @@ -8245,11 +8241,11 @@ dea înlături de la o provocare...","Когда-то Вы уже владели защитить вас от демонов тьмы, может быть, не следует брать её? Ведь её истинное предназначение осталось -для Вас тайной. +для вас тайной. -И всё же, Вы не устоите перед +И всё же, вы не устоите перед искушением и примете вызов...","Једном пре сте зграбили сферу хаоса дрхтећим рукама. Сада ваше руке дрхте са нечим што је више од похлепе, и ужасне мреже које су @@ -8275,25 +8271,25 @@ lépésedre vár.",\n...e altri giocatori aspettano.,"\n...更なる挑戦者を The door is locked,TXT_ACS_MAP01_5_THEDO,,,,Dveře jsou zamčené.,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,Drzwi są zablokowane,A porta está trancada,,Ușa e încuiată,Дверь заблокирована,Врата су закључана "Greetings, mortal",TXT_ACS_MAP02_9_GREET,,,,"Vítej, smrtelníče,","Sei gegrüßt, Sterblicher",,"Salutojn, mortemul'.","Saludos, mortal",,"Tervehdys, kuolevainen","Salutations, humain.","Üdvözöllek, halandó!","Salve, mortale",御機嫌よう、小僧,"환영한다, 필멸자여.","Groeten, sterfelijk",Witaj śmiertelniku,"Saudações, mortal.",,"Salutări, muritorule","Приветствую, смертный","Поздрав, смртниче" Are you ready to die?,TXT_ACS_MAP02_11_AREYO,,,,jsi připraven@[ao_cs] zemřít?,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?,Czy jesteś gotów na śmierć?,Você está pront@[ao_ptb] para morrer?,,Ești pregătit să mori?,Готов ли ты умереть?,Јеси ли спреман да умреш? -A door opened on the Guardian of Ice,TXT_ACS_MAP02_20_ADOOR,,,,Ve Strážci ledu se otevřely dveře.,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,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,Дверь открыта у Стража льда,Врата су отворена код Чувара леда +A door opened on the Guardian of Ice,TXT_ACS_MAP02_20_ADOOR,,,,Ve Strážci ledu se otevřely dveře.,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,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,Дверь открыта у стража льда,Врата су отворена код Чувара леда This path is barred,TXT_ACS_MAP03_12_THISP,,,,Cesta je zatarasená.,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,Ścieżka jest zablokowana,Este caminho está bloqueado,,Această cale e blocată,Сейчас этот путь закрыт,Овај пут је тренутно забрањен -One half of the puzzle has been solved,TXT_ACS_MAP04_9_ONEHA,,,,Jedna polovina rébusu byla vyřešena,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,Połowa zagadki rozwiązana,Metade do quebra-cabeça foi resolvido,,O jumătate din puzzle e rezolvată,Половина головоломки разгадана,Половина загонетке је решена -on the Seven Portals,TXT_ACS_MAP04_10_ONTHE,,,,u Sedmera portálů.,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,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала -One third of the puzzle has been solved,TXT_ACS_MAP04_11_ONETH,,,,Jedna třetina rébusu byla vyřešena,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,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена -Stairs have risen on the Seven Portals,TXT_ACS_MAP04_12_STAIR,,,,u Sedmera portálů.,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,Schody przy Siedmiu Portalach podniosły się,As escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнется на Семи порталах,Степенице се подижу на Седам портала -One third of the puzzle has been solved,TXT_ACS_MAP05_6_ONETH,,,,Jedna třetina rébusu byla vyřešena,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,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена -on the Seven Portals,TXT_ACS_MAP05_7_ONTHE,,,,u Sedmera portálů.,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,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на Семи порталах,на Седам портала -Stairs have risen on the Seven Portals,TXT_ACS_MAP05_8_STAIR,,,,Schody se zvedly u Sedmera portálů.,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,Schody przy Siedmiu Portalach podniosły się,Escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнется на Семи порталах,Степенице се подижу на Седам портала +One half of the puzzle has been solved,TXT_ACS_MAP04_9_ONEHA,,,,U Sedmera portálů byla vyřešena,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,Połowa zagadki rozwiązana,Metade do quebra-cabeça foi resolvido,,O jumătate din puzzle e rezolvată,Половина головоломки разгадана,Половина загонетке је решена +on the Seven Portals,TXT_ACS_MAP04_10_ONTHE,,,,jedna třetina rébusu.,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,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на семи порталах,на Седам портала +One third of the puzzle has been solved,TXT_ACS_MAP04_11_ONETH,,,,U Sedmera portálů byla vyřešena,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,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена +Stairs have risen on the Seven Portals,TXT_ACS_MAP04_12_STAIR,,,,jedna třetina rébusu.,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,Schody przy Siedmiu Portalach podniosły się,As escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнется на семи порталах,Степенице се подижу на Седам портала +One third of the puzzle has been solved,TXT_ACS_MAP05_6_ONETH,,,,U Sedmera portálů byla vyřešena,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,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle a fost rezolvată,Треть головоломки разгадана,Трећина загонетке је решена +on the Seven Portals,TXT_ACS_MAP05_7_ONTHE,,,,jedna třetina rébusu.,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,przy Siedmiu Portalach,nos Sete Portais,,pe cele Șapte Portaluri,на семи порталах,на Седам портала +Stairs have risen on the Seven Portals,TXT_ACS_MAP05_8_STAIR,,,,Schody se zvedly u Sedmera portálů.,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,Schody przy Siedmiu Portalach podniosły się,Escadas se ergueram nos Sete Portais,,S-au ridicat scări pe cele Șapte Portaluri,Лестница воздвигнется на семи порталах,Степенице се подижу на Седам портала You have to find another switch...,TXT_ACS_MAP05_9_YOUHA,,,,Musíš najít další spínač.,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...,Musisz znaleźć inny przełącznik...,Você precisa encontrar outro interruptor...,,Trebuie să găsești alt buton...,Остался ещё один переключатель...,Остао је још један прекидач... Stones grind on the Seven Portals,TXT_ACS_MAP05_10_STONE,,,,Kameny dřou u Sedmera portálů.,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,Kamienie przy Siedmiu Portalach zgrzytają,As pedras giram nos Sete Portais,,Pietrele încep să macine pe cele Șapte Portaluri,Каменная преграда отступила,Камена препрека се повлачи -One sixth of the puzzle has been solved,TXT_ACS_MAP08_6_ONESI,,,,Jedna šestina rébusu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена -on the Shadow Wood,TXT_ACS_MAP08_7_ONTHE,,,,v Temném hvozdu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в Лесу теней,у Шуми сенки +One sixth of the puzzle has been solved,TXT_ACS_MAP08_6_ONESI,,,,V Temném hvozdu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена +on the Shadow Wood,TXT_ACS_MAP08_7_ONTHE,,,,jedna šestina rébusu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки The door is barred from the inside,TXT_ACS_MAP08_10_THEDO,,,,Dveře jsou zatarasené zevnitř.,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.,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра -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ö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 a distanza,遠くから扉が開く音が聞こえる,멀리서 문이 열리는 소리가 들린다,In de verte hoor je een deur openstaan.,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,Слышен звук открывающейся двери,Чује се звук отварања врата -One sixth of the puzzle has been solved,TXT_ACS_MAP09_6_ONESI,,,,Jedna šestina rébusu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена -on the Shadow Wood,TXT_ACS_MAP09_7_ONTHE,,,,v Temném hvozdu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в Лесу теней,у Шуми сенки -One sixth of the puzzle has been solved,TXT_ACS_MAP10_6_ONESI,,,,Jedna šestina rébusu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена -on the Shadow Wood,TXT_ACS_MAP10_7_ONTHE,,,,v Temném hvozdu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в Лесу теней,у Шуми сенки +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ö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.,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,Слышен звук открывающейся двери,Чује се звук отварања врата +One sixth of the puzzle has been solved,TXT_ACS_MAP09_6_ONESI,,,,V Temném hvozdu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена +on the Shadow Wood,TXT_ACS_MAP09_7_ONTHE,,,,jedna šestina rébusu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки +One sixth of the puzzle has been solved,TXT_ACS_MAP10_6_ONESI,,,,V Temném hvozdu byla vyřešena,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,Jedna szósta zagadki rozwiązana,Um sexto do quebra-cabeça foi resolvido,,O șesime din puzzle a fost rezolvată,Одна шестая головоломки разгадана,Шестина загонетке је решена +on the Shadow Wood,TXT_ACS_MAP10_7_ONTHE,,,,jedna šestina rébusu.,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,w Lesie Cieni,na Floresta das Sombras,,în Pădurea Umbrelor,в лесу теней,у Шуми сенки \ ettins left,TXT_ACS_MAP11_0_ETTIN,"rus Нужно придумать что-то получше.",,,\ etinů zbývá.,\ Ettins übrig,,\ gigantaĉoj ceteraj,\ Ettins restantes,,\ ettiniä jäljellä,\ ettins restants,\ ettin maradt,\ Ettins rimasti,\ 匹のエティンが残っている,\ 마리 에틴이 남았음,\ overgebleven Ettins,\ pozostałych ettinów,\ ettins restantes,,\ etini rămași,\ оставшихся эттинов,Остало је \ еттина "You waited too long, now you die!",TXT_ACS_MAP11_1_YOUWA,,,,"Čekal@[ao_cs] jsi moc dlouho, teď zemřeš!","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!",Czekałeś zbyt długo. Teraz giń!,Você esperou demais. Agora morrerá!,,"Ți-a luat prea mult, acum mori!",Слишком долго! Готовься к смерти!,Предуго! Припреми се за смрт! @@ -8304,28 +8300,28 @@ A door opened in the Gibbet,TXT_ACS_MAP21_0_ADOOR,,,,Dveře se otevřely na Šib The door is barred from the inside,TXT_ACS_MAP21_2_THEDO,,,,Dveře jsou zatarasené zevnitř.,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.,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра A platform has lowered in the tower,TXT_ACS_MAP22_3_APLAT,,,,Plošina ve věži sjela dolů.,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,Platforma w wieży obniżyła się,Uma plataforma desceu na torre,,O platformă a coborât în turn,Площадка опустилась в центральной башне,Спустио се платформ у централном торњу "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 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...",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...","Ты слишком заигрался, смертный...","Превише си се заиграо, смртниче..." -I think I shall remove you from the board,TXT_ACS_MAP22_29_ITHIN,,,,"myslím, že bych tě měl odstranit ze šachovnice.",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ò dal tavolo da gioco,盤上から貴様を排除する,이 몸이 너를 말 치우듯이 제거하겠다.,Ik denk dat ik u van het bord zal verwijderen,"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ă,Пришло время завершить твою партию,Дошло је време да се заврши твоја партија -You hear a door open upstairs,TXT_ACS_MAP23_10_YOUHE,,,,Z patra slyšíš otevírající se dveře.,"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 a distanza,上層階の扉が開いた,윗층에서 문이 열리는 소리가 들린다,Je hoort een deur boven opengaan,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,Из северного зала доносится звук,Од северне дворане зачује се звук +I think I shall remove you from the board,TXT_ACS_MAP22_29_ITHIN,,,,"myslím, že bych tě měl odstranit ze šachovnice.",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,"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ă,Пришло время завершить твою партию,Дошло је време да се заврши твоја партија +You hear a door open upstairs,TXT_ACS_MAP23_10_YOUHE,,,,Z patra slyšíš otevírající se dveře.,"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,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,Из северного зала доносится звук,Од северне дворане зачује се звук "Worship me, and I may yet be merciful",TXT_ACS_MAP27_8_WORSH,,,,Uctívej mě a možná ještě budu milosrdný.,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","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ă","Преклонись предо мной, и, может быть, я буду милосерден","Преклони се преда мноме, и можда ћу бити милостив" -"Then again, maybe not",TXT_ACS_MAP27_10_THENA,,,,"Na druhou stranu, možná ne.","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","Poi di nuovo, forse no",まあ、有り得ないな,허나... 그러지는 않겠지.,"Maar nogmaals, misschien niet","Z drugiej strony, może nie...","Pensando melhor, talvez não",,"Dar apoi, poate că nu","А может быть, и нет",А можда и нећу -One ninth of the puzzle has been solved,TXT_ACS_MAP28_6_ONENI,,,,Jedna devítina rébusu byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена -On the Monastery,TXT_ACS_MAP28_7_ONTHE,,,,v Klášteře.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в Семинарии Ересиарха,у Јересијарховој семинарији -One ninth of the puzzle has been solved,TXT_ACS_MAP30_6_ONENI,,,,Jedna devítina rébusu byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена -On the Monastery,TXT_ACS_MAP30_7_ONTHE,,,,v Klášteře.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в Семинарии Ересиарха,у Јересијарховој семинарији -One ninth of the puzzle has been solved,TXT_ACS_MAP34_1_ONENI,,,,Jedna devítina rébusu byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена -On the Monastery,TXT_ACS_MAP34_2_ONTHE,,,,v Klášteře.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в Семинарии Ересиарха,у Јересијарховој семинарији +"Then again, maybe not",TXT_ACS_MAP27_10_THENA,,,,"Na druhou stranu, možná ne.","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","Z drugiej strony, może nie...","Pensando melhor, talvez não",,"Dar apoi, poate că nu","А может быть, и нет",А можда и нећу +One ninth of the puzzle has been solved,TXT_ACS_MAP28_6_ONENI,,,,V Klášteru byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена +On the Monastery,TXT_ACS_MAP28_7_ONTHE,,,,jedna devítina rébusu.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији +One ninth of the puzzle has been solved,TXT_ACS_MAP30_6_ONENI,,,,V Klášteru byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена +On the Monastery,TXT_ACS_MAP30_7_ONTHE,,,,jedna devítina rébusu.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији +One ninth of the puzzle has been solved,TXT_ACS_MAP34_1_ONENI,,,,V Klášteru byla vyřešena,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.,Jedna dziewiąta zagadki rozwiązana,Um nono do quebra-cabeça foi resolvido,,O noime din puzzle a fost rezolvată,Одна девятая головоломки разгадана,Деветина загонетке је решена +On the Monastery,TXT_ACS_MAP34_2_ONTHE,,,,jedna devítina rébusu.,Im Kloster,,en la Monaĥejo.,En el Monasterio,,luostarissa,dans le monastère.,A Monostorban,Nel Monastero,修道院 にわずかに影響を与えた,... 헤러시아크의 신학교에서,Op het klooster,w Klasztorze,No Mosteiro,,pe Mănăstire,в семинарии Ересиарха,у Јересијарховој семинарији The portal has been sealed,TXT_ACS_MAP35_0_THEPO,,,,Portál byl zapečeťen.,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,Portal został zapieczętowany,O portal foi selado,,Portalul a fost închis,Врата закрылись,Врата су затворена Choose your fate,TXT_ACS_MAP35_1_CHOOS,,,,Vyber si svůj osud.,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,Wybierz swoje przeznaczenie,Escolha o seu destino,,Alegeți destinul,Сделай свой выбор,Донеси своју одлуку The door is barred from the inside,TXT_ACS_MAP35_3_THEDO,,,,Dveře jsou zatarasené zevnitř.,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.,Drzwi są zabarykadowane od środka,A porta está barrada por dentro,,Ușa e blocată dinăuntru,Дверь заблокирована изнутри,Врата су забрављена изнутра -Are you strong enough,TXT_ACS_MAP35_12_AREYO,,,,Jsi dost siln@[adj_cs],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 forte abbastanza,お前がどれだけ強かろうと,네 놈은 주인들을 대면할 힘이...,Ben je sterk genoeg,Czy jesteś wystarczająco silny,Você é forte o suficiente,,Ești întradevăr suficient de puternic,"Достаточно ли ты силён,",Јеси ли довољно снажан -To face your own masters?,TXT_ACS_MAP35_14_TOFAC,,,,čelit svým vlastním pánům?,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?,Per affrontare i tuoi stessi maestri?,お前の師に立ち向かえるのか?,진심으로 있는 것인가?,Om je eigen meesters onder ogen te komen?,By stawić czoła swoim mistrzom?,Para enfrentar os seus próprios mestres?,,Să îți înfrunți proprii stăpâni?,чтобы сразиться со своими наставниками?,да се суочиш са својим господарима? +Are you strong enough,TXT_ACS_MAP35_12_AREYO,,,,"Jsi dost siln@[adj_cs],",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,Czy jesteś wystarczająco silny,Você é forte o suficiente,,Ești întradevăr suficient de puternic,"Достаточно ли ты силён,",Јеси ли довољно снажан +To face your own masters?,TXT_ACS_MAP35_14_TOFAC,,,,čelit svým vlastním pánům?,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?,By stawić czoła swoim mistrzom?,Para enfrentar os seus próprios mestres?,,Să îți înfrunți proprii stăpâni?,чтобы сразиться со своими наставниками?,да се суочиш са својим господарима? ,,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?,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 nella sala di aspetto?,挑戦する準備は整ったか?,감히 준비의 방에서 전투를 벌이다니...,Durf jij te vechten in de readyroom?,Śmiesz walczyć w pokoju przygotowań?,Como ousa batalhar na sala de espera?,,Îndrăznești să lupți în camera de așteptare?,Ты посмел сражаться в комнате ожидания?,Усуђујеш се борити у припремној соби? -"For that, you shall die!",TXT_ACS_MAP33_7_FORTH,,,,Pro to zemřeš!,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 quello, morirai!",ならば、死へ進め!,죽어서 값을 치러라!,Daarvoor zal je sterven!,Umrzesz za to!,Você morrerá por isso!,,"Pentru asta, vei muri!",Так умри же!,За то ћеш умрети! +You dare battle in the ready room?,TXT_ACS_MAP33_6_YOUDA,,,,Ty si dovoluješ rvát se v přípravné místnosti?,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?,Śmiesz walczyć w pokoju przygotowań?,Como ousa batalhar na sala de espera?,,Îndrăznești să lupți în camera de așteptare?,Ты посмел сражаться в комнате ожидания?,Усуђујеш се борити у припремној соби? +"For that, you shall die!",TXT_ACS_MAP33_7_FORTH,,,,Pro to zemřeš!,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!,Umrzesz za to!,Você morrerá por isso!,,"Pentru asta, vei muri!",Так умри же!,За то ћеш умрети! The waterfall is open,TXT_ACS_MAP41_6_THEWA,,,,Vodopád je otevřen.,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,Wodospad jest otwarty,A cascata está aberta,,Cascada e deschisă,Поток воды остановлен,Водопад је отворен The waterfall is blocked,TXT_ACS_MAP41_7_THEWA,,,,Vodopád je zatarasen.,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,Wodospad jest zablokowany,A cascata está bloqueada,,Cascada e închisă,Поток воды преграждает путь,Водопад је блокиран A door has opened in the chapel,TXT_ACS_MAP41_8_ADOOR,,,,Dveře se otevřely v kapli.,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,Drzwi w kaplicy zostały otwarte,Uma porta se abriu na capela,,O ușă s-a deschis în capelă,Дверь открылась в часовне,Врата су се отворила у катедрали -Now that's odd...,TXT_ACS_MAP42_4_NOWTH,,,,Tak to je divné...,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...,Ora questo è strano...,何かがおかしい...,무언가가 이상하다...,Dat is vreemd....,Dziwne...,Que estranho...,,Asta e ciudat...,Как странно...,То је чудно... +Now that's odd...,TXT_ACS_MAP42_4_NOWTH,,,,Tak to je divné...,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....,Dziwne...,Que estranho...,,Asta e ciudat...,Как странно...,То је чудно... Three more parts of the puzzle remain,TXT_ACS_MAP44_1_THREE,,,,Zbývají tři části rébusu.,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,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,Осталось три части головоломки,Остају још три дела загонетке Two more parts of the puzzle remain,TXT_ACS_MAP44_2_TWOMO,,,,Zbývají dvě části rébusu.,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,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,Осталось две части головоломки,Остају још два дела загонетке One more part of the puzzle remains,TXT_ACS_MAP44_3_ONEMO,,,,Zbývá jedna část rébusu.,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,Pozostała jeszcze jedna część zagadki,Falta mais uma parte do quebra-cabeça,,O parte din puzzle încă rămâne,Осталась одна часть головоломки,Остаје још један део загонетке @@ -8333,28 +8329,28 @@ The puzzle is complete,TXT_ACS_MAP44_4_THEPU,,,,Rébus je kompletní.,Das Rätse You have not completed the puzzle,TXT_ACS_MAP44_6_YOUHA,,,,Nesplnil jsi rébus.,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.,Nie ukończyłeś zagadki,Você não completou o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Нисте решили загонетку The floor is not safe!,TXT_ACS_MAP44_8_THEFL,,,,Podlaha není bezpečná!,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!,Ta podłoga nie jest bezpieczna!,O chão não está seguro!,,Podeaua nu e sigură!,Пол совсем прогнил!,Под није безбедан! One third of the puzzle is solved,TXT_ACS_MAP44_10_ONETH,,,,Jedna třetina rébusu je vyřešena.,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.,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена -Two thirds of the puzzle is solved,TXT_ACS_MAP44_11_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,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,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене -You hear a platform moving in the distance,TXT_ACS_MAP45_1_YOUHE,,,,Slyšíš v dálce pohybující se plošinu.,"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 a distanza,昇降機の音が遠くで聞こえる,멀리서 보행판이 움직이는 소리가 들려왔다,Je hoort een platform bewegen in de verte,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,"Неподалёку раздаётся звук +Two thirds of the puzzle is solved,TXT_ACS_MAP44_11_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,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,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене +You hear a platform moving in the distance,TXT_ACS_MAP45_1_YOUHE,,,,Slyšíš v dálce pohybující se plošinu.,"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,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,"Неподалёку раздаётся звук движущейся деревянной площадки",Чујете како се платформа помера у даљини -It is done...,TXT_ACS_MAP46_0_ITISD,,,,Je to dokonáno...,Es ist getan...,,Ĝi estas farita...,Está terminado...,,Se on tehty...,C'est terminé...,Készen van...,Fatto...,これで完了だ...,이제 끝났다...,Het is gebeurd,"Zrobione... +It is done...,TXT_ACS_MAP46_0_ITISD,,,,Je to dokonáno...,Es ist getan...,,Ĝi estas farita...,Está terminado...,,Se on tehty...,C'est terminé...,Készen van...,È fatto...,これで完了だ...,이제 끝났다...,Het is gebeurd,"Zrobione... ",Pronto...,,E gata...,Готово...,Готово је... You have not completed the puzzle,TXT_ACS_MAP46_1_YOUHA,,,,Nesplnil@[ao_cs] jsi rébus.,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...,Nie ukończyłeś zagadki,Você não terminou o quebra-cabeça,,Nu ai rezolvat puzzle-ul,Головоломка не разгадана,Ниси решио загонетку I'm warning you...,TXT_ACS_MAP46_2_IMWAR,,,,Varuju tě...,Ich warne dich...,,Mi avertas vin...,Te lo advierto...,,Varoitan sinua...,Je vous avertis...,Figyelmeztetlek...,Ti avverto...,お前に警告しよう...,나는 경고했다...,Ik waarschuw je...,Ostrzegam cię...,Estou te avisando...,,Te avertizez...,Я тебя предупреждаю...,Упозоравам те... -"Stubborn, aren't you?",TXT_ACS_MAP46_3_STUBB,,,,"Ty jsi ale tvrdohlav@[adj_cs], ne?","Du bist aber stur, was?",,"Vi estas obstina, ĉu ne?","Eres obstinado, ¿verdad?",,Oletpa itsepäinen,"Obstiné, n'est-ce pas?","Makacs vagy, ugye?","Testardo, no?",頑固だと、自らも思わないか?,정말 끈질기군.,"Koppig, nietwaar?","Jesteś uparty, prawda?","Você é teimos@[ao_ptb], não é mesmo?",,"Încăpățânat, nu-i așa?",Не слишком ли ты упрямый?,"Тврдоглав си, зар не?" -"And stupid, too",TXT_ACS_MAP46_4_ANDST,,,,A taky hloup@[adj_cs].,Und auch noch dumm,,Kaj ankaŭ stulta.,"Y estúpido, también",,Ja vieläpä tyhmä,"Et stupide, aussi.",És oktondi is.,E pure stupido,そして、あまりにも愚か者だ,어리석기도 하고.,En ook dom,Głupi też,E estúpid@[ao_ptb] também,,"Și prost, pe deasupra",И не слишком-то разумный!,А још си и глуп +"Stubborn, aren't you?",TXT_ACS_MAP46_3_STUBB,,,,"Ty jsi ale tvrdohlav@[adj_cs], ne?","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?","Jesteś uparty, prawda?","Você é teimos@[ao_ptb], não é mesmo?",,"Încăpățânat, nu-i așa?",Не слишком ли ты упрямый?,"Тврдоглав си, зар не?" +"And stupid, too",TXT_ACS_MAP46_4_ANDST,,,,A taky hloup@[adj_cs].,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,Głupi też,E estúpid@[ao_ptb] também,,"Și prost, pe deasupra",И не слишком-то разумный!,А још си и глуп One fourth of this puzzle is complete,TXT_ACS_MAP46_8_ONEFO,,,,Jedna čtvrtina rébusu je vyřešena.,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,Jedna czwarta tej zagadki ukończona,Um quarto deste quebra-cabeça está completo,,O pătrime din puzzle e rezolvată,Одна четвёртая этой головоломки разгадана,Четвртина загонетке је решена Bad choice...,TXT_ACS_MAP46_9_BADCH,,,,Špatná volba.,Falsche Wahl...,,Malbona elekto...,Mala decisión...,,Huono valinta...,Mauvaise décision...,Rossz választás...,Scelta sbagliata...,拙い選択だ...,서투른 선택이다...,Slechte keuze....,Zły wybór...,Péssima escolha...,,Proastă alegere...,Плохой выбор...,Лош избор... The symbols are not aligned,TXT_ACS_MAP47_2_THESY,,,,Symboly nejsou zarovnány.,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,Symbole nie są wyrównane,Os símbolos não estão alinhados,,Simbolurile nu sunt aliniate,Символы не совпадают,Симболи нису поравнати The door won't open from this side,TXT_ACS_MAP48_2_THEDO,,,,Dveře se z této strany neotevřou.,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,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,С этой стороны дверь не открыть,Врата неће да се отворе са стране The door is barred from the outside,TXT_ACS_MAP50_1_THEDO,,,,Dveře jsou zatarasené zvenku.,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,Drzwi są zabarykadowane od zewnątrz,A porta está barrada por fora,,Ușa e încuiată pe dinafară,Дверь заблокирована снаружи,Врата су блокирана споља Sacrilege !,TXT_ACS_MAP51_5_SACRI,,,,Svatokrádež!,Gotteslästerung!,,Sakrilegio !,¡Sacrilegio!,,Pyhäinhäväistys !,Sacrilège!,Szentségtörés!,Sacrilegio !,罰当たりが!,신성모독이다!,Heiligschennis!,Świętokradztwo !,Sacrilégio!,,Sacrilegiu!,Святотатство !,Светогрђе ! -You have defiled Eric's tomb !!,TXT_ACS_MAP51_6_YOUHA,,,,Znesvětil@[ao_cs] jsi Erikovu hrobku!!,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!,Adesso hai profanato la tomba di eric !!,貴様はエリックの墓を荒らしたな!!,네 놈은 성 에릭의 무덤을 더렵혔다!!,Je hebt Eric's graf bevlekt!!,Zhańbiłeś grób Erica !!,Você violou a tumba de Eric!,,Ai profanat mormântul lui Eric!!,Ты осквернил могилу Эрика !!,Оскрнавио си Ерикову гробницу !! +You have defiled Eric's tomb !!,TXT_ACS_MAP51_6_YOUHA,,,,Znesvětil@[ao_cs] jsi Erikovu hrobku!!,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!!,Zhańbiłeś grób Erica !!,Você violou a tumba de Eric!,,Ai profanat mormântul lui Eric!!,Ты осквернил могилу Эрика !!,Оскрнавио си Ерикову гробницу !! And now you die !!!,TXT_ACS_MAP51_7_ANDNO,,,,Teď zemřeš!!!,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!!!!!,I teraz zginiesz !!!,E agora você morrerá!!!,,"Iar acum, mori!!",И умрёшь за это страшной смертью !!!,И због тога ћеш умрети !!! One third of the puzzle is solved,TXT_ACS_MAP51_8_ONETH,,,,Jedna třetina rébusu je vyřešena.,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.,Jedna trzecia zagadki rozwiązana,Um terço do quebra-cabeça foi resolvido,,O treime din puzzle e rezolvată,Одна треть головоломки разгадана,Трећина загонетке је решена Two thirds of the puzzle is solved,TXT_ACS_MAP51_9_TWOTH,,,,Dvě třetiny rébusu jsou vyřešeny.,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,Dwie trzecie zagadki rozwiązane,Dois terços do quebra-cabeça foi resolvido,,Două treimi din puzzle sunt rezolvate,Две трети головоломки разгаданы,Две трећине загонетке су решене The crypt is open,TXT_ACS_MAP51_10_THECR,,,,Krypta je otevřena.,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,Krypta jest otwarta,A cripta está aberta,,Cripta e deschisă,Склеп открыт,Гробница је отворена Beware the spider's tomb,TXT_ACS_MAP51_11_BEWAR,,,,Vyvaruj se pavoučí hrobky.,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,Strzeż się grobowca pająków,Cuidado com a tumba da aranha,,Păzește-te de mormântul păianjenului,Опасайся гробницы паука,Чувај се паукове гробнице -You hear a platform rise outside,TXT_ACS_MAP51_13_YOUHE,,,,Slyšíš zvenku zvedající se platformu.,"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 a distanza,外で昇降機の音が聞こえる,밖에서 보행판이 올라오는 소리가 들려왔다,Je hoort een platform buiten opstijgen,Słyszysz odgłos unoszącej się na zewnątrz platformy,Você ouve uma plataforma subir lá fora,,Auzi o platformă ridicându-se în afară,"Снаружи слышен звук +You hear a platform rise outside,TXT_ACS_MAP51_13_YOUHE,,,,Slyšíš zvenku zvedající se platformu.,"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,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ă,"Снаружи слышен звук поднимающегося камня",Чујете како се платформа диже споља Do you feel lucky?,TXT_ACS_MAP51_14_DOYOU,,,,"Zdá se ti, že máš štěstí?",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?,Masz szczęście?,Está se sentindo com sorte?,,Te simți norocos?,Чувствуешь ли ты себя везучим?,Да ли се осећаш срећним? You guessed wrong!,TXT_ACS_MAP51_15_YOUGU,,,,To máš smůlu!,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!,Źle zgadłeś!,Adivinhou errado!,,N-ai ghicit!,Неправильное предположение!,Погрешно си погодио! @@ -8362,16 +8358,16 @@ Good guess,TXT_ACS_MAP51_16_GOODG,,,,Dobré zdání.,Gut geraten,,Bona diveno.,B Can you do all the scripting for my level?,TXT_ACS_MAP51_17_CANYO,,,,Můžeš všechno skriptování udělat za mě?,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?,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?,Можешь написать за меня все скрипты?,Можеш ли да напишеш све скриптове за мој ниво? Don't touch my gloppy,TXT_ACS_MAP51_18_DONTT,,,,Nesahej mi na slimáka!,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,Nie ruszaj moich słodyczy,Não toca no meu docinho!,,Nu-mi atinge bomboana,Не трогай мою вкусняшку,Не дирај мој слаткиш Vorpal ?!?!?!,TXT_ACS_MAP51_19_VORPA,,,,Šaršoun?!?!?!,Tödlich ?!?!?!,,Vorpal ?!?!?!,¡¿¡¿¡¿ Vorpal ?!?!?!,,Tappava ?!?!?!,,,,ボーパル ?!?!?!,드래곤 슬레이어 인가?!,,Śmiercionośny ?!?!?!,,,Vorpal?!?!?!,Остренько ?!?!?!,Вајтолни мач ?!?!?! -"Gimme some sugar, baby",TXT_ACS_MAP51_20_GIMME,,,,"Dej mi trochu cukru, zlato.","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 a magadévá, édes!",,砂糖が欲しいかい、ベイビー,등짝을 보자!...,"Geef me wat suiker, schatje.",Daj mi całusa skarbie,"Me dá um pouco de açúcar, baby",,"Dă-mi niște zahăr, dulceață","Подай-ка мне сахар, детка","Дај ми мало шећера, душо" -Duh-uhhh...,TXT_ACS_MAP51_21_DUHUH,,,,A jéje.,,,Da-aaaa...,,,Daa-aaa....,,Ahaaa...,,えぇーとぉー...,낙원이란 있을 수 없는거야.,,Oooooo...,Dãããã-ããã...,,,Ага-а-а-а...,Дух-уххх... +"Gimme some sugar, baby",TXT_ACS_MAP51_20_GIMME,,,,"Dej mi trochu cukru, zlato.","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.",Daj mi całusa skarbie,"Me dá um pouco de açúcar, baby",,"Dă-mi niște zahăr, dulceață","Подай-ка мне сахар, детка","Дај ми мало шећера, душо" +Duh-uhhh...,TXT_ACS_MAP51_21_DUHUH,,,,A jéje.,,,Da-aaaa...,,,Daa-aaa....,,Nyílván...,,えぇーとぉー...,낙원이란 있을 수 없는거야.,,Oooooo...,Dãããã-ããã...,,,Ага-а-а-а...,Дух-уххх... Film in an hour?,TXT_ACS_MAP51_22_FILMI,,,,Film za hodinu?,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?,Za godzinę film?,Quer ver um filme daqui a pouco?,,Film într-o oră?,Фильм на час?,Снимамо за сат времена? I don't even get my own tombstone - cf,TXT_ACS_MAP51_23_IDONT,,,,Ani nemám svůj vlastní náhrobek. -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,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 Let no blood be spilt,TXT_ACS_MAP51_24_LETNO,,,,Nechť není prolita žádná krev.,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,Nie pozwól by krew została przelana,Que sangue nenhum seja derramado,,Fie ca sângele să nu fie vărsat,Да не прольётся кровь,Нека се не пролије крв Let no hand be raised in anger,TXT_ACS_MAP51_25_LETNO,,,,Nechť není žádná ruka hněvem zvednuta.,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...,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,И да не поднимется рука во гневе,Нека се ни рука из беса не подигне Who dares disturb our slumber?,TXT_ACS_MAP52_9_WHODA,,,,Kdo se opovažuje narušit náš spánek?,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?,Kto śmie przeszkadzać nam w drzemce?,Quem ousa perturbar o nosso descanso?,,Cine cutează să-mi perturbe odihna?,Кто осмелился потревожить наш покой?,Ко се усуђује узнемиравати наш спокој? The way is open,TXT_ACS_MAP52_10_THEWA,,,,Cesta je otevřena.,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,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Путь открыт,Пролаз је отворен -You have ,TXT_ACS_MAP53_2_YOUHA,,,,Zbývají ti ,Du hast,,Vi havas,Tienes,,Sinulla on,Vous avez,Már csak,hai,スイッチはまだ,지금 ,Je hebt,Masz,Restam ainda,,Mai ai,Осталось,Остало је -\x20switches left,TXT_ACS_MAP53_3_SWITC,,,,\x20spínače.,\x20Schalter übrig,,\x20ŝaltilojn ceterajn.,\x20interruptores restantes,\x20switches restantes,\x20vipua jäljellä,\x20boutons à trouver,\x20kallantyú van hátra,\x20interuttori rimanenti,残っている,개의 개폐기들이 남았다,\x20schakelaars over,\x20pozostałych przełączników,\x20interruptores,,\x20butoane rămase,\x20Переключателей,\x20прекидача +You have ,TXT_ACS_MAP53_2_YOUHA,,,,Zbývají ti ,Du hast,,Vi havas,Tienes,,Sinulla on,Vous avez,Már csak,Hai,スイッチはまだ,지금 ,Je hebt,Masz,Restam ainda,,Mai ai,Осталось,Остало је +\x20switches left,TXT_ACS_MAP53_3_SWITC,,,,\x20spínače.,\x20Schalter übrig,,\x20ŝaltilojn ceterajn.,\x20interruptores restantes,\x20switches restantes,\x20vipua jäljellä,\x20boutons à trouver,\x20kallantyú van hátra,\x20interuttori rimanenti,残っている,개의 개폐기들이 남았다,\x20schakelaars over,\x20pozostałych przełączników,\x20interruptores,,\x20butoane rămase,\x20переключателей,\x20прекидача You have only ,TXT_ACS_MAP53_4_YOUHA,,,,Zbývá ti jen ,Du hast nur,,Vi nur havas,Tienes solo,,Sinulla on vain,Vous avez seulement,Már csak,Hai solamente,スイッチは,이제 오로지 ,Je hebt alleen,Masz tylko,Resta somente,,Mai ai doar,Остался всего,Остао је само \x20switch left,TXT_ACS_MAP53_5_SWITC,,,,\x20spínač.,\x20Schalter übrig,,\x20ŝaltilon ceteran.,\x20interruptor restante,\x20switch restante,\x20vipu jäljellä,\x20outon à trouver,\x20kallantyú van hátra,\x20interruttore rimanente,"だけ残っている ",개의 개폐기가 남았다,\x20schakelaar over,\x20przełącznik,\x20interruptor,,\x20buton rămas,\x20переключатель,\x20прекидач @@ -8380,15 +8376,15 @@ The doors won't open from this side,TXT_ACS_MAP54_1_THEDO,,,,Dveře se z této s The doors are open...,TXT_ACS_MAP54_4_THEDO,,,,Dveře jsou otevřené...,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....,Drzwi są otwarte...,As portas estão abertas...,,Ușile sunt deschise...,Путь в цитадель открыт...,Врата су отворена... ...if you are ready,TXT_ACS_MAP54_5_IFYOU,,,,...jestli jsi připraven@[ao_cs].,...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...,...jeśli jesteś gotów,...se você estiver preparad@[ao_ptb],,...dacă ești pregătit,...Осмелишься ли ты войти?,...ако си спреман A door has opened,TXT_ACS_MAP54_9_ADOOR,,,,Dveře se otevřely,Eine Tür hat sich geöffnet,,Pordo malfermiĝis,Una puerta se abrió,,Ovi on auennut,Une porte est ouverte,Egy ajtó kinyílt,Una porta è stata aperta,先へ進むドアは開いた,지금 문이 열렸다...,Een deur is geopend,Drzwi otworzyły się,Uma porta se abriu,,O ușă s-a deschis,Дверь откроется,Врата су се отворила -on the Chantry,TXT_ACS_MAP54_10_ONTHE,,,,v Modlitebně.,In der Kantorei,,en la Kapelo.,En la capilla,,kappelissa,dans la chapelle.,a kápolnánál,Nella Cappella,小礼拝堂 へ向かえ,... 예배당에서,op de Chantry,w Kaplicy Wotywnej,na Capela,,la Capelă,в Часовне,у Капели +on the Chantry,TXT_ACS_MAP54_10_ONTHE,,,,v Modlitebně.,In der Kantorei,,en la Kapelo.,En la capilla,,kappelissa,dans la chapelle.,a kápolnánál,Nella Cappella,小礼拝堂 へ向かえ,... 예배당에서,op de Chantry,w Kaplicy Wotywnej,na Capela,,la Capelă,в часовне,у Капели A bridge has been built,TXT_ACS_MAP54_11_ABRID,,,,Most byl postaven,Eine Brücke wurde errichtet,,Ponto estis konstruita,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,Most został utworzony,Uma ponte foi construída,,Un pod a fost construit,Мост воздвигнется,Мост се саградио -on the Abattoir,TXT_ACS_MAP54_12_ONTHE,,,,na Jatkách.,Im Schlachthaus,,en la Buĉejo.,En el matadero,,teurastamolla,dans l'abbatoir.,a vágóhídnál,Nella Macelleria, 屠殺場 へ向かえ,... 도살장에서,op het slachthuis,w Rzeźni,no Matadouro,,pe Abator,на Бойне,на Кланици +on the Abattoir,TXT_ACS_MAP54_12_ONTHE,,,,na Jatkách.,Im Schlachthaus,,en la Buĉejo.,En el matadero,,teurastamolla,dans l'abbatoir.,a vágóhídnál,Nella Macelleria, 屠殺場 へ向かえ,... 도살장에서,op het slachthuis,w Rzeźni,no Matadouro,,pe Abator,на бойне,на Кланици A stair has been built,TXT_ACS_MAP54_13_ASTAI,,,,Schody byly postaveny,Eine Treppe wurde errichtet,,Ŝtuparo estis konstruita,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,Schody zostały utworzone,Uma escada foi construída,,O scară a fost construită,Лестница воздвигнется,Степенице су се саградиле -on the Dark Watch,TXT_ACS_MAP54_14_ONTHE,,,,na Temné hlídce.,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,w Ciemnej Strażnicy,na Guarda Negra,,pe Gardianul Întunecat,у Тёмного стража,на Црној стражи +on the Dark Watch,TXT_ACS_MAP54_14_ONTHE,,,,na Temné hlídce.,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,w Ciemnej Strażnicy,na Guarda Negra,,pe Gardianul Întunecat,у тёмного стража,на Црној стражи One gear has been placed,TXT_ACS_MAP54_15_ONEGE,,,,Jedno kolo bylo umístěno.,Ein Zahnrad wurde eingesetzt,,Dentrado estis metita.,Un engranaje se ha puesto,Un engrane se ha puesto,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,Jedna zębatka została umieszczona,Uma engrenagem foi colocada,,Un mecanism a fost introdus,Шестерня установлена,Један зупчаник је постављен -\x20gears have been placed,TXT_ACS_MAP54_16_GEARS,,,,\x20kola byla umístěna.,\x20Zahnräder wurden eingesetzt,,\x20dentradoj estis metitaj.,\x20engranajes se han puesto,\x20engranes se han puesto,\x20ratasta on asetettu,\x20engrenages ont été placés,\x20fogaskerék a helyére került,\x20ingranaggi sono stati piazzati,歯車を配置した,톱니바퀴들이 배치되었다,\x20tandwielen zijn geplaatst,\x20zębatki zostały umieszczone,\x20engrenagens foram colocadas,,\x20mecanisme au fost introduse,\x20шестернёй установлено,\x20зупчаника су постављена -A barricade has opened,TXT_ACS_MAP54_17_ABARR,,,,Barikáda se otevřela,Eine Barrikade wurde geöffnet,,Barikado malfermiĝis,La barricada se ha abierto,,Tiesulku on auennut,Une barricade s'est ouverte,Egy barikád megszűnt,Una barricata è stata aperta,バリケードは開かれた,방벽이 열렸다...,Er is een barricade geopend,Barykada została otwarta,Uma barricada se abriu,,O baricadă s-a deschis,Преграда поднимется,Барикада је отворена -On the Cloaca,TXT_ACS_MAP54_18_ONTHE,,,,v Kloace.,In der Kloake,,en la Cloaca.,En la Cloaca,,kloaakilla,dans le cloaque,a Kloákánál,Nella Cloaca,排泄腔 へ向かえ,... 하수구에서,Op de Cloaca,W Kloace,Na Cloaca,,pe Cloaca,в Клоаке,у клоаци +\x20gears have been placed,TXT_ACS_MAP54_16_GEARS,,,,\x20kola byla umístěna.,\x20Zahnräder wurden eingesetzt,,\x20dentradoj estis metitaj.,\x20engranajes se han puesto,\x20engranes se han puesto,\x20ratasta on asetettu,\x20engrenages ont été placés,\x20fogaskerék a helyére került,\x20ingranaggi sono stati piazzati,歯車を配置した,톱니바퀴들이 배치되었다,\x20tandwielen zijn geplaatst,\x20zębatki zostały umieszczone,\x20engrenagens foram colocadas,,\x20mecanisme au fost introduse,\x20шестерней установлено,\x20зупчаника су постављена +A barricade has opened,TXT_ACS_MAP54_17_ABARR,,,,V Kloace se otevřela barikáda.,Eine Barrikade wurde geöffnet,,Barikado malfermiĝis,La barricada se ha abierto,,Tiesulku on auennut,Une barricade s'est ouverte,Egy barikád megszűnt,Una barricata è stata aperta,バリケードは開かれた,방벽이 열렸다...,Er is een barricade geopend,Barykada została otwarta,Uma barricada se abriu,,O baricadă s-a deschis,Преграда поднимется,Барикада је отворена +On the Cloaca,TXT_ACS_MAP54_18_ONTHE,,,,V Kloace se otevřela barikáda.,In der Kloake,,en la Cloaca.,En la Cloaca,,kloaakilla,dans le cloaque,a Kloákánál,Nella Cloaca,排泄腔 へ向かえ,... 하수구에서,Op de Cloaca,W Kloace,Na Cloaca,,pe Cloaca,в клоаке,у клоаци The way back is open,TXT_ACS_MAP54_20_THEWA,,,,Cesta zpět je otevřena.,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,Droga powrotna jest otwarta,O caminho de volta está aberto,,Calea e deschisă,Путь назад открыт,Пролаз назад је отворен The door is barred from the inside,TXT_ACS_MAP55_9_THEDO,,,,Dveře jsou zatarasené zevnitř.,Die Tür ist von innen verriegelt,,La pordo estas barita interne.,La puerta está atrancada desde el interior,,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.,Drzwi są zabarykadowane od wewnątrz,A porta está barrada por dentro,,Ușa e încuiată din interior,Дверь заблокирована изнутри,Врата су забрављена изнутра You dare plunder the tomb,TXT_ACS_MAP56_0_YOUDA,,,,Ty se opovažuješ rabovat,Wagst du es,,Vi aŭdacas rabi 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,Śmiesz plądrować grobowiec,Como ousa saquear a tumba,,Cutezi să jefuiești mormântul,Ты посмел ограбить могилу,Усуђујеш се пљачкати @@ -8402,144 +8398,144 @@ You have only ,TXT_ACS_MAP59_3_YOUHA,,,,Zbývá ti jen ,Du musst nur,,Vi nur hav The way to the tower is open,TXT_ACS_MAP59_5_THEWA,,,,Cesta do věže je otevřena.,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,Droga do wieży jest otwarta,O caminho para a torre está aberto,,Calea către turn e deschisă,Путь к башне открыт,Пут до куле је отворен The way is open,TXT_ACS_MAP60_3_THEWA,,,,Cesta je otevřena.,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,Droga jest otwarta,O caminho está aberto,,Calea e deschisă,Портал открыт,Портал је отворен ,,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,,,,"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.","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.",,,"No quiero ningún problema, aléjate de mí. He tenido suficientes problemas con lo que me hizo Harris. Me prometió dinero, en lugar de eso, ahora espero a ser cuestionado 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, stammi lontano. Ho già avuto abbastanza problemi con quello che quel bastardo di Harris ha fatto a me. Mi aveva promesso soldi, invece mi ritrovo ad avere l'opportunità di essere Interrogato dal Programmatore.","もう面倒事には御免だ、私に近づくな。 +"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,,,,"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.","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.",,,"No quiero ningún problema, aléjate de mí. He tenido suficientes problemas con lo que me hizo Harris. Me prometió dinero, en lugar de eso, ahora espero a ser cuestionado 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.","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.","Не подходи ко мне — мне не нужны неприятности! У меня их и так достаточно из-за этого мерзавца Харриса. Он обещал мне деньги, а вместо этого меня ожидает «допрос» у Программиста.", -I'll help you if you help me. Five pieces of gold and I'll tell all I know.,TXT_DLG_SCRIPT02_D0_ILLHE,,,,"Pomůžu ti, když pomůžeš ty mě. Pět zlaťáků a řeknu ti vše, co vím.",Ich helfe dir wenn du mir hilfst. Fünf Goldstücke und ich erzähle alles was ich weiß.,,,Te ayudaré 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 mi aiuti. 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.","Не подходи ко мне — мне не нужны неприятности! У меня их и так достаточно из-за этого мерзавца Харриса. Он обещал мне деньги, а вместо этого меня ожидает «допрос» у программиста.", +I'll help you if you help me. Five pieces of gold and I'll tell all I know.,TXT_DLG_SCRIPT02_D0_ILLHE,,,,"Pomůžu ti, když pomůžeš ty mě. Pět zlaťáků a řeknu ti vše, co vím.",Ich helfe dir wenn du mir hilfst. Fünf Goldstücke und ich erzähle alles was ich weiß.,,,Te ayudaré 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.,"助けてくれるなら援助する。 5ゴールドで知っている情報を全て教えよう",저를 도와준다면 당신을 돕겠습니다. 5 골드를 줌으로써 말이죠.,Ik zal je helpen als je me helpt. Vijf goudstukken en ik vertel alles wat ik weet.,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.","Я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу всё, что знаю.", -Here's the gold.,TXT_RPLY0_SCRIPT02_D0_HERES,,,,Tady máš to zlato.,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.,Oto złoto.,Aqui está o ouro.,,Poftiți aurul.,Вот золото., -"Be stealthy when you kill, you won't set off alarms.",TXT_RYES0_SCRIPT02_D0_BESTE,,,,"Když zabíjíš, dělej to potichu - nevyhlásíš tak poplach.","Sei leise, wenn du jemanden tötest, damit du keinen Alarm auslöst.",,,Sé cauteloso cuando mates y no activarás 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.","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.","Убивай бесшумно, чтобы не поднять тревогу.", -"Well, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D0_WELLI,,,,Zadarmo ti nic říkat nebudu!,"Na ja, für umsonst werde ich dir nichts erzählen!",,,"Bueno, ¡No te diré 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.",Io non ti dirò un bel niente a gratis!,いや、タダで情報は渡せない!,세상에 공짜가 어딨습니까? 먼저 돈을 주세요!,"Nou, ik zal je niets gratis vertellen!","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!","Что ж, я ничего не скажу даром!", +Here's the gold.,TXT_RPLY0_SCRIPT02_D0_HERES,,,,Tady jsou.,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.,Oto złoto.,Aqui está o ouro.,,Poftiți aurul.,Вот золото., +"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.","Sei leise, wenn du jemanden tötest, damit du keinen Alarm auslöst.",,,Sé cauteloso cuando mates y no activarás 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.","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.","Убивай бесшумно, чтобы не поднять тревогу.", +"Well, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D0_WELLI,,,,Zadarmo ti nic říkat nebudu!,"Na ja, für umsonst werde ich dir nichts erzählen!",,,"Bueno, ¡No te diré 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!","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!","Что ж, я ничего не скажу даром!", 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?,Hast du vielleicht 5 weitere Goldmünzen dabei?,,,¿Por casualidad has conseguido otros 5 de oro?,,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?,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 монеток?, 5 gold.,TXT_RPLY0_SCRIPT02_D1516_5GOLD,,,,Pět zlatých.,5 Gold.,,,5 de oro.,,5 kolikkoa.,5 pièces.,5 arany.,5 pezzi d'oro.,5ゴールドだ。,5 골드.,5 goud.,5 monet.,5 de ouro.,,5 monezi de aur.,5 золотых., -"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 nevyhlásí poplach.",Also Giftpfeile können die Wachen sofort töten und lösen keinen Alarm aus.,,,"Bien, las saetas envenenadas pueden matar a los guardias al instante sin activar las 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.,"そうだな、ポイズンボルトは警備員を簡単に殺せるし、 +"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.",Also Giftpfeile können die Wachen sofort töten und lösen keinen Alarm aus.,,,"Bien, las saetas envenenadas pueden matar a los guardias al instante sin activar las 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.","Więc, zatrute bełty mogą od razu zabić strażników i nie włączą alarmu.","Bem, setas venenosas podem matar os guardas instantâneamente e não ativarão os alarmes.",,"Păi, bolțurile otrăvite pot omorâ gardienii instant și nu vor declanșa alarma.","Что ж, отравленными болтами можно убивать охранников быстро и бесшумно.", -"No sir, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D1516_NOSIR,,,,"Ne, pane, nic vám zadarmo říkat nebudu!","Nein, ich werde dir nichts für umsonst erzählen!",,,"No, ¡No diré 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 gratis!",いやいや、タダでは話せないな!,"죄송합니다만, 전 아무것도 무료로 말해주지 않을 겁니다!","Nee meneer, ik zal u niets gratis vertellen!","Nie panie, nie będę ci mówił niczego za darmo!","Não senhor, não vou te dizer nada de graça!",,"Nu domnule, n-o să-ți zic nimic pe gratis!","Нет, товарищ! Даром — только за амбаром!", +"No sir, I won't be telling you anything for free!",TXT_RNO0_SCRIPT02_D1516_NOSIR,,,,"Ne, ne, zadarmo ti nic říkat nebudu!","Nein, ich werde dir nichts für umsonst erzählen!",,,"No, ¡No diré 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!","Nie panie, nie będę ci mówił niczego za darmo!","Não senhor, não vou te dizer nada de graça!",,"Nu domnule, n-o să-ți zic nimic pe gratis!","Нет, товарищ! Даром — только за амбаром!", 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 hast bereits das letzte bisschen Klatsch aus mir herausgequetscht!,,,¡Ya me has sacado 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!,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!,"Ты уже вытянул из меня всё, что только можно!", What can I get for you?,TXT_DLG_SCRIPT02_D4548_WHATC,,,,Co si budeš přát?,Was kann ich für dich tun?,,,¿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?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Что я могу тебе предложить?, Assault gun,TXT_RPLY0_SCRIPT02_D4548_ASSAU,,,,Útočnou pušku,Sturmgewehr,,,Fusil de Asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Karabin Szturmowy,Fuzil de assalto,,Pușcă de asalt,Штурмовую винтовку, -Here you go.,TXT_RYES0_SCRIPT02_D4548_HEREY,,,,Tu máš.,Bitte sehr!,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Tessék,Ecco per te.,毎度あり。,여기 있어.,Alsjeblieft.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., +Here you go.,TXT_RYES0_SCRIPT02_D4548_HEREY,,,,Tu máš.,Bitte sehr!,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Tessék,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., You can't afford that right now.,TXT_RNO0_SCRIPT02_D4548_YOUCA,,,,Tu si teď nemůžeš dovolit.,Das kannst du dir momentan nicht leisten.,,,No puedes adquirir esto 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.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,Ты пока не можешь себе это позволить., Clip of bullets,TXT_RPLY1_SCRIPT02_D4548_CLIPO,,,,Zásobník nábojů,Gewehrmunition.,,,Cargador con balas,,Luotilipas,Chargeur de balles,Egy tár töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов, Thanks.,TXT_RYES1_SCRIPT02_D4548_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고맙다!,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю., -"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D4548_COMEO,,,,"No tak, je to deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", -Ammo box,TXT_RPLY2_SCRIPT02_D4548_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Egy doboz lőszer,Scatole di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, +"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D4548_COMEO,,,,"No tak, jen deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", +Ammo box,TXT_RPLY2_SCRIPT02_D4548_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Egy doboz lőszer,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, Here's your ammo.,TXT_RYES2_SCRIPT02_D4548_HERES,,,,Tady je tvá munice.,Hier ist deine Munition.,,,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,탄약 여기 있어!,Hier is je munitie.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны., -Maybe some other time.,TXT_RNO2_SCRIPT02_D4548_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes Mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Forse qualche altra volta.,また後でな。,아마도 나중에...,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", +Maybe some other time.,TXT_RNO2_SCRIPT02_D4548_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes Mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,아마도 나중에...,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", 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,,,,"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.","Gute Nachrichten von der Front zur Abwechslung. Macil lässt dir eine Belohnung und Training zukommen. Er hat mir aufgetragen, es dir zu geben.",,,"Buenas noticias desde el Frente, para variar. Macil mandó una recompensa y entrenamiento para ti. 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 allenamento. Mi ha istruito che te li dovevo procurare.,"フロントから朗報だ。 +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.,"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.","Наконец-то, хорошие новости от Сопротивления. Ты пришёл от Мэйсила за наградой и обучением? Он распорядился, чтобы ты получил их от меня.", Thanks.,TXT_RPLY0_SCRIPT02_D6064_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,ありがとう。,고맙습니다.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо., -Glad to be of service.,TXT_RYES0_SCRIPT02_D6064_GLADT,,,,Rád jsem pomohl.,Es war mir eine Freude dir zu Diensten zu sein,,,Un placer atenderte.,,Onneksi voin olla avuksi.,Ravi de vous avoir servi.,Szíves örömest segítek.,Felice di essere al servizio.,感謝する。,도와줄 수 있어서 영광이야.,Blij om van dienst te zijn.,"Cieszę się, że mogłem pomóc.",É um prazer serví-los.,,Mă bucur să fiu util.,Рад помочь., -"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.",,,"De acuerdo, aquí algunos consejos: No te cruces en el camino de los Cruzados: disparar rachas cortas del Fusil de Asalto lo mantendrá en el objetivo.",,"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 mischiarti ai Crociati: scattare a raffiche con il tuo fucile d'assalto ti tiene sul bersaglio.","オーライ、 +Glad to be of service.,TXT_RYES0_SCRIPT02_D6064_GLADT,,,,Rád jsem pomohl.,Es war mir eine Freude dir zu Diensten zu sein,,,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.,"Cieszę się, że mogłem pomóc.",É um prazer serví-los.,,Mă bucur să fiu util.,Рад помочь., +"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.",,,"De acuerdo, aquí algunos consejos: No te cruces en el camino de los Cruzados: disparar rachas cortas del Fusil de Asalto lo mantendrá en el objetivo.",,"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.","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.","Отлично, вот несколько советов: не попадайся под ноги крестоносцам. Из штурмовой винтовки лучше всего стрелять короткими очередями.", -Is that it?,TXT_RPLY0_SCRIPT02_D7580_ISTHA,,,,To je všechno?,War es das?,,,¿Eso es todo?,,Siinä kaikki?,C'est tout?,Ennyi?,Questo è?,そうなのか?,그게 답니까?,Is dat het?,To wszystko?,Só isso?,,Asta e?,И всё?, +Is that it?,TXT_RPLY0_SCRIPT02_D7580_ISTHA,,,,To je všechno?,War es das?,,,¿Eso es todo?,,Siinä kaikki?,C'est tout?,Ennyi?,Tutto qui?,そうなのか?,그게 답니까?,Is dat het?,To wszystko?,Só isso?,,Asta e?,И всё?, "Look, you'll learn more later.",TXT_RYES0_SCRIPT02_D7580_LOOKY,,,,"Hele, víc se toho naučíš pak.",Fürs Erste ja. Du wirst später noch mehr lernen.,,,"Mira, aprenderás más tarde.",,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.","Zobacz, później nauczysz się więcej.","Olha, você vai aprender mais depois.",,"Uite, o să afli mai multe mai târziu.","Позже узнаешь больше, хорошо?", -"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 lidské použití. Oh, mohu ti sehnat ještě něco?","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?",,,"Creo que puedo convertir un lanzallamas de uno de los cruzados para que un humano pueda utilizarlo. Oh, ¿Algo más que pueda 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 posso convertire un lanciafiamme da uno dei Crociati per essere usato da un umano. Oh, desideri qualcos'altro?","俺ならクルセイダー専用の火炎放射器を +"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?","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?",,,"Creo que puedo convertir un lanzallamas de uno de los cruzados para que un humano pueda utilizarlo. Oh, ¿Algo más que pueda 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?","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?","Думаю, я смогу приспособить огнемёт для ручного использования. А, ты что-то ещё хотел? ", Flamethrower.,TXT_RPLY0_SCRIPT02_D9096_FLAME,,,,Plamenomet.,Flammenwerfer,,,Lanzallamas.,,Liekinheitin.,Lance-flammes.,Lángszóró.,Lanciafiamme.,火炎放射器,화염방사기?,Vlammenwerper.,Miotacz Ognia,Lança-chamas.,,Aruncător de flăcări.,Огнемёт., -"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ě ji rozpal!","Ich wusste das würde funktionieren! Bitte sehr, probiere ihn mal aus!",,,"¡Sabía que eso funcionaría! Aquí tienes, ¡Dale un paseo!","¡Sabía que eso funcionaría! Aquí tienes, ¡Dale una vuelta!","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! Prendila e vai a provarla!,よくやってくれた! どうよ、このアツアツな子を!,"역시 잘 작동할 줄 알았어! 여기, 화염방사기야. 한번 놈들에게 사용해봐!","Ik wist dat dat zou werken! Alsjeblieft, neem haar mee voor een ritje!","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ă!","Я и не сомневался, что всё получится! Держи, испробуй его на ком-нибудь!", -"Listen, I can't make anything without the right parts!",TXT_RNO0_SCRIPT02_D9096_LISTE,,,,"Poslyš, bez těch správných komponent ti nic nesestavím!","Hör zu, ohne die richtigen Teile kann ich dir nichts machen!",,,"Escucha, ¡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 giusti pezzi!",部品が無ければ何も出来ない!,"이봐, 제대로 된 부품 없이는 아무 것도 할 수 없다고!","Luister, ik kan niets maken zonder de juiste onderdelen!","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!","Слушай, у меня нет нужных деталей!", +"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!","Ich wusste das würde funktionieren! Bitte sehr, probiere ihn mal aus!",,,"¡Sabía que eso funcionaría! Aquí tienes, ¡Dale un paseo!","¡Sabía que eso funcionaría! Aquí tienes, ¡Dale una vuelta!","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!","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ă!","Я и не сомневался, что всё получится! Держи, испробуй его на ком-нибудь!", +"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 zu, ohne die richtigen Teile kann ich dir nichts machen!",,,"Escucha, ¡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!","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!","Слушай, у меня нет нужных деталей!", Assault gun,TXT_RPLY1_SCRIPT02_D9096_ASSAU,,,,Útočnou pušku,Sturmgewehr,,,Fusil de Asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку, -"Well, here you go sir!",TXT_RYES1_SCRIPT02_D9096_WELLH,,,,"Tak tady máte, pane!","Alles klar, bitteschön!",,"Nu, jen, sinjoro!","Bien, ¡Aquí tiene, caballero!",,"Kas tässä, hyvä herra!","Voilà pour vous, monsieur!","Nos, parancsoljon!",Ecco qua signore!,ほら、毎度あり!,여기 대령이요!,"Nou, alsjeblieft, meneer!",Oto jest proszę pana!,"Bem, aqui está, senhor!",,"Poftiți, domnule!",Забирай!, -"Obviously, you can't afford that right now.",TXT_RNO1_SCRIPT02_D9096_OBVIO,,,,"Je nabíledni, že tohle si teď nemůžeš dovolit.",Offensichtlich kannst du dir das im Moment nicht leisten.,,,"Obviamente, no puedes adquirir esto 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 hai abbastanza soldi.",明らかに、今買える余裕は無い。,"당연하겠지만, 아직 가질 수가 없겠네.",Dat kunt je zich natuurlijk nu niet veroorloven.,"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.","Похоже, тебе это не по карману.", +"Well, here you go sir!",TXT_RYES1_SCRIPT02_D9096_WELLH,,,,"Tak tady máte, pane!","Alles klar, bitteschön!",,"Nu, jen, sinjoro!","Bien, ¡Aquí tiene, caballero!",,"Kas tässä, hyvä herra!","Voilà pour vous, monsieur!","Nos, parancsoljon!","Bene, ecco qua signore!",ほら、毎度あり!,여기 대령이요!,"Nou, alsjeblieft, meneer!",Oto jest proszę pana!,"Bem, aqui está, senhor!",,"Poftiți, domnule!",Забирай!, +"Obviously, you can't afford that right now.",TXT_RNO1_SCRIPT02_D9096_OBVIO,,,,Tu si teď opravdu nemůžeš dovolit.,Offensichtlich kannst du dir das im Moment nicht leisten.,,,"Obviamente, no puedes adquirir esto 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.,"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.","Похоже, тебе это не по карману.", Clip of bullets,TXT_RPLY2_SCRIPT02_D9096_CLIPO,,,,Zásobník nábojů,Gewehrmunition.,,,Cargador con balas,,Luotilipas,Chargeur de balles,Egy tár töltény.,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов, Thanks.,TXT_RYES2_SCRIPT02_D9096_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю., -"Come on, 10 gold.",TXT_RNO2_SCRIPT02_D9096_COMEO,,,,"No tak, je to deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 10 de oro.,,"Antaa tulla, 10 kolikkoa.","Allez, 10 pièces.","Rajta, 10 arnyat.","Avanti, 10 pezzi d'oro.",頼むぜ、10ゴールドだぞ。,"이봐, 그건 10 골드짜리라고.","Kom op, 10 goud.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", -Ammo box,TXT_RPLY3_SCRIPT02_D9096_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatole di munizioni,弾薬箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, +"Come on, 10 gold.",TXT_RNO2_SCRIPT02_D9096_COMEO,,,,"No tak, jen deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", +Ammo box,TXT_RPLY3_SCRIPT02_D9096_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,弾薬箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, Here's your ammo.,TXT_RYES3_SCRIPT02_D9096_HERES,,,,Tady je tvá munice.,Hier ist deine Munition.,,Jen via municio.,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약.,Hier is je munitie.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны., -Maybe some other time. Goodbye!,TXT_RNO3_SCRIPT02_D9096_MAYBE,,,,Možná někdy jindy. Nashledanou!,Vielleicht ein anderes mal. Auf Wiedersehen!,,,Tal vez en otra ocasión. ¡Adiós!,,Ehkä jokin toinen aika. Näkemiin!,"Peut être une autre fois, au revoir!",Talán majd valamikor máskor. Viszlát!,Forse qualche altra volta. Arrivederci!,またの機会に、じゃあな!,다음번에 돈을 챙기고 예기하자. 잘 가!,Misschien een andere keer. Tot ziens!,Może innym razem. Do widzenia!,Talvez outra hora. Até mais!,,Poate altădată. La revedere!,"Может, в другой раз. Пока!", +Maybe some other time. Goodbye!,TXT_RNO3_SCRIPT02_D9096_MAYBE,,,,Možná někdy jindy. Nashledanou!,Vielleicht ein anderes mal. Auf Wiedersehen!,,,Tal vez en otra ocasión. ¡Adiós!,,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!,Może innym razem. Do widzenia!,Talvez outra hora. Até mais!,,Poate altădată. La revedere!,"Может, в другой раз. Пока!", "Now that you have the flamethrower, is there anything else I can get you?",TXT_DLG_SCRIPT02_D10612_NOWTH,,,,"Teď když máš ten plamenomet, můžu pro tebe udělat něco jiného?","Jetzt wo du den Flammenwerfer hast, gibt es etwas anderes was ich dir besorgen kann?",,,"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?","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?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?", Assault gun,TXT_RPLY0_SCRIPT02_D10612_ASSAU,,,,Útočnou pušku,Sturmgewehr,,,Fusil de Asalto,,Rynnäkkökivääri,Fusil d'Assaut,Gépfegyver,Fucile d'assalto,アサルトガン,돌격소총,Aanvalswapen,Karabin Szturmowy,Fuzil de assalto,,Armă de asalt,Штурмовую винтовку, -Here you go.,TXT_RYES0_SCRIPT02_D10612_HEREY,,,,Tu máš.,Bitte sehr!,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Itt is van!,Ecco qua.,毎度あり。,여기 있어.,Alsjeblieft.,Proszę bardzo.,Aqui está.,,Poftiți.,Забирай!, +Here you go.,TXT_RYES0_SCRIPT02_D10612_HEREY,,,,Tu máš.,Bitte sehr!,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Itt is van!,Ecco a te.,毎度あり。,여기 있어.,Alsjeblieft.,Proszę bardzo.,Aqui está.,,Poftiți.,Забирай!, You can't afford that right now.,TXT_RNO0_SCRIPT02_D10612_YOUCA,,,,Tu si teď nemůžeš dovolit.,Das kannst du dir im Moment nicht leisten.,,,No puedes adquirir esto 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.,Nie możesz teraz tego kupić.,Você não pode comprar isso no momento.,,Nu-ți poți permite asta încă.,"Похоже, тебе это не по карману.", Clip of bullets,TXT_RPLY1_SCRIPT02_D10612_CLIPO,,,,Zásobník nábojů,Gewehrmunition.,,,Cargador con balas,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов, Thanks.,TXT_RYES1_SCRIPT02_D10612_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszi.,Grazie.,どうも。,고마워.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю., -"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D10612_COMEO,,,,"No tak, je to deset zlatých.","Komm schon, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", -Ammo box,TXT_RPLY2_SCRIPT02_D10612_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Boîte de balles,Töltényes doboz,Scatole di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, +"Come on, 10 gold.",TXT_RNO1_SCRIPT02_D10612_COMEO,,,,"No tak, jen deset zlatých.","Komm schon, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", +Ammo box,TXT_RPLY2_SCRIPT02_D10612_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Boîte de balles,Töltényes doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, Here's your ammo.,TXT_RYES2_SCRIPT02_D10612_HERES,,,,Tady je tvá munice.,Hier ist deine Munition.,,Jen via municio.,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a töltényed.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 네 탄약이야.,Hier is je munitie.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны., -Maybe some other time.,TXT_RNO2_SCRIPT02_D10612_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán Máskor.,Forse un'altra volta.,また後でな。,지금 말고. 아마도 나중에?,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", +Maybe some other time.,TXT_RNO2_SCRIPT02_D10612_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán Máskor.,Magari un'altra volta.,また後でな。,지금 말고. 아마도 나중에?,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", "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?","Jetzt wo du den Flammenwerfer hast, gibt es etwas anderes was ich dir besorgen kann?",,,"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?","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?","Ну, огнемёт у тебя теперь есть. Могу я ещё чем-нибудь помочь?", Clip of bullets,TXT_RPLY0_SCRIPT02_D12128_CLIPO,,,,Zásobník nábojů,Gewehrmunition.,,,Caja de balas,,Luotilipas,Chargeur de balles,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,Magazynek,Carregador de balas,,Cartuș de gloanțe,Обойму патронов, Thanks.,TXT_RYES0_SCRIPT02_D12128_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,どうも。,고맙네.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю., -"Come on, 10 gold.",TXT_RNO0_SCRIPT02_D12128_COMEO,,,,"No tak, je to deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", -Ammo box,TXT_RPLY1_SCRIPT02_D12128_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatole di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, +"Come on, 10 gold.",TXT_RNO0_SCRIPT02_D12128_COMEO,,,,"No tak, jen deset zlatých.","Na komm, 10 Gold.",,,¡Vamos! 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.","No weź, 10 monet.","Vamos lá, 10 de ouro.",,"Haide, 10 monezi de aur.","Ну же, 10 золотых.", +Ammo box,TXT_RPLY1_SCRIPT02_D12128_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de balas,,Ammuslaatikko,Bôite de balles,Lőszeres doboz.,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitie doos,Pudło z amunicją,Caixa de balas,,Cutie cu muniție,Коробку патронов, Here's your ammo.,TXT_RYES1_SCRIPT02_D12128_HERES,,,,Tady je tvá munice.,Hier ist deine Munition.,,Jen via municio.,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでアンタのブツだ。,여기 탄약이야.,Hier is je munitie.,Oto twoja amunicja.,Aqui está a sua munição.,,Poftiți muniția.,Вот твои патроны., -Maybe some other time.,TXT_RNO1_SCRIPT02_D12128_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes Mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Forse un'altra volta.,また後でな。,다음 번에 찾아와서 알려줘.,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", -Phosphor grenades,TXT_RPLY2_SCRIPT02_D12128_PHOSP,,,,Fosforečné granáty,Phosphorgranaten,,,Granadas de Fósforo,,Fosforikranaatteja,Grenades phosphoriques,Foszforgránátok,Granate al Fosforo.,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforowe granaty,Granadas de fósforo,,Grenade cu fosfor,Фосфорные гранаты, +Maybe some other time.,TXT_RNO1_SCRIPT02_D12128_MAYBE,,,,Možná někdy jindy.,Vielleicht ein anderes Mal.,,,Tal vez en otra ocasión.,,Ehkä joku toinen kerta.,Peut être une autre fois.,Talán majd máskor.,Magari un'altra volta.,また後でな。,다음 번에 찾아와서 알려줘.,Misschien een andere keer.,Może innym razem.,Talvez outra hora.,,Poate altădată.,"Может, в другой раз.", +Phosphor grenades,TXT_RPLY2_SCRIPT02_D12128_PHOSP,,,,Fosforové granáty,Phosphorgranaten,,,Granadas de Fósforo,,Fosforikranaatteja,Grenades phosphoriques,Foszforgránátok,Granate al Fosforo.,白リングレネード弾,소이 유탄,Fosforgranaten,Fosforowe granaty,Granadas de fósforo,,Grenade cu fosfor,Фосфорные гранаты, Thanks.,TXT_RYES2_SCRIPT02_D12128_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,どうも。,고마워.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Благодарю., You don't have enough,TXT_RNO2_SCRIPT02_D12128_YOUDO,,,,Nemáš u sebe dost.,Du hast nicht genug,,Vi ne havas sufiĉon.,No tienes suficiente,,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...,Nie wystarczy ci.,Você não tem o suficiente.,,Nu ai suficiente,Тебе не хватает на них., Poison bolts,TXT_RPLY3_SCRIPT02_D12128_POISO,,,,Otrávené šípy,Giftbolzen,,,Saetas envenenadas,,Myrkkynuolia,Carreaux Empoisonnés,Mérgezett nyilak,Frecce avvelenate.,ポイズンボルト,맹독 볼트,Giftige bouten,Zatrute bełty,Setas venenosas,,Bolțuri cu otravă,Отравленные болты, Worth every gold!,TXT_RYES3_SCRIPT02_D12128_WORTH,,,,Ty se vyplatí!,Jedes Goldstück wert!,,,¡Valen cada moneda de oro!,,Joka kolikon väärti!,Ca vaut son prix!,Minden aranyat megér,Ne vale la pena!,値段に合う価値だぜ!,아주 가치가 있는 것이지!,Elk goud waard!,Warte każdych pieniędzy!,Vale cada moeda de ouro!,,Merită fiecare bănuț!,Они того стоят!, -"Come on, 200 gold!",TXT_RNO3_SCRIPT02_D12128_COMEO,,,,"No tak, 200 zlatých!","Na komm, 200 Gold!",,,¡Vamos! 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!","No weź, 200 monet!","Vamos lá, 200 de ouro!",,"Haide, 200 monezi de aur!","Ну же, 200 золотых!", +"Come on, 200 gold!",TXT_RNO3_SCRIPT02_D12128_COMEO,,,,"No tak, 200 zlatých!","Na komm, 200 Gold!",,,¡Vamos! 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!","No weź, 200 monet!","Vamos lá, 200 de ouro!",,"Haide, 200 monezi de aur!","Ну же, 200 золотых!", 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,,,,"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!","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!",,,No puedo creer que me quedara con esta tarea. Dicen que algo maligno salió de esta compuerta de alcantarilla... ¡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!,"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!,"Не могу поверить, что застрял на дежурстве. Они говорят, что какая-то пакость поднимается из этого люка... и теперь я должен стоять тут и ждать, пока она не появится снова!", What gate?,TXT_RPLY0_SCRIPT02_D13644_WHATG,,,,Jaké brány?,Welches Tor?,,,¿Qué compuerta?,,Mikä luukku?,Quelle barrière?,Milyen Kapu?,Quale chiusa? ,何のゲートだ?,무슨 입구?,Welk hek?,Jakiej bramy?,Que comporta?,,Care poartă?,Какого люка?, The sewer overflow gate.,TXT_RYES0_SCRIPT02_D13644_THESE,,,,Odpadní přepadové brány.,Das Überlauftor der Kanalisation.,,,La compuerta de desagüe de 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.,Bramy do kanałów.,A comporta de transborda de esgoto.,,Poarta de revărsare.,Канализационного люка., -Hello friend. What can I get for you?,TXT_DLG_SCRIPT02_D15160_HELLO,,,,"Ahoj, příteli. Co pro tebe můžu udělat?","Hallo, Freund. Was darf es sein?",,,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 prenderti? ,どうも同士よ。何か必要か?,안녕하십니까. 뭘 드릴까요?,Hallo vriend. Wat kan ik voor je halen?,Witaj kolego. Co mogę dla ciebie zrobić?,Olá amigo. Como posso ajudá-lo?,,Salut prietene. Ce pot să-ți aduc?,Здравствуй. Что-нибудь интересует?, +Hello friend. What can I get for you?,TXT_DLG_SCRIPT02_D15160_HELLO,,,,"Zdravím, příteli. Co pro vás můžu udělat?","Hallo, Freund. Was darf es sein?",,,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?,Witaj kolego. Co mogę dla ciebie zrobić?,Olá amigo. Como posso ajudá-lo?,,Salut prietene. Ce pot să-ți aduc?,Здравствуй. Что-нибудь интересует?, Electric bolts,TXT_RPLY0_SCRIPT02_D15160_ELECT,,,,Elektrické šípy,Elektrische Bolzen,,,Virotes eléctricos,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты, -You got the electric bolts.,TXT_RYES0_SCRIPT02_D15160_YOUGO,,,,Tady máš své šípy.,Du hast die elektrischen Bolzen erhalten.,,,Obtuviste los virotes eléctricos.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Megkaptad az elektromos nyilakat.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 받았습니다.,Je hebt de elektrische bouten.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты., +You got the electric bolts.,TXT_RYES0_SCRIPT02_D15160_YOUGO,,,,Tady je máte.,Du hast die elektrischen Bolzen erhalten.,,,Obtuviste los virotes eléctricos.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Megkaptad az elektromos nyilakat.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 받았습니다.,Je hebt de elektrische bouten.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты., Ammo satchel,TXT_RPLY1_SCRIPT02_D15160_AMMOS,,,,Brašnu na munici,Munitionstasche,,,Bolsa de Municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres táska.,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец для боеприпасов, -No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D15160_NOYOU,,,,"Ne. Nemáš, co za ně chci!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,,No. ¡No tienes lo que quiero por las saetas eléctricas!,,"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!,"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!,Нет. У тебя нет денег на электрические болты!, -No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D16676_NOYOU,,,,"Ne. Nemáš, co za ně chci!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,,No. ¡No tienes lo que quiero por las saetas eléctricas!,,"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!,"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!,Нет. У тебя нет денег на электрические болты!, +No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D15160_NOYOU,,,,"Ne. Nemáte, co za ně chci!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,,No. ¡No tienes lo que quiero por las saetas eléctricas!,,"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!,"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!,Нет. У тебя нет денег на электрические болты!, +No. You don't have what I want for the electric bolts!,TXT_RNO0_SCRIPT02_D16676_NOYOU,,,,"Ne. Nemáte, co za ně chci!","Nein. Du hast nicht das, was ich für die elektrischen Pfeile haben möchte!",,,No. ¡No tienes lo que quiero por las saetas eléctricas!,,"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!,"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!,Нет. У тебя нет денег на электрические болты!, Thank you. Anything else?,TXT_RYES1_SCRIPT02_D15160_THANK,,,,Děkuji. Něco dalšího?,Danke. Sonst noch etwas?,,,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?",Köszönöm. Még valamit?,Grazie. Qualcos'altro? ,ありがとう。 他に何か?,감사합니다. 다른 건 없나요?,"Bedankt, nog iets anders?",Dziękuję. Coś jeszcze?,Agradeço. Mais alguma coisa?,,Mulțumesc. Mai dorești ceva?,Благодарю. Что-нибудь ещё?, -"You can't afford that, good day.",TXT_RNO1_SCRIPT02_D15160_YOUCA,,,,"To si nemůžeš dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag.,,,"No puedes adquirir esto, 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.","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ă.,У тебя не хватает денег. Всего доброго., -What can I get for you?,TXT_DLG_SCRIPT02_D16676_WHATC,,,,Co bych ti mohl sehnat?,Was darf es sein?,,,¿Qué puedo ofrecerte?,,Mitä saisi olla?,Que puis-je faire pour vous?,Mivel szolgáhatok?,Cosa ti offro? ,何か必要か?,"무엇을 구매하고 싶으신가요, 좋은 친구여?",Wat kan ik voor je halen?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Чем могу быть полезен?, +"You can't afford that, good day.",TXT_RNO1_SCRIPT02_D15160_YOUCA,,,,"To si nemůžete dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag.,,,"No puedes adquirir esto, 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.","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ă.,У тебя не хватает денег. Всего доброго., +What can I get for you?,TXT_DLG_SCRIPT02_D16676_WHATC,,,,Co vám mohu nabídnout?,Was darf es sein?,,,¿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?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot să-ți aduc?,Чем могу быть полезен?, Electric bolts,TXT_RPLY0_SCRIPT02_D16676_ELECT,,,,Elektrické šípy,Elektrische Bolzen,,,Saetas eléctricas,,Sähkönuolia,Carreaux électriques,Elektromos nyilak.,Dardi elettrificati ,エレクトリックボルト,전격 볼트,Elektrische bouten,Elektryczne bełty,Setas elétricas,,Bolțuri electrice,Электрические болты, -You got the electric bolts.,TXT_RYES0_SCRIPT02_D16676_YOUGO,,,,Tady máš své šípy.,Du hast die elektrischen Bolzen erhalten.,,,Obtuviste las saetas eléctricas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Elektromos nyilakra tettél szert.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 구매했습니다.,Je hebt de elektrische bouten.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты., -Ammo satchel,TXT_RPLY1_SCRIPT02_D16676_AMMOS,,,,Brašnu na munici,Munitionstasche,,,Bolsa de Municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres hátizsák,,弾薬鞄,탄약 배낭,Munitie tasje,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец для боеприпасов, -"Thank you, anything else?",TXT_RYES1_SCRIPT02_D16676_THANK,,,,Děkuji. Něco dalšího?,Danke. Sonst noch etwas?,,,Gracias. ¿Algo más?,,Kiitos. Jotain muuta?,"Merci, Autre chose?","Köszönöm, bármi mást?",,ありがとう。 他に何か?,감사합니다. 다른 건 더 없나요?,"Bedankt, nog iets anders?","Dziękuję, coś jeszcze?",Agradeço. Mais alguma coisa?,,"Mulțumesc, mai dorești ceva?",Благодарю. Что-нибудь ещё?, -"You can't afford that, good day to you!",TXT_RNO1_SCRIPT02_D16676_YOUCA,,,,"To si nemůžeš dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag!,,,"No puedes adquirir esto, 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!",,それを買える余裕は無い、また今度。,살 돈이 부족하신가요? 그럼 갈 길 가시길!,"Dat kunt u zich niet veroorloven, een goede dag voor je!","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!,У тебя не хватает денег. Всего доброго!, -Welcome. What may I show you?,TXT_DLG_SCRIPT02_D18192_WELCO,,,,Vítej. Co bych ti mohl nabídnout?,Willkommen. Was kann ich dirZeigen.,,,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä haluaisitte vilkaista?,"Bienvenue, que souhaitez vous?",Üdvözletem! Miben segíthetek?,,ようこそ、何を見ていきますか?,환영합니다! 보여드릴 게 아주 많아요.,Welkom. Wat kan ik je laten zien?,"Witaj. Co mogę ci pokazać? +You got the electric bolts.,TXT_RYES0_SCRIPT02_D16676_YOUGO,,,,Tady je máte.,Du hast die elektrischen Bolzen erhalten.,,,Obtuviste las saetas eléctricas.,,Sait sähkönuolet.,Vous recevez les carreaux électriques.,Elektromos nyilakra tettél szert.,Hai preso dei dardi elettrificati ,エレクトリックボルト 入手。,전격 볼트를 구매했습니다.,Je hebt de elektrische bouten.,Masz elektryczne bełty.,Você pegou as setas elétricas,,Ai ridicat bolțurile electrice.,Вот твои электрические болты., +Ammo satchel,TXT_RPLY1_SCRIPT02_D16676_AMMOS,,,,Brašnu na munici,Munitionstasche,,,Bolsa de Municiones,,Ammusreppu,Sacoche de Munitions,Lőszeres hátizsák,Sacca di munizioni ,弾薬鞄,탄약 배낭,Munitie tasje,Torba z amunicją,Mochila de munição,,Sacoșă cu muniție,Ранец для боеприпасов, +"Thank you, anything else?",TXT_RYES1_SCRIPT02_D16676_THANK,,,,Děkuji. Něco dalšího?,Danke. Sonst noch etwas?,,,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?","Dziękuję, coś jeszcze?",Agradeço. Mais alguma coisa?,,"Mulțumesc, mai dorești ceva?",Благодарю. Что-нибудь ещё?, +"You can't afford that, good day to you!",TXT_RNO1_SCRIPT02_D16676_YOUCA,,,,"To si nemůžete dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag!,,,"No puedes adquirir esto, 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!","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!,У тебя не хватает денег. Всего доброго!, +Welcome. What may I show you?,TXT_DLG_SCRIPT02_D18192_WELCO,,,,Vítejte. Co vám mohu nabídnout?,Willkommen. Was kann ich dirZeigen.,,,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä haluaisitte vilkaista?,"Bienvenue, que souhaitez vous?",Üdvözletem! Miben segíthetek?,Benvenuto. Cosa posso mostrarti?,ようこそ、何を見ていきますか?,환영합니다! 보여드릴 게 아주 많아요.,Welkom. Wat kan ik je laten zien?,"Witaj. Co mogę ci pokazać? ",Seja bem-vindo. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?, -Environmental suit,TXT_RPLY0_SCRIPT02_D18192_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje Ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,,耐環境スーツ,환경 방호복,Milieupak,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм, -"Well, here you are.",TXT_RYES0_SCRIPT02_D18192_WELLH,,,,"Tak, tady to je.",Bitte sehr.,,"Nu, jen.","Bien, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, tessék.",,はい、これをどうぞ。,"자, 여기있습니다.","Nou, hier ben je dan.","Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.", -I'm sorry but you don't have enough money for that.,TXT_RNO0_SCRIPT02_D18192_IMSOR,,,,"Promiň, ale na ten nemáš dost peněz.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,,"Lo siento, no tienes suficiente dinero para esto.",,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.",,すみませんが、貴方は十分なお金を持っていません。,"죄송합니다만, 그걸 사기엔 돈이 부족해 보입니다.","Het spijt me, maar daar heb je niet genoeg geld voor.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.",Sinto muito mas você não tem dinheiro o suficiente para isso.,,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.", -Leather armor,TXT_RPLY1_SCRIPT02_D18192_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de Cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,,レザーアーマー,가죽 갑옷,Leren pantser,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня, -Here you are.,TXT_RYES1_SCRIPT02_D18192_HEREY,,,,Tady máš.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék.,,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., -Perhaps some other time?,TXT_RNO1_SCRIPT02_D18192_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Quizás en otra ocasión?,,Ehkä joskus toiste?,Peut être une autre fois?,Esetleg talán máskor?,,また別の機会に?,아마 나중에 사야 할 것 같은데?,Misschien een andere keer?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?", -Metal armor,TXT_RPLY2_SCRIPT02_D18192_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de Metal,,Metallihaarniska,Armure en Métal,Fémpáncél,,メタルアーマー,강철 갑옷,Metalen harnas,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня, -Wear it in good health.,TXT_RYES2_SCRIPT02_D18192_WEARI,,,,Nes ho ve zdraví.,Trage sie mit Stolz.,,,Úsala con buena salud.,,Kaikin voimin pukeutukaa.,Portez la en bonne santé.,Viseld jó egészséggel!,,着ると安心しますよ。,건강하게 입으세요.,Draag het in goede gezondheid.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье., -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!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,,"¡Vuelve cuando puedas comprar algo, patán! ",,"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ó!",,余裕がある時にまたどうぞ!,뭔가를 살 여유가 있을 때 오세요!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,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ă!","Вернёшься, когда поднакопишь на то, что хочешь!", -Welcome. What may I show you?,TXT_DLG_SCRIPT02_D19708_WELCO,,,,Vítej. Co bych ti mohl nabídnout?,Willkommen. Was kann ich dir zeigen.,,,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä haluaisitte vilkaista?,"Bienvenue, que souhaitez vous?","Üdvözlet, mire volnál kíváncsi?",,ようこそ、何をお探しで?,어서 오십시오. 어떤 걸 보여드릴까요?,Welkom. Wat kan ik je laten zien?,"Witaj. Co mogę ci pokazać? +Environmental suit,TXT_RPLY0_SCRIPT02_D18192_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje Ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Milieupak,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм, +"Well, here you are.",TXT_RYES0_SCRIPT02_D18192_WELLH,,,,"Tak, tady to je.",Bitte sehr.,,"Nu, jen.","Bien, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, tessék.","Bene, ecco a te.",はい、これをどうぞ。,"자, 여기있습니다.","Nou, hier ben je dan.","Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.", +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.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,,"Lo siento, no tienes suficiente dinero para esto.",,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.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.",Sinto muito mas você não tem dinheiro o suficiente para isso.,,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.", +Leather armor,TXT_RPLY1_SCRIPT02_D18192_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de Cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren pantser,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня, +Here you are.,TXT_RYES1_SCRIPT02_D18192_HEREY,,,,Tady máte.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék.,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., +Perhaps some other time?,TXT_RNO1_SCRIPT02_D18192_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Quizás 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?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?", +Metal armor,TXT_RPLY2_SCRIPT02_D18192_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de Metal,,Metallihaarniska,Armure en Métal,Fémpáncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня, +Wear it in good health.,TXT_RYES2_SCRIPT02_D18192_WEARI,,,,Noste jej ve zdraví.,Trage sie mit Stolz.,,,Úsala con buena salud.,,Kaikin voimin pukeutukaa.,Portez la en bonne santé.,Viseld jó egészséggel!,Che possa esserti utile!,着ると安心しますよ。,건강하게 입으세요.,Draag het in goede gezondheid.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье., +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!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,,"¡Vuelve cuando puedas comprar algo, patán! ",,"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!,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ă!","Вернёшься, когда поднакопишь на то, что хочешь!", +Welcome. What may I show you?,TXT_DLG_SCRIPT02_D19708_WELCO,,,,Vítejte. Co vám mohu nabídnout?,Willkommen. Was kann ich dir zeigen.,,,Bienvenido. ¿Qué puedo mostrarte?,,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?,"Witaj. Co mogę ci pokazać? ",Seja bem-vindo. O que posso te mostrar?,,Bun venit. Ce aș putea să-ți arăt?,Здравствуй. Что-нибудь интересует?, -Environmental suit,TXT_RPLY0_SCRIPT02_D19708_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje Ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,,耐環境スーツ,환경 방호복,Beschermend Pak,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм, -"Well, here you are.",TXT_RYES0_SCRIPT02_D19708_WELLH,,,,"Tak, tady to je.",Bitte sehr.,,"Nu, jen.","Bien, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, íme.",,では、これをどうぞ。,"자, 여기 있습니다.","Nou, hier ben je dan.","Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.", -I'm sorry but you don't have enough money for that.,TXT_RNO0_SCRIPT02_D19708_IMSOR,,,,"Promiň, ale na ten nemáš dost peněz.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,,"Lo siento, no tienes suficiente dinero para esto.",,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.",,すみませんが、貴方は十分なお金を持っていません。,"미안하지만, 구매하기 위한 돈이 부족하신 것 같군요.","Het spijt me, maar daar heb je niet genoeg geld voor.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.",Sinto muito mas você não tem dinheiro o suficiente para isso.,,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.", -Leather armor,TXT_RPLY1_SCRIPT02_D19708_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de Cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,,レザーアーマー,가죽 갑옷,Leren harnas,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня, -Here you are.,TXT_RYES1_SCRIPT02_D19708_HEREY,,,,Tady máš.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék,,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., -Perhaps some other time?,TXT_RNO1_SCRIPT02_D19708_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Quizás en otra ocasión?,,Ehkä joskus toiste?,Peut être une autre fois?,Talán majd máskor?,,また別の機会に?,나중에 돈을 모아서 구매하세요.,Misschien een andere keer?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?", -Metal armor,TXT_RPLY2_SCRIPT02_D19708_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de Metal,,Metallihaarniska,Armure en Métal,Fém páncél,,メタルアーマー,강철 갑옷,Metalen harnas,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня, -Wear it in good health.,TXT_RYES2_SCRIPT02_D19708_WEARI,,,,Nes ho ve zdraví.,Trage sie mit Stolz.,,,Úsala con buena salud.,,Käyttäkää hyvällä omallatunnolla.,Portez la en bonne santé.,Viseld jó egészséggel!,,着ると安心しますよ。,믿고 입으셔도 됩니다.,Draag het in goede gezondheid.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье., -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!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,,"¡Vuelve cuando puedas comprar algo, patán! ",,"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ó!",,余裕がある時にまたどうぞ!,이런 거래는 못 하겠습니다. 돈을 모아서 다시 찾아오시길!,Kom terug wanneer je het je kunt veroorloven om iets te kopen wat je louteren kunt!,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ă!","Вернёшься, когда поднакопишь на то, что хочешь!", -How may I assist you?,TXT_DLG_SCRIPT02_D21224_HOWMA,,,,Jak ti mohu pomoci?,Wie kann ich dir helfen?,,Kiel mi rajtas asisti vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,,何かお困りですか?,제가 어떻게 도와드릴까요?,Hoe kan ik u helpen?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce vă pot ajuta?,Чем могу помочь?, -Med patch,TXT_RPLY0_SCRIPT02_D21224_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche Médico,,Sidekääre,Pansement,Ragtapasz,,医薬パッチ,의료 붕대,Med-patch,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами, -Here's your patch.,TXT_RYES0_SCRIPT02_D21224_HERES,,,,Tady je tvůj obvaz.,Hier ist deine Bandage,,,Aquí tienes tu parche.,,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod,,これをどうぞ。,의료 붕대 여깄습니다.,Hier is je patch.,Oto twój bandaż.,Aqui está sua compressa,,Poftiți trusa.,Вот они., -You need 10 gold for that.,TXT_RNO0_SCRIPT02_D21224_YOUNE,,,,Na ty potřebuješ deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitarás 10 de oro para esto.,,Siihen tarvitset 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 Aranyra lesz szükséged ehhez.,,10 ゴールド必要です。,10 골드가 필요합니다.,Daar heb je 10 goud voor nodig.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых., -Medical kit,TXT_RPLY1_SCRIPT02_D21224_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit Médico,,Lääkintälaukku,Kit médical,Elsősegély készlet,,医療用キット,구급 키트,Medische kit,Apteczka,Kit médico.,,Kit de Prim-Ajutor,Аптечкой, -Thank you.,TXT_RYES1_SCRIPT02_D21224_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,,ありがとうございます。,이용 감사드려요.,Bedankt.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо., -"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.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.",,譲渡したい所ですが、25 ゴールド必要です。,"주고 싶지만, 이것의 가격은 25 골드입니다.","Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","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 золотых.", -Field surgery kit,TXT_RPLY2_SCRIPT02_D21224_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit Quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,,手術キット,수술 키트,Veld chirurgie kit,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплектом, -There you go. Take care now.,TXT_RYES2_SCRIPT02_D21224_THERE,,,,Tady máš. Buď opatrný.,Bitte schön. Mach's gut.,,Jen. Prizorgu nun.,Aquí tienes. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,"Tessék, minden jót!",,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!, -"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D21224_WELLM,,,,"No, možná by sis mohl spíš dovolit nějaké obvazy?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,,"Bien, ¿Quizás te alcance para algunos parches médicos?",,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?,,ところで、医薬パッチを買う余裕はありますか?,"글쎄요, 아마 의료 붕대 정돈 살 수 있을걸요?","Nou ja, misschien kunt je zich wat med-patches veroorloven?","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?","Тогда, может быть, купишь несколько бинтов?", -"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,,,,"Doufám, že Macil ví, co dělá. Jestli Řád zjistí, že pomáhám Frontě, jsem mrtvý... Ne, že by tě to mělo trápit. Medik Fronty mi pro tebe dal vylepšovací čip, jsi připravený?","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?",,,"Espero que Macil sepa lo que está haciendo. Si la Orden descubre que ayudo al Frente, estoy muerto... Tampoco es que te importe nada. El médico del Frente me dio un chip 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?",,"マシルの行いが正しければ良いですが。 +Environmental suit,TXT_RPLY0_SCRIPT02_D19708_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje Ambiental,,Ympäristösuojapuku,Combinaison hazmat,Természetálló öltözet,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,Skafander Ochronny,Traje de proteção,,Costum de protecție,Защитный костюм, +"Well, here you are.",TXT_RYES0_SCRIPT02_D19708_WELLH,,,,"Tak, tady to je.",Bitte sehr.,,"Nu, jen.","Bien, aquí tienes.",,"Kas tässä, olkaa hyvä.",Voilà pour vous.,"Nos, íme.","Bene, ecco a te.",では、これをどうぞ。,"자, 여기 있습니다.","Nou, hier ben je dan.","Proszę, masz.","Muito bem, aqui está.",,Poftiți.,"Хорошо, бери.", +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.","Es tut mir Leid, aber du hast nicht genug Geld dabei.",,,"Lo siento, no tienes suficiente dinero para esto.",,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.","Przepraszam, ale nie masz wystarczająco dużo monet, aby to kupić.",Sinto muito mas você não tem dinheiro o suficiente para isso.,,"Îmi pare rău, dar nu ai suficienți bani pentru asta.","Извини, но у тебя не хватает денег.", +Leather armor,TXT_RPLY1_SCRIPT02_D19708_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de Cuero,,Nahkasuojus,Armure en cuir,Bőr páncél,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,Skórzany Pancerz,Armadura de couro,,Armură din piele,Кожаная броня, +Here you are.,TXT_RYES1_SCRIPT02_D19708_HEREY,,,,Tady máte.,Bitte sehr.,,Jen.,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Tessék,Ecco qua.,これをどうぞ。,여기 있습니다.,Hier ben je dan.,Proszę bardzo.,Aqui está.,,Poftiți.,Держи., +Perhaps some other time?,TXT_RNO1_SCRIPT02_D19708_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Quizás 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?,Może innym razem?,Talvez uma outra hora?,,Poate altădată?,"Может, в следующий раз?", +Metal armor,TXT_RPLY2_SCRIPT02_D19708_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de Metal,,Metallihaarniska,Armure en Métal,Fém páncél,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,Metalowy Pancerz,Armadura de metal,,Armură din metal,Металлическая броня, +Wear it in good health.,TXT_RYES2_SCRIPT02_D19708_WEARI,,,,Noste jej ve zdraví.,Trage sie mit Stolz.,,,Úsala con buena salud.,,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.,Bądź zdrów nosząc go.,Vista ela com orgulho.,,Să o porți sănătos.,Носи на здоровье., +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!","Komm zurück wenn du dir etwas leisten kannst, du Rüpel!",,,"¡Vuelve cuando puedas comprar algo, patán! ",,"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!,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ă!","Вернёшься, когда поднакопишь на то, что хочешь!", +How may I assist you?,TXT_DLG_SCRIPT02_D21224_HOWMA,,,,Jak vám mohu pomoci?,Wie kann ich dir helfen?,,Kiel mi rajtas asisti 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?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce vă pot ajuta?,Чем могу помочь?, +Med patch,TXT_RPLY0_SCRIPT02_D21224_MEDPA,,,,Obvaz,Medizinische Bandage,,,Parche Médico,,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами, +Here's your patch.,TXT_RYES0_SCRIPT02_D21224_HERES,,,,Jeden obvaz.,Hier ist deine Bandage,,,Aquí tienes tu parche.,,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod,Ecco le bende.,これをどうぞ。,의료 붕대 여깄습니다.,Hier is je patch.,Oto twój bandaż.,Aqui está sua compressa,,Poftiți trusa.,Вот они., +You need 10 gold for that.,TXT_RNO0_SCRIPT02_D21224_YOUNE,,,,Na ten potřebujete deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitarás 10 de oro para esto.,,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.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых., +Medical kit,TXT_RPLY1_SCRIPT02_D21224_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit Médico,,Lääkintälaukku,Kit médical,Elsősegély készlet,Kit medico,医療用キット,구급 키트,Medische kit,Apteczka,Kit médico.,,Kit de Prim-Ajutor,Аптечкой, +Thank you.,TXT_RYES1_SCRIPT02_D21224_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm,Grazie.,ありがとうございます。,이용 감사드려요.,Bedankt.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо., +"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.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.","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 золотых.", +Field surgery kit,TXT_RPLY2_SCRIPT02_D21224_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit Quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплектом, +There you go. Take care now.,TXT_RYES2_SCRIPT02_D21224_THERE,,,,Tady máte. Buďte opatrný.,Bitte schön. Mach's gut.,,Jen. Prizorgu nun.,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.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!, +"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D21224_WELLM,,,,"No, spíš byste si mohl dovolit nějaké obvazy?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,,"Bien, ¿Quizás te alcance para algunos parches médicos?",,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?","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?","Тогда, может быть, купишь несколько бинтов?", +"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,,,,"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?","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?",,,"Espero que Macil sepa lo que está haciendo. Si la Orden descubre que ayudo al Frente, estoy muerto... Tampoco es que te importe nada. El médico del Frente me dio un chip 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?","マシルの行いが正しければ良いですが。 私がフロントを援助しているとオーダーが 知ったら、私は...これは貴方には関係無いか。 フロントのメディックが貴方へ @@ -8547,220 +8543,220 @@ There you go. Take care now.,TXT_RYES2_SCRIPT02_D21224_THERE,,,,Tady máš. Buď 装着しますか? ",마실 사령관님이 하는 일이 무엇인지 알고 있기를... 만약 오더가 내가 프론트를 위해 일한다는 걸 눈치챈다면 절 죽일 거예요. 물론 당신이 알 바는 아니지만. 프론트 의무관님이 업그레이드 칩을 당신에게 이식하라고 여기까지 가져왔더군요. 준비되셨습니까?,"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?","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?","Надеюсь, Мэйсил знает, что делает. Если Орден обнаружит, что я помогаю повстанцам, я не жилец... хотя тебе-то какое дело. Медик Сопротивления передал мне этот чип для тебя. Ты готов? ", -"Yes, I'm ready.",TXT_RPLY0_SCRIPT02_D22740_YESIM,,,,"Ano, jsem připravený.","Ja, ich bin bereit.",,"Jes, mi pretas.","Si, estoy listo.",,"Kyllä, olen valmis.","Oui, je suis prêt.","Igen, készen állok.",,ああ、準備良しだ。,"좋아요, 준비 됐습니다.","Ja, ik ben er klaar voor.","Tak, jestem gotowy.","Sim, estou preparado.",,"Da, sunt pregătit.","Да, готов.", -"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.","Nun dann, das wird nicht mal eine Sekunde dauern. So, bereits erledigt.",,,"Bueno entonces. Esto no tomará sino un segundo. Bien, hecho.",,"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.",,それでは、これに時間は掛かりません。はい、完了しました。,"그럼 잠깐이면 됩니다. 자, 다 됐어요.","Nou dan, dit duurt maar een seconde. Daar, al klaar.","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.","Хорошо. Секундочку... Всё, готово.", -How may I assist you?,TXT_DLG_SCRIPT02_D24256_HOWMA,,,,Jak ti mohu pomoci?,Wie kann ich dir helfen?,,Kiel mi rajtas asisti vin?,¿Cómo puedo ayudarte?,,Kuinka voin olla avuksi?,Comment puis-je vous assister?,Miben segíthetek?,,何かお困りですか?,어떻게 도와드릴까요?,Hoe kan ik je helpen?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce vă pot ajuta?,Чем могу тебе помочь?, -Med patch,TXT_RPLY0_SCRIPT02_D24256_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche Médico,,Sidekääre,Pansement,Ragtapasz,,医薬パッチ,의료 붕대,Med-patch,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами, -Here's your patch.,TXT_RYES0_SCRIPT02_D24256_HERES,,,,Tady je tvůj obvaz.,Hier ist deine Bandage,,,Aquí tienes tu parche.,,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod.,,これをどうぞ。,여기 의료 붕대입니다.,Hier is je patch.,Oto twój bandaż.,Aqui está sua compressa,,Poftiți trusa.,Вот они., -You need 10 gold for that.,TXT_RNO0_SCRIPT02_D24256_YOUNE,,,,Na ty potřebuješ deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitarás 10 de oro para esto.,,Tarvitset siihen 10 kolikkoa.,Il vous faut 10 pièces pour cela.,10 aranyra van szükséged ehhez.,,10 ゴールド必要です。,10 골드가 필요한데.,Daar heb je 10 goud voor nodig.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых., -Medical kit,TXT_RPLY1_SCRIPT02_D24256_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit Médico,,Lääkintälaukku,Kit médical,Orvosi csomag.,,医療用キット,구급 키트,Medische kit,Apteczka,Kit médico.,,Kit de Prim-Ajutor,Аптечкой, -Thank you.,TXT_RYES1_SCRIPT02_D24256_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm.,,ありがとうございます。,또 오세요.,Bedankt.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо., -"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.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.",,譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있다면 이건 당신 것인데 말이죠.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.","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 золотых.", -Field surgery kit,TXT_RPLY2_SCRIPT02_D24256_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit Quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,,手術キット,수술 키트,Veld chirurgie kit,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплект, -There you go. Take care now.,TXT_RYES2_SCRIPT02_D24256_THERE,,,,Tady máš. Buď opatrný.,Bitte schön. Mach's gut.,,Jen. Prizorgu nun.,Aquí Tienes. Cuídate.,,Olkaa hyvä. Pitäkää itsestänne huoli.,Voilà pour vous. Faites attention à vous maintenant.,Parancsolj! Aztán vigyázz magadra!,,こちらになります、お気をつけて。,여기 있습니다. 잘 쓰세요.,Daar ga je. Pas goed op jezelf.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!, -"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D24256_WELLM,,,,"No, možná by sis mohl spíš dovolit nějaké obvazy?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,,"Bien, ¿Quizás te alcance para algunos parches médicos?",,Olisiko teillä ehkä varaa sidekääreisiin?,"Eh bien, peut être que vous pouvez vous acheter quelques pansements?","Nos, talán tellik pár ragtapaszra is?",,ところで、医薬パッチを買う余裕はありますか?,글쎄요... 의료 붕대는 어떻습니까?,"Nou ja, misschien kunt je zich wat med-patches veroorloven?","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?","Тогда, может быть, купишь несколько бинтов?", -"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,,,,"Vítej, cizinče, tebe jsem tu ještě neviděl. Tady je drobná rada na začátek grátis: Být tebou, byl bych opatrný. Řád netoleruje svobodnou vůli a jejich spravedlnost je hbitá. ","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.",,,"Hola extranjero, no te he visto por aquí antes. Déjame darte 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áttalakm ég itt a környéken. Had 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.",,"どうも余所者、この辺では見かけない顔だな。 +"Yes, I'm ready.",TXT_RPLY0_SCRIPT02_D22740_YESIM,,,,"Ano, jsem připravený.","Ja, ich bin bereit.",,"Jes, mi pretas.","Si, estoy listo.",,"Kyllä, olen valmis.","Oui, je suis prêt.","Igen, készen állok.","Sì, sono pronto.",ああ、準備良しだ。,"좋아요, 준비 됐습니다.","Ja, ik ben er klaar voor.","Tak, jestem gotowy.","Sim, estou preparado.",,"Da, sunt pregătit.","Да, готов.", +"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.","Nun dann, das wird nicht mal eine Sekunde dauern. So, bereits erledigt.",,,"Bueno entonces. Esto no tomará sino un segundo. Bien, hecho.",,"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.","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.","Хорошо. Секундочку... Всё, готово.", +How may I assist you?,TXT_DLG_SCRIPT02_D24256_HOWMA,,,,Jak vám mohu pomoci?,Wie kann ich dir helfen?,,Kiel mi rajtas asisti 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?,Jak mogę ci pomóc?,Como posso ajudá-lo?,,Cu ce vă pot ajuta?,Чем могу тебе помочь?, +Med patch,TXT_RPLY0_SCRIPT02_D24256_MEDPA,,,,Obvaz,Medizinische Bandage,,,Parche Médico,,Sidekääre,Pansement,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,Bandaż,Compressa médica,,Trusă de Prim-Ajutor,Бинтами, +Here's your patch.,TXT_RYES0_SCRIPT02_D24256_HERES,,,,Jeden obvaz.,Hier ist deine Bandage,,,Aquí tienes tu parche.,,Tässä kääreenne.,Voilà votre pansement.,Itt a tapaszod.,Ecco le bende.,これをどうぞ。,여기 의료 붕대입니다.,Hier is je patch.,Oto twój bandaż.,Aqui está sua compressa,,Poftiți trusa.,Вот они., +You need 10 gold for that.,TXT_RNO0_SCRIPT02_D24256_YOUNE,,,,Na ten potřebujete deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitarás 10 de oro para esto.,,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.,Potrzebujesz 10 monet aby to kupić.,Você precisa de 10 de ouro pra isso.,,Ai nevoie de 10 monezi de aur pentru asta.,Тебе не хватает 10 золотых., +Medical kit,TXT_RPLY1_SCRIPT02_D24256_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit Médico,,Lääkintälaukku,Kit médical,Orvosi csomag.,Kit medico,医療用キット,구급 키트,Medische kit,Apteczka,Kit médico.,,Kit de Prim-Ajutor,Аптечкой, +Thank you.,TXT_RYES1_SCRIPT02_D24256_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Köszönöm.,Grazie.,ありがとうございます。,또 오세요.,Bedankt.,Dziękuję.,Agradeço.,,Mulțumesc.,Спасибо., +"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.","Ich wünschte ich könnte sie weggeben, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.","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 золотых.", +Field surgery kit,TXT_RPLY2_SCRIPT02_D24256_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit Quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,Polowy zestaw chirurga,Kit de cirurgia,,Trusă de chirurgie de teren,Медкомплект, +There you go. Take care now.,TXT_RYES2_SCRIPT02_D24256_THERE,,,,Tady máte. Buďte opatrný.,Bitte schön. Mach's gut.,,Jen. Prizorgu nun.,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.,Proszę bardzo. Trzymaj się.,Aqui está. Se cuida.,,Poftiți. Aveți grijă.,Пожалуйста. Береги себя!, +"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT02_D24256_WELLM,,,,"No, spíš byste si mohl dovolit nějaké obvazy?","Nun, vielleicht kannst du dir ein paar medizinische Bandagen leisten?",,,"Bien, ¿Quizás te alcance para algunos parches médicos?",,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?","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?","Тогда, может быть, купишь несколько бинтов?", +"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,,,,"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á. ","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.",,,"Hola extranjero, no te he visto por aquí antes. Déjame darte 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.","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ă.","Привет, незнакомец. Что-то я не видел тебя тут раньше. Позволь дать тебе бесплатный совет: я на твоём месте был бы поосторожнее. Орден не терпит неповиновения, и они быстры на правосудие.", -What's the word?,TXT_RPLY0_SCRIPT02_D25772_WHATS,,,,Nějaké zvěsti?,Was erzählt man sich so?,,Kio estas la vorto?,¿Qué se dice por aquí?,,Mikä on päivän sana?,C'est quoi la rumeur?,Mi a hír?,,他には?,무슨 뜻이죠?,Wat is het woord?,Jakieś wieści?,Quais são as últimas?,,Ai vreo veste?,Есть новости?, -The word is... The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT02_D25772_THEWO,,,,Zvěsti jsou... že stoky ukrývají víc než jen krysy a roboty.,"Man erzählt sich, dass die Kanalisation mehr als Ratten und Roboter zu bieten hat.",,,Se dice que... Las alcantarillas albergan 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.,,他は...下水道には鼠やロボが沢山だ。,"무슨 말이냐 하면, 하수도 안에는 시궁쥐만 있는 게 아니라 로봇들도 숨어 있다는 거지.",Het woord is.... De riolen bevatten meer dan alleen ratten en robots.,"Wieści są takie, że... kanały skrywają coś więcej niż tylko szczury i roboty.",As ultimas 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.,В канализации водятся не только крысы и роботы., -What can I do for you now?,TXT_DLG_SCRIPT02_D27288_WHATC,,,,Co pro tebe můžu udělat teď?,Was kann ich jetzt für dich tun?,,,¿Qué puedo hacer por ti?,,"No niin, miten voin olla teille avuksi?",Que puis-je faire pour vous?,Mit tehetek ma Önért?,,何か用か?,이제 자네에게 무엇을 해드릴까?,Wat kan ik nu voor je doen?,Co mogę dla ciebie zrobić?,O que posso fazer por você agora?,,Cu ce te mai pot ajuta?,Тебе что-нибудь нужно?, -More info.,TXT_RPLY0_SCRIPT02_D27288_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Muuta tietoa.,Plus d'infos.,Több információt.,,話のネタ。,더 많은 정보를 주세요.,Meer info.,Więcej informacji.,Mais informações.,,Mai multe informații.,Расскажи больше, -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í.","Der Gouverneur ist eine einfache Erinnerung daran, das wir keine freien Menschen mehr sind.",,,El gobernador es un simple recordatorio de que ya no somos personas 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.",,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 우리들이 자유롭게 남들을 도울 수 없는 이유 중 하나이기도 하다네.,De gouverneur herinnert ons er eenvoudigweg aan dat we geen vrije mensen meer zijn.,"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.,"Губернатор — живое напоминание, что мы больше не свободные люди.", -Come back when you get some gold.,TXT_RNO0_SCRIPT02_D27288_COMEB,,,,"Vrať se, až budeš mít trochu zlata.","Komm zurück, wenn du etwas Gold hast.",,,Vuelve cuando hayas obtenido algo de 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.",,銭を一杯分持って戻ってきな。,골드가 더 있다면 더 알려주지.,Kom terug als je wat goud krijgt.,Wróć kiedy będziesz miał więcej monet.,Volte quando tiver ouro.,,Revin-o când ai niște aur.,"Возвращайся, когда у тебя будет золото.", -"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.","Hmm, du stellst aber ziemlich viele Fragen für jemand der nicht versucht zu sterben. Lass dich nicht umbringen, oder schlimmeres.",,,"Bueno, estás haciendo muchas preguntas para ser alguien que no está tratando de morir. Asegúrate 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.",,"所で、アンタは死に行かない人達に +What's the word?,TXT_RPLY0_SCRIPT02_D25772_WHATS,,,,Nějaké zvěsti?,Was erzählt man sich so?,,Kio estas la vorto?,¿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?,Jakieś wieści?,Quais são as últimas?,,Ai vreo veste?,Есть новости?, +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.,"Man erzählt sich, dass die Kanalisation mehr als Ratten und Roboter zu bieten hat.",,,Se dice que... Las alcantarillas albergan 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.,"Wieści są takie, że... kanały skrywają coś więcej niż tylko szczury i roboty.",As ultimas 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.,В канализации водятся не только крысы и роботы., +What can I do for you now?,TXT_DLG_SCRIPT02_D27288_WHATC,,,,Co pro vás můžu udělat teď?,Was kann ich jetzt für dich tun?,,,¿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?,Co mogę dla ciebie zrobić?,O que posso fazer por você agora?,,Cu ce te mai pot ajuta?,Тебе что-нибудь нужно?, +More info.,TXT_RPLY0_SCRIPT02_D27288_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Muuta tietoa.,Plus d'infos.,Több információt.,Altre informazioni.,話のネタ。,더 많은 정보를 주세요.,Meer info.,Więcej informacji.,Mais informações.,,Mai multe informații.,Расскажи больше, +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í.","Der Gouverneur ist eine einfache Erinnerung daran, das wir keine freien Menschen mehr sind.",,,El gobernador es un simple recordatorio de que ya no somos personas 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.,"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.,"Губернатор — живое напоминание, что мы больше не свободные люди.", +Come back when you get some gold.,TXT_RNO0_SCRIPT02_D27288_COMEB,,,,"Vrať se, až budeš mít trochu zlata.","Komm zurück, wenn du etwas Gold hast.",,,Vuelve cuando hayas obtenido algo de 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.,Wróć kiedy będziesz miał więcej monet.,Volte quando tiver ouro.,,Revin-o când ai niște aur.,"Возвращайся, когда у тебя будет золото.", +"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.","Hmm, du stellst aber ziemlich viele Fragen für jemand der nicht versucht zu sterben. Lass dich nicht umbringen, oder schlimmeres.",,,"Bueno, estás haciendo muchas preguntas para ser alguien que no está tratando de morir. Asegúrate 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.","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.","Ты задаёшь слишком много вопросов для того, кто не хочет сдохнуть. Перед тем, как выйти отсюда, проверь своё оружие.", -More info.,TXT_RPLY0_SCRIPT02_D28804_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Muuta tietoa.,Plus d'infos.,Több infót.,,話のネタ。,정보를 좀 더 알려주시오.,Meer info.,Więcej informacji.,Mais informações.,,Mai multe informații.,Говори дальше, -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á.",An dem Orden ist mehr dran als man auf den ersten Blick denkt.,,,Hay más de la Orden de lo que parece.,,"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.",,オーダーは見えてる以上に強大だ。,오더의 뒤에는 더 많은 것들이 숨겨져 있다네. 비밀 같은 것들 말일세.,De Orde heeft meer te bieden dan je op het eerste gezicht zou denken.,"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.,"Орден — нечто большее, чем кажется.", -We'll talk when you get gold!,TXT_RNO0_SCRIPT02_D28804_WELLT,,,,"Popovídáme si, když budeš mít zlato!","Wir werden reden, wenn du Gold hast!",,,¡Hablaremos cuando traigas oro!,,"Puhutaan, kun sinulla on kultaa.",On parlera quand tu auras des sous!,"Majd beszélünk, ha lesz aranyad.",,銭を持ってたら話すさ!,골드를 더 가져오면 의논을 시작해보지.,We praten wel als je goud krijgt!,Pomówimy jeśli masz złoto.,Conversaremos quando você tiver ouro!,,Vorbim când aduci aur!,"Поговорим, когда принесешь золото!", -"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.","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.",,,Ya está amigo. El pozo del conocimiento se ha secado. De todas formas te he dicho más de lo que debería. Buena 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.",,"これはこれは親友、心得の瓶は切らしてるぞ。 +More info.,TXT_RPLY0_SCRIPT02_D28804_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Muuta tietoa.,Plus d'infos.,Több infót.,Altre informazioni.,話のネタ。,정보를 좀 더 알려주시오.,Meer info.,Więcej informacji.,Mais informações.,,Mai multe informații.,Говори дальше, +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á.",An dem Orden ist mehr dran als man auf den ersten Blick denkt.,,,Hay más de la Orden de lo que parece.,,"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.,"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.,"Орден — нечто большее, чем кажется.", +We'll talk when you get gold!,TXT_RNO0_SCRIPT02_D28804_WELLT,,,,"Popovídáme si, když budeš mít zlato!","Wir werden reden, wenn du Gold hast!",,,¡Hablaremos 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!,Pomówimy jeśli masz złoto.,Conversaremos quando você tiver ouro!,,Vorbim când aduci aur!,"Поговорим, когда принесёшь золото!", +"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.","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.",,,Ya está amigo. El pozo del conocimiento se ha secado. De todas formas te he dicho más de lo que debería. Buena 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.","To wszystko kolego, studnia wiedzy wyschła. Powiedziałem ci więcej niż powinienem. Powodzenia... I nie wracaj.","Isso é tudo, amigo. 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.","Это всё, дружище. Кладезь мудрости исчерпан. Я и так рассказал тебе больше, чем следовало. Удачи... и не возвращайся.", -"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,,,,"Hej, já jsem tu jen pro případ nouze. Jestli se něco stane s jádrem, zajistím, že se nikdo nedostane dovnitř... ani ven.","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.",,,"Oye, sólo estoy aquí en caso de una emergencia. Si el núcleo se rompe, entonces 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.",,"おう、俺は緊急時の為にここにいる。 +"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,,,,"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, ich bin nur für den Fall eines Notfalls hier. Im Falle eines Kernbruchs sorge ich dafür das niemand rein kommt... oder raus.",,,"Oye, sólo estoy aquí en caso de una emergencia. Si el núcleo se rompe, entonces 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.","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.","Слушай, меня сюда поставили на всякий случай. Если реактор даст течь, я позабочусь, чтобы никто не вошёл... и не вышел.", "Watch your step, peasant!",TXT_DLG_SCRIPT02_D33352_WATCH,,,,"Dávej si na sebe pozor, poddaný! -","Pass auf wo du hintrittst, Bauer!",,,"¡Cuida por donde caminas, campesino!",,"Katso, mihin astut, maallikko!","Regarde où tu va, paysan!","Nézz a lábad elé, paraszt!",,気を付けろ、田舎モン!,"똑바로 보고 다녀라, 시민!","Kijk uit waar je loopt, boer!",Uważaj jak leziesz kmiocie!,"Cuida por onde anda, plebeu!",,"Ai grijă pe unde calci, plebeule!","Смотри, куда прёшь, рабочий!", +","Pass auf wo du hintrittst, Bauer!",,,"¡Cuida 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!",Uważaj jak leziesz kmiocie!,"Cuida por onde anda, plebeu!",,"Ai grijă pe unde calci, plebeule!","Смотри, куда прёшь, рабочий!", We're going to kill you! ,TXT_DLG_SCRIPT02_D34868_WEREG,,,,Zabijeme tě!,Wir werden dich umbringen!,,,"¡Vamos a matarte! -",,Tapamme sinut!,On va te descendre!,Megdöglesz!,,お前を粛正する!,우린 널 죽일거야!,We gaan je vermoorden!,Zabijemy cię!,Nós vamos matar você!,,O să te omorâm!,Готовься к смерти!, -Who in the blazes are you? No one's supposed to be loitering about in this area!,TXT_DLG_SCRIPT02_D36384_WHOIN,,,,Kdo k čertu jsi? Tady se nikdo nemá potloukat!,Wer zum Teufel bist du? Hier soll doch eigentlich niemand rumschnüffeln!,,,¿Quién diantres eres tú? ¡Se supone que nadie debería de estar merodeando por esta área!,¿Quién demonios eres tú? ¡Se supone que nadie debería de estar merodeando por esta área!,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.,,"誰だお前は?この区域を立ち入ることは +",,Tapamme sinut!,On va te descendre!,Megdöglesz!,Adesso ti ammazziamo!,お前を粛正する!,우린 널 죽일거야!,We gaan je vermoorden!,Zabijemy cię!,Nós vamos matar você!,,O să te omorâm!,Готовься к смерти!, +Who in the blazes are you? No one's supposed to be loitering about in this area!,TXT_DLG_SCRIPT02_D36384_WHOIN,,,,Kdo k čertu jsi? Tady se nikdo nemá potloukat!,Wer zum Teufel bist du? Hier soll doch eigentlich niemand rumschnüffeln!,,,¿Quién diantres eres tú? ¡Se supone que nadie debería de estar merodeando por esta área!,¿Quién demonios eres tú? ¡Se supone que nadie debería de estar merodeando por esta área!,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!,Kim u diaska jesteś? Nikt nie powinien się tu włóczyć!,Quem diabos é você? Não pode ficar perambulando por aqui!,,Cine naiba mai ești tu? Nimeni nu ar trebui să zăbovească în zona asta!,"Кто ты, чёрт побери, такой? Никому не разрешено тут шляться!", -"You there, nobody's allowed in here. Move along!",TXT_DLG_SCRIPT02_D37900_YOUTH,,,,"Hej ty, sem nikdo nesmí. Jdi dál!","Hey, du da. Hier darfst du nicht rein. Geh weiter!",,,"¡Oye tú! No está permitido que estés aquí, ¡Muévete!",,"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!",,お前は許可していないぞ。立ち去れ!,"거기 너, 아무도 이곳에 지나갈 수 없다. 가던 길이나 가!","Jij daar, niemand mag hier naar binnen. Ga verder!","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!","Эй, ты! Никому не позволено тут ошиваться. Проваливай!", -Irale will set you right up!,TXT_DLG_SCRIPT02_D39416_IRALE,,,,Irale tě hned vyzbrojí!,Irale wird sich darum kümmern!,,,¡Irale te pondrá a punto!,¡Irale te pondrá listo!,Irale järkkää sinulle varusteet!,Irale a ce qu'il te faut!,Irale majd ellát.,,イラールが貴方を手助けします!,여기 이롤리가 중요한 물품을 판매할 거야.,Irale zal je er goed in luizen!,Irale dobrze cię przygotuje!,O Irale vai te ajudar!,,Irale te va pregăti adecvat!,Ирэйл снабдит тебя всем необходимым!, -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,,,,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.,"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.",,,Soy algo así como un buscador de talento para los rebeldes. Alguien que es 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.",,"俺は反乱者への斡旋屋さ。才能を生かして +"You there, nobody's allowed in here. Move along!",TXT_DLG_SCRIPT02_D37900_YOUTH,,,,"Hej ty, sem nikdo nesmí. Jdi dál!","Hey, du da. Hier darfst du nicht rein. Geh weiter!",,,"¡Oye tú! No está permitido que estés aquí, ¡Muévete!",,"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!","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!","Эй, ты! Никому не позволено тут ошиваться. Проваливай!", +Irale will set you right up!,TXT_DLG_SCRIPT02_D39416_IRALE,,,,Irale tě hned vyzbrojí!,Irale wird sich darum kümmern!,,,¡Irale te pondrá a punto!,¡Irale te pondrá listo!,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 dobrze cię przygotuje!,O Irale vai te ajudar!,,Irale te va pregăti adecvat!,Ирэйл снабдит тебя всем необходимым!, +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,,,,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.,"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.",,,Soy algo así como un buscador de talento para los rebeldes. Alguien que es 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.,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.,"Я, скажем так, вербовщик повстанцев. Такой парень, как ты, может неплохо заработать... если состыкуется с нужными людьми.", -I'm interested.,TXT_RPLY0_SCRIPT02_D40932_IMINT,,,,Mám zájem.,Ich bin interessiert.,,Mi interestiĝas.,Me interesa.,,Olen kiinnostunut.,Je suis intéressé.,Érdekel.,,興味ある。,흥미롭군.,Ik ben geïnteresseerd.,Jestem zainteresowany.,Estou interessado.,,Sunt interesat.,Я заинтригован., -Screw the rebels!,TXT_RPLY1_SCRIPT02_D40932_SCREW,,,,Kašlu na rebely!,Scheiß auf die Rebellen!,,,¡Al demonio los rebeldes!,,Paskat kapinallisista!,Je m'en fous des rebelles!,Francba a lázadókkal!,,何が反逆だ!,반란군은 집어치워!,De pot op met de rebellen!,Pieprzyć rebeliantów!,Que se danem os rebeldes!,,La naiba cu rebelii!,К чёрту повстанцев!, -"No, no second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D42448_NONOS,,,,"Druhou šanci už nedostaneš. Á, stráže, zabte ho.","Nein, keine zweite Chance. Oh, Wachen, tötet ihn.",,,"No, no hay otra oportunidad. Oh 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!",,"次はねえな。おぅガードの旦那、 +I'm interested.,TXT_RPLY0_SCRIPT02_D40932_IMINT,,,,Mám zájem.,Ich bin interessiert.,,Mi interestiĝas.,Me interesa.,,Olen kiinnostunut.,Je suis intéressé.,Érdekel.,Sono interessato.,興味ある。,흥미롭군.,Ik ben geïnteresseerd.,Jestem zainteresowany.,Estou interessado.,,Sunt interesat.,Я заинтригован., +Screw the rebels!,TXT_RPLY1_SCRIPT02_D40932_SCREW,,,,Kašlu na rebely!,Scheiß auf die Rebellen!,,,¡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!,Pieprzyć rebeliantów!,Que se danem os rebeldes!,,La naiba cu rebelii!,К чёрту повстанцев!, +"No, no second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D42448_NONOS,,,,"Druhou šanci už nedostaneš. Á, stráže, zabte ho.","Nein, keine zweite Chance. Oh, Wachen, tötet ihn.",,,"No, no hay otra oportunidad. Oh 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.","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.","Нет, никакого второго шанса. Эй, стража, убейте его.", -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.,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. Escondido adentro hay un cáliz dorado. Tráemelo y recoges tú 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.",,"良い判断だ。川沿いにあるオーダーの聖域は +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.,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. Escondido adentro hay un cáliz dorado. Tráemelo y recoges tú 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.,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.,Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её и получаешь свою награду., -How am I supposed to do that?,TXT_RPLY0_SCRIPT02_D43964_HOWAM,,,,Jak to mám udělat?,Wie soll ich das anstellen?,,,¿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?,,どうすればいい?,내가 그걸 어떻게 하지?,Hoe moet ik dat doen?,Jak powinienem to zrobić?,Como eu vou conseguir fazer isso?,,Și cum ar trebui să fac asta?,И как я это сделаю?, -"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--. Pamatuj, popadni fešný hrnek a přijď do taverny.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,,"Toma una ballesta, solo apunta en línea recta y --splat--. Recuerda, toma la bonita copa y ven 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!",,"このクロスボウを使いな、狙いを定めて +How am I supposed to do that?,TXT_RPLY0_SCRIPT02_D43964_HOWAM,,,,Jak to mám udělat?,Wie soll ich das anstellen?,,,¿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?,Jak powinienem to zrobić?,Como eu vou conseguir fazer isso?,,Și cum ar trebui să fac asta?,И как я это сделаю?, +"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.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,,"Toma una ballesta, solo apunta en línea recta y --splat--. Recuerda, toma la bonita copa y ven 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.","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ă.",Вот арбалет — просто прицеливаешься и «шлёп!» Запомни — хватаешь чашку и возвращаешься в таверну., -Cool. I'll get it.,TXT_RPLY0_SCRIPT02_D45480_COOLI,,,,"Fajn, přinesu ho.",Cool. Ich werde ihn holen.,,,Genial. La conseguiré.,,Selvä. Saan sen.,Ok. Je m'en occupe.,Király. Meglesz majd.,,良い物だ、貰っとく。,"멋지군, 이해 했어.",Cool. Ik zal het krijgen.,Fajnie. Wchodzę w to.,Beleza. Vou lá pegar.,,Tare. O voi lua.,"Класс. Я достану её. +Cool. I'll get it.,TXT_RPLY0_SCRIPT02_D45480_COOLI,,,,"Fajn, přinesu ho.",Cool. Ich werde ihn holen.,,,Genial. La conseguiré.,,Selvä. Saan sen.,Ok. Je m'en occupe.,Király. Meglesz majd.,Va bene. Vado a prenderlo.,良い物だ、貰っとく。,"멋지군, 이해 했어.",Cool. Ik zal het krijgen.,Fajnie. Wchodzę w to.,Beleza. Vou lá pegar.,,Tare. O voi lua.,"Класс. Я достану её. ", -What are you waiting for? Bring me that chalice.,TXT_DLG_SCRIPT02_D46996_WHATA,,,,Na co čekáš? Přines mi ten kalich.,Worauf wartest du noch? Bring mir den Kelch.,,,¿A que estas esperando? Tráeme ese cáliz.,¿Qué estas 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.,,何ボーっとしてんだ?とっとと聖杯を持ってこい。,뭘 기다리는 거야? 가서 성배를 찾아.,Waar wacht je nog op? Breng me die kelk.,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.,Чего ты ждёшь? Принеси мне эту чашу., -"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, vím, že to vypadá jako bouda. Takovému zabijákovi 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í.","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.",,,"Si, lo sé, esto parece un timo. Nunca le haría eso a una gran máquina de matar. ¿Tienes el objeto? ¡Genial! Ahora prepárate, oro y gloria tal como lo prometí. Toma esta llave y el gobernador te 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.",,"おう、罠みたいだと思ったか。 +What are you waiting for? Bring me that chalice.,TXT_DLG_SCRIPT02_D46996_WHATA,,,,Na co čekáš? Přines mi ten kalich.,Worauf wartest du noch? Bring mir den Kelch.,,,¿A que estas esperando? Tráeme ese cáliz.,¿Qué estas 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.,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.,Чего ты ждёшь? Принеси мне эту чашу., +"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í.","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.",,,"Si, lo sé, esto parece un timo. Nunca le haría eso a una gran máquina de matar. ¿Tienes el objeto? ¡Genial! Ahora prepárate, oro y gloria tal como lo prometí. Toma esta llave y el gobernador te 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.","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.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты. Достал то, что я просил? Отлично! Тебя ждёт золото и слава, как я и обещал. Возьми этот ключ — губернатор лично наградит тебя.", -He'd better. For your sake!,TXT_RPLY0_SCRIPT02_D48512_HEDBE,,,,"To by tedy měl, pro tvoje vlastní dobro!",Das macht er besser. Deinetwillen!,,,Más le vale. ¡Por tu propio bien!,Será lo mejor. ¡Por tu propio bien!,Parasta palkitakin! Sinun kannaltasi!,"Il a intérêt, pour votre bien!",Jobban teszi. A Te érdekedben!,,戻せ、お前の為だ!,"살고 싶으면, 이 말이 사실이야 할 거다!",Dat is hem maar beter gelukt. Voor uw eigen bestwil!,Mam nadzieję. Dla twojego dobra!,Acho bom mesmo. Pro seu bem!,,Ar face bine. De dragul tău!,Надеюсь. Это в твоих интересах!, -What! Where's my money?,TXT_RPLY1_SCRIPT02_D48512_WHATW,,,,Co! Kde jsou moje peníze?,Was! Wo ist mein Geld?,,,¡Qué! ¿Dónde está mi dinero?,,Mitä! Missä on rahani?,Quoi? Où est mon argent!,Mi a túró! Hol van a pénzem?,,何だと! 金はどこだ?,뭐라고! 내 돈은 어디있지?,Wat! Waar is mijn geld?,Co! Gdzie moje pieniądze?,Como é? Cadê o meu dinheiro!,,Ce! Unde sunt banii mei?,Что? Где мои деньги?, -"Get lost kid, you bother me.",TXT_DLG_SCRIPT02_D50028_GETLO,,,,"Odprejskni, mladej, otravuješ mě.","Verzieh dich Jungchen, du störst mich.",,,"Piérdete mocoso, me molestas.",,"Häivy nulikka, häiritset minua.","Dégage, gamin, tu m'agaces.","Kopj le kölyök, ne itt lábatlankodj.",,失せろ、うざってえ。,사라져. 신경 거슬리게 하지 말고.,"Rot op, jongen, je stoort me.","Spadaj mały, przeszkadzasz mi.","Some daqui, garoto. Você está me incomodando.",,"Cară-te puștiule, mă deranjezi.","Пропади, малой. Ты меня раздражаешь.", -"No second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D51544_NOSEC,,,,"Žádná druhá šance. Á, stráže, zabte ho.","Keine zweite Chance. Oh Wachen, tötet ihn.",,,"No hay otra oportunidad. Oh 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.",,"次はねえな。おぅガードの旦那、 +He'd better. For your sake!,TXT_RPLY0_SCRIPT02_D48512_HEDBE,,,,"To by tedy měl, pro tvoje vlastní dobro!",Das macht er besser. Deinetwillen!,,,Más le vale. ¡Por tu propio bien!,Será lo mejor. ¡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!,Mam nadzieję. Dla twojego dobra!,Acho bom mesmo. Pro seu bem!,,Ar face bine. De dragul tău!,Надеюсь. Это в твоих интересах!, +What! Where's my money?,TXT_RPLY1_SCRIPT02_D48512_WHATW,,,,Cože? Kde jsou moje peníze?,Was! Wo ist mein Geld?,,,¡Qué! ¿Dónde está 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?,Co! Gdzie moje pieniądze?,Como é? Cadê o meu dinheiro!,,Ce! Unde sunt banii mei?,Что? Где мои деньги?, +"Get lost kid, you bother me.",TXT_DLG_SCRIPT02_D50028_GETLO,,,,"Odprejskni, mladej, otravuješ mě.","Verzieh dich Jungchen, du störst mich.",,,"Piérdete mocoso, me molestas.",,"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.","Spadaj mały, przeszkadzasz mi.","Some daqui, garoto. Você está me incomodando.",,"Cară-te puștiule, mă deranjezi.","Пропади, малой. Ты меня раздражаешь.", +"No second chance. Oh guards, kill him.",TXT_DLG_SCRIPT02_D51544_NOSEC,,,,"Žádná druhá šance. Á, stráže, zabte ho.","Keine zweite Chance. Oh Wachen, tötet ihn.",,,"No hay otra oportunidad. Oh 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.","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.","Нет, никакого второго шанса. Эй, стража, убейте его.", -"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,,,,"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 sakra chceš?",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?,,,"Primero matan a miles, ahora quieren a todos los campesinos sanos para 'Pruebas' no especificadas. ¿Cómo espera la orden que yo guarde la paz? ¿Qué demonios 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?",,"あいつら散々大量虐殺しといて、今度は'実験' +"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,,,,"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š?",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?,,,"Primero matan a miles, ahora quieren a todos los campesinos sanos para 'Pruebas' no especificadas. ¿Cómo espera la orden que yo guarde la paz? ¿Qué demonios 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?","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?","Сначала они убивают людей тысячами, а теперь им нужны все пригодные рабочие для каких-то «экспериментов»! И Орден ещё хочет, чтобы я поддерживал мир? Какого чёрта тебе нужно?", -"A prison pass, let's deal.",TXT_RPLY0_SCRIPT02_D53060_APRIS,,,,"Propustku do vězení, dohodněme se.",Ein Gefängnispass. Lassen Sie uns verhandeln.,,,"Un pase de la prisión, negociemos.",,Vankilan pääsyluvan; hierotaan diili.,Un passe de la prison. Faisons affaires.,Egy börtön belépő. Üzleteljünk.,,刑務所の許可証だ、取引をしよう。,감옥 통행증만 있으면 돼.,"Een gevangenispasje, laten we dealen.","Przepustkę do więzienia, ponegocjujmy.","Um passe da prisão, vamos negociar.",,O legitimație pentru închisoare. Să facem un târg.,Пропуск в тюрьму. Заключим сделку., +"A prison pass, let's deal.",TXT_RPLY0_SCRIPT02_D53060_APRIS,,,,"Propustku do vězení, udělejme dohodu.",Ein Gefängnispass. Lassen Sie uns verhandeln.,,,"Un pase de 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.","Przepustkę do więzienia, ponegocjujmy.","Um passe da prisão, vamos negociar.",,O legitimație pentru închisoare. Să facem un târg.,Пропуск в тюрьму. Заключим сделку., "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á.","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.",,,"Ya me caes bien. Tengo dos tareas que no quiero hacer yo mismo. Una es sucia, 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.",,"いいだろう。仕事は二つあるのだが +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.","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ă.","Мне нравится твой настрой! У меня есть два неприятных дела, которыми я не хочу заниматься сам. Одно грязное, а другое кровавое.", -Call me the cleaner,TXT_RPLY0_SCRIPT02_D54576_CALLM,,,,Říkej mi pan uklízeč.,Nennen Sie mich den Säuberer,,,Llámame el limpiador,,Olen siivoojasi,Appelez-moi le nettoyeur.,Hívj csak takarítónak.,,まだ手は汚したくない,청소부라 불러줘.,Noem me de schoonmaakster,Nazywaj mnie czyścicielem.,Pode me chamar de faxineiro,,Spune-mi curățătorul,Я — лучший чистильщик!, -I'm not squeamish,TXT_RPLY1_SCRIPT02_D54576_IMNOT,,,,Mám silný žaludek.,Ich bin nicht zimperlich.,,,No soy escrupuloso,,En ole heikkohermoinen,J'ai pas peur de me tacher les mains.,Nem vagyok finnyás,,汚れ仕事でも構わない,나는 비위가 약하지 않아.,Ik ben niet katholiek.,Nie jestem wybredny.,Não sou muito escrupuloso,,Nu sunt mofturos,Я не боюсь крови., -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,,,,"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.","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!",,,"Uno de mis secuaces está robando energía interviniendo la red en algún lugar. Encuéntralo, trunca su suministro y te proporcionaré lo que quieras. Tráeme algo como prueba de que está hecho.",,"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",,"私の手下の一人が水力発電から電力を盗んで +Call me the cleaner,TXT_RPLY0_SCRIPT02_D54576_CALLM,,,,Říkej mi pan uklízeč.,Nennen Sie mich den Säuberer,,,Llámame el limpiador,,Olen siivoojasi,Appelez-moi le nettoyeur.,Hívj csak takarítónak.,Risolvere problemi è la mia specialità,まだ手は汚したくない,청소부라 불러줘.,Noem me de schoonmaakster,Nazywaj mnie czyścicielem.,Pode me chamar de faxineiro,,Spune-mi curățătorul,Я — лучший чистильщик!, +I'm not squeamish,TXT_RPLY1_SCRIPT02_D54576_IMNOT,,,,Mám silný žaludek.,Ich bin nicht zimperlich.,,,No soy escrupuloso,,En ole heikkohermoinen,J'ai pas peur de me tacher les mains.,Nem vagyok finnyás,Non mi impressiono facilmente,汚れ仕事でも構わない,나는 비위가 약하지 않아.,Ik ben niet katholiek.,Nie jestem wybredny.,Não sou muito escrupuloso,,Nu sunt mofturos,Я не боюсь крови., +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,,,,"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.","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!",,,"Uno de mis secuaces está robando energía interviniendo la red en algún lugar. Encuéntralo, trunca su suministro y te proporcionaré lo que quieras. Tráeme algo como prueba de que está hecho.",,"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.,"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ă.","Кто-то из моих подчинённых отводит энергию откуда-то из питающей сети. Найди и отключи эту установку — тогда получишь то, за чем пришёл. И принеси мне что-нибудь в качестве доказательства.", -Where do I find this tap?,TXT_RPLY0_SCRIPT02_D56092_WHERE,,,,Kde najdu tohle stáčedlo?,Wo finde ich die Anzapfung?,,,¿Dónde encuentro la intervención?,,Mistä tämä kytkentä löytyy?,Où est-ce que je trouve cette connection?,Hol találom ezt a dugaszt?,,どうやって突き止めたらいい?,그 추출기는 어디에 찾을 수 있지?,Waar vind ik deze kraan?,Gdzie znajdę ten przełącznik?,Onde encontro essa ligação clandestina?,,Unde-i găsesc robinetul?,Где может находиться эта установка?, -"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 mu přívod.","Wenn ich das wüsste, wäre das keine lästige Angelegenheit, nicht wahr? Benutze deinen Charme, aber schalte seine Versorgung aus.",,,"Si lo supiera, no sería un recado, ¿no? Usa tu encanto, pero corta su suministro. +Where do I find this tap?,TXT_RPLY0_SCRIPT02_D56092_WHERE,,,,Kde najdu to stáčedlo?,Wo finde ich die Anzapfung?,,,¿Dónde encuentro la intervención?,,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?,Gdzie znajdę ten przełącznik?,Onde encontro essa ligação clandestina?,,Unde-i găsesc robinetul?,Где может находиться эта установка?, +"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.","Wenn ich das wüsste, wäre das keine lästige Angelegenheit, nicht wahr? Benutze deinen Charme, aber schalte seine Versorgung aus.",,,"Si lo supiera, no sería un recado, ¿no? Usa tu encanto, pero corta su suministro. ","Si lo supiera, no sería un problema ahora, ¿verdad? 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.",,"私が知っていたら、こんな雑用はさせない +","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.","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.","Если бы я знал, то справился бы с этим сам, как считаешь? Делай что хочешь, но прекрати утечку энергии.", -"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,,,,"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.","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.",,,"Te diré qué, hay un saco mentiroso llamado Derwin que ha estado vendiendo niños a La Orden. No toleraré ese tipo de depravación. No sin mi parte. Derwin trabaja en el almacén. Mátalo y tráeme su, oreja, y 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.",,"教えよう、ダーウィンとかいう恥知らずが +"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,,,,"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.","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.",,,"Te diré qué, hay un saco mentiroso llamado Derwin que ha estado vendiendo niños a La Orden. No toleraré ese tipo de depravación. No sin mi parte. Derwin trabaja en el almacén. Mátalo y tráeme su, oreja, y 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.","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.","Лживый мешок дерьма по имени Дервин продаёт Ордену детей. Я не терплю такой безнравственности, особенно когда меня не берут в долю. Дервин работает на складе. Убей его и принеси мне его... ухо, и я посмотрю, чем cмогу тебе помочь.", -How do I get in?,TXT_RPLY0_SCRIPT02_D59124_HOWDO,,,,Jak se dostanu dovnitř?,Wie komme ich hinein?,,,¿Cómo entro?,,Miten pääsen sisään?,Comment j'y rentre?,Hogy jutok be?,,どうすれば入れる?,어떻게 들어가지?,Hoe kom ik binnen?,Jak się tam dostanę?,Como faço para entrar?,,Cum ajung înăuntru?,Как мне туда попасть?, -"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. Na druhou stranu, nejprve mu uřízni ucho, pak ho zabij. Mnohem lepší.","Dieser Schlüssel wird dich ins Kraftwerk bringen. Andererseits, schneide ihm erst das Ohr ab und dann töte ihn. Viel besser.",,,"Esta llave te llevará a 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. ",,"この鍵で発電所に入るんだ。出来れば、 +How do I get in?,TXT_RPLY0_SCRIPT02_D59124_HOWDO,,,,Jak se dostanu dovnitř?,Wie komme ich hinein?,,,¿Cómo entro?,,Miten pääsen sisään?,Comment j'y rentre?,Hogy jutok be?,Come ci arrivo?,どうすれば入れる?,어떻게 들어가지?,Hoe kom ik binnen?,Jak się tam dostanę?,Como faço para entrar?,,Cum ajung înăuntru?,Как мне туда попасть?, +"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ší.","Dieser Schlüssel wird dich ins Kraftwerk bringen. Andererseits, schneide ihm erst das Ohr ab und dann töte ihn. Viel besser.",,,"Esta llave te llevará a 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.","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.","С этим ключом ты пройдёшь на электростанцию. А, да, я тут подумал — сначала отрежь ему ухо, а затем убей. Так будет намного лучше.", -"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,,,,"Ó, 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.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,,"Oh, me encantan los recuerdos. Toma, esto te llevará a la prisión. Habla con el director 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.",,"嬉しい手土産だ。では、これがあれば +"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,,,,"Ó, 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.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,,"Oh, me encantan los recuerdos. Toma, esto te llevará a la prisión. Habla con el director 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.","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.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.", -Thanks.,TXT_RPLY0_SCRIPT02_D62156_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,,ありがとう。,고마워.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо., -"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 pro tebe odchod.","Hier mal ein Tipp. Wenn ich aufgehört habe mit dir zu reden, dann gehst du.",,,"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.",,ヒントを出そう。話すのを止めたら去りたまえ。,"힌트를 하나 주지. 나랑 대화가 끝났으면, 넌 떠나는 거야.","Ik geef je een hint. Als ik niet meer met je praat, ga je weg.",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.","Дам тебе подсказку: когда я закончу говорить, ты уходишь.", -Do you have good news for me? I'm all ears.,TXT_DLG_SCRIPT02_D65188_DOYOU,,,,Máš pro mě dobré zprávy? Uši mám nastražené.,Hast du gute Neuigkeiten für mich? Ich bin ganz Ohr.,,,¿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.,,私の耳に吉報を伝えに来たかね?,날 위한 좋은 소식이 있나? 열심히 듣고 있다구.,Heb je goed nieuws voor mij? Ik ben een en al oor.,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.,Есть для меня хорошие новости? Слушаю во все уши., -The deed is done!,TXT_RPLY0_SCRIPT02_D65188_THEDE,,,,Skutek je dokonán!,Es ist geschehen!,,,¡El trato está hecho!,,Se on tehty!,C'est bel est bien fait.,Véghezvittem a büntettet.,,やることはヤった,임무 완료!,De daad is gedaan!,Wszystko zrobione!,Está feito!,,Fapta e făcută.,Дело сделано!, -"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.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,,"Oh, me encantan los recuerdos. Toma, esto te llevará a la prisión. Habla con el director Montag. 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.",,"嬉しい手土産だ。では、これがあれば +Thanks.,TXT_RPLY0_SCRIPT02_D62156_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고마워.,Bedankt.,Dzięki.,Agradeço.,,Mulțumesc.,Спасибо., +"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.","Hier mal ein Tipp. Wenn ich aufgehört habe mit dir zu reden, dann gehst du.",,,"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.",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.","Дам тебе подсказку: когда я закончу говорить, ты уходишь.", +Do you have good news for me? I'm all ears.,TXT_DLG_SCRIPT02_D65188_DOYOU,,,,Máš pro mě dobré zprávy? Uši mám nastražené.,Hast du gute Neuigkeiten für mich? Ich bin ganz Ohr.,,,¿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.,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.,Есть для меня хорошие новости? Слушаю во все уши., +The deed is done!,TXT_RPLY0_SCRIPT02_D65188_THEDE,,,,Skutek je dokonán!,Es ist geschehen!,,,¡El trato está hecho!,,Se on tehty!,C'est bel est bien fait.,Véghezvittem a büntettet.,È fatta!,やることはヤった,임무 완료!,De daad is gedaan!,Wszystko zrobione!,Está feito!,,Fapta e făcută.,Дело сделано!, +"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.","Oh, ich liebe Souvenirs. Hier, damit kommst du in das Gefängnis. Sprich mit Direktor Montag. Was du danach machen musst, weiß ich nicht.",,,"Oh, me encantan los recuerdos. Toma, esto te llevará a la prisión. Habla con el director Montag. 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.","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.","О, как я люблю сувениры! Вот твой пропуск в тюрьму. Обратись к тюремщику Монтагу, а что ты будешь делать потом, я и знать не желаю.", -Fine by me.,TXT_RPLY0_SCRIPT02_D66704_FINEB,,,,To je dobře.,Ist mir recht.,,,Bien por mi.,,Sopii minulle.,Ca me convient.,Felőlem rendben van.,,良好だ。,난 괜찮아.,Ik vind het prima.,"Jak dla mnie, w porządku.","Por mim, sem problemas.",,Mie-mi convine.,По рукам!, -"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.","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.",,,"¿Así que tú eres el necio que robó el cáliz? Voy a arrestarte como ladrón rebelde... Con ello mejorando mi posición con la Orden. ¿Cómo se siente ser un inconsciente peón? Te daré una pista, va a doler.","¿Tú eres quién robó el cáliz? Voy a arrestarte como ladrón rebelde... Con ello, mejoraré mi posición con La Orden. ¿Cómo se siente ser un peón? Te daré 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.,,"それで、お前が聖杯を盗んだ愚か者か? +Fine by me.,TXT_RPLY0_SCRIPT02_D66704_FINEB,,,,To je dobře.,Ist mir recht.,,,Bien por mi.,,Sopii minulle.,Ca me convient.,Felőlem rendben van.,Per me va bene.,良好だ。,난 괜찮아.,Ik vind het prima.,"Jak dla mnie, w porządku.","Por mim, sem problemas.",,Mie-mi convine.,По рукам!, +"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.","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.",,,"¿Así que tú eres el necio que robó el cáliz? Voy a arrestarte como ladrón rebelde... Con ello mejorando mi posición con la Orden. ¿Cómo se siente ser un inconsciente peón? Te daré una pista, va a doler.","¿Tú eres quién robó el cáliz? Voy a arrestarte como ladrón rebelde... Con ello, mejoraré mi posición con La Orden. ¿Cómo se siente ser un peón? Te daré 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.","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ă.","Так это ты тот недоумок, что украл чашу? Я передам тебя Ордену, как вора повстанцев... Это укрепит мои отношения с ним. Каково чувствовать себя безмозглой пешкой? Дам тебе подсказку: очень больно! ", -It sucks!,TXT_RPLY0_SCRIPT02_D68220_ITSUC,,,,Je to na hovno!,Scheiße!,,Ĝi aĉas!,¡Apesta!,,Ihan syvältä!,Quelle merde!,Szopás!,,クソが!,이거 정말 난감한데?,Het is klote!,Cholera!,Que merda!,,E nașpa!,Чтоб ты сдох!, -For you it does.,TXT_RYES0_SCRIPT02_D68220_FORYO,,,,Pro tebe určitě.,Du steckst ganz tief drin.,,,Para ti si.,,"Kyllä, sinun tilanteesi.","Pour vous, en effet.","Igen, neked.",,私もそう思う。,너한테는 더욱 그럴걸.,Voor jou wel.,Dla ciebie tak.,"Pra você, sim.",,"Pentru tine, cu siguranță.",Скоро сдохнешь ты., -Harris promised me money!,TXT_RPLY1_SCRIPT02_D68220_HARRI,,,,Harris mi slíbil peníze!,Harris hat mir Geld versprochen!,,,¡Harris me prometió dinero!,,Harris lupasi minulle rahaa!,Harris m'a promis de l'argent!,Harris pénzt igért!,,ハリスは俺に金を渡すと約束したのに!,해리스는 내게 돈을 약속했어!,Harris beloofde me geld!,Harris obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!, -Too bad. The only thing you're getting is dead!,TXT_RYES1_SCRIPT02_D68220_TOOBA,,,,"Smůla. Jediné, co dostaneš, je smrt.",Jammerschade. Das Einzige was du bekommen wirst ist der Tod!,,,Que mal. ¡Lo único que vas a tener es la muerte!,Que mal. ¡Lo único que obtendrás 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!",,残念だな、お前にやれるものは死のみだ!,그거 안됐네. 네가 얻는 거라곤 죽음뿐이니까!,Wat jammer. Het enige dat je zult krijgen is de dood!,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!,"Увы. Всё, что ты получишь, — это смерть!", -"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,,,,"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?","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 un mundo pequeño, las palabras viajan rápido. Escuché que acabas de quitar algunos obstáculos de tu camino. Buen trabajo. ¿Estás interesado 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?,,"この小さな世界では噂が広まるのは早いもんだ。 +It sucks!,TXT_RPLY0_SCRIPT02_D68220_ITSUC,,,,Je to na hovno!,Scheiße!,,Ĝi aĉas!,¡Apesta!,,Ihan syvältä!,Quelle merde!,Szopás!,È uno schifo!,クソが!,이거 정말 난감한데?,Het is klote!,Cholera!,Que merda!,,E nașpa!,Чтоб ты сдох!, +For you it does.,TXT_RYES0_SCRIPT02_D68220_FORYO,,,,Pro tebe určitě.,Du steckst ganz tief drin.,,,Para ti si.,,"Kyllä, sinun tilanteesi.","Pour vous, en effet.","Igen, neked.",A te lo farà.,私もそう思う。,너한테는 더욱 그럴걸.,Voor jou wel.,Dla ciebie tak.,"Pra você, sim.",,"Pentru tine, cu siguranță.",Скоро сдохнешь ты., +Harris promised me money!,TXT_RPLY1_SCRIPT02_D68220_HARRI,,,,Harris mi slíbil peníze!,Harris hat mir Geld versprochen!,,,¡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 obiecał mi pieniądze!,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!, +Too bad. The only thing you're getting is dead!,TXT_RYES1_SCRIPT02_D68220_TOOBA,,,,"Smůla. Jediné, co dostaneš, je smrt.",Jammerschade. Das Einzige was du bekommen wirst ist der Tod!,,,Que mal. ¡Lo único que vas a tener es la muerte!,Que mal. ¡Lo único que obtendrás 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!,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!,"Увы. Всё, что ты получишь, — это смерть!", +"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,,,,"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?","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 un mundo pequeño, las palabras viajan rápido. Escuché que acabas de quitar algunos obstáculos de tu camino. Buen trabajo. ¿Estás interesado 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?","この小さな世界では噂が広まるのは早いもんだ。 あんたが素早く厄介事を片付けたと聞いたぞ。 もっと儲かる仕事をやってみる気はないかね?","이처럼 작은 세상엔, 소문이 빨리 전해지지. 방금 자네가 장애물들을 처리한 걸 들었다네. 수고했어. 수익이 아주 짭짤한 일자리에 관심이 있나? ",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?,"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ê removeu 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?","Мир тесен, и новости разлетаются быстро. Я слышал, как ты только что убрал пару препятствий со своего пути. Хорошая работа. Заинтересован в более прибыльных занятиях?", -"Sure, why not.",TXT_RPLY0_SCRIPT02_D69736_SUREW,,,,"Klidně, proč ne.","Sicher, warum nicht.",,"Ja, kial ne?","Por supuesto, por que no.",,Miksipä ei.,"Ouais, pourquoi pas.","Persze, miért is ne.",,ああ、もちろんだ。,그거 좋군요.,"Tuurlijk, waarom niet.","Jasne, czemu nie.","Claro, por que não?",,"Da, de ce nu.","Конечно, почему бы и нет.", -No thanks.,TXT_RPLY1_SCRIPT02_D69736_NOTHA,,,,"Ne, díky.",Nein danke.,,Ne dankon.,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,,やめとくよ。,필요 없어요.,"Nee, dank je wel.","Nie, dziękuję.","Não, obrigado.",,Nu mulțumesc.,"Нет, спасибо.", -Then get lost!,TXT_RYES1_SCRIPT02_D69736_THENG,,,,Tak vypadni!,Dann verzieh dich!,,,¡Entonces piérdete!,,Sitten häivy!,Alors dégage!,Akkor húzz el innen!,,じゃあ失せるんだな!,그럼 꺼져!,Dan verdwalen!,W takim razie spadaj!,Então suma daqui!,,Atunci valea!,Тогда проваливай!, -"Fool! Guards, rid me of this meddlesome peon.",TXT_DLG_SCRIPT02_D71252_FOOLG,,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.","Du Narr! Wachen, entledigt mich dieses lästigen Tagelöhners.",,,"¡Insensato! Guardias, líbrenme de este entrometido peón.","¡Tonto! Guardias, líbrenme 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!",,"なんと愚かな! +"Sure, why not.",TXT_RPLY0_SCRIPT02_D69736_SUREW,,,,"Klidně, proč ne.","Sicher, warum nicht.",,"Ja, kial ne?","Por supuesto, por que no.",,Miksipä ei.,"Ouais, pourquoi pas.","Persze, miért is ne.","Certo, perché no.",ああ、もちろんだ。,그거 좋군요.,"Tuurlijk, waarom niet.","Jasne, czemu nie.","Claro, por que não?",,"Da, de ce nu.","Конечно, почему бы и нет.", +No thanks.,TXT_RPLY1_SCRIPT02_D69736_NOTHA,,,,"Ne, díky.",Nein danke.,,Ne dankon.,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,"No, grazie.",やめとくよ。,필요 없어요.,"Nee, dank je wel.","Nie, dziękuję.","Não, obrigado.",,Nu mulțumesc.,"Нет, спасибо.", +Then get lost!,TXT_RYES1_SCRIPT02_D69736_THENG,,,,Tak vypadni!,Dann verzieh dich!,,,¡Entonces piérdete!,,Sitten häivy!,Alors dégage!,Akkor húzz el innen!,E allora sparisci!,じゃあ失せるんだな!,그럼 꺼져!,Dan verdwalen!,W takim razie spadaj!,Então suma daqui!,,Atunci valea!,Тогда проваливай!, +"Fool! Guards, rid me of this meddlesome peon.",TXT_DLG_SCRIPT02_D71252_FOOLG,,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.","Du Narr! Wachen, entledigt mich dieses lästigen Tagelöhners.",,,"¡Insensato! Guardias, líbrenme de este entrometido peón.","¡Tonto! Guardias, líbrenme 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.","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ț.","Глупец! Стража, избавьте меня от этого недоумка.", -"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.","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.",,,"Bien. Algunos uh, amigos míos necesitan a alguien silenciado. Beldin es retenido por La Orden en su santuario. Hay una entrada rara vez utilizada por un pequeño muelle frente 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.",,"それでいい。ええと、私の友人がある人物を +"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.","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.",,,"Bien. Algunos uh, amigos míos necesitan a alguien silenciado. Beldin es retenido por La Orden en su santuario. Hay una entrada rara vez utilizada por un pequeño muelle frente 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.","それでいい。ええと、私の友人がある人物を 黙らせて欲しいと望んでいるんだ。 ベルディンはオーダーの連中の聖域に 囚われている。建物への入り口は川に掛かった 桟橋の先にあり、そこは誰も警備してないし ほぼ使われていない。潜入してヤツを黙らせて、 仕事をした証拠としてヤツの指輪を見せてくれ。","좋구만... 그래서, 내 지인이 말하기를 벨딘이라는 사람의 입을 다물게 만들라는군. 그는 지금 오더에 의해 성소에 감금됐네. 그 근처 강가에 있는 작은 부두 옆에 자주 쓰이지 않는 입구가 있다네. 거기로 향해서, 그의 입을 막게. 그리고 그의 반지를 증거로 가져오게.","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.","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ă.","Хорошо. Некоторые мои, э-э-э, приятели, хотят, чтобы кое-кто замолчал. Орден держит предателя по имени Белдин в своём святилище. На берегу реки есть вход, который редко используется, а потому не охраняется. Проберись внутрь, заставь предателя замолчать навсегда и принеси мне его кольцо в качестве доказательства.", -Will it be worth the effort?,TXT_RPLY0_SCRIPT02_D72768_WILLI,,,,Bude mi to stát za to?,Wird es die Mühe denn wert sein?,,,¿Valdrá 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?,,苦労に見合った報酬だろうな?,노력할만한 가치가 있나요?,Zal het de moeite waard zijn?,Czy będzie to warte moich starań?,Será que vale a pena o esforço?,,O să merite efortul?,Оно того стоит?, -"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.","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.",,,"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.",,"50ゴールドは保証するし街の警報を鳴らさず +Will it be worth the effort?,TXT_RPLY0_SCRIPT02_D72768_WILLI,,,,Bude mi to stát za to?,Wird es die Mühe denn wert sein?,,,¿Valdrá 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?,Czy będzie to warte moich starań?,Será que vale a pena o esforço?,,O să merite efortul?,Оно того стоит?, +"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.","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.",,,"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.","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 золотых. И ты сможешь заработать куда больше, если выполнишь задание, не переполошив всю стражу в городе. А чтобы у тебя было некоторое преимущество, вот тебе небольшой помощник. ", -"Thanks, I'll need it.",TXT_RPLY0_SCRIPT02_D74284_THANK,,,,"Díky, budu ho potřebovat.","Danke, das werde ich brauchen.",,,"Gracias, lo necesitaré.",,"Kiitos, tarvitsen sitä.","Merci, j'en aurais besoin.","Köszönöm, kelleni is fog.",,ありがとよ、これは後々必要になるな。,고마워요. 도움이 될 것 같습니다.,"Bedankt, ik zal het nodig hebben.",Dzięki. Będę go potrzebował.,"Obrigado, vou precisar.",,"Merci, voi avea nevoie de el.",Спасибо. Он мне пригодится., -"Good. Remember, his silence is golden.",TXT_DLG_SCRIPT02_D75800_GOODR,,,,"Dobře. Pamatuj, že jeho mlčení má cenu zlata.",Gut. Denke dran. Sein Schweigen ist Gold wert.,,,"Bien. Recuerda, su silencio es oro.",,"Hyvä. Muista, että hänen vaikenemisensa on kultaa.",Bien. Souvenez-vous. Le silence est d'or.,"Remek, a hallgatása arany.",,いいぞ。覚えておけ、彼が沈黙したら金だ。,천만에. 그리고 기억하게. 그를 입막음하는 게 유일한 희망일세.,"Goed. Vergeet niet, zijn stilte is goud waard.","Dobrze. Pamiętaj, jego cisza jest cenna.","Ótimo. Lembre-se, o silêncio dele vale ouro.",,"Bun. Reține, tăcerea e de aur.","Превосходно. Запомни, его молчание — золото.", -I'll get him.,TXT_RPLY0_SCRIPT02_D75800_ILLGE,,,,Dostanu ho.,Ich krieg ihn.,,,Lo encontraré.,,Saan hänet.,Je m'occupe de lui.,Elintézem.,,始末してみせる。,그를 잡겠어요.,Ik krijg hem wel.,Dorwę go.,Vou pegá-lo.,,O să-l aduc.,Я прикончу его., -Mission accomplished? You have the ring of the traitor?,TXT_DLG_SCRIPT02_D77316_MISSI,,,,Mise splněna? Máš zrádcův prsten?,Mission ausgeführt? Hast du den Ring des Verräters?,,,¿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?,,"任務完了か? +"Thanks, I'll need it.",TXT_RPLY0_SCRIPT02_D74284_THANK,,,,"Díky, budu ho potřebovat.","Danke, das werde ich brauchen.",,,"Gracias, lo 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.",Dzięki. Będę go potrzebował.,"Obrigado, vou precisar.",,"Merci, voi avea nevoie de el.",Спасибо. Он мне пригодится., +"Good. Remember, his silence is golden.",TXT_DLG_SCRIPT02_D75800_GOODR,,,,"Dobře. Pamatuj, že jeho mlčení má cenu zlata.",Gut. Denke dran. Sein Schweigen ist Gold wert.,,,"Bien. Recuerda, su silencio es 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.","Dobrze. Pamiętaj, jego cisza jest cenna.","Ótimo. Lembre-se, o silêncio dele vale ouro.",,"Bun. Reține, tăcerea e de aur.","Превосходно. Запомни, его молчание — золото.", +I'll get him.,TXT_RPLY0_SCRIPT02_D75800_ILLGE,,,,Dostanu ho.,Ich krieg ihn.,,,Lo encontraré.,,Saan hänet.,Je m'occupe de lui.,Elintézem.,Lo vado a prendere.,始末してみせる。,그를 잡겠어요.,Ik krijg hem wel.,Dorwę go.,Vou pegá-lo.,,O să-l aduc.,Я прикончу его., +Mission accomplished? You have the ring of the traitor?,TXT_DLG_SCRIPT02_D77316_MISSI,,,,Mise splněna? Máš zrádcův prsten?,Mission ausgeführt? Hast du den Ring des Verräters?,,,¿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?,Misja ukończona? Masz pierścień zdrajcy?,Missão cumprida? Está com o anel do traidor?,,Misiune îndeplinită? Ai inelul trădătorului?,Задание выполнено? Ты принёс кольцо предателя?, -"He's dead, where's my money?",TXT_RPLY0_SCRIPT02_D77316_HESDE,,,,"Je mrtvý, kde jsou moje peníze?","Er ist tot, wo ist mein Geld?",,,"Está muerto, ¿dónde está mi dinero?",,"Hän on kuollut, missä on rahani?","Il est mort, où est mon argent?","Meghalt, hol a pénzem?",,奴は死んだ、報酬はあるんだろうな?,"그는 죽었습니다, 제 보상은요?","Hij is dood, waar is mijn geld?",Jest martwy. Gdzie moje pieniądze?,"Ele está morto, cadê o meu dinheiro?",,"E mort, unde sunt banii?",Он мёртв. Где мои деньги?, -Liar! Go get the ring!,TXT_RNO0_SCRIPT02_D77316_LIARG,,,,Lháři! Jdi pro jeho prsten!,Lügner! Hol' den Ring!,,,¡Mentiroso! ¡Ve por el anillo!,,Valehtelija! Mene hakemaan sormus!,Mensonges! Ramenez-moi l'anneau!,Hazug! Menj és szerezd meg a gyűrűt!,,嘘をつくな、指輪を取ってこい!,거짓말쟁이! 가서 반지를 가져오게!,Leugenaar! Ga de ring halen!,Kłamca! Idź po pierścień!,Mentiroso! Vá pegar o anel!,,Mincinos! Adu inelul!,Лжец! Принеси мне кольцо!, -"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?","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?",,,"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?",,"よし、報酬はお前のものだ。お前が殺した +"He's dead, where's my money?",TXT_RPLY0_SCRIPT02_D77316_HESDE,,,,"Je mrtvý, kde jsou moje peníze?","Er ist tot, wo ist mein Geld?",,,"Está muerto, ¿dónde está 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?",Jest martwy. Gdzie moje pieniądze?,"Ele está morto, cadê o meu dinheiro?",,"E mort, unde sunt banii?",Он мёртв. Где мои деньги?, +Liar! Go get the ring!,TXT_RNO0_SCRIPT02_D77316_LIARG,,,,Lháři! Jdi pro jeho prsten!,Lügner! Hol' den Ring!,,,¡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!,Kłamca! Idź po pierścień!,Mentiroso! Vá pegar o anel!,,Mincinos! Adu inelul!,Лжец! Принеси мне кольцо!, +"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?","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?",,,"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?","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?","Вот, ты их заслужил. Убитый тобой предатель мог выдать Ордену местоположение базы Сопротивления. Ты спас много жизней. Тебе бы не хотелось ещё золота и будущего, свободного от тирании?", -Tell me more.,TXT_RPLY0_SCRIPT02_D78832_TELLM,,,,Řekni mi víc.,Erzähl mir mehr.,,Diru al mi pli multe.,Dime más.,,Kerro lisää.,Dites-moi en plus.,Mesélj még.,,もっと教えてくれ。,더 말해주시오.,Vertel me meer.,Mów dalej.,Me conte mais.,,Spune-mi mai multe.,Расскажи мне больше., -Not my style.,TXT_RPLY1_SCRIPT02_D78832_NOTMY,,,,To není můj styl.,Nicht mein Stil.,,,No es mi estilo.,,Ei kuulu tyyliini.,Pas mon genre.,Nem az Én stílusom.,,俺の趣味じゃないな。,내 취향은 아닌데.,Niet mijn stijl.,To nie w moim stylu.,Não faz o meu estilo.,,Nu-i genul meu.,Не в моём вкусе., -"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.","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.",,,"Tengo una relación de negocios con el líder del frente, Macil. Sé que necesita un compañero incisivo como tú, y paga bien. Toma esta unidad de comunicaciones recuperada y serás conducido 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.",,"私はフロントのリーダー、マシルと取引を +Tell me more.,TXT_RPLY0_SCRIPT02_D78832_TELLM,,,,Řekni mi víc.,Erzähl mir mehr.,,Diru al mi pli multe.,Dime más.,,Kerro lisää.,Dites-moi en plus.,Mesélj még.,Dimmi di più.,もっと教えてくれ。,더 말해주시오.,Vertel me meer.,Mów dalej.,Me conte mais.,,Spune-mi mai multe.,Расскажи мне больше., +Not my style.,TXT_RPLY1_SCRIPT02_D78832_NOTMY,,,,To není můj styl.,Nicht mein Stil.,,,No es mi estilo.,,Ei kuulu tyyliini.,Pas mon genre.,Nem az Én stílusom.,Non fa per me.,俺の趣味じゃないな。,내 취향은 아닌데.,Niet mijn stijl.,To nie w moim stylu.,Não faz o meu estilo.,,Nu-i genul meu.,Не в моём вкусе., +"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.","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.",,,"Tengo una relación de negocios con el líder del frente, Macil. Sé que necesita un compañero incisivo como tú, y paga bien. Toma esta unidad de comunicaciones recuperada y serás conducido 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.","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 лидером повстанцев, Мэйсилом. Я знаю, что ему нужны толковые парни вроде тебя, и он неплохо платит. Возьми этот передатчик, и перед тобой откроются, скажем так, новые перспективы.", -Thanks.,TXT_RPLY0_SCRIPT02_D80348_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,,ありがとう。,알겠어요.,Bedankt.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо., -"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.","Beweg dich. Wenn wir beide hier rumhängen, dann sind wir beide tot.",,,"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.",,"うまくやれよ。こんな所でもたもたしていると +Thanks.,TXT_RPLY0_SCRIPT02_D80348_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,알겠어요.,Bedankt.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо., +"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.","Beweg dich. Wenn wir beide hier rumhängen, dann sind wir beide tot.",,,"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.",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.","Двигай. Если продолжишь тут ошиваться, нас обоих убьют.", -"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í!","Ein Jammer, aber nun, da du über meine Freunde Bescheid weißt, muss ich dich umbringen. Wachen? Entsorgt ihn!",,,"Una pena, pero ahora que sabes de mis amigos, debo matarte. ¡Guardias, saquen esta 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!",,"残念だ、だがお前は私の友の事を知った以上 +"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í!","Ein Jammer, aber nun, da du über meine Freunde Bescheid weißt, muss ich dich umbringen. Wachen? Entsorgt ihn!",,,"Una pena, pero ahora que sabes de mis amigos, debo matarte. ¡Guardias, saquen esta 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!","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!","Жаль, но раз уж ты узнал о моих друзьях, мне придётся тебя убить. Стража, уберите его!", -Fool. Guards! Rid me of meddlesome peon.,TXT_DLG_SCRIPT02_D84896_FOOLG,,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.",Du Narr! Wachen! Entledigt mich von diesem lästigen Tagelöhner.,,,"¡Insensato! Guardias, líbrenme de este entrometido peón.","¡Tonto! Guardias, líbrenme 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!",,"愚かな。 +Fool. Guards! Rid me of meddlesome peon.,TXT_DLG_SCRIPT02_D84896_FOOLG,,,,"Blázne! Stráže, zbavte se tohohle zbytečného nuzáka.",Du Narr! Wachen! Entledigt mich von diesem lästigen Tagelöhner.,,,"¡Insensato! Guardias, líbrenme de este entrometido peón.","¡Tonto! Guardias, líbrenme 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.,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ț.","Глупец! Стража, избавьте меня от этого недоумка.", -"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D86412_WALKA,,,,"Jdi pryč, chlapče, prostě odejdi.","Geh weg Jungchen, geh einfach weg.",,,"Aléjate, muchacho, sólo aléjate.",,"Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.",,どっか行け、若造、とっとと行け。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень.", -What are you doing here?,TXT_DLG_SCRIPT02_D87928_WHATA,,,,Co ty tu děláš?,Was machst du hier?,,,¿Qué estás haciendo aquí?,,Mitäs sinä täällä teet?,Qu'est-ce que vous foutez ici?,Mit művelsz itt?,,ここで何をしている?,여기서 뭘 하는거야?,Wat doe jij hier?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,Что ты тут делаешь?, -"Hey, I need gold!",TXT_RPLY0_SCRIPT02_D87928_HEYIN,,,,"Hej, potřeboval bych zlato!","Hey, ich brauche Gold!",,"He, mi bezonas oron!","¡Hey, necesito oro!",,"Hei, tarvitsen kultaa!","Hé, j'ai besoin de sous!","Héj, nekem arany kell!",,よう、金が必要だ!,"이봐, 난 골드가 필요해!","Hé, ik heb goud nodig!","Hej, potrzebuję złota!","Ei, eu preciso de ouro!",,"Hei, am nevoie de aur!","Эй, мне нужно золото!", -"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 hat dir den Code gegeben, wie? Lass mich mal eben den Alarm abschalten. Macil ist eine Etage tiefer.",,,"Blackbird te dijo el código, ¿eh? Déjame apagar la alarma. Macil está un vuelo hacia abajo.",,"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.",,"ブラックバードに教えてもらったんだな? +"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D86412_WALKA,,,,"Jdi pryč, chlapče, prostě odejdi.","Geh weg Jungchen, geh einfach weg.",,,"Aléjate, muchacho, sólo aléjate.",,"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.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень.", +What are you doing here?,TXT_DLG_SCRIPT02_D87928_WHATA,,,,Co ty tu děláš?,Was machst du hier?,,,¿Qué estás haciendo aquí?,,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?,Co ty tu robisz?,O que você está fazendo aqui?,,Ce cauți aici?,Что ты тут делаешь?, +"Hey, I need gold!",TXT_RPLY0_SCRIPT02_D87928_HEYIN,,,,"Hej, potřeboval bych zlato!","Hey, ich brauche Gold!",,"He, mi bezonas oron!","¡Hey, 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!","Hej, potrzebuję złota!","Ei, eu preciso de ouro!",,"Hei, am nevoie de aur!","Эй, мне нужно золото!", +"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 hat dir den Code gegeben, wie? Lass mich mal eben den Alarm abschalten. Macil ist eine Etage tiefer.",,,"Blackbird te dijo el código, ¿eh? Déjame apagar la alarma. Macil está un vuelo hacia abajo.",,"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.","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.","Чёрный дрозд сказал тебе пароль, так? Давай я отключу сигнализацию. Мэйсил этажом ниже.", -Thanks.,TXT_RPLY0_SCRIPT02_D89444_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,,ありがとう。,고맙다.,Bedankt.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо., -"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D90960_WALKA,,,,"Jdi pryč, chlapče, prostě odejdi.","Geh weg Jungchen, geh einfach weg.",,,"Aléjate, muchacho, sólo aléjate.",,"Kävele pois vain, poju, kävele pois.","Pars, gamin, pars.","Csak sétálj el innen, sétálj el szépen.",,向こうへ行け、新入り、急ぐんだ。,"지나가라고 친구, 그냥 지나가.","Loop weg, jongen, loop gewoon weg.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень.", -Do you have an appointment with the Governor? ,TXT_DLG_SCRIPT02_D92476_DOYOU,,,,Máte domluvený termín schůzky s guvernérem?,Hast du einen Termin bei dem Gouverneur?,,,¿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?,,知事とアポイントメントは取ってますか?,총독과 약속이 있으십니까?,Heb je een afspraak met de gouverneur?,Masz spotkanie z Gubernatorem?,Você tem hora marcada com o Governador?,,Ai o programare cu Guvernatorul?,У Вас назначена встреча с губернатором?, -Of course!,TXT_RPLY0_SCRIPT02_D92476_OFCOU,,,,Samozřejmě!,Natürlich!,,Kompreneble!,¡Claro que sí!,,Totta kai!,Bien sûr!,Persze!,,問題ない!,당연하지!,Natuurlijk!,Oczywiście!,Claro que sim!,,Desigur!,Конечно!, -"No, and I don't need one!",TXT_RPLY1_SCRIPT02_D92476_NOAND,,,,Ne a žádný nepotřebuju!,"Nein, und ich brauche auch keinen!",,"Ne, kaj mi ne bezonas unu!","¡No, y no la necesito!",,"Ei, enkä sellaista tarvitsekaan!","Non, et j'en ai pas besoin!","Nincs, és nem is kell!",,いや、必要ない!,아니. 없는데?,"Nee, en die heb ik niet nodig!","Nie mam, i nie chcę mieć!",Não e eu não preciso de hora marcada!,,"Nu, nici n-am nevoie de una!","Нет, и я в ней не нуждаюсь!", -Sorry! I didn't mean... Please go right up.,TXT_DLG_SCRIPT02_D93992_SORRY,,,,"Pardon! Nechtěl jsem... jeďte tady nahoru, prosím.",Entschuldigung! Das war nicht so gemeint... Bitte geh durch.,,,"¡Lo siento! No quise decir ... Por favor, sube.",,"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.,,"すいません!知らずに... +Thanks.,TXT_RPLY0_SCRIPT02_D89444_THANK,,,,Díky.,Danke.,,Dankon.,Gracias.,,Kiitos.,Merci.,Kösz.,Grazie.,ありがとう。,고맙다.,Bedankt.,Dzięki.,Obrigado.,,Mulțumesc.,Спасибо., +"Walk away, boy, just walk away.",TXT_DLG_SCRIPT02_D90960_WALKA,,,,"Jdi pryč, chlapče, prostě odejdi.","Geh weg Jungchen, geh einfach weg.",,,"Aléjate, muchacho, sólo aléjate.",,"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.","Odejdź stąd mały, po prostu odejdź.","Suma daqui, garoto. Apenas suma daqui.",,"Pleacă, băiete, pleacă.","Иди своей дорогой, парень.", +Do you have an appointment with the Governor? ,TXT_DLG_SCRIPT02_D92476_DOYOU,,,,Máte domluvený termín schůzky s guvernérem?,Hast du einen Termin bei dem Gouverneur?,,,¿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?,Masz spotkanie z Gubernatorem?,Você tem hora marcada com o Governador?,,Ai o programare cu Guvernatorul?,У Вас назначена встреча с губернатором?, +Of course!,TXT_RPLY0_SCRIPT02_D92476_OFCOU,,,,Samozřejmě!,Natürlich!,,Kompreneble!,¡Claro que sí!,,Totta kai!,Bien sûr!,Persze!,Certo!,問題ない!,당연하지!,Natuurlijk!,Oczywiście!,Claro que sim!,,Desigur!,Конечно!, +"No, and I don't need one!",TXT_RPLY1_SCRIPT02_D92476_NOAND,,,,Ne a žádný nepotřebuju!,"Nein, und ich brauche auch keinen!",,"Ne, kaj mi ne bezonas unu!","¡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!","Nie mam, i nie chcę mieć!",Não e eu não preciso de hora marcada!,,"Nu, nici n-am nevoie de una!","Нет, и я в ней не нуждаюсь!", +Sorry! I didn't mean... Please go right up.,TXT_DLG_SCRIPT02_D93992_SORRY,,,,"Pardon! Nechtěl jsem... jeďte tady nahoru, prosím.",Entschuldigung! Das war nicht so gemeint... Bitte geh durch.,,,"¡Lo siento! No quise decir ... Por favor, sube.",,"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.,"Przepraszam! Nie chciałem... Proszę, idź na górę.",Desculpe! Eu não queria... Por favor pode subir.,,"Scuze! Te rog, poftește sus.","Простите! Я не думал... Пожалуйста, проходите наверх.", -I knew you'd say that.,TXT_RPLY0_SCRIPT02_D93992_IKNEW,,,,"Věděl jsem, že to řekneš.","Ich dachte mir schon, das du das sagen würdest.",,,Sabía que dirías eso.,,"Arvasin, että sanoisit noin.",Je savais que vous diriez ceci.,"Tudtam, hogy ezt mondod.",,そう言うと思った。,그렇게 말할 줄 알았어.,Ik wist dat je dat zou zeggen.,"Wiedziałem, że to powiesz.",Eu sabia que você diria isso.,,Știam că vei spune asta.,"Я знал, что ты это скажешь.", -"If you're in such a hurry, don't waste your time with me.",TXT_DLG_SCRIPT02_D95508_IFYOU,,,,"Jestli tolik spěcháš, neztrácej čas se mnou.","Wenn du so in Eile bist, dann verschwende deine Zeit nicht mit mir.",,,"Si tienes tanta prisa, 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.",,"そんなに急いでいるなら、 +I knew you'd say that.,TXT_RPLY0_SCRIPT02_D93992_IKNEW,,,,"Věděl jsem, že to řekneš.","Ich dachte mir schon, das du das sagen würdest.",,,Sabía que dirías 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.,"Wiedziałem, że to powiesz.",Eu sabia que você diria isso.,,Știam că vei spune asta.,"Я знал, что ты это скажешь.", +"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.","Wenn du so in Eile bist, dann verschwende deine Zeit nicht mit mir.",,,"Si tienes tanta prisa, 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.","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.","Если вы так торопитесь, не тратьте на меня время.", -"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D97024_RELEA,,,,"Drž se dál, nech starce na pokoji.","Pack mich nicht an, lass einen alten Mann in Ruhe",,,"Suéltame, deja en paz 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.",,ほっといてくれ、年寄り一人にしてくれ。,부탁일세. 이 노인을 내버려 두게.,"Laat me vrij, laat een oude man met rust.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!, -"You seek wisdom, my son? The order has seen to it that we only ask one question, 'Why?'",TXT_DLG_SCRIPT02_D98540_YOUSE,,,,"Hledáš moudrost, chlapče? Řád dohlédl na to, abychom se ptali jen na jedno: „Proč?“","Du suchst Weisheit, mein Sohn? Der Orden hat zugesehen das wir nur noch eine Frage stellen, „Warum?“",,,"¿Buscas sabiduría, hijo mío? La orden se ha asegurado de que solo hagamos 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?'",,"知恵が欲しそうだな、ボウズ? +"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D97024_RELEA,,,,"Drž se dál, nech starce na pokoji.","Pack mich nicht an, lass einen alten Mann in Ruhe",,,"Suéltame, deja en paz 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.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!, +"You seek wisdom, my son? The order has seen to it that we only ask one question, 'Why?'",TXT_DLG_SCRIPT02_D98540_YOUSE,,,,"Hledáš moudrost, chlapče? Řád dohlédl na to, abychom se ptali jen na jedno: „Proč?“","Du suchst Weisheit, mein Sohn? Der Orden hat zugesehen das wir nur noch eine Frage stellen, „Warum?“",,,"¿Buscas sabiduría, hijo mío? La orden se ha asegurado de que solo hagamos 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?","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?'","Ищешь совета, сын мой? Орден заботится о том, чтобы нас занимал только один вопрос: «За что?»", -Where's the power coupling?,TXT_RPLY0_SCRIPT02_D98540_WHERE,,,,Kde je elektrická spojka?,Wo ist der Stromabnehmer?,,,¿Dónde está el acoplamiento eléctrico?,,Missä virtaliitin on?,Où est le coupleur énergétique?,Hol van az áram kapcsoló?,,配電機 は何処だ?,동력선은 어디있나요?,Waar is de krachtkoppeling?,Gdzie jest odbierak prądu?,Cadê a conexão de energia?,,Unde e cuplajul energiei?,Где соединительная муфта?, -Where's the Order's main?,TXT_RPLY1_SCRIPT02_D98540_WHERE,,,,Kde má Řád napájecí síť?,Wo ist die Stromleitung des Ordens?,,,¿Dónde está la red principal de la Orden?,,Missä on Veljeskunnan pääsähkölinja?,Où est le transformateur de l'Ordre?,Hol a Rend fővonala?,,オーダーの本管 は何処だ?,오더의 동력 공급 시설은 어디있나요?,Waar is de hoofdopdracht van de Orde?,Gdzie jest przewód Zakonu?,Cadê o transformador da Ordem?,,Unde e linia electrică a Ordinului?,Где линия электропередачи Ордена?, -Where's the illegal tap?,TXT_RPLY2_SCRIPT02_D98540_WHERE,,,,Kde je nelegální stáčedlo?,Wo ist die illegale Anzapfung?,,,¿Dónde está la intervención ilegal?,,Missä laiton kytkentä on?,Où est la connection pirate?,Hol az illegális lék?,,違法供給源 は何処だ?,불법 추출기는 어디있나요?,Waar is de illegale kraan?,Gdzie jest nielegalny przełącznik prądu?,Cadê a ligação clandestina?,,Unde e conexiunea ilegală?,Где нелегальное подключение?, -"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.","Ich sage dir wo er ist, aber ich weiß nicht, an wessen Anzapfung du herummanipulieren willst. Er ist genau hier in der Kläranlage.",,,"Te diré dónde está, pero no sé de quién será la línea eléctrica que estarás manipulando. 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.",,"それが何処にあるかは話そう、だがオレには +Where's the power coupling?,TXT_RPLY0_SCRIPT02_D98540_WHERE,,,,Kde je elektrická spojka?,Wo ist der Stromabnehmer?,,,¿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?,Gdzie jest odbierak prądu?,Cadê a conexão de energia?,,Unde e cuplajul energiei?,Где соединительная муфта?, +Where's the Order's main?,TXT_RPLY1_SCRIPT02_D98540_WHERE,,,,Kde má Řád napájecí síť?,Wo ist die Stromleitung des Ordens?,,,¿Dónde está la red principal 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?,Gdzie jest przewód Zakonu?,Cadê o transformador da Ordem?,,Unde e linia electrică a Ordinului?,Где линия электропередачи Ордена?, +Where's the illegal tap?,TXT_RPLY2_SCRIPT02_D98540_WHERE,,,,Kde je nelegální stáčedlo?,Wo ist die illegale Anzapfung?,,,¿Dónde está la intervención 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?,Gdzie jest nielegalny przełącznik prądu?,Cadê a ligação clandestina?,,Unde e conexiunea ilegală?,Где нелегальное подключение?, +"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.","Ich sage dir wo er ist, aber ich weiß nicht, an wessen Anzapfung du herummanipulieren willst. Er ist genau hier in der Kläranlage.",,,"Te diré dónde está, pero no sé de quién será la línea eléctrica que estarás manipulando. 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.","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.","Я скажу тебе, где она, но не знаю, которая тебе нужна. Она прямо здесь, в очистной системе.", -Thanks,TXT_RPLY0_SCRIPT02_D100056_THANK,,,,Díky.,Danke,,Dankon,Gracias,,Kiitos,Merci.,Kösz.,,ありがとう。,그렇군요.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., +Thanks,TXT_RPLY0_SCRIPT02_D100056_THANK,,,,Díky.,Danke,,Dankon,Gracias,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,그렇군요.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., 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.","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.",,,"Eso es justo aquí en la planta de aguas residuales. Pero es el acoplamiento del frente. Quien te dijo que era de la Orden estaba equivocado. -",,"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.",,"正にここの下水処理場にあるさ。 +",,"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.","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.,"Она прямо здесь, в очистном сооружении. Но это линия Сопротивления. Тот, кто сказал тебе, что она принадлежит Ордену, ошибся. ", -Thanks,TXT_RPLY0_SCRIPT02_D101572_THANK,,,,Díky.,Danke.,,Dankon,Gracias,,Kiitos,Merci.,Kösz.,,ありがとう。,고맙습니다.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., -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.","Wenn du sagst, es sei illegal, möchte ich nichts damit zu tun haben. Ich habe schon genug Probleme.",,,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.",,"それが違法だっつうんならオレには関係無い。 +Thanks,TXT_RPLY0_SCRIPT02_D101572_THANK,,,,Díky.,Danke.,,Dankon,Gracias,,Kiitos,Merci.,Kösz.,Grazie,ありがとう。,고맙습니다.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., +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.","Wenn du sagst, es sei illegal, möchte ich nichts damit zu tun haben. Ich habe schon genug Probleme.",,,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.","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.","Раз ты говоришь, что оно нелегально, я не хочу иметь с тобой дел. Мне и так хватает проблем.", -Thanks,TXT_RPLY0_SCRIPT02_D103088_THANK,,,,Díky.,Danke,,Dankon,Gracias,,Kiitos,Merci.,Kösz,,ありがとう。,감사합니다.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., -"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D104604_RELEA,,,,"Drž se dál, nech starce na pokoji.",Bitte lass einen alten Mann in Ruhe,,,"Suéltame, deja en paz 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.",,ほっといてくれ、年寄り一人にしてくれ。,보내주게. 이 노인은 이제 아무것도 몰라.,"Laat me vrij, laat een oude man met rust.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!, -"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,,,,"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. Pomoz nám.","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.",,,"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 inteligentes y muchos cuerpos capaces, pero nos falta un, uh ... solucionador de problemas, quien nos dará 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!",,"ようこそ、ここは我々の僅かな希望が集まる +Thanks,TXT_RPLY0_SCRIPT02_D103088_THANK,,,,Díky.,Danke,,Dankon,Gracias,,Kiitos,Merci.,Kösz,Grazie,ありがとう。,감사합니다.,Bedankt,Dzięki,Obrigado,,Mulțumesc,Спасибо., +"Release me, leave an old man alone.",TXT_DLG_SCRIPT02_D104604_RELEA,,,,"Drž se dál, nech starce na pokoji.",Bitte lass einen alten Mann in Ruhe,,,"Suéltame, deja en paz 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.","Nie zbliżaj się, zostaw starca w spokoju.","Me solte, deixe um velho em paz.",,"Lasă-mă, lasă bătrânii în pace.",Оставь старика в покое!, +"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,,,,"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.","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.",,,"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 inteligentes y muchos cuerpos capaces, pero nos falta un, uh ... solucionador de problemas, quien nos dará 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!","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. Aiutaci!","ようこそ、ここは我々の僅かな希望が集まる 最後の場所だ。オーダーへと立ち向かう意思を 持っているのは我々くらいだ。 ここには素晴らしい頭脳を持つ学者たち、そして @@ -8768,434 +8764,434 @@ Thanks,TXT_RPLY0_SCRIPT02_D103088_THANK,,,,Díky.,Danke,,Dankon,Gracias,,Kiitos, だがしかし、我々には問題解決に優れた者、 つまり私達の力となる者が足りていないんだ。 我々に手を貸してくれ。","최후의 희망 한 가닥을 잡은 것을 환영합니다. 우리만이 오더를 거부할 수 있는 의지를 갖추고 있죠. 뛰어난 과학력과 전투력은 다 갖추고 있습니다만, 정작 '해결사' 몫을 해주는 인물이 없어서 말입니다... 부디 우리를 도와주시길 바랍니다.","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.","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.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «разрешителя проблем», который поможет нам получить необходимое преимущество. Помоги нам.", -"All right, I accept.",TXT_RPLY0_SCRIPT03_D0_ALLRI,,,,"Dobře, příjimám.","Klar, ich bin dabei.",,,"De acuerdo, acepto.",,"Hyvä on, suostun auttamaan.",Très bien. J'accepte.,"Rendben, elfogadom.",,いいぞ、引き受けよう。,좋아요. 받아들이죠.,"Oké, ik accepteer het.","Dobrze, zgadzam się.","Tá certo, eu aceito.",,"În regulă, accept.",Хорошо. Я согласен., -No thanks!,TXT_RPLY1_SCRIPT03_D0_NOTHA,,,,"Ne, díky.","Nein, danke!",,Ne dankon!,¡No gracias!,,Ei kiitos!,Non merci.,Nem kösz!,,断る!,사양할게요!,"Nee, dank je wel!","Nie, dziękuję!","Não, obrigado!",,Nu merci!,"Нет уж, спасибо!", -"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.","Bitte überdenke das nochmal, angesichts der Tatsache, dass du von befaffneten und zornigen Rebellen umgeben bist.",,,"Es posible que desees reconsiderar, ya que estas rodeado de rebeldes enojados fuertemente 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.",,"少し考え直したほうが良さそうだぞ、 +"All right, I accept.",TXT_RPLY0_SCRIPT03_D0_ALLRI,,,,"Dobře, příjimám.","Klar, ich bin dabei.",,,"De acuerdo, acepto.",,"Hyvä on, suostun auttamaan.",Très bien. J'accepte.,"Rendben, elfogadom.","Va bene, accetto.",いいぞ、引き受けよう。,좋아요. 받아들이죠.,"Oké, ik accepteer het.","Dobrze, zgadzam się.","Tá certo, eu aceito.",,"În regulă, accept.",Хорошо. Я согласен., +No thanks!,TXT_RPLY1_SCRIPT03_D0_NOTHA,,,,"Ne, díky.","Nein, danke!",,Ne dankon!,¡No gracias!,,Ei kiitos!,Non merci.,Nem kösz!,"No, grazie!",断る!,사양할게요!,"Nee, dank je wel!","Nie, dziękuję!","Não, obrigado!",,Nu merci!,"Нет уж, спасибо!", +"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.","Bitte überdenke das nochmal, angesichts der Tatsache, dass du von befaffneten und zornigen Rebellen umgeben bist.",,,"Es posible que desees reconsiderar, ya que estas rodeado de rebeldes enojados fuertemente 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.","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.","Возможно, при виде нервных и вооружённых до зубов повстанцев ты передумаешь.", -"All right, I'm in!",TXT_RPLY0_SCRIPT03_D1516_ALLRI,,,,"Dobře, jdu do toho!","Na gut, ich bin dabei.",,,"De acuerdo, ¡quiero entrar!",,"Hyvä on, olen messissä!","Ok, d'accord, j'accepte!","Rendben, benne vagyok!",,わかった、乗ろう!,그럼 도와주도록 하죠.,"Oké, ik doe mee!","Dobra, wchodzę w to!","Tá certo, estou dentro!",,"Bine, mă bag!","Хорошо, я с вами!", -No thanks.,TXT_RPLY1_SCRIPT03_D1516_NOTHA,,,,"Ne, díky.","Nein, danke!",,,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,,断る。,싫어요! 당신은 낯선 사람이잖아요!,"Nee, bedankt.","Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.", -Then die in shame and dishonor.,TXT_DLG_SCRIPT03_D3032_THEND,,,Then die in shame and dishonour.,Pak zemři v hanbě a potupě!,Dann wirst du in Schande und Unehre sterben.,,,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.,,では、恥と不名誉と共に死ぬがいい。,그럼 불명예스럽고 초라하게 죽어버리시길!,Sterf dan in schaamte en oneer.,Więc giń we wstydzie i hańbie.,Então morra com desonra e vergonha!,,Atunci mori în rușine și dezonoare.,Тогда умри в бесчестии и позоре., -"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.","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.",,,"Bien, Blackbird continuará siendo tu guía. Parece que le caes bien. Juntos debéis descubrir los secretos de la Orden y sus sirvientes inhumanos. Entrad y echadlos abajo.","Bien, Blackbird continuará siendo tu guía. Parece que le caes bien. Juntos deberán descubrir los secretos de la Orden y sus sirvientes inhumanos. Penetrar y echarlos abajo.",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.",,"よし、君のガイドをブラックバードが今後務める +"All right, I'm in!",TXT_RPLY0_SCRIPT03_D1516_ALLRI,,,,"Dobře, jdu do toho!","Na gut, ich bin dabei.",,,"De acuerdo, ¡quiero entrar!",,"Hyvä on, olen messissä!","Ok, d'accord, j'accepte!","Rendben, benne vagyok!","Va bene, vi aiuterò!",わかった、乗ろう!,그럼 도와주도록 하죠.,"Oké, ik doe mee!","Dobra, wchodzę w to!","Tá certo, estou dentro!",,"Bine, mă bag!","Хорошо, я с вами!", +No thanks.,TXT_RPLY1_SCRIPT03_D1516_NOTHA,,,,"Ne, díky.","Nein, danke!",,,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,断る。,싫어요! 당신은 낯선 사람이잖아요!,"Nee, bedankt.","Nie, dziękuję.","Não, obrigado.",,Nu merci.,"Нет, спасибо.", +Then die in shame and dishonor.,TXT_DLG_SCRIPT03_D3032_THEND,,,Then die in shame and dishonour.,Pak zemři v hanbě a potupě!,Dann wirst du in Schande und Unehre sterben.,,,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.,Więc giń we wstydzie i hańbie.,Então morra com desonra e vergonha!,,Atunci mori în rușine și dezonoare.,Тогда умри в бесчестии и позоре., +"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.","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.",,,"Bien, Blackbird continuará siendo tu guía. Parece que le caes bien. Juntos debéis descubrir los secretos de la Orden y sus sirvientes inhumanos. Entrad y echadlos abajo.","Bien, Blackbird continuará siendo tu guía. Parece que le caes bien. Juntos deberán descubrir los secretos de la Orden y sus sirvientes inhumanos. Penetrar y echarlos abajo.",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.","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.",Хорошо. Чёрный дрозд останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его бесчеловечных слуг. Проникни на их территорию и ударь по ним как следует! , -Where do I start?,TXT_RPLY0_SCRIPT03_D4548_WHERE,,,,Kde mám začít?,Wo fange ich an?,,Kie mi komencas?,¿Por dónde empiezo?,,Mistä aloitan?,Où est-ce que je commence?,Hol kezdjem?,,どこから始めればいいんだ?,어디서부터 시작하면 되죠?,Waar moet ik beginnen?,Gdzie zaczynam?,Por onde eu começo?,,Unde încep?,С чего мне начать?, -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,,,,"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.","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.",,,Fráncamente la situación es un lío. Debes completar varias misiones para preparar el camino a más ataques contra la Orden. Nuestra última incursión fue un desastre y la mayoría de nuestras tropas fueron capturadas. Necesito que liberes a estos prisioneros.,,"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!",,"はっきり言えば、今の状況は全く良くない。 +Where do I start?,TXT_RPLY0_SCRIPT03_D4548_WHERE,,,,Kde mám začít?,Wo fange ich an?,,Kie mi komencas?,¿Por dónde empiezo?,,Mistä aloitan?,Où est-ce que je commence?,Hol kezdjem?,Da dove comincio?,どこから始めればいいんだ?,어디서부터 시작하면 되죠?,Waar moet ik beginnen?,Gdzie zaczynam?,Por onde eu começo?,,Unde încep?,С чего мне начать?, +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,,,,"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.","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.",,,Fráncamente la situación es un lío. Debes completar varias misiones para preparar el camino a más ataques contra la Orden. Nuestra última incursión fue un desastre y la mayoría de nuestras tropas fueron capturadas. Necesito que liberes a estos prisioneros.,,"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.,"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.,"Честно говоря, наши дела идут не лучшим образом. Тебе предстоит выполнить несколько заданий, чтобы подготовить почву для дальнейших атак на Орден. Наша последняя вылазка обернулась катастрофой, и большинство наших бойцов были схвачены. Мне нужно, чтобы ты освободил их.", -I think I can handle it.,TXT_RPLY0_SCRIPT03_D6064_ITHIN,,,,"Myslím, že to zvládnu.","Ich denke, das kann ich schaffen.",,,Creo que puedo hacerlo.,,Eiköhän se onnistu.,Je pense pouvoir m'en occuper.,Azt hiszem el tudom intézni.,,俺ならできるはずだ。,아마도 제가 할 수 있을 것 같군요.,Ik denk dat ik het aankan.,"Myślę, że dam sobie z tym radę.",Acho que eu posso dar conta disso.,,Cred că mă pot descurca.,"Думаю, справлюсь.", -"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.","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.",,,"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 compatriotas.",,"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.",,"この金で、我らの武器を調達してくれている +I think I can handle it.,TXT_RPLY0_SCRIPT03_D6064_ITHIN,,,,"Myslím, že to zvládnu.","Ich denke, das kann ich schaffen.",,,Creo que puedo 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.,"Myślę, że dam sobie z tym radę.",Acho que eu posso dar conta disso.,,Cred că mă pot descurca.,"Думаю, справлюсь.", +"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.","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.",,,"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 compatriotas.",,"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.","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.","Возьми эти деньги и посети Ирэйла, нашего поставщика оружия. Затем, с этим ключом, ты пройдёшь к губернатору. Он продажная марионетка Ордена, но обожает торговаться. Делай всё, что сочтёшь нужным, но освободи наших братьев по оружию.", -I'll see to it.,TXT_RPLY0_SCRIPT03_D7580_ILLSE,,,,Dohlédnu na to.,"Ich seh, was ich machen kann.",,,Veré que hacer.,,Hoidan asian.,Je m'y attelle.,Megteszem.,,了解した。,한 번 확인하러 가보겠습니다.,Ik zal ervoor zorgen.,Zajmę się tym.,Vou dar um jeito nisso.,,O să mă ocup.,Я позабочусь об этом., -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D9096_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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!,,フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Verhuizen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., -"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,,,,"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.","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.",,,"Los prisioneros han sido bienvenidos de vuelta, gracias a ti. Aquí tienes algo de oro, ve a ver al médico y al entrenador de armamento 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'll see to it.,TXT_RPLY0_SCRIPT03_D7580_ILLSE,,,,Dohlédnu na to.,"Ich seh, was ich machen kann.",,,Veré que hacer.,,Hoidan asian.,Je m'y attelle.,Megteszem.,Mi darò da fare.,了解した。,한 번 확인하러 가보겠습니다.,Ik zal ervoor zorgen.,Zajmę się tym.,Vou dar um jeito nisso.,,O să mă ocup.,Я позабочусь об этом., +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D9096_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., +"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,,,,"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.","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.",,,"Los prisioneros han sido bienvenidos de vuelta, gracias a ti. Aquí tienes algo de oro, ve a ver al médico y al entrenador de armamento 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.","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.","Благодаря тебе, пленники вернулись к нам. Вот немного золота. Посети медика и инструктора по стрельбе, а потом тебя ждут ещё более ответственные задания.", -I will. What's next?,TXT_RPLY0_SCRIPT03_D10612_IWILL,,,,Půjdu. Co dál?,"Alles klar, was gibt's als Nächstes?",,,Lo haré. ¿Qué es lo siguiente?,Lo haré. ¿Qué sigue?,Menen. Mitä seuraavaksi on luvassa?,"Très bien, quoi maintenant?",Így teszek. Mi a következő lépés?,,次は何だ?,그렇군요. 그 다음은 뭐죠?,Dat zal ik doen. Wat is het volgende?,Dobrze. Co dalej?,Farei isso. Qual a próxima missão?,,Mă voi conforma. Ce facem mai departe?,Хорошо. Что дальше?, -"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 zasadíš obří ránu obranám Řádu. Straka tě navede ke špiónovi, který zná cestu dovnitř. Hodně štěstí.","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.",,,"Un único cristal alimenta la red eléctrica que mantiene los escudos de la Orden. 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.",,"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.",,"とあるパワークリスタルがオーダー基地の +I will. What's next?,TXT_RPLY0_SCRIPT03_D10612_IWILL,,,,Půjdu. Co dál?,"Alles klar, was gibt's als Nächstes?",,,Lo haré. ¿Qué es lo siguiente?,Lo haré. ¿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?,Dobrze. Co dalej?,Farei isso. Qual a próxima missão?,,Mă voi conforma. Ce facem mai departe?,Хорошо. Что дальше?, +"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í.","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.",,,"Un único cristal alimenta la red eléctrica que mantiene los escudos de la Orden. 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.",,"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.","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ă.","Энергосеть, которая питает щиты Ордена, работает от одного кристалла. Уничтожь этот кристалл, и ты пробьёшь огромную брешь в их обороне. Чёрный дрозд приведёт тебя к шпиону, который знает, как проникнуть на станцию. Удачи!", -We'll get it.,TXT_RPLY0_SCRIPT03_D12128_WELLG,,,,Zničíme jej.,Das werden wir hinkriegen.,,,Lo conseguiremos.,,Saamme sen.,Je m'en occupe.,Megszerezzük.,,すぐ始めよう。,그 수정체를 파괴하겠습니다.,We krijgen het wel.,Poradzimy sobie.,Vamos conseguir.,,Vom ajunge în interior.,Мы справимся., -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D13644_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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!,,フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptați pentru Front și libertate. Acum plecați.,Сражайся за свободу и справедливость. Вперёд., -"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,,,,"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. Zabijte Programátora. Je čas odhalit, co jsme se dozvěděli o Řádu.","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.",,,"Has superado todas nuestras expectativas. Por tú hazaña nuestras tropas están en movimiento. Quiero que los dos os unais al asalto, con un objetivo específico. Acabar con el Programador. Es hora de revelar lo que hemos encontrado de esta capa de la Orden.","Has superado todas nuestras expectativas. Por tú hazaña nuestras tropas están en movimiento. Quiero que ambos se unan al asalto, con un objetivo específico. Acabar con el Programador. Es hora de revelar lo que hemos encontrado de esta capa 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.,,"君達は我々の期待を超える活躍を行ってくれた。 +We'll get it.,TXT_RPLY0_SCRIPT03_D12128_WELLG,,,,Zničíme jej.,Das werden wir hinkriegen.,,,Lo conseguiremos.,,Saamme sen.,Je m'en occupe.,Megszerezzük.,Ce la faremo.,すぐ始めよう。,그 수정체를 파괴하겠습니다.,We krijgen het wel.,Poradzimy sobie.,Vamos conseguir.,,Vom ajunge în interior.,Мы справимся., +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D13644_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptați pentru Front și libertate. Acum plecați.,Сражайся за свободу и справедливость. Вперёд., +"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,,,,"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 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.",,,"Has superado todas nuestras expectativas. Por tú hazaña nuestras tropas están en movimiento. Quiero que los dos os unais al asalto, con un objetivo específico. Acabar con el Programador. Es hora de revelar lo que hemos encontrado de esta capa de la Orden.","Has superado todas nuestras expectativas. Por tú hazaña nuestras tropas están en movimiento. Quiero que ambos se unan al asalto, con un objetivo específico. Acabar con el Programador. Es hora de revelar lo que hemos encontrado de esta capa 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.","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.","Ты превзошёл все наши ожидания. Благодаря твоей отваге, наши войска уже в пути. Я хочу, чтобы вы двое присоединились к атаке, с особой целью — уничтожить Программиста. Настало время рассказать всё, что мы смогли узнать об этом уровне власти в Ордене.", -Tell me what we know.,TXT_RPLY0_SCRIPT03_D15160_TELLM,,,,"Řekni mi, co víme.",Sag mir was du weißt.,,,Dime lo que sabemos.,,"Kerro, mitä tiedämme.",Donnez-moi ce que vous savez.,Mondd el mit tudtunk meg.,,こちらに知っている事を教えてくれ。,그 비밀에 대해서 알려주세요.,Vertel me wat we weten.,Powiedz co wiadomo.,Conte-me o que sabemos.,,Spune-mi ce știi.,Расскажи мне всё., -"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.",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 guarida del Programador está en el castillo. Ahora, ve a ver al médico, toma algo de munición y ve a por él.","La guarida del Programador está en el castillo. Ahora, ve a ver al médico, toma algo de 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.",,"プログラマーの居場所は城内だ。それと、 +Tell me what we know.,TXT_RPLY0_SCRIPT03_D15160_TELLM,,,,"Řekni mi, co víme.",Sag mir was du weißt.,,,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.,Powiedz co wiadomo.,Conte-me o que sabemos.,,Spune-mi ce știi.,Расскажи мне всё., +"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.",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 guarida del Programador está en el castillo. Ahora, ve a ver al médico, toma algo de munición y ve a por él.","La guarida del Programador está en el castillo. Ahora, ve a ver al médico, toma algo de 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.","プログラマーの居場所は城内だ。それと、 メディックと訓練士に会い弾薬を補給したら 奴を倒せ。","프로그래머가 거주하는 곳은 성채 안에 있습니다. 의무관과 무기 담당관을 찾아뵈서 준비를 당당히 하시길 바랍니다. \cy일생일대의 격전에 대비해. 돈 아끼지 말고 있는 대로 다 써.","Het hol van de programmeur is in het kasteel. Ga nu naar de dokter, pak wat munitie en ga hem halen.","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.","Программист устроил себе логово в замке. Теперь проверь снаряжение, возьми всё, что тебе понадобится, и расправься с ним.", -Let me at 'em!,TXT_RPLY0_SCRIPT03_D16676_LETME,,,,Pusť mě na ně!,Lass mich das nur machen.,,,¡Voy a por ellos!,¡Voy por ellos!,Päästä minut niiden kimppuun!,Je vais me le faire!,Elkapom mindet!,,任せろ!,한 번 저질러 봅시다!,Laat me er naartoe gaan!,Niech ja go dorwę!,Pode deixar!,,Le voi arăta eu lor!,Я им покажу!, -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D18192_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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!,,フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., -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,,,,"Pamatuješ si, jak dřív vypadala radnice? To je jemná přípomínka toho, co jsou schopni udělat nám. Buď opatrný.","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.",,,¿Recuerdas cómo se ve el ayuntamiento? Ese es un pequeño recordatorio 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.",,"市庁舎の外観を見たか?あれが我々に対する +Let me at 'em!,TXT_RPLY0_SCRIPT03_D16676_LETME,,,,Pusť mě na ně!,Lass mich das nur machen.,,,¡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!,Niech ja go dorwę!,Pode deixar!,,Le voi arăta eu lor!,Я им покажу!, +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT03_D18192_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., +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,,,,"Pamatuješ si, jak dřív vypadala radnice? To je jemná přípomínka toho, co jsou schopni nám udělat. Buď opatrný.","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.",,,¿Recuerdas cómo se ve el ayuntamiento? Ese es un pequeño recordatorio 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.,"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ă.,"Видел, что стало с городской ратушей? Это мягкий намёк на то, что они сделают, если доберутся до нас. Будь осторожен.", -Talk to Macil. He'll be able to help you.,TXT_DLG_SCRIPT03_D21224_TALKT,,,,Promluv si s Macilem. On ti pomůže.,Rede mit Macil. Er kann dir helfen.,,,Habla con Macil. Él te podrá ayudar.,,Puhu Macilille. Hän pystyy auttamaan sinua.,Parlez à Macil. Il pourra vous aider.,Beszélj Macil-lal. Ő tud segíteni neked.,,マシルと話すんだ。彼から援助が得られるはず。,도움이 필요한가? 그럼 마실 사령관님을 찾아.,Praat met Macil. Hij zal je kunnen helpen.,Porozmawiaj z Macilem. Pomoże ci.,Fale com Macil. Ele vai poder te ajudar.,,Discută cu Macil. Te va ajuta el.,Поговори с Мэйсилом. Он сможет тебе помочь., -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,,,,"Slyšel jsem, že Macil má plán, jak porazit Řád. Doufejme, že dobrý. Ještě jeden nezdar a všichni jsme mrtví.","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 tiene un plan para desestabilizar a la Orden. Más vale que sea bueno. Un fallo más y somos carne muerta.,,"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.",,"私はマシルがオーダーを転覆させる計画を +Talk to Macil. He'll be able to help you.,TXT_DLG_SCRIPT03_D21224_TALKT,,,,Promluv si s Macilem. On ti pomůže.,Rede mit Macil. Er kann dir helfen.,,,Habla con Macil. Él te podrá 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.,Porozmawiaj z Macilem. Pomoże ci.,Fale com Macil. Ele vai poder te ajudar.,,Discută cu Macil. Te va ajuta el.,Поговори с Мэйсилом. Он сможет тебе помочь., +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,,,,"Slyšel jsem, že Macil má plán, jak porazit Řád. Doufejme, že dobrý. Ještě jeden nezdar a všichni jsme mrtví.","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 tiene un plan para desestabilizar a la Orden. Más vale que sea bueno. Un fallo más y somos carne muerta.,,"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.,"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ă.,"Я слышал, что Мэйсил разработал план свержения Ордена. Лучше бы ему сработать. Ещё одна ошибка, и мы все покойники.", -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.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,,Unos cuantos de estos barriles arrojados en su suministro de agua deberían igualar las probabilidades un poco.,,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.,,"ここの樽は捨てられていた物で +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.,"Wenn wir ein paar von diesen Fässern in die Wasserversorgung kippen, sollte das unsere Chancen etwas verbessern.",,,Unos cuantos de estos barriles arrojados en su suministro de agua deberían igualar las probabilidades un poco.,,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.",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.,"Несколько таких бочек, сброшенных в их водоснабжение, причинят немало неприятностей.", -"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í.","So, du bist der neue Agent? Danke, ohne dich wären wir schon alle tot.",,,"¿Así que eres el nuevo operativo? Gracias, sin ti, 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.",,"貴方が新しい工作員かい? それはありがたい、 +"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í.","So, du bist der neue Agent? Danke, ohne dich wären wir schon alle tot.",,,"¿Así que eres el nuevo operativo? Gracias, sin ti, 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.","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.","Так это ты наш новый агент? Спасибо. Если бы не ты, мы бы все уже были мертвы.", -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,,,,"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?","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?",,,Estoy trabajando en algo que nos dará una ventaja. Aumentará tu aguante y te pondrá las pilas. 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?",,"私は研究にも取り組んでいる。貴方のスタミナを +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,,,,"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?","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?",,,Estoy trabajando en algo que nos dará una ventaja. Aumentará tu aguante y te pondrá las pilas. 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?,"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?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Или тебе нужно что-то ещё?", -Patch me up.,TXT_RPLY0_SCRIPT03_D27288_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., -"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,君、滅茶苦茶だな。なんとかしよう。,"당신, 정말 엉망이네요... 어떻게든 치료해줄게요.","Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","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.","Парень, да на тебя смотреть страшно. Приступим...", -Stamina implant?,TXT_RPLY1_SCRIPT03_D27288_STAMI,,,,Implantát pro výdrž?,Ausdauerimplantat?,,,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Implant zwiększający wytrzymałość?,Implante de resistência?,,Implant pentru rezistență?,Выносливостный имплант?, -"All right, this won't take but a moment.",TXT_RYES1_SCRIPT03_D27288_ALLRI,,,,"Dobře, tohle potrvá jen chvilku.","Alles klar, das haben wir sofort.",,,"Muy bien, esto solo 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.",,いいでしょう、これは時間を取りません。,좋습니다. 시간이 오래 걸리진 않을 거예요.,"Oké, dit duurt maar een momentje.","Dobra, to zajmie tylko chwilę.","Ok, só um momento.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.", -It's not done yet.,TXT_RNO1_SCRIPT03_D27288_ITSNO,,,,Ještě není hotový.,Es ist noch nicht soweit.,,,Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,,まだ完成していません。,아직 완료되지는 않았어요.,Het is nog niet klaar.,Jeszcze nie jest gotowy.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов., -"Hey, I'm working on an updated version of your implant. Is there anything else I can do?",TXT_DLG_SCRIPT03_D28804_HEYIM,,,,"Hej, pracuju na vylepšené verzi tvého implantátu. Můžu pro tebe udělat něco jiného?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Hey, 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?,,"どうも、私は今最新版のインプラントに +Patch me up.,TXT_RPLY0_SCRIPT03_D27288_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., +"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.","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.","Парень, да на тебя смотреть страшно. Приступим...", +Stamina implant?,TXT_RPLY1_SCRIPT03_D27288_STAMI,,,,Implantát pro výdrž?,Ausdauerimplantat?,,,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,Implant zwiększający wytrzymałość?,Implante de resistência?,,Implant pentru rezistență?,Выносливостный имплант?, +"All right, this won't take but a moment.",TXT_RYES1_SCRIPT03_D27288_ALLRI,,,,"Dobře, tohle potrvá jen chvilku.","Alles klar, das haben wir sofort.",,,"Muy bien, esto solo 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.","Dobra, to zajmie tylko chwilę.","Ok, só um momento.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.", +It's not done yet.,TXT_RNO1_SCRIPT03_D27288_ITSNO,,,,Ještě není hotový.,Es ist noch nicht soweit.,,,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.,Jeszcze nie jest gotowy.,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов., +"Hey, I'm working on an updated version of your implant. Is there anything else I can do?",TXT_DLG_SCRIPT03_D28804_HEYIM,,,,"Hej, pracuju na vylepšené verzi tvého implantátu. Můžu pro tebe udělat něco jiného?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Hey, 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?","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?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?", -Patch me up.,TXT_RPLY0_SCRIPT03_D28804_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., -Well at least your seeing action.,TXT_RYES0_SCRIPT03_D28804_WELLA,,,,"No, alespoň se nenudíš.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,Bueno al menos estás viendo 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ó.,,貴方の働きは聞き届いてるよ。,이제 전장에 힘을 발휘해보세요!,"Nou ja, in ieder geval uw zien actie.",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.","Что ж, зато ты участвуешь в операциях.", -Implant upgrade?,TXT_RPLY1_SCRIPT03_D28804_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Ulepszenie implantu?,Versão aprimorada do implante?,,Upgrade pentru implant?,Улучшение импланта?, -"Good thing, never can be too safe.",TXT_RYES1_SCRIPT03_D28804_GOODT,,,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Alles klar, das haben wir sofort.",,,"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.",,良いことだ、安全すぎることはない。,좋은 선택입니다. 이거 없이는 안전할 수가 없죠.,"Goede zaak, kan nooit te veilig zijn.","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.","Очень советую, ни в чём нельзя быть уверенным до конца.", -"I'm almost finished, but not quite.",TXT_RNO1_SCRIPT03_D28804_IMALM,,,,"Už je skoro hotový, ale ne úplně.",Es ist noch nicht soweit.,,,"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.",,もうすぐ出来上がる、それほど掛からない。,"거의 다 돼가지만, 아직 완성된 게 아니에요.","Ik ben bijna klaar, maar niet helemaal.","Prawie skończyłem, ale nie do końca.",Estou quase terminando. Só mais um pouco.,,"Sunt aproape gata, dar nu tocmai.",Я почти закончил. Ещё немного., -"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,,,,"Tak dobře, už mi skoro všechno perfektně funguje. Ještě tam bylo pár problémů. Potřebuješ ještě něco?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Muy bien, tengo casi todo funcionando a la perfección. Solo quedaron algunos problemas que eliminar. ¿Necesitas algo mas?",,"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?",,"大丈夫、全て順調だ。残っていた問題も +Patch me up.,TXT_RPLY0_SCRIPT03_D28804_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., +Well at least your seeing action.,TXT_RYES0_SCRIPT03_D28804_WELLA,,,,"No, alespoň se nenudíš.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,Bueno al menos estás viendo 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.",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.","Что ж, зато ты участвуешь в операциях.", +Implant upgrade?,TXT_RPLY1_SCRIPT03_D28804_IMPLA,,,,Vylepšený implantát?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Ulepszenie implantu?,Versão aprimorada do implante?,,Upgrade pentru implant?,Улучшение импланта?, +"Good thing, never can be too safe.",TXT_RYES1_SCRIPT03_D28804_GOODT,,,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Alles klar, das haben wir sofort.",,,"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.","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.","Очень советую, ни в чём нельзя быть уверенным до конца.", +"I'm almost finished, but not quite.",TXT_RNO1_SCRIPT03_D28804_IMALM,,,,"Už je skoro hotový, ale ne úplně.",Es ist noch nicht soweit.,,,"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.","Prawie skończyłem, ale nie do końca.",Estou quase terminando. Só mais um pouco.,,"Sunt aproape gata, dar nu tocmai.",Я почти закончил. Ещё немного., +"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,,,,"Tak dobře, už mi skoro všechno perfektně funguje. Ještě tam bylo pár problémů. Potřebuješ ještě něco?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Muy bien, tengo casi todo funcionando a la perfección. Solo quedaron algunos problemas que eliminar. ¿Necesitas algo mas?",,"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?","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?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?", -Patch me up.,TXT_RPLY0_SCRIPT03_D30320_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Tratează-mă.,Перебинтуй меня., -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?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,¿Qué has intentado hacer? ¿Encabezonarte con un Cruzado?,¿Qué has intentado hacer? ¿Pelear cabeza a cabeza 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?,,"今度は何を始めるんだ? +Patch me up.,TXT_RPLY0_SCRIPT03_D30320_PATCH,,,,Dej mě dohromady.,Flick mich zusammen.,,,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,Opatrz mnie.,Trate meus ferimentos.,,Tratează-mă.,Перебинтуй меня., +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?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,¿Qué has intentado hacer? ¿Encabezonarte con un Cruzado?,¿Qué has intentado hacer? ¿Pelear cabeza a cabeza 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?,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?,"Ты что, бился один на один с крестоносцем?", -Implant upgrade?.,TXT_RPLY1_SCRIPT03_D30320_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Ulepszenie implantu?,Melhoria de implante?,,Upgrade pentru implant?,Улучшение импланта?, -That should do it for you.,TXT_RYES1_SCRIPT03_D30320_THATS,,,,Tohle by mělo fungovat.,"Alles klar, das haben wir sofort.",,,Con esto debería estar.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez már így jó lesz.,,今取り掛かっている。,이것만 있음 될 겁니다.,Dat zou het voor u moeten doen.,To powinno ci wystarczyć.,Isso deve funcionar.,,Ar trebui să fie bine acum.,Вот оно., -Let me run some more tests first.,TXT_RNO1_SCRIPT03_D30320_LETME,,,,Ještě ho musím dál otestovat.,Es ist noch nicht soweit.,,,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.,,もう少しテストしてからにしよう。,"우선, 시험을 좀 거쳐야 해요.",Laat me eerst nog wat testen doen.,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.,Дай мне ещё времени на тесты., -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í?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,,Eso es todo lo que puedo hacer con el implante por ahora. ¿Qué tal una cura?,,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?,,"インプラントはこれ以上ない程完成した。 +Implant upgrade?.,TXT_RPLY1_SCRIPT03_D30320_IMPLA,,,,Vylepšený implantát?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,Ulepszenie implantu?,Melhoria de implante?,,Upgrade pentru implant?,Улучшение импланта?, +That should do it for you.,TXT_RYES1_SCRIPT03_D30320_THATS,,,,Tohle by mělo fungovat.,"Alles klar, das haben wir sofort.",,,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.,To powinno ci wystarczyć.,Isso deve funcionar.,,Ar trebui să fie bine acum.,Вот оно., +Let me run some more tests first.,TXT_RNO1_SCRIPT03_D30320_LETME,,,,Ještě ho musím dál otestovat.,Es ist noch nicht soweit.,,,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.,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.,Дай мне ещё времени на тесты., +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í?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,,Eso es todo lo que puedo hacer con el implante por ahora. ¿Qué tal una cura?,,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?,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?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?, -Yeah.,TXT_RPLY0_SCRIPT03_D31836_YEAH,,,,Jo.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,,ああ。,네.,Ja.,Pewnie.,Pode ser.,,Da.,Давай., -"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,君、滅茶苦茶だな。なんとかしよう。,심각한 부상을 입은 것 같군요. 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.","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.","Ты просто месиво. Посмотрим, что я смогу сделать.", -What can I do for you?,TXT_DLG_SCRIPT03_D33352_WHATC,,,,Co pro tebe můžu udělat?,Was kann ich für dich tun?,,,¿Qué puedo hacer por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Miben segíthetek?,,どういったご用件で?,필요한 게 있으면 말씀하세요.,Wat kan ik voor je doen?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?, -I'm out of bullets.,TXT_RPLY0_SCRIPT03_D33352_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D33352_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,,この弾をどうぞ、無駄遣いしないように。,여기 조금의 탄약을 나눠줄게요. 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., -Teach me.,TXT_RPLY1_SCRIPT03_D33352_TEACH,,,,Uč mě.,Unterrichte mich.,,,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -"All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT03_D33352_ALLRI,,,,"Dobře, ukážu ti pár triků.","Alles klar, ich zeige dir ein paar Kniffe.",,,"Muy bien, te daré algunos pequeños 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.,,わかった、貴方にやり方を幾つか教えよう。,좋아요. 훈련에 도움이 될 만한 표적을 보여주겠습니다.,"Oké, ik zal je gewoon een paar kleine tips laten zien.","Dobrze, podam ci parę wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, o să îți arăt niște repere.",Хорошо. Покажу тебе пару приёмов., -You're not ready yet.,TXT_RNO1_SCRIPT03_D33352_YOURE,,,,Ještě nejsi připravený.,Du bist noch nicht so weit.,,,Aun no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Még nem állsz készen.,,貴方の準備がまだ整ってないように思えます。,아직 준비가 안 됐어요.,Je bent nog niet klaar.,Nie jesteś jeszcze gotowy.,Você ainda não está pronto.,,Nu ești pregătit încă.,Ты ещё не готов., -Back again? What do you need?,TXT_DLG_SCRIPT03_D34868_BACKA,,,,Zase zpátky? Co potřebuješ?,Scxhon zurück? Was brauchst du?,,,¿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?,,もう戻りましたか?何が必要ですか?,또 왔네? 뭐가 필요합니까?,Weer terug? Wat heb je nodig?,Wróciłeś? Czego chcesz?,Você novamente? Do que precisa?,,Te-ai întors iar? De ce ai nevoie?,Ты вернулся? Что тебе нужно?, -I'm out of bullets.,TXT_RPLY0_SCRIPT03_D34868_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a golyókból.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D34868_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,,この弾をどうぞ、無駄遣いしないように。,뭘 하다 탄약을 낭비한 겁니까? 여기 조금 줄게요.,Hier is wat munitie voor je. Verspil het niet.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT03_D34868_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,弾は十分に見えます。,당신은 충분한 탄약을 가졌어요.,Je hebt genoeg munitie.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Au destulă muniție.,У тебя их достаточно., -Teach me.,TXT_RPLY1_SCRIPT03_D34868_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -"All right, this should keep you going for a while.",TXT_RYES1_SCRIPT03_D34868_ALLRI,,,,"Dobře, tohle by ti mělo pomoct.","Alles klar, das sollte fürs erste reichen.",,,"Muy bien, esto te mantendrá por un tiempo.",,"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.",,わかりました、これで長くやり合えるでしょう。,그렇군요. 가능한 오래 싸울 수 있을겁니다.,"Oké, dit zou je een tijdje op de been moeten houden.","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.","Хорошо, это не раз спасёт тебе жизнь.", -"Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT03_D34868_SORRY,,,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,,"Lo siento, no puedo. Solo sigo las ó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.",,すまないが、できません。マシルの命令です。,미안합니다. 마실 사령관님의 명령을 따라야해요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.","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.","Увы, не могу. Я подчиняюсь Мэйсилу.", -"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,,,,"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.","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.",,,"Bien, ¿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.",,"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ú.",,"弾薬と訓練、どっちの用件ですか? +Yeah.,TXT_RPLY0_SCRIPT03_D31836_YEAH,,,,Jo.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,네.,Ja.,Pewnie.,Pode ser.,,Da.,Давай., +"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.","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.","Ты просто месиво. Посмотрим, что я смогу сделать.", +What can I do for you?,TXT_DLG_SCRIPT03_D33352_WHATC,,,,Co pro tebe můžu udělat?,Was kann ich für dich tun?,,,¿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?,Co mogę dla ciebie zrobić?,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?, +I'm out of bullets.,TXT_RPLY0_SCRIPT03_D33352_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D33352_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., +Teach me.,TXT_RPLY1_SCRIPT03_D33352_TEACH,,,,Uč mě.,Unterrichte mich.,,,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +"All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT03_D33352_ALLRI,,,,"Dobře, ukážu ti pár triků.","Alles klar, ich zeige dir ein paar Kniffe.",,,"Muy bien, te daré algunos pequeños 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.","Dobrze, podam ci parę wskazówek.","Ok, vou te dar algumas dicas.",,"În regulă, o să îți arăt niște repere.",Хорошо. Покажу тебе пару приёмов., +You're not ready yet.,TXT_RNO1_SCRIPT03_D33352_YOURE,,,,Ještě nejsi připravený.,Du bist noch nicht so weit.,,,Aun 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.,Nie jesteś jeszcze gotowy.,Você ainda não está pronto.,,Nu ești pregătit încă.,Ты ещё не готов., +Back again? What do you need?,TXT_DLG_SCRIPT03_D34868_BACKA,,,,Zase zpátky? Co potřebuješ?,Scxhon zurück? Was brauchst du?,,,¿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?,Wróciłeś? Czego chcesz?,Você novamente? Do que precisa?,,Te-ai întors iar? De ce ai nevoie?,Ты вернулся? Что тебе нужно?, +I'm out of bullets.,TXT_RPLY0_SCRIPT03_D34868_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,Nie mam nabojów.,Estou sem balas.,,Nu mai am gloanțe.,У меня кончились патроны., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D34868_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT03_D34868_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,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.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Au destulă muniție.,У тебя их достаточно., +Teach me.,TXT_RPLY1_SCRIPT03_D34868_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +"All right, this should keep you going for a while.",TXT_RYES1_SCRIPT03_D34868_ALLRI,,,,"Dobře, tohle by ti mělo pomoct.","Alles klar, das sollte fürs erste reichen.",,,"Muy bien, esto te mantendrá por un tiempo.",,"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.","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.","Хорошо, это не раз спасёт тебе жизнь.", +"Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT03_D34868_SORRY,,,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,,"Lo siento, no puedo. Solo sigo las ó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.","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.","Увы, не могу. Я подчиняюсь Мэйсилу.", +"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,,,,"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.","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.",,,"Bien, ¿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.",,"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.","弾薬と訓練、どっちの用件ですか? 奪った新しい武器が届くのを待ち切れないです。 少しの訓練でデカい復讐を。","무엇을 원하십니까? 보급? 아니면 훈련? 방금 전달된 새로운 무기들을 만지고 싶습니다! 아무튼, 훈련을 거치면 복수를 멋지게 해내실 거에요.","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.","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.","Что скажешь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Небольшая подготовка, и они за всё заплатят.", -I'm out of ammo.,TXT_RPLY0_SCRIPT03_D36384_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Nie mam amunicji.,Estou sem munição.,,Nu mai am muniție.,У меня кончились боеприпасы., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D36384_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,,この弾をどうぞ、無駄遣いしないように。,여기 탄약입니다. 부디 열심히 싸우고 정확하게 쏘시길.,Hier is wat munitie voor je. Verspil het niet.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT03_D36384_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,弾は十分に見えます。,거짓말. 탄약을 충분히 가졌잖아요.,Je hebt genoeg munitie.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Ai destulă muniție.,У тебя хватает патронов., -Teach me.,TXT_RPLY1_SCRIPT03_D36384_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -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.","OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,,OK. Toma lo que has aprendido y muéstrales a esos patanes de la Orden el camino 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.,,"オーケー、ここで学んだ事を生かして +I'm out of ammo.,TXT_RPLY0_SCRIPT03_D36384_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,Nie mam amunicji.,Estou sem munição.,,Nu mai am muniție.,У меня кончились боеприпасы., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT03_D36384_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,Masz tu trochę amunicji. Nie zmarnuj jej.,Tome um pouco de munição. Não desperdice.,,Uite niște muniție. N-o risipi.,Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT03_D36384_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,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.,Masz już wystarczająco dużo amunicji.,Você já tem munição o suficiente.,,Ai destulă muniție.,У тебя хватает патронов., +Teach me.,TXT_RPLY1_SCRIPT03_D36384_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Entréname.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Ucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +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.","OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,,OK. Toma lo que has aprendido y muéstrales a esos patanes de la Orden el camino 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. 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.,"Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.", -"Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT03_D36384_COMEB,,,,"Přijď někdy jindy, až řekne Macil.","Komm wieder, wenn Macil dir Bescheid gibt.",,,"Vuelve más tarde, cuando Macil diga que 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.",,マシルの命令を受けてから、また来なさい。,사령관님은 인내심이 많은 분입니다. 나중에 확인해주시길.,"Kom later terug, als Macil zegt dat het tijd is.","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.","Приходи позже, когда прикажет Мэйсил.", -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,,,,"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.","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.",,,"Te he enseñado todo lo que puedo por ahora. Dame un tiempo para poner las nuevas armas a punto. Claro está, si no es que te has quedado sin balas.",,"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.",,"私が教えられる事はもうありません。 +"Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT03_D36384_COMEB,,,,"Přijď někdy jindy, až řekne Macil.","Komm wieder, wenn Macil dir Bescheid gibt.",,,"Vuelve más tarde, cuando Macil diga que 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.","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.","Приходи позже, когда прикажет Мэйсил.", +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,,,,"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.","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.",,,"Te he enseñado todo lo que puedo por ahora. Dame un tiempo para poner las nuevas armas a punto. Claro está, si no es que te has quedado sin balas.",,"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.,"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.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?, -Yes I am.,TXT_RPLY0_SCRIPT03_D37900_YESIA,,,,"Ano, potřebuju.","Ja, bin ich.",,"Jes, mi estas.",Eso mismo.,,Kyllä on.,"En effet, je le suis.","Igen, az vagyok.",,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",Zgadza się.,"Sim, estou.",,"Da, am rămas fără.","Да, закончились.", -Here you go.,TXT_RYES0_SCRIPT03_D37900_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,,どうぞ。,여기 있어요!,Alsjeblieft.,Masz.,Aqui está.,,Iată.,Держи., -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,,,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,,No te líes a tiros en el pueblo. Activarás las alarmas y empezarán a enviar 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.",,"街の中で銃をバンバン撃ったりするんじゃないぞ +Yes I am.,TXT_RPLY0_SCRIPT03_D37900_YESIA,,,,"Ano, potřebuju.","Ja, bin ich.",,"Jes, mi estas.",Eso mismo.,,Kyllä on.,"En effet, je le suis.","Igen, az vagyok.",Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",Zgadza się.,"Sim, estou.",,"Da, am rămas fără.","Да, закончились.", +Here you go.,TXT_RYES0_SCRIPT03_D37900_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기 있어요!,Alsjeblieft.,Masz.,Aqui está.,,Iată.,Держи., +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,,,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,,No te líes a tiros en el pueblo. Activarás las alarmas y empezarán a enviar 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.,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.,"Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.", -"Welcome, we can always use more help.",TXT_DLG_SCRIPT03_D40932_WELCO,,,,"Vítej, pomoc se nám vždycky hodí.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,,"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.",,ようこそ、我々が貴方の助けに成ります。,환영합니다. 당신 같은 사람들이 더 있었더라면...,"Welkom, we kunnen altijd meer hulp gebruiken.","Witaj, każda pomoc się przyda.",Seja bem-vindo. Qualquer ajuda é sempre bem-vinda.,,"Bun venit, mereu putem primi o mână de ajutor.",Добро пожаловать. Нам всегда пригодится помощь., -"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é.","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!",,,"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.",,"私がまだ活動していた時、我々が増援に +"Welcome, we can always use more help.",TXT_DLG_SCRIPT03_D40932_WELCO,,,,"Vítej, pomoc se nám vždycky hodí.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,,"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.","Witaj, każda pomoc się przyda.",Seja bem-vindo. Qualquer ajuda é sempre bem-vinda.,,"Bun venit, mereu putem primi o mână de ajutor.",Добро пожаловать. Нам всегда пригодится помощь., +"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é.","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!",,,"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.","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.","Пока я был в оперативной группе, нам удалось вскрыть одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.", -"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT03_D43964_WERET,,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,,"Estamos intentando encontrar donde se encuentran los mecanismos de la puerta del castillo, pero de momento no hemos tenido 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.",,"我々は城門のメカニズムが何処にあるか +"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT03_D43964_WERET,,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,,"Estamos intentando encontrar donde se encuentran los mecanismos de la puerta del castillo, pero de momento no hemos tenido 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.","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.","Мы ищем механизм управления воротами замка, но пока безуспешно.", -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.","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.",,,Que no te atrapen. He oído historias terroríficas sobre lo que hacen con nuestra gente después de ser detenidos. Símplemente 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.,,"決して捕まるな。投獄されると奴等が +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.","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.",,,Que no te atrapen. He oído historias terroríficas sobre lo que hacen con nuestra gente después de ser detenidos. Símplemente 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.,"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ă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.", -"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 jdi. Jsou rychlí a suroví.","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,,"Un consejo, si ves ir alguno de los soldaditos de la Orden ve para otro lado. 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.",,"伝えておく、オーダーの錫兵は +"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í.","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,,"Un consejo, si ves ir alguno de los soldaditos de la Orden ve para otro lado. 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.","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.,"Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Они быстры и жестоки.", -Leave me be. I'm doing something for Macil.,TXT_DLG_SCRIPT03_D48512_LEAVE,,,,"Teď mě nech, dělám něco pro Macila.",Lass mich in Ruhe. Ich muss etwas für Macil erledigen.,,,Déjame. 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.,,"すまないが忙しい。 +Leave me be. I'm doing something for Macil.,TXT_DLG_SCRIPT03_D48512_LEAVE,,,,"Teď mě nech, dělám něco pro Macila.",Lass mich in Ruhe. Ich muss etwas für Macil erledigen.,,,Déjame. 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.,Zostaw mnie. Robię coś dla Macila.,Me deixe em paz. Estou fazendo algo pro Macil.,,Lasă-mă. Fac ceva pentru Macil.,"Не отвлекай меня. Я выполняю поручение Мэйсила. ", -"Sorry, no. You do not have clearance.",TXT_DLG_SCRIPT04_D0_SORRY,,,,"Pardon, ne. Sem nemůžete.","Tut mir leid, aber Sie haben keine Berechtigung.",,,"Lo siento, 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.,,すまないが、お前にクリアランスはない。,"유감이지만, 신분 휘장 없이는 보내줄 수 없어.","Sorry, nee. Je hebt geen toestemming.","Wybacz, ale nie. Nie masz zezwolenia.",Desculpe mas não. Você não tem permissão.,,"Scuze, nu. Nu ai acces.","Увы, нет. У тебя нет пропуска.", -Stop! Show me your ID badge.,TXT_DLG_SCRIPT04_D1516_STOPS,,,,Stát! Ukažte mi svůj identifikační průkaz.,Halt. Zeigen Sie mir Ihre Identitätskarte.,,,¡Alto! Muéstrame tu insignia de identificación.,,Seis! Näytä minulle henkilötunnisteesi.,Stop! Montrez moi votre carte d'identité.,Állj! Mutasd az igazolványod.,,待て! IDバッジを見せろ。,멈춰라! 너의 신분 휘장을 보여줘.,Stop! Laat me je ID-badge zien.,Stój! Pokaż mi swoją odznakę identyfikacyjną.,Alto! Mostre a sua identificação.,,Stop! Arată-mi cardul de identitate.,Стой! Покажи мне своё удостоверение., -Here's my I.D.,TXT_RPLY0_SCRIPT04_D1516_HERES,,,,Tady je moje průkazka.,Hier ist sie.,,,Aquí está mi identificación.,,Tässä.,La voilà.,Itt az igazolványom.,,これだ。,"여기, 휘장.",Hier is mijn ID.,Oto ona.,Aqui está ela.,,Aici e cardul.,Вот оно., -"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.","Alles klar, ich wünsche einen schönen Tag.",,,"Oh, ok. Vale, 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.",,あぁ、宜しい。通れ。良い一日を。,"오, 정말이네. 환영한다. 좋은 하루 보내고.","Oh, oké. Ga je gang. Nog een prettige 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ă.","Ладно, проходи. Всего доброго.", -"Derwin? Yeah, he's down in the warehouse, but you're not getting in unless you're cleared.",TXT_DLG_SCRIPT04_D4548_DERWI,,,,"Derwin? Jo, ten je dole ve skladu, ale ty nikam nejdeš jestliže nemáš povolení.","Derwin? Ja, der ist unten im Lagerhaus, aber da kommst du nicht rein ohne Berechtigung.",,,"¿Derwin? Si, 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.",,"ダーウィン? ああ、奴はこの倉庫内にいるが、 +"Sorry, no. You do not have clearance.",TXT_DLG_SCRIPT04_D0_SORRY,,,,"Pardon, ne. Sem nemůžete.","Tut mir leid, aber Sie haben keine Berechtigung.",,,"Lo siento, 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.","Wybacz, ale nie. Nie masz zezwolenia.",Desculpe mas não. Você não tem permissão.,,"Scuze, nu. Nu ai acces.","Увы, нет. У тебя нет пропуска.", +Stop! Show me your ID badge.,TXT_DLG_SCRIPT04_D1516_STOPS,,,,Stát! Ukažte mi svůj identifikační průkaz.,Halt. Zeigen Sie mir Ihre Identitätskarte.,,,¡Alto! Muéstrame tu insignia de identificación.,,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.,Stój! Pokaż mi swoją odznakę identyfikacyjną.,Alto! Mostre a sua identificação.,,Stop! Arată-mi cardul de identitate.,Стой! Покажи мне своё удостоверение., +Here's my I.D.,TXT_RPLY0_SCRIPT04_D1516_HERES,,,,Tady je moje průkazka.,Hier ist sie.,,,Aquí está mi identificación.,,Tässä.,La voilà.,Itt az igazolványom.,Eccolo qua.,これだ。,"여기, 휘장.",Hier is mijn ID.,Oto ona.,Aqui está ela.,,Aici e cardul.,Вот оно., +"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.","Alles klar, ich wünsche einen schönen Tag.",,,"Oh, ok. Vale, 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.","Oh, ok. Proszę, wchodź. Miłego dnia.","Ah, ok. Pode passar. Tenha um bom dia.",,"Ah, în regulă. Mergi mai departe. O zi bună.","Ладно, проходи. Всего доброго.", +"Derwin? Yeah, he's down in the warehouse, but you're not getting in unless you're cleared.",TXT_DLG_SCRIPT04_D4548_DERWI,,,,"Derwin? Jo, ten je dole ve skladu, ale ty nikam nejdeš jestliže nemáš povolení.","Derwin? Ja, der ist unten im Lagerhaus, aber da kommst du nicht rein ohne Berechtigung.",,,"¿Derwin? Si, 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? 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.","Дервин? Да, он внизу, на складе, но тебя туда не пустят, если у тебя нет пропуска.", -I've got clearance.,TXT_RPLY0_SCRIPT04_D4548_IVEGO,,,,Mám povolení.,Ich habe eine Berechtigung.,,,Tengo permiso.,,Minulla on lupa.,J'ai une autorisation.,Van jogosultságom.,,クリアランスはある。,허가를 받았어.,Ik heb toestemming.,Mam zezwolenie.,Eu tenho permissão.,,Am acces.,У меня есть пропуск., -Go on.,TXT_DLG_SCRIPT04_D6064_GOON,,,,Tak jdi.,Alles klar.,,Daŭrigu.,Ve entonces.,,Jatkakaa.,Allez-y.,Mesélj csak.,,続けろ。,그럼 가도 좋다.,Ga door.,Wchodź.,Pode passar.,,Intră.,Проходи., -Do you know where he is?,TXT_RPLY0_SCRIPT04_D6064_DOYOU,,,,"Nevíš, kde je?","Weißt du, wo er ist?",,"Ĉu vi scias, kie li estas?",¿Sabes donde está?,,"Tiedätkö, missä hän on?",Vous savez où il est?,Tudod hol találom meg?,,ソイツが何処にいるか知っているか?,그가 어디 있는지 아는가?,Weet je waar hij is?,Wiesz gdzie on jest?,Você sabe onde ele está?,,Știi unde e?,"Вы знаете, где Дервин?", -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.,"Ich weiß von niemandem, wo er ist. Ich kümmere mich nur um die Rattenfalle.",,,No se donde está nadie. Solo mantengo la tapa de la trampa de ratones.,,"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.,,"俺には何処にいるかは分からない。 +I've got clearance.,TXT_RPLY0_SCRIPT04_D4548_IVEGO,,,,Mám povolení.,Ich habe eine Berechtigung.,,,Tengo permiso.,,Minulla on lupa.,J'ai une autorisation.,Van jogosultságom.,Ce l'ho l'autorizzazione.,クリアランスはある。,허가를 받았어.,Ik heb toestemming.,Mam zezwolenie.,Eu tenho permissão.,,Am acces.,У меня есть пропуск., +Go on.,TXT_DLG_SCRIPT04_D6064_GOON,,,,Tak jdi.,Alles klar.,,Daŭrigu.,Ve entonces.,,Jatkakaa.,Allez-y.,Mesélj csak.,Va pure.,続けろ。,그럼 가도 좋다.,Ga door.,Wchodź.,Pode passar.,,Intră.,Проходи., +Do you know where he is?,TXT_RPLY0_SCRIPT04_D6064_DOYOU,,,,"Nevíš, kde je?","Weißt du, wo er ist?",,"Ĉu vi scias, kie li estas?",¿Sabes donde está?,,"Tiedätkö, missä hän on?",Vous savez où il est?,Tudod hol találom meg?,Sai dov'è?,ソイツが何処にいるか知っているか?,그가 어디 있는지 아는가?,Weet je waar hij is?,Wiesz gdzie on jest?,Você sabe onde ele está?,,Știi unde e?,"Вы знаете, где Дервин?", +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.,"Ich weiß von niemandem, wo er ist. Ich kümmere mich nur um die Rattenfalle.",,,No se donde está nadie. Solo mantengo la tapa de la trampa de ratones.,,"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.,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.","Ничего я не знаю. Я просто слежу, чтобы никто из них не сбежал из западни.", -You are an unpleasant distraction.,TXT_DLG_SCRIPT04_D9096_YOUAR,,,,Jsi nepříjemná otrava.,Du bist eine unerwünschte Ablenkung,,,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.,,お前は不快で目障りだ。,당신은 지금 내 감시일을 방해하고 있다.,Je bent een onaangename afleiding.,Bardzo mnie rozpraszasz.,Você é uma distração bem incômoda.,,Ești o distragere neplăcută.,Ты — досадная помеха., -Move along or taste metal.,TXT_DLG_SCRIPT04_D10612_MOVEA,,,,"Jdi dál, nebo okus ocel.",Beweg dich oder du schmeckst Metall.,,,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.",,同行か鉄を味わうかだ。,어서 움직여. 총알 먹기 싫으면.,Ga verder of proef metaal.,Odejdź stąd albo posmakujesz mojej pukawki.,Vá embora ou vai tomar chumbo grosso.,,Mșcă-te sau înghiți metal.,"Прочь, или отведаешь металла.", -Pass your ID through here for access.,TXT_DLG_SCRIPT04_D12128_PASSY,,,,Pro přístup tady nahrajte svou legitimaci.,Reichen Sie Ihre Identitätskarte hier durch!,,,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.,,彼方のI.D.をここに提示してください。,신분증을 보여줘. 입장하고 싶으면.,Geef je ID hier door voor toegang.,"Pokaż tu swój identyfikator, aby otrzymać dostęp.",Passe a sua identificação por aqui para acessar.,,Trece cardul de acces pe aici.,"Покажи своё удостоверение, чтобы получить допуск.", -"Get back to work, now!",TXT_DLG_SCRIPT04_D13644_GETBA,,,,"Vrať se do práce, hned!",Gehen Sie sofort zurück an die Arbeit!,,,"Vuelve al trabajo, ¡Ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,,仕事へ戻れ、今すぐ!,당장 일해. 어서.,"Ga terug aan het werk, nu!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!, -"Get back to work, now!",TXT_DLG_SCRIPT04_D15160_GETBA,,,,"Vrať se do práce, hned!",Gehen Sie sofort zurück an die Arbeit!,,,"Vuelve al trabajo, ¡Ahora!",,"No niin, takaisin töihisi!","Retournez au boulot, maintenant!",Nyomás vissza dolgozni!,,今すぐ仕事へ戻れ!,쉬면 알지? 어서 일해.,"Ga terug aan het werk, nu!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!, -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,,,,"Celé týdny makáme bez přestávek. Řekl bych, že Řád má v plánu nějaký útok na Frontu.","Die Station hier läuft seit Wochen ohne Stillstand. Ich vermute mal, der Orden bereitet einen großen Schlag gegen die Front vor.",,,"Hemos trabajado todo el tiempo durante semanas, sin descanso. 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.",,"もう数週間も休日返上で働いているんだ。 +You are an unpleasant distraction.,TXT_DLG_SCRIPT04_D9096_YOUAR,,,,Jsi nepříjemná otrava.,Du bist eine unerwünschte Ablenkung,,,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.,Bardzo mnie rozpraszasz.,Você é uma distração bem incômoda.,,Ești o distragere neplăcută.,Ты — досадная помеха., +Move along or taste metal.,TXT_DLG_SCRIPT04_D10612_MOVEA,,,,"Jdi dál, nebo okus ocel.",Beweg dich oder du schmeckst Metall.,,,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.,Odejdź stąd albo posmakujesz mojej pukawki.,Vá embora ou vai tomar chumbo grosso.,,Mșcă-te sau înghiți metal.,"Прочь, или отведаешь металла.", +Pass your ID through here for access.,TXT_DLG_SCRIPT04_D12128_PASSY,,,,Pro přístup tady nahrajte svou legitimaci.,Reichen Sie Ihre Identitätskarte hier durch!,,,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.,"Pokaż tu swój identyfikator, aby otrzymać dostęp.",Passe a sua identificação por aqui para acessar.,,Trece cardul de acces pe aici.,"Покажи своё удостоверение, чтобы получить допуск.", +"Get back to work, now!",TXT_DLG_SCRIPT04_D13644_GETBA,,,,"Vrať se do práce, hned!",Gehen Sie sofort zurück an die Arbeit!,,,"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!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!, +"Get back to work, now!",TXT_DLG_SCRIPT04_D15160_GETBA,,,,"Vrať se do práce, hned!",Gehen Sie sofort zurück an die Arbeit!,,,"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!","Do roboty, już!","Volte ao trabalho, agora!",,"Treci înapoi la muncă, acum!",Немедленно за работу!, +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,,,,"Celé týdny makáme bez přestávek. Řekl bych, že Řád má v plánu nějaký útok na Frontu.","Die Station hier läuft seit Wochen ohne Stillstand. Ich vermute mal, der Orden bereitet einen großen Schlag gegen die Front vor.",,,"Hemos trabajado todo el tiempo durante semanas, sin descanso. 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.","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.,"Мы работаем круглые сутки без перерыва уже несколько недель. Мне кажется, Орден готовит решительный рейд, чтобы окончательно покончить с Сопротивлением.", -"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,,,,"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.","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.",,,"Oh, maldición. El gobernador te ha enviado. Iba a darle su parte, en serio. Ok, escucha. Tengo un puñado escondido. Es tuyo si miras a 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.",,"クソッ、知事の回し者だな。 +"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,,,,"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.","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.",,,"Oh, maldición. El gobernador te ha enviado. Iba a darle su parte, en serio. Ok, escucha. Tengo un puñado escondido. Es tuyo si miras a 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.","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.","Ох, чёрт. Ты от губернатора. Я собирался отдать ему его долю — клянусь. Слушай, я поднакопил изрядно денег — они твои, если найдёшь иной выход из ситуации.", -"All right, I'll let you go.",TXT_RPLY0_SCRIPT04_D18192_ALLRI,,,,"Dobře, nechám tě jít.","Ok, ich lass dich gehen.",,,"Muy bien, te dejaré ir.",,"Hyvä on, päästän sinut.","D'accord, tu peux y aller.","Rendben, elengedlek.",,分かった、見逃そう。,좋아. 그럼 널 살려주지.,"Oké, ik laat je gaan.","Dobra, zostawię cię w spokoju.","Ok, vou te deixar em paz.",,"În regulă, te las în pace.","Ладно, я дам тебе уйти.", -"Sorry, nothing personal.",TXT_RPLY1_SCRIPT04_D18192_SORRY,,,,"Promiň, nic osobního.","Tut mir leid, nimm es nicht persönlich",,,"Lo siento, no es nada personal.",,"Pahoittelut, ei mitään henkilökohtaista.","Désolé, rien de personnel.","Sajnálom, nem személyes.",,悪いが、仕事なんでね。,"미안해, 사적인 건 아니야.","Sorry, niets persoonlijks.","Wybacz, nic osobistego.",Desculpe. Não é nada pessoal.,,"Scuze, nimic personal.","Прости, ничего личного.", -"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!","Scheiße, aber wenn ich dran bin, bist du es auch. Wärter!",,,"Cuernos, si caigo, tú lo harás conmigo. ¡¡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!",,"社会の厳しさを分けてやるよ、お前もそうなれ。 +"All right, I'll let you go.",TXT_RPLY0_SCRIPT04_D18192_ALLRI,,,,"Dobře, nechám tě jít.","Ok, ich lass dich gehen.",,,"Muy bien, te dejaré 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.","Dobra, zostawię cię w spokoju.","Ok, vou te deixar em paz.",,"În regulă, te las în pace.","Ладно, я дам тебе уйти.", +"Sorry, nothing personal.",TXT_RPLY1_SCRIPT04_D18192_SORRY,,,,"Promiň, nic osobního.","Tut mir leid, nimm es nicht persönlich",,,"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.","Wybacz, nic osobistego.",Desculpe. Não é nada pessoal.,,"Scuze, nimic personal.","Прости, ничего личного.", +"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!","Scheiße, aber wenn ich dran bin, bist du es auch. Wärter!",,,"Cuernos, si caigo, tú lo harás conmigo. ¡¡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!!","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!!","К чёрту — раз уж я сдохну, то и ты со мной. Стража!", -"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!","Scheiß' aufs Geschäft. Wärter, ich habe hier einen Eindringling.",,,"¿Negocios? Al demonio. 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.",,"クソ野郎が、タダでは死なねえ。 +"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!","Scheiß' aufs Geschäft. Wärter, ich habe hier einen Eindringling.",,,"¿Negocios? Al demonio. 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.","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.","Дело дрянь. Стража, на помощь! Тут живой повстанец.", -"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,,,,"Á, doneslo se mi od Macila, že přijdeš. Mám pro tebe cestu, jak se dostat do elektrárny, ale je trochu riskantní.","Ah, Macil hat mir mitgeteilt, dass du kommst. Ich kenne einen Weg, um in das Werk reinzukommen, aber es ist etwas riskant.",,,"Ah, tengo palabra de Macil de que vendrías. Tengo una forma de meterte en la estación 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, 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,,,,"Á, doneslo se mi od Macila, že přijdeš. Mám pro tebe cestu, jak se dostat do elektrárny, ale je trochu riskantní.","Ah, Macil hat mir mitgeteilt, dass du kommst. Ich kenne einen Weg, um in das Werk reinzukommen, aber es ist etwas riskant.",,,"Ah, tengo palabra de Macil de que vendrías. Tengo una forma de meterte en la estación 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.","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ă.","А-а, мне сообщили, что ты от Мэйсила. Я знаю способ проникнуть на станцию, но он довольно рискованный.", -I'll take my chances.,TXT_RPLY0_SCRIPT04_D22740_ILLTA,,,,Já to zkusím.,Ich riskiere es.,,,Puedo asumir el riesgo.,,Kokeilen onneani.,Je suis prêt à prendre ces risques.,Vállalom a kockázatot.,,大丈夫だ。,그 정도야 각오하고 있습니다.,Ik neem mijn kansen.,Zaryzykuję.,Estou disposto a arriscar.,,Voi risca.,Я рискну., -"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.","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.",,,"Muy bien, he robado la idenficiación del cadaver de un inútil que cayó en el pozo de refrigeración 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.",,"わかった、このIDを受け取れ。 +I'll take my chances.,TXT_RPLY0_SCRIPT04_D22740_ILLTA,,,,Já to zkusím.,Ich riskiere es.,,,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.,Zaryzykuję.,Estou disposto a arriscar.,,Voi risca.,Я рискну., +"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.","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.",,,"Muy bien, he robado la idenficiación del cadaver de un inútil que cayó en el pozo de refrigeración 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.","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.,"Очень хорошо. Я украл удостоверение с трупа одного идиота, который упал прямо в котёл реактора. «Шмяк!» Моментальное прожаривание до костей.", -What should I do once I'm in?,TXT_RPLY0_SCRIPT04_D24256_WHATS,,,,Co mám udělat uvnitř?,"Was soll ich machen, wenn ich drin bin?",,,¿Qué debo hacer una vez dentro?,,Mitä teen päästyäni sisään?,Qu'est ce que je fais une fois que je suis rentré?,Mit tegyek amikor bejutottam?,,中に入ったらどうすればいい?,그곳으로 들어간 후엔 뭘 해야 하죠?,Wat moet ik doen als ik eenmaal binnen ben?,Co mam zrobić jak wejdę?,O que devo fazer depois de entrar?,,Ce trebuie să fac odată ce ajung în interior?,И что дальше?, -"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.","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.",,,"Dile a quien pregunte que eres el sustituto del Sr. Crujiente. Es suficientemente estúpido para que funcione. Oh, y puede que quieras comprobar el cuarto de alacenamiento 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.",,"誰かに聞かれたら、クリスピーの代わりに来た +What should I do once I'm in?,TXT_RPLY0_SCRIPT04_D24256_WHATS,,,,Co mám udělat uvnitř?,"Was soll ich machen, wenn ich drin bin?",,,¿Qué debo hacer una vez dentro?,,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?,Co mam zrobić jak wejdę?,O que devo fazer depois de entrar?,,Ce trebuie să fac odată ce ajung în interior?,И что дальше?, +"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.","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.",,,"Dile a quien pregunte que eres el sustituto del Sr. Crujiente. Es suficientemente estúpido para que funcione. Oh, y puede que quieras comprobar el cuarto de alacenamiento 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.","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ă.","Говори всем, что тебя прислали заменить г-на Поджаренного. Это так глупо, что должно сработать. И ещё, наверное, тебе захочется наведаться на склад, прямо над нами.", -Boy I hope this I.D. Works.,TXT_RPLY0_SCRIPT04_D25772_BOYIH,,,,Snad tahle karta funguje.,"Mann, ich hoffe, dass diese Karte auch funktioniert.",,,"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.,,このIDで上手くいけばいいが。,이 방법이 통했으면 좋겠네요.,"Jongen, ik hoop dat deze I.D. werkt.","Mam nadzieję, że ten identyfikator zadziała.","Olha, espero que esta identificação funcione.",,Mamă frate sper ca legitimația să funcționeze.,"Ох. Надеюсь, это сработает.", -"Get out of here, unless you want to end up Mr. Dead.",TXT_DLG_SCRIPT04_D27288_GETOU,,,,"Jdi odsud, leda že by z tebe chtěl být pan Mrtvý.","Und nun verschwinde, wenn du nicht als Mister Tot enden willst.",,,"Lárgate de aqui, a menos que quieras acabar 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.",,"ここを離れた方がいい、君がミスターポックリに +Boy I hope this I.D. Works.,TXT_RPLY0_SCRIPT04_D25772_BOYIH,,,,Snad tahle karta funguje.,"Mann, ich hoffe, dass diese Karte auch funktioniert.",,,"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.","Mam nadzieję, że ten identyfikator zadziała.","Olha, espero que esta identificação funcione.",,Mamă frate sper ca legitimația să funcționeze.,"Ох. Надеюсь, это сработает.", +"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ý.","Und nun verschwinde, wenn du nicht als Mister Tot enden willst.",,,"Lárgate de aqui, a menos que quieras acabar 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.","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.","Уходи сейчас же, если не хочешь получить имя «г-н Покойник».", -"Hey, leave me alone. If they catch us wasting time we get dead, or extra work.",TXT_DLG_SCRIPT04_D28804_HEYLE,,,,"Hej, nech mě bejt. Jestli nás chytěj ztrácet čas, dostanem kulku, nebo práci navíc.","Lass mich in Ruhe. Wenn sie uns beim Quatschen erwischen, sind wir entweder beide tot oder kriegen Extraarbeit aufgebrummt.",,,"Hey, déjame en paz. Si nos pillan 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.",,"話しかけないでくれ、 +"Hey, leave me alone. If they catch us wasting time we get dead, or extra work.",TXT_DLG_SCRIPT04_D28804_HEYLE,,,,"Hej, nech mě bejt. Jestli nás chytěj ztrácet čas, dostanem kulku, nebo práci navíc.","Lass mich in Ruhe. Wenn sie uns beim Quatschen erwischen, sind wir entweder beide tot oder kriegen Extraarbeit aufgebrummt.",,,"Hey, déjame en paz. Si nos pillan 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.","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.","Эй, оставь меня в покое. Если они увидят, что мы болтаем, нас убьют... или добавят работы.", -"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,,,,"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í.","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.",,,"Cuanta presión, a este ritmo podremos volver pronto a turnos normales. Estamos dando montones de potencia al castillo y casi he terminado el registro de 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.",,"この圧力、この速さならすぐ通常のシフトに +"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,,,,"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í.","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.",,,"Cuanta presión, a este ritmo podremos volver pronto a turnos normales. Estamos dando montones de potencia al castillo y casi he terminado el registro de 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.","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.","Такая нагрузка! С такими темпами мы вернёмся к нормальному графику совсем скоро. Мы направляем массу энергии в замок, и я почти закончил с погрузкой нового оружия.", -Weapons?,TXT_RPLY0_SCRIPT04_D30320_WEAPO,,,,Zbraní?,Waffen?,,,¿Armas?,,Aseet?,Des armes?,Fegyverek?,,武器?,신무기?,Wapens?,Bronie?,Armas?,,Arme?,Оружия?, -"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?","Was dachtest du denn, glaubst du wir verteidigen uns mit Socken?",,,"¿Qué crees, que vamos con calcetines?",,"No mitä luulet meidän varastoineen, sukkia?",Vous croyez quoi? Qu'on a un surplus de chausettes?,"Mit gondolsz, zoknikkal vagyunk felfegyverkezve?",,どう思う、ズボンがずり落ちないか?,"무슨 생각해? 양말 더 지급 받는 거? +Weapons?,TXT_RPLY0_SCRIPT04_D30320_WEAPO,,,,Zbraní?,Waffen?,,,¿Armas?,,Aseet?,Des armes?,Fegyverek?,Armi?,武器?,신무기?,Wapens?,Bronie?,Armas?,,Arme?,Оружия?, +"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?","Was dachtest du denn, glaubst du wir verteidigen uns mit Socken?",,,"¿Qué crees, que vamos con 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?","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?","А ты думал, мы носки грузим?", -What kind of weapons?,TXT_RPLY0_SCRIPT04_D31836_WHATK,,,,Jaké zbraně?,Was für Waffen?,,,¿Qué clase de armas?,,Minkälaisia aseita?,Quel type d'armes?,Miféle fegyverek?,,どんな武器だ?,어떤 신무기?,Wat voor wapens?,Jakie bronie?,Que tipo de armas?,,Ce fel de arme?,Какое оружие?, -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.","Bist du taub? Ich hab dir dock gerade gesagt, wie beschäftigt ich bin. Geh zurück an die Arbeit.",,,¿Estás sordo? Ya te he dicho 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!,,難聴か? 私は、忙しい、から、仕事に、戻れ。,귀머거리야? 조금 전에 내가 얼마나 바쁜지 설명 했을 텐데? 일이나 해.,Ben je doof? Ik heb je net verteld hoe druk ik het heb. Ga terug aan het werk.,"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ă.,"Ты глухой, что ли? Я же сказал тебе, что я занят. Иди работать!", -Who are you? Only clearance level two personnel are permitted in this area.,TXT_DLG_SCRIPT04_D34868_WHOAR,,,,Kdo jsi? Pouze pracovníci druhé úrovně sem mají povolen přístup.,Wer bist du? Nur Personal mit Zugangsstufe 2 hst hier Zutritt.,,,¿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.,,"誰だ? レベル2のクリアランスを持たない者は +What kind of weapons?,TXT_RPLY0_SCRIPT04_D31836_WHATK,,,,Jaké zbraně?,Was für Waffen?,,,¿Qué clase de armas?,,Minkälaisia aseita?,Quel type d'armes?,Miféle fegyverek?,Che tipo di armi?,どんな武器だ?,어떤 신무기?,Wat voor wapens?,Jakie bronie?,Que tipo de armas?,,Ce fel de arme?,Какое оружие?, +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.","Bist du taub? Ich hab dir dock gerade gesagt, wie beschäftigt ich bin. Geh zurück an die Arbeit.",,,¿Estás sordo? Ya te he dicho 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.,"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ă.,"Ты глухой, что ли? Я же сказал тебе, что я занят. Иди работать!", +Who are you? Only clearance level two personnel are permitted in this area.,TXT_DLG_SCRIPT04_D34868_WHOAR,,,,Kdo jsi? Pouze pracovníci druhé úrovně sem mají povolen přístup.,Wer bist du? Nur Personal mit Zugangsstufe 2 hst hier Zutritt.,,,¿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.,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.,Ты кто такой? Только персоналу второго уровня допуска разрешено находиться в этой зоне., -I'm the replacement worker.,TXT_RPLY0_SCRIPT04_D34868_IMTHE,,,,Jsem náhradník.,Ich bin der Ersatzarbeiter.,,,Soy el sustituto.,,Olen täydennystyöntekijä.,Je suis le remplaçant.,Én vagyok a helyettes.,,代替要員だ。,후임 근무자로 왔습니다.,Ik ben de vervanger.,Jestem tu na zastępstwo.,Eu sou o operário substituto.,,Sunt înlocuitorul muncitorului.,Я замещаю рабочего., -"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?","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?",,,"Ya era hora. Ve a hablar con Ketrick en el núcleo. Oh, 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.",,"そろそろ来ると思っていたよ。コアにいる +I'm the replacement worker.,TXT_RPLY0_SCRIPT04_D34868_IMTHE,,,,Jsem náhradník.,Ich bin der Ersatzarbeiter.,,,Soy el sustituto.,,Olen täydennystyöntekijä.,Je suis le remplaçant.,Én vagyok a helyettes.,Sono il lavoratore sostitutivo.,代替要員だ。,후임 근무자로 왔습니다.,Ik ben de vervanger.,Jestem tu na zastępstwo.,Eu sou o operário substituto.,,Sunt înlocuitorul muncitorului.,Я замещаю рабочего., +"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?","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?",,,"Ya era hora. Ve a hablar con Ketrick en el núcleo. Oh, 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?","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?","Как раз вовремя. Иди поговори с Кетриком возле ядра реактора. О, и возьми эту карточку. Мы ведь не хотим, чтобы тебя подстрелили в первый же рабочий день?", -Where's the power crystal?,TXT_RPLY0_SCRIPT04_D36384_WHERE,,,,Kde je energetický krystal?,Wo ist der Energiekristall?,,,¿Dónde está el cristal de poder?,,Missä voimakristalli on?,Où se trouve le cristal du réacteur?,Hol van az erőkristály?,,パワークリスタルは何処だ?,동력 수정체는 어디에 있죠?,Waar is het energiekristal?,Gdzie jest kryształ mocy?,Onde fica o cristal de energia?,,Unde e cristalul de alimentare?,Где энергетический кристалл?, -"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!","Wenn du nicht arbeitest, wirst du eh erschossen. Und nun beweg deinen Arsch!",,,"Si no te pones a trabajar, te pegarán un tiro igual. 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!",,"今すぐ作業しないと奴等にバレて撃たれるぞ。 +Where's the power crystal?,TXT_RPLY0_SCRIPT04_D36384_WHERE,,,,Kde je energetický krystal?,Wo ist der Energiekristall?,,,¿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?,Gdzie jest kryształ mocy?,Onde fica o cristal de energia?,,Unde e cristalul de alimentare?,Где энергетический кристалл?, +"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!","Wenn du nicht arbeitest, wirst du eh erschossen. Und nun beweg deinen Arsch!",,,"Si no te pones a trabajar, te pegarán un tiro igual. 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.","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.","Если ты не приступишь к работе, тебя всё равно пристрелят. Шевелись!", -"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,,,,"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.","Ich will ja nicht herumunken, aber wenn sie den Kristall weiter so überstrapazieren, nimmt er Schaden, und dann *bumm*! ...nur so ein Gedanke.",,,"No quiero sonar alarmante, pero ¡Si siguen forzando tanto el cristal de poder se rallará, y luego se partirá, y luego *boom*! ... Solo 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.",,"オーダーがもしパワークリスタルに負荷を +"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,,,,"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.","Ich will ja nicht herumunken, aber wenn sie den Kristall weiter so überstrapazieren, nimmt er Schaden, und dann *bumm*! ...nur so ein Gedanke.",,,"No quiero sonar alarmante, pero ¡Si siguen forzando tanto el cristal de poder se rallará, y luego se partirá, y luego *boom*! ... Solo 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.","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.","Не хочу показаться паникёром, но если продолжать так же сильно нагружать кристалл, он треснет, потом расколется, а потом «бум!».. Просто предположение.", -"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,,,,"Abych byl přesný: Jestli tenhle terminál znovu zamrzne, hladina chladiva poklesne a všichni se budeme muset zodpovídat Programátorovi. Pokud přežijeme.","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.",,,"Que quede claro. Si esta terminal vuelve a bloquearse, el nivel de refrigerante caerá y todos tendremos que responderle al Programador. Si sobrevivimos.",,"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.",,"万が一このターミナルがフリーズしたら、 +"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,,,,"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.","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.",,,"Que quede claro. Si esta terminal vuelve a bloquearse, el nivel de refrigerante caerá y todos tendremos que responderle al Programador. Si sobrevivimos.",,"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.","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.","Давай говорить начистоту. Если этот терминал опять заклинит, то уровень охлаждения упадёт, и нам всем придётся отвечать перед Программистом — если выживем.", -"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,,,,"Ty! Jo, ty. Pro tuhle oblast nemáš povolení. Ukaž mi svou kartu, hned. Mám hodně špatnou náladu!","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!",,,"¡Tú! Si, tú. No tienes permiso en esta área. Déjame tu tarjeta llave, rápido. ¡Estoy de tan 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.",,"お前!そうだお前だ。ここは立入禁止だ。 +"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,,,,"Ty! Jo, ty. Pro tuhle oblast nemáš povolení. Ukaž mi svou kartu, hned. Mám hodně špatnou náladu!","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!",,,"¡Tú! Si, tú. No tienes permiso en esta área. Déjame tu tarjeta llave, rápido. ¡Estoy de tan 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!","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!","Ты! Да, ты. У тебя нет сюда допуска. Давай свою карточку, быстро. Я сегодня в плохом настроении!", -"Here, here's my card.",TXT_RPLY0_SCRIPT04_D42448_HEREH,,,,"Tady, to je moje karta.","Hier, hier ist meine Karte.",,,"Toma, aquí está mi tarjeta.",,Tässä on minun korttini.,Voilà mon passe.,"Parancsolj, itt a kártyám.",,ほら、これがカードだ。,"자, 카드 여기 있어요.","Hier, hier is mijn kaart.",Oto moja karta.,"Tome, aqui está o cartão.",,"Aici, aici e cardul.","Вот, вот моя карта.", -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!","Das ist ja wohl die Höhe! Warte hier. Ach was. Wärter, tötet hn!",,,"¡Esto es basura! Espera aquí. Oh que más da. 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!",,"なんだこのゴミは! いや待て。ああ、畜生。 +"Here, here's my card.",TXT_RPLY0_SCRIPT04_D42448_HEREH,,,,"Tady, to je moje karta.","Hier, hier ist meine Karte.",,,"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.",Oto moja karta.,"Tome, aqui está o cartão.",,"Aici, aici e cardul.","Вот, вот моя карта.", +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!","Das ist ja wohl die Höhe! Warte hier. Ach was. Wärter, tötet hn!",,,"¡Esto es basura! Espera aquí. Oh que más da. 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!","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!","Этой карточкой можно только подтереться! Жди здесь. А, к чёрту. Стража, здесь нарушитель! Убейте его!", -"Work, sleep, get tortured, what a life. Say, you the replacement for the careless pit diver?",TXT_DLG_SCRIPT04_D45480_WORKS,,,,"Práce, spánek, poležení si na skřipci, dobrej život. Hele, ty jsi ta náhrada za toho neopatrného skokana?","Arbeiten, schlafen, gefoltert werden, was für ein Leben. Sag mal, bist du der Ersatz für diesen sorglosen Grubentaucher?",,,"Trabajar, dormir, ser torturado, vaya vida. Dime, ¿eres el sustituto del imprudente buceador?",,"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?",,"働いて、寝て、処罰されて、なんて人生だ。 +"Work, sleep, get tortured, what a life. Say, you the replacement for the careless pit diver?",TXT_DLG_SCRIPT04_D45480_WORKS,,,,"Práce, spánek, poležení si na skřipci, dobrej život. Hele, ty jsi ta náhrada za toho neopatrného skokana?","Arbeiten, schlafen, gefoltert werden, was für ein Leben. Sag mal, bist du der Ersatz für diesen sorglosen Grubentaucher?",,,"Trabajar, dormir, ser torturado, vaya vida. Dime, ¿eres el sustituto del imprudente buceador?",,"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?","働いて、寝て、処罰されて、なんて人生だ。 で、お前はあの冷却炉に落ちたアイツの 代替要員か?","일하고, 자고, 고문받고, 인생 참 멋지네. 자, 네가 그 부주의하게 추락사한 친구의 후임 맞지?","Werk, slaap, word gemarteld, wat een leven. Zeg, ben jij de vervanger van de onzorgvuldige pitduiker?","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?","Работа, сон и пытки, что за жизнь. Так ты заменяешь нашего беспечного ныряльщика?", -"Yeah, can't wait to start.",TXT_RPLY0_SCRIPT04_D45480_YEAHC,,,,"Jo, už se nemůžu dočkat.","Ja, ich kanns kaum erwarten, hier anzufangen.",,,"Sí, tengo ganas de empezar.",,"Kyllä, en malta odottaa.","Oui, j'ai hâte de commencer.","Igen, már alig várom, hogy kezdhessek.",,そうだ、もう待てない。,"네, 일이 정말 기대됩니다.","Ja, ik kan niet wachten om te beginnen.","Tak, nie mogę się już doczekać.","É, mal posso esperar pra começar.",,"Deah, abia aștept să încep.","Да, поскорей бы уже за дело.", -"Yeah, right. OK, get your ass to work.",TXT_DLG_SCRIPT04_D46996_YEAHR,,,,"Jo, jasně. Dobře, začni makat.","Na gut, schwing deinen Arsch zur Arbeit.",,,"Sí, claro. Ok, 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.",,わかった。さっさと働け。,"그래, 좋아. 일이나 하라고.","Ja, juist. Oké, ga aan het werk.","Dobra. Ok, rusz swoją dupę do roboty.","Sim, sei. Tá, comece a trabalhar de uma vez.",,"Deah, sigur. Bine, hai, la muncă.","Да, конечно. Ладно, шуруй работать.", -Where's the crystal?,TXT_RPLY0_SCRIPT04_D46996_WHERE,,,,Kde je krystal?,Wo ist der Kristall?,,,¿Dónde está el cristal?,,Missä kristalli on?,Où est le cristal?,Hol van a kristály?,,クリスタルは何処だ?,수정체는 어디에 있죠?,Waar is het kristal?,Gdzie kryształ?,Onde fica o cristal?,,Unde e cristalul?,Где кристалл?, -"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. Zvedni tlačítky schodiště a pak ve výtahu použij tuhle kartu.,"Rede mit Ketrick. Hebe den Steg mit den Schaltern an, dann benutze dies ID für den Lift.",,,"Habla con Ketrick. Alza la pasarela usando los interruptores, luego usa esta identificación para el ascensor.","Habla con Ketrick. Alza la pasarela usando los interruptores, luego usa esta identificación para el elevador.",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.",,"ケトリックと話をしろ。 +"Yeah, can't wait to start.",TXT_RPLY0_SCRIPT04_D45480_YEAHC,,,,"Jo, už se nemůžu dočkat.","Ja, ich kanns kaum erwarten, hier anzufangen.",,,"Sí, 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.","Tak, nie mogę się już doczekać.","É, mal posso esperar pra começar.",,"Deah, abia aștept să încep.","Да, поскорей бы уже за дело.", +"Yeah, right. OK, get your ass to work.",TXT_DLG_SCRIPT04_D46996_YEAHR,,,,"Jo, jasně. Dobře, začni makat.","Na gut, schwing deinen Arsch zur Arbeit.",,,"Sí, claro. Ok, 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.","Dobra. Ok, rusz swoją dupę do roboty.","Sim, sei. Tá, comece a trabalhar de uma vez.",,"Deah, sigur. Bine, hai, la muncă.","Да, конечно. Ладно, шуруй работать.", +Where's the crystal?,TXT_RPLY0_SCRIPT04_D46996_WHERE,,,,Kde je krystal?,Wo ist der Kristall?,,,¿Dónde está el cristal?,,Missä kristalli on?,Où est le cristal?,Hol van a kristály?,Dov'è il cristallo?,クリスタルは何処だ?,수정체는 어디에 있죠?,Waar is het kristal?,Gdzie kryształ?,Onde fica o cristal?,,Unde e cristalul?,Где кристалл?, +"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.,"Rede mit Ketrick. Hebe den Steg mit den Schaltern an, dann benutze dies ID für den Lift.",,,"Habla con Ketrick. Alza la pasarela usando los interruptores, luego usa esta identificación para el ascensor.","Habla con Ketrick. Alza la pasarela usando los interruptores, luego usa esta identificación para el elevador.",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.,"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.","Сходи поговори с Кетриком. Используй переключатели на стене, чтобы подняться наверх, потом запусти лифт этой карточкой.", -Where's the crystal again?,TXT_RPLY0_SCRIPT04_D48512_WHERE,,,,"Můžeš mi znovu říct, kde je krystal?","Wo ist der Kristall, nochmal?",,,"De nuevo, ¿Dónde está el cristal?",,Missä kristalli olikaan?,Mais où est le cristal?,Hol is van a kristály?,,いいからクリスタルは何処だ?,수정체가 어디에 있다고요?,Waar is het kristal ook alweer?,"Jeszcze raz, gdzie kryształ?",Onde fica o cristal mesmo?,,Unde ziceai că e cristalul?,Ещё раз: где кристалл?, -"None of your business, go talk to Ketrick.",TXT_DLG_SCRIPT04_D50028_NONEO,,,,"Do toho ti nic není, jdi si promluvit s Ketrickem.","Geht dich nichts an, und jetzt rede mit 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.",,大きなお世話だ、ケトリックと話をしろ。,"상관 말고, 케트릭에게 물어봐.","Gaat je niets aan, ga met Ketrick praten.","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.,Не твоё дело. Иди поговори с Кетриком., -OK.,TXT_RPLY0_SCRIPT04_D50028_OK,,,,Dobře.,Ok.,,Okej.,Ok.,,OK.,OK.,OK.,,オーケー,알겠습니다.,OKÉ.,Ok.,Ok.,,Bine.,Понял., -"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,,,,"Jestli chceš tvrdou práci, jdi na chvíli zírat na tamtu obrazovku, unudí tě to k slzám.","Wenn du richtige Arbeit willst, dann starre mal für längere Zeit auf den Bildschirm. Das langweilt zu Tränen.",,,"Si es trabajo ocioso lo que buscas, ve a mirar esa pantalla un rato, te aburrirá hasta llorar.",,"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.",,"忙しい仕事を望んでいるなら、 +Where's the crystal again?,TXT_RPLY0_SCRIPT04_D48512_WHERE,,,,"Můžeš mi znovu říct, kde je krystal?","Wo ist der Kristall, nochmal?",,,"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?,"Jeszcze raz, gdzie kryształ?",Onde fica o cristal mesmo?,,Unde ziceai că e cristalul?,Ещё раз: где кристалл?, +"None of your business, go talk to Ketrick.",TXT_DLG_SCRIPT04_D50028_NONEO,,,,"Do toho ti nic není, jdi si promluvit s Ketrickem.","Geht dich nichts an, und jetzt rede mit 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.","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.,Не твоё дело. Иди поговори с Кетриком., +OK.,TXT_RPLY0_SCRIPT04_D50028_OK,,,,Dobře.,Ok.,,Okej.,Ok.,,OK.,OK.,OK.,OK.,オーケー,알겠습니다.,OKÉ.,Ok.,Ok.,,Bine.,Понял., +"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,,,,"Jestli chceš tvrdou práci, jdi na chvíli zírat na tamtu obrazovku. Unudí tě to k pláči.","Wenn du richtige Arbeit willst, dann starre mal für längere Zeit auf den Bildschirm. Das langweilt zu Tränen.",,,"Si es trabajo ocioso lo que buscas, ve a mirar esa pantalla un rato, te aburrirá hasta llorar.",,"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.","忙しい仕事を望んでいるなら、 そのスクリーンをしばらく見ていなさい、 飽きて涙が浮かぶでしょう。",만약 더 쉬운 일을 원한다면 저 차단기를 계속 쳐다봐봐. 눈물 나도록 지루해 죽을걸.,"Als het druk werk is dat je wilt, ga dan een tijdje naar dat scherm staren, het zal je tot tranen toe vervelen.","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.","Если ты хочешь муравьиной работы, попялься какое-то время на тот экран... Наскучит до слёз.", -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,,,,"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.","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.",,,El todopoderoso Programador tiene tal paranoia de infiltración que ha cerrado el núcleo de la computadora. ¿Cómo se supone que voy a hacer mi trabajo? La única entrada es 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.",,"プログラマー様は潜入されるのを +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,,,,"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.","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.",,,El todopoderoso Programador tiene tal paranoia de infiltración que ha cerrado el núcleo de la computadora. ¿Cómo se supone que voy a hacer mi trabajo? La única entrada es 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.,"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.,"Всемогущий Программист настолько боится диверсии, что закрыл компьютерную комнату. И как мне теперь выполнять свою работу? Есть один способ пройти туда, но это чистое самоубийство.", -Suicide run? What's that?,TXT_RPLY0_SCRIPT04_D53060_SUICI,,,,Běh pro sebevrahy? Co to je?,"Selbstmordpfad, was ist das?",,,¿Vía suicida? ¿Qué es eso?,,Itsemurhareitti? Mikä se on?,Couloir du suicide? Comment ça?,Halál inga? Az meg mi a fene?,,危ない?どういう事だ?,자살기행? 그건 뭡니까?,Zelfmoordactie? Wat is dat?,Ścieżka samobójców? Co to?,Maneira suicida? O que é isso?,,O cale sinucigașă? Cum așa?,Самоубийство? О чём ты?, -"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á.","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.",,,"Es una forma segura de matarte, pero eso no importa ahora. Baja por el ascensor si te atreves.",,"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.",,"下手に立ち入ると射殺されるが、 +Suicide run? What's that?,TXT_RPLY0_SCRIPT04_D53060_SUICI,,,,Běh pro sebevrahy? Co to je?,"Selbstmordpfad, was ist das?",,,¿Vía suicida? ¿Qué 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?,Ścieżka samobójców? Co to?,Maneira suicida? O que é isso?,,O cale sinucigașă? Cum așa?,Самоубийство? О чём ты?, +"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á.","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.",,,"Es una forma segura de matarte, pero eso no importa ahora. Baja por el ascensor si te atreves.",,"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.","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.","Сунуться туда — верная гибель. Впрочем, сейчас это уже не важно. Спускайся на лифте, если не боишься.", -Halt. No one gets through here without authorization from the Warden or the Governor.,TXT_DLG_SCRIPT05_D0_HALTN,,,,Stát. Nikdo tudy nesmí projít bez povolení dozorce nebo guvernéra.,Halt. Niemand kommt hier ohne Autorisierung des Direktors durch.,,,Alto. Nadie entra aquí sin autorización del Carcelero o el Gobernador.,Alto. Nadie entra aquí sin autorización del Director 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.,,"止まれ。所長か知事の許可が無い限り +Halt. No one gets through here without authorization from the Warden or the Governor.,TXT_DLG_SCRIPT05_D0_HALTN,,,,Stát. Nikdo tudy nesmí projít bez povolení dozorce nebo guvernéra.,Halt. Niemand kommt hier ohne Autorisierung des Direktors durch.,,,Alto. Nadie entra aquí sin autorización del Carcelero o el Gobernador.,Alto. Nadie entra aquí sin autorización del Director 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.,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.,Стой. Никто не может пройти сюда без разрешения от тюремщика или губернатора., -"Here's my pass, let me in.",TXT_RPLY0_SCRIPT05_D0_HERES,,,,"Tady je moje propustka, pusť mě dál.","Hier is mein Pass, lassen Sie mich rein.",,,"Aquí está mi pase, déjame entrar.",,Tässä lupani; päästäkää minut sisään.,Voilà mon passe. Laissez-moi entrer.,"Itt az igazolásom, engedj be.",,これが許可証だ、入れてくれ。,여기 통행증입니다. 들여보내 주세요.,"Hier is mijn pas, laat me binnen.",Oto moja przepustka. Wpuść mnie.,Aqui está o meu passe. Deixe-me entrar.,,"Aici e legitimația, lasă-mă să intru.",Вот мой пропуск. Дай войти., -"OK, but talk only to the Warden.",TXT_DLG_SCRIPT05_D1516_OKBUT,,,,"Dobře, ale mluvte pouze s dozorcem.","Ok, aber reden Sie nur mit dem Direktor.",,,"Ok, pero habla solo con el Carcelero.","Ok, pero habla solo con el Director.","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.",,良いだろう、ただし話すのは所長とだけだ。,"알겠다. 하지만 간수장에게만 대화해라. +"Here's my pass, let me in.",TXT_RPLY0_SCRIPT05_D0_HERES,,,,"Tady je moje propustka, pusť mě dál.","Hier is mein Pass, lassen Sie mich rein.",,,"Aquí está mi pase, déjame 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.",Oto moja przepustka. Wpuść mnie.,Aqui está o meu passe. Deixe-me entrar.,,"Aici e legitimația, lasă-mă să intru.",Вот мой пропуск. Дай войти., +"OK, but talk only to the Warden.",TXT_DLG_SCRIPT05_D1516_OKBUT,,,,"Dobře, ale mluvte pouze s dozorcem.","Ok, aber reden Sie nur mit dem Direktor.",,,"Ok, pero habla solo con el Carcelero.","Ok, pero habla solo con el Director.","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, ale rozmawiaj tylko z Naczelnikiem.","Ok, mas você só pode falar com o Carcereiro.",,"Bine, dar vorbești doar cu Directorul.","Проходи, но говори только с тюремщиком.", -"Do I look like the Warden to you? Keep moving, this area's off limits.",TXT_DLG_SCRIPT05_D3032_DOILO,,,,"Vypadám snad jako dozorce? Pokračuj dál, do této oblasti je vstup zakázán.","Sehe ich wie ein Direktor aus? Beweg dich, du hast hier nichts zu suchen.",,,"¿Te parezco el Carcelero? Sigue andando, esta área está fuera de límite.","¿Te parezco el Director? Sigue moviéndote, esta área está fuera de límite.",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ó.",,"俺がワーデンに見えるか? どっか行け、 +"Do I look like the Warden to you? Keep moving, this area's off limits.",TXT_DLG_SCRIPT05_D3032_DOILO,,,,"Vypadám snad jako dozorce? Pokračuj dál, do této oblasti je vstup zakázán.","Sehe ich wie ein Direktor aus? Beweg dich, du hast hier nichts zu suchen.",,,"¿Te parezco el Carcelero? Sigue andando, esta área está fuera de límite.","¿Te parezco el Director? Sigue moviéndote, esta área está fuera de límite.",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.","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.","Я что, похож на тюремщика? Двигай отсюда. Здесь закрытая территория!", -The Order's wrath will rain down on these servants until they beg for death.,TXT_DLG_SCRIPT05_D4548_THEOR,,,,Hněv Řádu dopadne na ty služebníky dokud nebudou prosit o smrt.,"Der Zorn des Ordens wird auf diese Untergebenen herabregnen, bis sie um den Tod betteln.",,,La ira de la Orden 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.",,"オーダーの怒りは、奴等が死を望むまで +The Order's wrath will rain down on these servants until they beg for death.,TXT_DLG_SCRIPT05_D4548_THEOR,,,,Hněv Řádu dopadne na ty služebníky dokud nebudou prosit o smrt.,"Der Zorn des Ordens wird auf diese Untergebenen herabregnen, bis sie um den Tod betteln.",,,La ira de la Orden 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.,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.,"Гнев Ордена обрушится на этих рабов, и они будут молить о смерти.", -"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,,,,"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.","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.",,,"No me importa que Mourel te diera un pase. Ésta es mi prisión. Mi llave es la única forma de entrar o salir, y no voy a arriesgarme. 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.",,"モーレルが許可しようが構わん。 +"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,,,,"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.","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.",,,"No me importa que Mourel te diera un pase. Ésta es mi prisión. Mi llave es la única forma de entrar o salir, y no voy a arriesgarme. 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.,"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.","Мне плевать, дал ли тебе Морел пропуск или нет. Это моя тюрьма, и без моего ключа не войти и не выйти. И я не хочу рисковать — Орден не прощает ошибок!", -Give me the damn key!,TXT_RPLY0_SCRIPT05_D6064_GIVEM,,,,Dej mi ten zatracený klíč!,Geben Sie mir den verdammten Schlüssel!,,,¡Dame la maldita llave!,,Anna minulle se pahuksen avain!,Donne moi cette putain de clé!,Add ide az istenverte kulcsot!,,いいからとっととキーを寄越せ!,그 망할 놈의 키를 건네!,Geef me die verdomde sleutel!,Daj mi ten cholerny klucz!,Me dê a droga da chave!,,Dă-mi afurisita de cheie!,Дай мне чёртов ключ!, -Over my dead body!,TXT_DLG_SCRIPT05_D7580_OVERM,,,,Jen přes mou mrtvolu!,Nur über meine Leiche!,,,¡Sobre mi tumba!,,Vain kuolleen ruumiini yli!,Il faudra me passer sur le corps!,Csak a holttestemen át!,,欲しけりゃ取りに来い。,"내 시체를 밟고 얻어라! +Give me the damn key!,TXT_RPLY0_SCRIPT05_D6064_GIVEM,,,,Dej mi ten zatracený klíč!,Geben Sie mir den verdammten Schlüssel!,,,¡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!,Daj mi ten cholerny klucz!,Me dê a droga da chave!,,Dă-mi afurisita de cheie!,Дай мне чёртов ключ!, +Over my dead body!,TXT_DLG_SCRIPT05_D7580_OVERM,,,,Jen přes mou mrtvolu!,Nur über meine Leiche!,,,¡Sobre mi tumba!,,Vain kuolleen ruumiini yli!,Il faudra me passer sur le corps!,Csak a holttestemen át!,Sul mio cadavere!,欲しけりゃ取りに来い。,"내 시체를 밟고 얻어라! \cy아마 네가 “부탁”을 안 해서 이러나 봐.",Over mijn lijk!,Po moim trupie!,Só sobre o meu cadáver!,,Doar peste cadavrul meu!,Только через мой труп!, -Great idea!,TXT_RPLY0_SCRIPT05_D7580_GREAT,,,,Skvělý nápad!,Gute Idee!,,Bonega ideo!,¡Buena idea!,,Loistoidea!,Excellente idée!,Kiváló ötlet!,,良い案だ!,좋은 생각이야!,Geweldig idee!,Dobry pomysł!,Boa idéia!,,Grozavă idee!,Хорошая мысль!, -"Shackles or chains, I want you to hang around.",TXT_DLG_SCRIPT05_D9096_SHACK,,,,"Pouta či řetězy, chci tě tu vidět viset.",Fesseln oder Ketten - ich will dich hier herumhängen sehen.,,,"Grilletes o cadenas, te quiero ver colgado.",,"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.",,鎖や手錠で、繋いだ方が良いな。,"동아줄, 아님 쇠사슬... 네 목에 잘 어울리겠네. 으하하하!","Sluitingen of kettingen, ik wil dat je blijft hangen.",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.","Кандалы или цепи? Я хочу, чтобы ты подольше тут задержался.", -"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,,,,"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.","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.",,,"No sé como has logrado pasar por los guardias y el Carcelero, pero espero que te guste la decoración, porque te acabas de mudar aquí.","No sé como has logrado pasar por los guardias y el Director, 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.",,"どうやってガードやセキュリティを +Great idea!,TXT_RPLY0_SCRIPT05_D7580_GREAT,,,,Skvělý nápad!,Gute Idee!,,Bonega ideo!,¡Buena idea!,,Loistoidea!,Excellente idée!,Kiváló ötlet!,Ottima idea!,良い案だ!,좋은 생각이야!,Geweldig idee!,Dobry pomysł!,Boa idéia!,,Grozavă idee!,Хорошая мысль!, +"Shackles or chains, I want you to hang around.",TXT_DLG_SCRIPT05_D9096_SHACK,,,,"Pouta či řetězy, chci tě tu vidět viset.",Fesseln oder Ketten - ich will dich hier herumhängen sehen.,,,"Grilletes o cadenas, te quiero ver colgado.",,"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.",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.","Кандалы или цепи? Я хочу, чтобы ты подольше тут задержался.", +"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,,,,"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.","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.",,,"No sé como has logrado pasar por los guardias y el Carcelero, pero espero que te guste la decoración, porque te acabas de mudar aquí.","No sé como has logrado pasar por los guardias y el Director, 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.","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.","Не знаю, как тебе удалось миновать стражу и Монтага, но, я надеюсь, тебе нравится интерьер? Потому что отсюда ты уже не выйдешь.", -Free my comrades or die!,TXT_RPLY0_SCRIPT05_D10612_FREEM,,,,"Osvoboď mé druhy, nebo zemři!",Befreien Sie meine Kameraden oder sterben Sie!,,,¡Libera a mis camaradas o muere!,,Vapauta toverini tai kuole!,Libère mes camarades ou meurs!,"Engedd el a társaimat, vagy meghalsz!",,命が惜しければ仲間を解放しろ!,"내 전우를 풀어주든지, 죽든지!",Bevrijd mijn kameraden of sterf!,Uwolnij moich towarzyszy lub giń!,Liberte meus companheiros ou morra!,,"Eliberează-mi camarazii, sau mori!","Освободи моих товарищей, или ты умрёшь!", -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.","Töte mich und du befreist niemanden. Ich bin der einzige, der autorisiert ist, die Gefangenen freizulassen.",,,Mátame y nunca liberarás 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.",,"私を殺せば誰も助かる事はない。 +Free my comrades or die!,TXT_RPLY0_SCRIPT05_D10612_FREEM,,,,"Osvoboď mé druhy, nebo zemři!",Befreien Sie meine Kameraden oder sterben Sie!,,,¡Libera a mis camaradas 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!,Uwolnij moich towarzyszy lub giń!,Liberte meus companheiros ou morra!,,"Eliberează-mi camarazii, sau mori!","Освободи моих товарищей, или ты умрёшь!", +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.","Töte mich und du befreist niemanden. Ich bin der einzige, der autorisiert ist, die Gefangenen freizulassen.",,,Mátame y nunca liberarás 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.,"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.,"Убив меня, ты никого не освободишь. Только у меня есть ключ, которым можно открыть камеры.", -Can you lend me a hand then?,TXT_RPLY0_SCRIPT05_D12128_CANYO,,,,Mohl bys mi tedy půjčit ruku?,Können Sie mir Ihre Hand leihen?,,,¿Me puedes echar una mano entonces?,,Voisitko sitten ojentaa auttavaa kättäsi?,"Tu peux me prêter main forte, alors?",Tudsz nekem segíteni?,,じゃあ 手を貸して くれるか?,그럼 네 손길이 좀 필요할 것 같아...,Kun je me dan een handje helpen?,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?,"Может быть, ты дашь мне руку помощи?", -Move along or join your friends.,TXT_DLG_SCRIPT05_D13644_MOVEA,,,,"Jdi, nebo se přidej ke svým kamarádům.",Hau ab oder zieh bei deinen Freunden ein.,,,Mué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.",,共に行こう友よ。,"무죄, 아니면 사형 선고. 정하시게.",Ga mee of sluit je aan bij je vrienden.,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.,"Не подходи ко мне, или присоединишься к своим друзьям.", -"Don't just stand there, get us out of here!",TXT_DLG_SCRIPT05_D15160_DONTJ,,,,"Nestůj tam tak, dostaň nás odsud!","Steh da nicht so rum, hol uns raus!",,,"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!",,もう待てない、早くここを出よう!,"거기 서 있지 말고, 어서 우릴 내보내 줘!","Blijf daar niet staan, haal ons hier weg!","Nie stój tak, uwolnij nas stąd!",Não fique parado aí. Nos tire daqui!,,"Nu sta acolo, scoate-ne de aici!",Не стой просто так. Вытащи нас отсюда!, -"The sky, I want to see the sky.",TXT_DLG_SCRIPT05_D16676_THESK,,,,"Nebe, chci vidět nebe.","Der Himmel, ich möchte den Himmel sehen.",,,"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.",,空を、空を見たい。,"하늘, 하늘을 보고 싶어.","De lucht, ik wil de lucht zien.",Niebo... tak bardzo chcę zobaczyć niebo.,O céu. Eu quero ver o céu.,,"Cerul, vreau să văd cerul!",Небо. Я хочу увидеть небо., -"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.","Fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß...",,,"Cinco pies por cuatro pies, cinco pies por cuatro pies, cinco pies por cuatro pies.",,"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.",,"ファイブフィート バイ フォーフィート、 +Can you lend me a hand then?,TXT_RPLY0_SCRIPT05_D12128_CANYO,,,,Mohl bys mi tedy půjčit ruku?,Können Sie mir Ihre Hand leihen?,,,¿Me puedes echar 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?,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?,"Может быть, ты дашь мне руку помощи?", +Move along or join your friends.,TXT_DLG_SCRIPT05_D13644_MOVEA,,,,"Jdi, nebo se přidej ke svým kamarádům.",Hau ab oder zieh bei deinen Freunden ein.,,,Mué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.,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.,"Не подходи ко мне, или присоединишься к своим друзьям.", +"Don't just stand there, get us out of here!",TXT_DLG_SCRIPT05_D15160_DONTJ,,,,"Nestůj tam tak, dostaň nás odsud!","Steh da nicht so rum, hol uns raus!",,,"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!","Nie stój tak, uwolnij nas stąd!",Não fique parado aí. Nos tire daqui!,,"Nu sta acolo, scoate-ne de aici!",Не стой просто так. Вытащи нас отсюда!, +"The sky, I want to see the sky.",TXT_DLG_SCRIPT05_D16676_THESK,,,,"Nebe, chci vidět nebe.","Der Himmel, ich möchte den Himmel sehen.",,,"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.",Niebo... tak bardzo chcę zobaczyć niebo.,O céu. Eu quero ver o céu.,,"Cerul, vreau să văd cerul!",Небо. Я хочу увидеть небо., +"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.","Fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß, fünf Fuß mal vier Fuß...",,,"Cinco pies por cuatro pies, cinco pies por cuatro pies, cinco pies por cuatro pies.",,"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.","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.",Пять шагов на четыре шага. Пять шагов на четыре шага. Пять шагов на четыре шага., -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.","Bitte befreie mich nicht, wenn der Orden hier noch herrscht, ich halte den Horror nicht aus.",,,No me dejes ir si la Orden sigue al mando. No puedo soportar 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.,,"まだオーダーがいる内は出たくない。 +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.","Bitte befreie mich nicht, wenn der Orden hier noch herrscht, ich halte den Horror nicht aus.",,,No me dejes ir si la Orden sigue al mando. No puedo soportar 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.,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.,"Не освобождай меня, если Орден всё ещё у власти. Я не вынесу преследования.", -"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.","Ich möchte ja nicht meckern, aber es wurde auch Zeit, dass Macil jemanden schickt, der uns hier rausholt",,,"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.",,"意地が悪いな、だがマシルが解放の為に +"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.","Ich möchte ja nicht meckern, aber es wurde auch Zeit, dass Macil jemanden schickt, der uns hier rausholt",,,"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.","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ă.","Не хочу ныть, но пора бы Мэйсилу уже послать кого-нибудь освободить нас.", -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.,Ich gäbe alles für eine Brotkruste. Ich habe so einen Hunger.,,,Daría lo que fuera por una migaja 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.",,"いつもパンの耳ばかりだったんだ。 +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.,Ich gäbe alles für eine Brotkruste. Ich habe so einen Hunger.,,,Daría lo que fuera por una migaja 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.,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.,Я бы всё отдал просто за ломоть хлеба. Я так голоден., -"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,,,"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.","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.",,,"Ah, alguien de la superficie que necesita un favor. Aquí abajo se ofrece un favor a cambio de otro favor y necesito abierta la entrada al pueblo que es nuestro camino a la comida. La Orden lo tiene sellado y guardado.",,"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, 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,,,"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.","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.",,,"Ah, alguien de la superficie que necesita un favor. Aquí abajo se ofrece un favor a cambio de otro favor y necesito abierta la entrada al pueblo que es nuestro camino a la comida. La Orden lo tiene sellado y guardado.",,"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, 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ă.","А-а, гостю с поверхности нужно одолжение. Здесь, внизу, ты должен что-то сделать, прежде чем о чём-то попросить, и мне нужно, чтобы дверь в город, наш путь к пище, была открыта. Орден закрыл её и поставил охрану.", -Where is the gate mechanism?,TXT_RPLY0_SCRIPT06_D0_WHERE,,,,Kde je mechanismus brány?,Wo ist der Tormechanismus?,,,¿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?,,ゲートメカニズムは何処だ?,성문 관리 장치는 어딨지?,Waar is het poortmechanisme?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?, -"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.",Tu erst mir einen Gefallen oder ich sage gar nichts.,,,"Cumple mi favor primero, o no tendrás nada de mi.",,"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.",,俺の言った問題が先だ、でないと手助けできねえ。,"나를 도와주려, 아니면 너를 도륙할 거랴! +Where is the gate mechanism?,TXT_RPLY0_SCRIPT06_D0_WHERE,,,,Kde je mechanismus brány?,Wo ist der Tormechanismus?,,,¿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?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?, +"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.",Tu erst mir einen Gefallen oder ich sage gar nichts.,,,"Cumple mi favor primero, o no tendrás nada de mi.",,"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.",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.","Сначала выполни мою просьбу, или ты ничего не получишь.", -How will you know it's open?,TXT_RPLY0_SCRIPT06_D1516_HOWWI,,,,"Jak budeš vědět, že je otevřená?","Wodurch wirst du wissen, ob er offen ist?",,,¿Cómo sabrás si está abierto?,,"Mistä tiedät, että se on auki?",Comment est-ce que je saurais qu'elle est ouverte?,"Honnan tudod, hogy nyitva lesz?",,開放を知らせるには?,어떻게 도와주면 방법을 알 수 있지?,Hoe weet je dat het open is?,"Skąd będziesz wiedział, że jest już otwarta?",Como você vai saber que ela está aberta?,,Cum vei știi că e deschisă?,"Как ты узнаешь, что дверь открыта?", -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.","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.",,,Tráeme el uniforme del guardia. Así uno de mis rateros lo llevará y nadie intentará cerrar la puerta 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.",,"ガードの制服を持ってくればいい。 +How will you know it's open?,TXT_RPLY0_SCRIPT06_D1516_HOWWI,,,,"Jak budeš vědět, že je otevřená?","Wodurch wirst du wissen, ob er offen ist?",,,¿Cómo sabrás si está abierto?,,"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?,"Skąd będziesz wiedział, że jest już otwarta?",Como você vai saber que ela está aberta?,,Cum vei știi că e deschisă?,"Как ты узнаешь, что дверь открыта?", +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.","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.",,,Tráeme el uniforme del guardia. Así uno de mis rateros lo llevará y nadie intentará cerrar la puerta 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.,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ă.","Принеси мне униформу стражника. Тогда один из моих приятелей сможет носить её, и никто не попытается снова закрыть дверь.", -You want his uniform?,TXT_RPLY0_SCRIPT06_D3032_YOUWA,,,,Ty chceš jeho uniformu?,Du möchtest seine Uniform haben?,,,¿Quieres su uniforme?,,Haluat siis tämän univormun?,Vous voulez son uniforme?,Kell az egyenruhája?,,あんたに制服を渡せばいいか?,그 전투복이 정말로 필요한가?,Wil je zijn uniform?,Chcesz jego mundur?,Você quer o uniforme dele?,,Vrei uniforma lui?,Тебе нужна его форма?, -"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.","Öffne die Tür, bring mir die Uniform und wir können handeln. Ansonsten verschwinde.",,,"Abre la puerta, tráeme el uniforme y negociamos. Si no, que te den.",,"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.",,"そうだ、ゲートを開いて制服を奪うんだ。 +You want his uniform?,TXT_RPLY0_SCRIPT06_D3032_YOUWA,,,,Ty chceš jeho uniformu?,Du möchtest seine Uniform haben?,,,¿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?,Chcesz jego mundur?,Você quer o uniforme dele?,,Vrei uniforma lui?,Тебе нужна его форма?, +"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.","Öffne die Tür, bring mir die Uniform und wir können handeln. Ansonsten verschwinde.",,,"Abre la puerta, tráeme el uniforme y negociamos. Si no, que te den.",,"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.",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.","Открой эту дверь, принеси мне униформу и мы сторгуемся. Иначе, отвали.", -Have you brought me what I want?,TXT_DLG_SCRIPT06_D6064_HAVEY,,,,"Přinesl jsi mi, co chci?",Hast du mir was mitgebracht?,,,¿Me has traído lo que quiero?,,"Oletko tuonut minulle sen, mitä haluan?",Avez-vous ramené ce dont j'ai besoin?,"Elhoztad, amit kértem?",,必要な物は持ってきたか?,내가 원하는 것을 가지고 왔나랴?,Heb je me gebracht wat ik wil?,Przyniosłeś to o co cię prosiłem?,Você trouxe o que eu quero?,,Mi-ai adus ceea ce doresc?,"Ты принёс мне то, что я просил?", -How about this uniform?,TXT_RPLY0_SCRIPT06_D6064_HOWAB,,,,Co tahle uniforma?,Wie findest du diese Uniform?,,,¿Qué tal este uniforme?,,Miten olisi tämä univormu?,"Il vous convient, cet uniforme?",És mi az újság ezzel az egyenruhával?,,この制服はどうだ?,이 전투복은 어때?,Hoe zit het met dit uniform?,Może być ten mundur?,Que tal este uniforme?,,Ce zici de uniforma asta?,Эта униформа подойдёт?, -Bring me the uniform.,TXT_RNO0_SCRIPT06_D6064_BRING,,,,Přines mi tu uniformu.,Bring mir seine Uniform.,,,Tráeme el uniforme.,,Tuo univormu minulle.,Amenez moi l'uniforme.,Hozdd ide az egyenruhát.,,制服を持ってこい。,전투복을 가져와랴...,Breng me het uniform.,Przynieś mi mundur.,Me traga o uniforme.,,Adu-mi uniforma.,Принеси мне униформу., -"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,,,,"Dobře. Tady je něco navíc. Mí stoupenci urvali tohle ze zničeného Křižáka, jsou to části, ze kterých se skládá plamenomet. Teď ti jeden může Irale vytvořit. Můžeš mít takové legrace.",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...,,,"Bien. Aquí tienes algo extra. Mis compañeros arrancaron esto de un Cruzado caído, son las partes que componen un lanzallamas. Ahora Irale puede hacer uno para ti. Te vas a divertir cantidad.","Bien. Aquí tienes algo extra. Mis compañeros arrancaron esto de un Cruzado caído, son las partes que componen un lanzallamas. Ahora Irale puede hacer uno para ti. ¡Tendrás tanta diversión!","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.",,"良し。礼は果たそう。 +Have you brought me what I want?,TXT_DLG_SCRIPT06_D6064_HAVEY,,,,"Přinesl jsi mi, co chci?",Hast du mir was mitgebracht?,,,¿Me has traído 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?,Przyniosłeś to o co cię prosiłem?,Você trouxe o que eu quero?,,Mi-ai adus ceea ce doresc?,"Ты принёс мне то, что я просил?", +How about this uniform?,TXT_RPLY0_SCRIPT06_D6064_HOWAB,,,,Co tahle uniforma?,Wie findest du diese Uniform?,,,¿Qué tal 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?,Może być ten mundur?,Que tal este uniforme?,,Ce zici de uniforma asta?,Эта униформа подойдёт?, +Bring me the uniform.,TXT_RNO0_SCRIPT06_D6064_BRING,,,,Přines mi tu uniformu.,Bring mir seine Uniform.,,,Tráeme el uniforme.,,Tuo univormu minulle.,Amenez moi l'uniforme.,Hozdd ide az egyenruhát.,Portami l'uniforme.,制服を持ってこい。,전투복을 가져와랴...,Breng me het uniform.,Przynieś mi mundur.,Me traga o uniforme.,,Adu-mi uniforma.,Принеси мне униформу., +"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,,,,"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.",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...,,,"Bien. Aquí tienes algo extra. Mis compañeros arrancaron esto de un Cruzado caído, son las partes que componen un lanzallamas. Ahora Irale puede hacer uno para ti. Te vas a divertir cantidad.","Bien. Aquí tienes algo extra. Mis compañeros arrancaron esto de un Cruzado caído, son las partes que componen un lanzallamas. Ahora Irale puede hacer uno para ti. ¡Tendrás tanta diversión!","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.","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.","Хорошо. Я могу предложить тебе кое-что сверх уговора. Мои приятели сняли это с подбитого крестоносца. Это детали огнемёта. Ирэйл соберёт его для тебя, и ты сможешь повеселиться от души.", -Where's the gate mechanism?,TXT_RPLY0_SCRIPT06_D7580_WHERE,,,,Kde je mechanismus brány?,Wo ist der Tormechanismus?,,,¿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?,,ゲートメカニズムは何処だ?,관리 장치는 이제 어디있지?,Waar is het poortmechanisme?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?, -"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,,,,Musíš vejít do jiné části stok. Musíš se údržbovými dveřmi dostat do hradu a vypustit vodní nádrž. Na dně je schovaný vchod do stok a hned za ním je manuální ovládání brány.,"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.",,,"Tienes que adentrarte en 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 fluído. Al fondo está la entrada oculta a las cloacas, y justo más allá está 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ó.",,"下水道の別の部分に入る必要がある。 +Where's the gate mechanism?,TXT_RPLY0_SCRIPT06_D7580_WHERE,,,,Kde je mechanismus brány?,Wo ist der Tormechanismus?,,,¿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?,Gdzie jest mechanizm sterujący bramą?,Onde fica o mecanismo do portão?,,Unde e mecanismul de acționare al porții?,Где механизм управления воротами?, +"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,,,,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 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.",,,"Tienes que adentrarte en 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 fluído. Al fondo está la entrada oculta a las cloacas, y justo más allá está 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.","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.","Это в другой части канализации. Чтобы попасть туда, пройди в замок через дверь обслуживания канализации и слей жидкость из бака для переработки. На его дне есть скрытый вход в стоки, и прямо за ним — ручной механизм управления воротами.", -Anything else you can do?,TXT_RPLY0_SCRIPT06_D9096_ANYTH,,,,Mohl bys udělat ještě něco?,Kannst du sonst noch was für mich tun?,,,¿Algo más que puedas hacer?,,Voitko olla vielä jotenkin muuten avuksi?,Que pouvez vous faire d'autre?,Tudsz még valamit tenni?,,他に出来ることは?,그 외에 당신이 할 수 있는 일은?,Kun je nog iets anders doen?,Czy coś jeszcze możesz zrobić?,Algo mais que você possa fazer?,,Mai poți face altceva?,Можешь помочь мне чем-нибудь ещё?, -"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 hrozné barvy.","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...",,,"Buena suerte. He abierto varios de nuestros tuneles para ti. Te debería hacer el trabajo más fácil. Oh, talla diez, ¡perfecto! ... Pero colores horribles.",,"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.",,"頑張れよ。それとアンタの為に俺達は幾つか +Anything else you can do?,TXT_RPLY0_SCRIPT06_D9096_ANYTH,,,,Mohl bys udělat ještě něco?,Kannst du sonst noch was für mich tun?,,,¿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?,Czy coś jeszcze możesz zrobić?,Algo mais que você possa fazer?,,Mai poți face altceva?,Можешь помочь мне чем-нибудь ещё?, +"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á.","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...",,,"Buena suerte. He abierto varios de nuestros tuneles para ti. Te debería hacer el trabajo más fácil. Oh, talla diez, ¡perfecto! ... Pero colores horribles.",,"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.","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 dez, perfeito! ...Mas as cores são horríveis.",,"Noroc. Am deschis câteva canale pentru tine. Ar trebui să îți ușureze munca. Ah, mărimea zece, perfect! ...Dar cumplite culori.","Разве что пожелать удачи. Я открыл для тебя несколько наших туннелей, это может сделать твою задачу чуть проще. О, десятый размер! Как раз впору!.. Но ужасные цвета.", -Thanks for your help.,TXT_RPLY0_SCRIPT06_D10612_THANK,,,,Díky za pomoc.,Danke für deine Hilfe.,,,Gracias por tu ayuda.,,Kiitos avustasi.,Merci pour votre aide.,Köszi a segítséget.,,協力ありがとう。,도움 정말 고마워.,Bedankt voor je hulp.,Dzięki za twoją pomoc.,Obrigado pela ajuda.,,Merci de ajutor.,Спасибо за помощь., -"You give me nothing, you get nothing.",TXT_DLG_SCRIPT06_D12128_YOUGI,,,,"Ty mi nic nedáš, já ti nic nedám.","Du gibst mir nichts, ich gebe dir nichts.",,,"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.",,何も無ければ、何も渡すモンは無い。,헤헤... 아무 일도 없는 거니 괜찮야!,"Je geeft me niets, je krijgt niets.","Nic mi nie dajesz, nic nie dostajesz.","Você não me dá nada, não ganha nada.",,"Nu dai nimic, primești nimic.",Ничего не даёшь — ничего не получаешь., -Weran will save us. He's never failed us yet.,TXT_DLG_SCRIPT06_D13644_WERAN,,,,Weran nás zachrání. Ještě nás nezklamal.,Weran wird uns retten. Er hat uns noch nie enttäuscht.,,,Weran nos 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.,,"ウェランは皆を保護してくれている。 +Thanks for your help.,TXT_RPLY0_SCRIPT06_D10612_THANK,,,,Díky za pomoc.,Danke für deine Hilfe.,,,Gracias por tu ayuda.,,Kiitos avustasi.,Merci pour votre aide.,Köszi a segítséget.,Grazie del tuo aiuto.,協力ありがとう。,도움 정말 고마워.,Bedankt voor je hulp.,Dzięki za twoją pomoc.,Obrigado pela ajuda.,,Merci de ajutor.,Спасибо за помощь., +"You give me nothing, you get nothing.",TXT_DLG_SCRIPT06_D12128_YOUGI,,,,"Ty mi nic nedáš, já ti nic nedám.","Du gibst mir nichts, ich gebe dir nichts.",,,"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.","Nic mi nie dajesz, nic nie dostajesz.","Você não me dá nada, não ganha nada.",,"Nu dai nimic, primești nimic.",Ничего не даёшь — ничего не получаешь., +Weran will save us. He's never failed us yet.,TXT_DLG_SCRIPT06_D13644_WERAN,,,,Weran nás zachrání. Ještě nás nezklamal.,Weran wird uns retten. Er hat uns noch nie enttäuscht.,,,Weran nos 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 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.,Уэран поможет нам. Он ещё ни разу не подводил нас., -"If you seek an answer to your problem, find Weran. ",TXT_DLG_SCRIPT06_D15160_IFYOU,,,,"Jestli hledáš odpověď na svou otázku, najdi Werana.","Wenn du Lösungen für deine Probleme suchst, frag Weran.",,,"Si buscas una respuesta a tú problema, encuentra a 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.",,"君の問題の答えが欲しいなら、 +"If you seek an answer to your problem, find Weran. ",TXT_DLG_SCRIPT06_D15160_IFYOU,,,,"Jestli hledáš odpověď na svou otázku, najdi Werana.","Wenn du Lösungen für deine Probleme suchst, frag Weran.",,,"Si buscas una respuesta a tú problema, encuentra a 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.","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.",Тебе нужен ответ? Найди Уэрана., -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.,Lang lebe die Front? Was für ein Mist. Wir warten doch nur auf den Tod.,,,¿Larga vida al frente? Menuda mierda. Todos esperamos 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.",,"フロントに入れ? 馬鹿げてる。 +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.,Lang lebe die Front? Was für ein Mist. Wir warten doch nur auf den Tod.,,,¿Larga vida al frente? Menuda mierda. Todos esperamos 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.,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.,Да здравствует Сопротивление? Это всё чушь. Мы все просто ждём смерти., -"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.","Da unser Zugang zur Oberfläche verschlossen ist, haben wir nichts mehr zu essen.",,,"Con nuestro pasaje a la superficie sellado, 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.",,"外への出入口が封鎖されてるから、 +"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.","Da unser Zugang zur Oberfläche verschlossen ist, haben wir nichts mehr zu essen.",,,"Con nuestro pasaje a la superficie sellado, 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.",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.","Пока выход на поверхность закрыт, мы не можем даже прокормить себя.", -"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.","Essen, hast du was zu essen? Bitte hilf uns.",,,"Comida, ¿Tienes algo de comida? Por favor ayúdanos.",,"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.",,食い物、食い物を恵んでくれないか? 頼むよ。,굶어 죽을 것 같습니다... 부디 음식 찌꺼기라도 괜찮으니까 음식을...,"Eten, heb je eten? Help ons alstublieft.","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.","Еда. У тебя есть еда? Пожалуйста, помоги нам.", -"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,,,,"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.","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!",,,"Ésta es mi recompensa por dejar a prisioneros escapar, vigilar las cloacas. Si encuentro al tipo que los liberó, me lo cargo.","Ésta es mi recompensa por dejar escapar a los prisioneros, vigilar las cloacas. Si encuentro al tipo que los liberó, lo mataré.","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.",,"この下水道から囚人を脱走させた奴を探す為、 +"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.","Essen, hast du was zu essen? Bitte hilf uns.",,,"Comida, ¿Tienes algo de comida? Por favor ayúdanos.",,"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.","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.","Еда. У тебя есть еда? Пожалуйста, помоги нам.", +"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,,,,"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.","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!",,,"Ésta es mi recompensa por dejar a prisioneros escapar, vigilar las cloacas. Si encuentro al tipo que los liberó, me lo cargo.","Ésta es mi recompensa por dejar escapar a los prisioneros, vigilar las cloacas. Si encuentro al tipo que los liberó, lo mataré.","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.","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.","Я отбываю наказание за то, что не остановил побег из тюрьмы: охраняю канализацию. Если я когда-нибудь найду того парня, что освободил пленников, я его на куски порву.", -"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,,,,"Máme ty žebráčky přesně tam, kde chceme. Ještě pár dní a vyhladoví se do zapomnění.","Wir haben diese armseligen Bettler doch genau da, wo wir sie haben wollen. Noch ein paar Tage und sie wären verhungert.",,,"Tenemos a esos indigentes justo donde los queremos. Unos cuantos días más así, y se habrán consumido por el 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.",,"この辺の何処かに乞食共がいるはずだ。 +"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,,,,"Máme ty žebráčky přesně tam, kde chceme. Ještě pár dní a vyhladoví se do zapomnění.","Wir haben diese armseligen Bettler doch genau da, wo wir sie haben wollen. Noch ein paar Tage und sie wären verhungert.",,,"Tenemos a esos indigentes justo donde los queremos. Unos cuantos días más así, y se habrán consumido por el 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.,"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.","Мы загнали этих жалких нищих туда, где им самое место. Ещё несколько дней, и все они подохнут с голоду.", -What's your clearance? There's no unauthorized personnel allowed up here.,TXT_DLG_SCRIPT06_D24256_WHATS,,,,Máš oprávnění? Žádná nepovolená osoba tady nahoře nemá co dělat!,Wo ist deine Berechtigung? Unautorisiertes Personal darf hier nicht rein.,,,¿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.,,"お前のクリアランスは何だ? +What's your clearance? There's no unauthorized personnel allowed up here.,TXT_DLG_SCRIPT06_D24256_WHATS,,,,Máš oprávnění? Žádná nepovolená osoba tady nahoře nemá co dělat!,Wo ist deine Berechtigung? Unautorisiertes Personal darf hier nicht rein.,,,¿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.,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.,Где твой пропуск? Здесь нечего делать неуполномоченному персоналу., -What the hell? Who opened the gates? Sound the alarm!!!,TXT_DLG_SCRIPT07_D0_WHATT,,,,Co to sakra? Kdo otevřel bránu? Volej na poplach!,Was zur Hölle? Wer hat die Tore geöffne? Alarm!,,,¿Qué demonios? ¿Quién ha abierto 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!,,"何をしやがった? +What the hell? Who opened the gates? Sound the alarm!!!,TXT_DLG_SCRIPT07_D0_WHATT,,,,Co to sakra? Kdo otevřel bránu? Volej na poplach!,Was zur Hölle? Wer hat die Tore geöffne? Alarm!,,,¿Qué demonios? ¿Quién ha abierto 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!!!,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!!!,Что за чертовщина? Кто открыл ворота? Бейте тревогу!, -"There's another way into the sewers, throw that switch and then go up and purge the reclamation tank.",TXT_DLG_SCRIPT07_D1516_THERE,,,,"Do stok vede další cesta, zatáhni za tuhle páku a pak jdi nahoru a vypusť obnovnou nádrž.",Da ist ein anderer Weg in die Kanalisation. Drück den Schalter da und leere den Rückgewinnungstank.,,,"Hay otra entrada a las cloacas, activa ese interruptor y luego sube y purga el tanque de recuperación.",,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.",,"下水道に別の入り口がある、スイッチを入れ +"There's another way into the sewers, throw that switch and then go up and purge the reclamation tank.",TXT_DLG_SCRIPT07_D1516_THERE,,,,"Do stok vede další cesta, zatáhni za tuhle páku a pak jdi nahoru a vypusť obnovnou nádrž.",Da ist ein anderer Weg in die Kanalisation. Drück den Schalter da und leere den Rückgewinnungstank.,,,"Hay otra entrada a las cloacas, activa ese interruptor y luego sube y purga el tanque de recuperación.",,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.","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.","Есть другой путь в канализацию. Переведи этот рычаг, затем иди наверх и слей жидность из бака для переработки.", -"What the hell's your problem. If the Programmer comes up from his audience chamber, you're dead.",TXT_DLG_SCRIPT07_D3032_WHATT,,,,"Co máš sakra za problém? Jestli Programátor vyjde ze svého sálu, jsi mrtvý.","Was, verdammt, ist dein Problem? Wenn der Programmierer seine Audienzkammer verläßt, bist du tot.",,,"¡Qué demonios te pasa! Si el Programador viene de su cámara de audición, 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.",,"一体何をしに来た。プログラマーが +"What the hell's your problem. If the Programmer comes up from his audience chamber, you're dead.",TXT_DLG_SCRIPT07_D3032_WHATT,,,,"Co máš sakra za problém? Jestli Programátor vyjde ze svého sálu, jsi mrtvý.","Was, verdammt, ist dein Problem? Wenn der Programmierer seine Audienzkammer verläßt, bist du tot.",,,"¡Qué demonios te pasa! Si el Programador viene de su cámara de audición, 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.",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.","Проклятье, что с тобой не так? Если Программист поднимется из приёмного зала, ты покойник!", -"Hey, you're not cleared to go down there.",TXT_DLG_SCRIPT07_D4548_HEYYO,,,,"Hej, nemáš povolení jít tam dolů.","He, du darfst da nicht runtergehen.",,,"Hey, 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.",,"おい、あんたはここを降りる事は +"Hey, you're not cleared to go down there.",TXT_DLG_SCRIPT07_D4548_HEYYO,,,,"Hej, nemáš povolení jít tam dolů.","He, du darfst da nicht runtergehen.",,,"Hey, 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.","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.","Эй, у тебя нет разрешения спускаться туда.", -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,,,,"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.","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.",,,¿Programador? ¿Quién te ha dicho eso? No hay Programador. Esa historia se ha extendido hace años. No me digas que el frente realmente se ha creído el cuento. 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.",,"プログラマー?誰ガそんなことヲ言った? +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,,,,"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.","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.",,,¿Programador? ¿Quién te ha dicho eso? No hay Programador. Esa historia se ha extendido hace años. No me digas que el frente realmente se ha creído el cuento. 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.,"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.,"Программист? Кто тебе это сказал? Нет никакого программиста. Этой байке уже сто лет. Только не говори мне, что Сопротивление и правда поверило в эту чушь. Идиоты.", -"Well, what's the truth then?",TXT_RPLY0_SCRIPT07_D6064_WELLW,,,,Pravda je tedy kde?,"Nun, was ist denn die Wahrheit?",,,"Bien, ¿Cuál es la verdad entonces?",,"No, mikä totuus sitten on?","Quelle est la vérité, alors?","Nos, mi az igazság akkor?",,それなら、本当の事は何だ?,"그럼, 진실이 뭐야?","Nou, wat is de waarheid dan?",Więc co jest prawdą?,"Bem, qual é a verdade?",,"Păi, care e adevărul atunci?","Ладно, и что же тогда правда?", -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.","Ich habe alles gesagt, was ich weiß. Du verschwendest deine Zeit.",,,Te he dicho 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.",,"私ハ知っていることヲ教えた。 +"Well, what's the truth then?",TXT_RPLY0_SCRIPT07_D6064_WELLW,,,,Kde je tedy pravda?,"Nun, was ist denn die Wahrheit?",,,"Bien, ¿Cuál es la verdad entonces?",,"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?",Więc co jest prawdą?,"Bem, qual é a verdade?",,"Păi, care e adevărul atunci?","Ладно, и что же тогда правда?", +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.","Ich habe alles gesagt, was ich weiß. Du verschwendest deine Zeit.",,,Te he dicho 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.,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.","Я рассказал всё, что знаю. Ты попусту тратишь время.", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D9096_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D9096_FIGHT,,,,"Bojuj dál, však my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D10612_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"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!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D12128_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"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!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D13644_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"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!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D15160_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"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!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"Fight on, we will triumph. This day will belong to us!",TXT_DLG_SCRIPT07_D16676_FIGHT,,,,"Bojuj dál, my zvítězíme! Dnešek bude patřit nám!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!,,"我々は勝利を志し、戦う。 +"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!","Lass uns kämpfen, wir werden gewinnen. Dieser Tag gehört uns!",,,"Luchad, triunfaremos. ¡Este día nos pertenece!",Luchemos y triunfaremos. ¡Este día nos pertenece!,"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!","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!","Сражайся, и нас ждёт триумф. Сегодняшний день будет нашим!", -"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,,,,"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 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.",,,"Has matado a todos los guardias. No me hagas daño. Le dije que era una idea estúpida. El verdadero Programador está en el torreón. Ten, toma esta llave.","Has matado a todos los guardias. No me hagas daño. Le dije que era una idea estúpida. El verdadero Programador está en la torre. 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.",,"君がガードを全員殺したノカ。 +"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,,,,"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 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.",,,"Has matado a todos los guardias. No me hagas daño. Le dije que era una idea estúpida. El verdadero Programador está en el torreón. Ten, toma esta llave.","Has matado a todos los guardias. No me hagas daño. Le dije que era una idea estúpida. El verdadero Programador está en la torre. 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.","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.,"Ты убил всех стражников. Не трогай меня! Я говорил ему, что это глупая идея. Настоящий Программист в цитадели. Вот, возьми этот ключ.", -You're the Programmer!,TXT_RPLY0_SCRIPT08_D0_YOURE,,,,Ty jsi Programátor!,Du bist der Programmierer!,,,¡Tú eres el Programador!,,Sinä olet Ohjelmoitsija!,Vous êtes le Programmeur!,Te vagy a Programozó!,,アンタがプログラマーだろ!,넌 프로그래머잖아!,Jij bent de programmeur!,To ty jesteś Programistą!,Você é o Programador!,,Tu ești Programatorul!,Ты программист!, -"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ý.","Sehe ich so aus, als ob ich unendliche Macht hätte? Der Orden benutzt uns alle. Nun geh, ich bin ohnehin schon tot.",,,"¿Te parece que posea el poder absoluto? La Orden nos usa a todos. Ahora ve, yo ya estoy muerto.","¿Te parece que posea el poder absoluto? La Orden nos usa a todos. Vete, 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.",,"私ガそんな凄まじい力ヲ振舞っていると思うか? +You're the Programmer!,TXT_RPLY0_SCRIPT08_D0_YOURE,,,,Ty jsi Programátor!,Du bist der Programmierer!,,,¡Tú eres el Programador!,,Sinä olet Ohjelmoitsija!,Vous êtes le Programmeur!,Te vagy a Programozó!,Sei tu il Programmatore!,アンタがプログラマーだろ!,넌 프로그래머잖아!,Jij bent de programmeur!,To ty jesteś Programistą!,Você é o Programador!,,Tu ești Programatorul!,Ты программист!, +"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ý.","Sehe ich so aus, als ob ich unendliche Macht hätte? Der Orden benutzt uns alle. Nun geh, ich bin ohnehin schon tot.",,,"¿Te parece que posea el poder absoluto? La Orden nos usa a todos. Ahora ve, yo ya estoy muerto.","¿Te parece que posea el poder absoluto? La Orden nos usa a todos. Vete, 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.","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.",Разве я похож на обладателя невероятной мощи? Орден использует нас всех. Теперь иди. Я уже всё равно мёртв., -Power is the key!,TXT_DLG_SCRIPT08_D3032_POWER,,,,Moc je tím klíčem!,Macht ist der Schlüssel!,,,¡El poder es la clave!,,Valta on avain!,Le pouvoir est la clé!,Az erő a kulcs!,,キーが力だ!,힘이 곧 열쇠다!,Kracht is de sleutel!,Moc jest kluczem!,O poder é a chave!,,Puterea e cheia!,В силе — всё!, -"Good, you're conscious again. When you grabbed that item the Programmer dropped, you let loose some terrible secrets.",TXT_DLG_SCRIPT10_D0_GOODY,,,,"Už jsi vzhůru, dobře. Když jsi sebral tu věc, kterou Programátor upustil, odhalil jsi děsivá tajemství.","Gut, du bist wieder wach. Als du das Ding, das der Programmierer fallengelassen hat, packtest, hast du einige schlimme Geheimnisse enthüllt.",,,"Bien, vuelves a estar consciente. Cuando agarraste ese objeto que el Programador soltó has dejado sueltos algunos secretos terribles.",,"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.",,"良し、意識が戻ったか。 +Power is the key!,TXT_DLG_SCRIPT08_D3032_POWER,,,,Moc je tím klíčem!,Macht ist der Schlüssel!,,,¡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!,Moc jest kluczem!,O poder é a chave!,,Puterea e cheia!,В силе — всё!, +"Good, you're conscious again. When you grabbed that item the Programmer dropped, you let loose some terrible secrets.",TXT_DLG_SCRIPT10_D0_GOODY,,,,"Už jsi vzhůru, dobře. Když jsi sebral tu věc, kterou Programátor upustil, odhalil jsi děsivá tajemství.","Gut, du bist wieder wach. Als du das Ding, das der Programmierer fallengelassen hat, packtest, hast du einige schlimme Geheimnisse enthüllt.",,,"Bien, vuelves a estar consciente. Cuando agarraste ese objeto que el Programador soltó has dejado sueltos algunos secretos terribles.",,"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.","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.","Хорошо, ты пришёл в себя. Взяв в руки артефакт, который выронил Программист, ты раскрыл страшные тайны.", -What kind of secrets. ,TXT_RPLY0_SCRIPT10_D0_WHATK,,,,Jaká tajemství?,Was für Geheimnisse?,,,¿Qué clase de secretos?,,Minkälaisia salaisuuksia?,De quels secrets parlez-vous?,Miféle titkok?,,その秘密とは。,어떤 비밀인가요?,Wat voor geheimen.,Jakich sekretów?,Que tipos de segredos?,,Ce fel de secrete?,Какие тайны?, -"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.","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.",,,"No sabemos de donde ha venido esta arma, pero debemos averiguarlo. Has arrebatado una de la Orden, pero debemos tener las cinco. Hemos alcanzado el límite de mis conocimientos. 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.",,"この武器が何処で造られたかは分からないが、 +What kind of secrets. ,TXT_RPLY0_SCRIPT10_D0_WHATK,,,,Jaká tajemství?,Was für Geheimnisse?,,,¿Qué clase de secretos?,,Minkälaisia salaisuuksia?,De quels secrets parlez-vous?,Miféle titkok?,Che tipo di segreti.,その秘密とは。,어떤 비밀인가요?,Wat voor geheimen.,Jakich sekretów?,Que tipos de segredos?,,Ce fel de secrete?,Какие тайны?, +"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.","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.",,,"No sabemos de donde ha venido esta arma, pero debemos averiguarlo. Has arrebatado una de la Orden, pero debemos tener las cinco. Hemos alcanzado el límite de mis conocimientos. 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.","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.","Мы понятия не имеем, откуда взялось это оружие, но обязаны выяснить. Ты отбил один фрагмент у Ордена, но нам нужны все пять. Я рассказал тебе всё, что знал. Найди Оракула и попроси его о помощи.", -I'm gonna need more supplies.,TXT_RPLY0_SCRIPT10_D1516_IMGON,,,,Budu potřebovat zásoby.,Ich brauche mehr Ausrüstung.,,,Voy a necesitar más suministros.,,Tarvitsen lisää varusteita.,Il me faut de l'équipment.,Szükségem lesz még felszerelésre.,,それには補給がもっと必要だ。,물자가 좀 필요할 것 같은데.,Ik zal meer voorraden nodig hebben.,Będę potrzebować więcej zaopatrzenia.,Vou precisar de mais equipmento.,,O să am nevoie de mai multe provizii.,Мне потребуются ещё припасы., -"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!",Hier ist etwas Gold. Geh zum Sanitäter und zum Waffentrainer und dann los!,,,"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!",,"資金を提供しよう。 +I'm gonna need more supplies.,TXT_RPLY0_SCRIPT10_D1516_IMGON,,,,Budu potřebovat zásoby.,Ich brauche mehr Ausrüstung.,,,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.,Będę potrzebować więcej zaopatrzenia.,Vou precisar de mais equipmento.,,O să am nevoie de mai multe provizii.,Мне потребуются ещё припасы., +"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!",Hier ist etwas Gold. Geh zum Sanitäter und zum Waffentrainer und dann los!,,,"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!,"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!","Вот немного золота. Посети медика и инструктора по стрельбе, и выдвигайся!", -Right!,TXT_RPLY0_SCRIPT10_D3032_RIGHT,,,,Ano!,Ja.,,Ĝuste!,¡Claro!,,Selvä!,Bien!,Igenis!,,わかった!,네!,Juist!,Dobrze!,Certo!,,Într-adevăr!,Есть!, -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D4548_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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!,,フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het front en vrijheid. Verhuizen.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., -"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ť.","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.",,"何が帰還を促した?怪我をしたのか? +Right!,TXT_RPLY0_SCRIPT10_D3032_RIGHT,,,,Ano!,Ja.,,Ĝuste!,¡Claro!,,Selvä!,Bien!,Igenis!,Sarà fatto!,わかった!,네!,Juist!,Dobrze!,Certo!,,Într-adevăr!,Есть!, +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D4548_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., +"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ť.","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.","何が帰還を促した?怪我をしたのか? 屈している場合ではない。 シジルを完成させる使命を果たすんだ。",돌아왔습니까? 상처라도 입었나요? 시간이 없으니 임무를 속행하고 시질 조각을 마저 모으시길 바랍니다.,"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.","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.",С какой целью ты вернулся? Ты ранен? Нельзя терять ни минуты. Продолжай выполнение задания. Собери Сигил!, -The Oracle says you must die!,TXT_RPLY0_SCRIPT10_D6064_THEOR,,,,"Věštec říká, že musíš zemřít!","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!",,オラクルは死ぬべきだと言った!,오라클의 이름으로 넌 죽어야 해!,Het Orakel zegt dat je moet sterven!,Wyrocznia mówi że musisz zginąć!,O Oráculo diz que você deve morrer!,,Oracolul spune că trebuie să mori!,"Оракул сказал, что я должен убить тебя!", -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.",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.,,"私は皆の自由を誓った。 +The Oracle says you must die!,TXT_RPLY0_SCRIPT10_D6064_THEOR,,,,"Věštec říká, že musíš zemřít!","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!,Wyrocznia mówi że musisz zginąć!,O Oráculo diz que você deve morrer!,,Oracolul spune că trebuie să mori!,"Оракул сказал, что я должен убить тебя!", +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.",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.,"私は皆の自由を誓った。 三つ目の部品を持つのはオラクルだ。 君は裏切るつもりか。",전 자유를 지키겠다고 맹세했습니다. 오라클이 세 번째 조각을 가지고 있단 말입니다. 그자가 바로 배신자입니다!,Ik heb mezelf gezworen tot vrijheid. Het is het Orakel dat het derde deel vasthoudt. Daar is je verrader.,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.,Я присягнул борьбе за свободу. Третий фрагмент хранится у Оракула. Так и кто же из нас предатель?, -The Oracle will die then!,TXT_RPLY0_SCRIPT10_D7580_THEOR,,,,Pak Věštec zemře!,Dann wird das Orakel sterben.,,,¡El Oráculo morirá entonces!,,Siinä tapauksessa Oraakkeli kuolkoon!,L'Oracle va donc mourir!,Akkor meghal az Orákulum!,,オラクルは後で仕留める!,그럼 오라클을 죽여야겠군.,Het Orakel zal dan sterven!,A więc to Wyrocznia zginie!,O Oráculo morrerá então!,,Oracolul va pieri atunci!,Тогда умрёт Оракул!, -I think you're the traitor!,TXT_RPLY1_SCRIPT10_D7580_ITHIN,,,,"Myslím, že ty jsi ten zrádce!","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ó!,,裏切り者はお前の方だ!,배신자는 바로 당신이야!,Ik denk dat jij de verrader bent!,Według mnie to ty jesteś zdrajcą!,Eu acho que você que é o traidor!,,Eu cred că tu ești trădătorul!,"Я думаю, что предатель — это ты!", -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!,"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.",,"唯一神の魂が私を討てば +The Oracle will die then!,TXT_RPLY0_SCRIPT10_D7580_THEOR,,,,Pak Věštec zemře!,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!,A więc to Wyrocznia zginie!,O Oráculo morrerá então!,,Oracolul va pieri atunci!,Тогда умрёт Оракул!, +I think you're the traitor!,TXT_RPLY1_SCRIPT10_D7580_ITHIN,,,,"Myslím, že ty jsi ten zrádce!","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!,Według mnie to ty jesteś zdrajcą!,Eu acho que você que é o traidor!,,Eu cred că tu ești trădătorul!,"Я думаю, что предатель — это ты!", +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!,"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.,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șă.,Дух Единого Бога отомстит за меня и обратит этот мир в прах., -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 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.",,"君は正しい決断をした。 +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 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.,"君は正しい決断をした。 オラクルがオーダーに悪しき支配をしているのは 明白だ。戻って三番目のシジルを手に入れろ。","좋은 선택입니다. 아무래도 오더가 이끄는 악에서 오라클을 조종하는 것이 명백해졌으니, 녀석을 찾아가 시질의 세 번째 조각을 회수하세요. \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.,"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.,"Ты сделал правильный выбор. Ясно, что Оракулом управляет то же самое зло, что стоит за Орденом. Вернись к Оракулу и потребуй отдать тебе третий фрагмент Сигила!", -"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 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.",,"どうやら我々の直面する恐怖は +"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 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인간개조? 음, 이거 때문에 녀석들이 끊임없이 나오는 거였어! 녀석들 성질 더러운 것도 그렇고.","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.","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.","Иногда кажется, что эти ужасы никогда не закончатся. Мы узнали, что Орден не убивает наших людей. Он перерабатывает их в биомеханических солдат. Найди фабрику, где происходит эта переработка, и закрой её раз и навсегда!", -Where is this located?,TXT_RPLY0_SCRIPT10_D12128_WHERE,,,,Kde ji najdu?,Wo finde ich sie?,,,¿Dónde se encuentra?,,Missä se sijaitsee?,Où se trouve-elle?,Hol van ez?,,手掛かりは何処にある?,이 장소는 어디에 있죠?,Waar bevindt deze faciliteit zich?,Gdzie się znajduje?,Onde se encontra?,,Unde este localizată?,Где она находится?, -"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 předměstí Řádu. Továrnu už viděl a může ti poradit, jak dovnitř. Zastav tuhle ohavnost, hned.","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.",,"キャプテンの一人、リヒターが +Where is this located?,TXT_RPLY0_SCRIPT10_D12128_WHERE,,,,Kde ji najdu?,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?,Gdzie się znajduje?,Onde se encontra?,,Unde este localizată?,Где она находится?, +"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.","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.","キャプテンの一人、リヒターが コモンズの滝で待っている。 彼は施設を発見し生還した者だ。 早急にそのふざけた行為を止めさせろ。","우리 군의 한 대대장인 릭터가 식당가에 위치한 폭포 근처에서 당신을 기다리고 있습니다. 그는 그 끔찍한 시설을 보았다고 했으며, 침투할 수 있게 도와주고 싶다는군요. 부디 이 잔혹 행위를 멈출 수 있기를 바랍니다.","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.","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.","Один из наших капитанов, Рихтер, ожидает тебя возле водопада в поселении Ордена. Он уже проникал на фабрику, и он скажет тебе, как туда попасть. Положи конец этим зверствам, немедленно!", -They'll pay for this!,TXT_RPLY0_SCRIPT10_D13644_THEYL,,,,Za tohle budou pykat!,Dafür werden sie bezahlen.,,,¡Pagarán por esto!,,Ne saavat maksaa tästä!,Ils paieront pour cela!,Megfizetnek ezért!,,奴等に対価を払わせてやるさ!,그놈들은 죗값을 치를 것입니다!,Zij zullen hiervoor betalen!,Zapłacą za to!,Eles pagarão por isso!,,Vor plătii pentru asta!,Они за всё заплатят!, -Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D15160_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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!,,フロントと自由の為の闘争を。さあ向かえ。,"프론트와 자유를 향하여, 전진하세요!",Vecht voor het Front en vrijheid. Ga weg.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., -"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...","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...",,"我が唯一神だ...我は己の肉体を離れ +They'll pay for this!,TXT_RPLY0_SCRIPT10_D13644_THEYL,,,,Za tohle budou pykat!,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!,Zapłacą za to!,Eles pagarão por isso!,,Vor plătii pentru asta!,Они за всё заплатят!, +Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D15160_FIGHT,,,,Bojuj za Frontu a svobodu! Odchod.,Kämpfe für die Front und die Freiheit. Nun geh.,,,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.,Walcz dla Frontu i wolności. Wykonać.,Lute pela Frente e pela liberdade. Agora vá.,,Luptă pentru Front și libertate. Acum pleacă.,Сражайся за свободу и справедливость. Вперёд., +"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...","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...","我が唯一神だ...我は己の肉体を離れ 自由となり、神の魂と共に飛び立てる。 貴様には何も分かりもしないだろう... そして垣間見る恐怖もな... @@ -9203,15 +9199,15 @@ Fight for the Front and freedom. Move out.,TXT_DLG_SCRIPT10_D15160_FIGHT,,,,Boju そして神は我を表彰するだろう... 我は一つとなる...","유일신... 그분의 영혼의 힘으로... 나의 육신을 버리고... 그분과 자유롭게 날아가리라... 그대가 소유한 것, 그대가 직면할 운명... 모두 모를 것이다... 유일신이 자유가 되면... 나에게 보답하시매, 그와 하나가 되리라!! \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....",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...","Я Единый Бог... Я должен высвободить его дух, тогда я смогу покинуть бренную оболочку моего тела и воссоединиться с ним в полёте. Ты и понятия не имеешь, чем обладаешь... и с каким кошмаром столкнулся... Единый Бог должен быть освобождён... И он вознаградит меня... Это сделаю я!", -I will destroy you!,TXT_RPLY0_SCRIPT10_D16676_IWILL,,,,Zničím tě!,Ich werde dich zerstören!,,,¡Te destruiré!,,Tuhoan sinut!,L'heure est venue de vous détruire!,Megsemmisítelek!,,お前を滅ぼす!,당신을 처단하겠어!,Ik zal je vernietigen!,Zniszczę cię!,Eu vou destruir você!,,Te voi distruge!,Я уничтожу тебя!, -Glad to see you made it. What do you need? ,TXT_DLG_SCRIPT10_D18192_GLADT,,,,"Jsem rád, žes to zvládnul. Co bys potřeboval?","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?",,お会いできて光栄です。何が必要ですか?,여기까지 오시다니 놀랍군요. 뭔가 필요한 게?,Blij te zien dat je het gehaald hebt. Wat heb je nodig?,"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?,"Я рад, что ты справился. Чем могу помочь?", -Heal me.,TXT_RPLY0_SCRIPT10_D18192_HEALM,,,,Potřebuju ošetřit.,Mach mich gesund.,,,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료해주세요.,Genees me.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня., -"Well, lets get you fixed up.",TXT_RYES0_SCRIPT10_D18192_WELLL,,,,"Dobře, tak tě dáme dohromady.","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.",,では、すぐ治療しましょう。,그럼 긴급 치료하겠습니다.,"Nou, laten we je opknappen.","Dobra, pozbieram cię do kupy.","Ok, vamos dar um jeito em você.",,"Păi, să te aranjăm.","Ну, давай приведём тебя в порядок.", -You're fine.,TXT_RNO0_SCRIPT10_D18192_YOURE,,,,Jsi v pořádku.,Die geht es gut.,,,Estás bien.,,Olet kunnossa.,Vous allez bien.,Rendben is vagy.,,貴方は大丈夫です。,괜찮아 보이는데.,Je bent in orde.,Jesteś zdrowy.,Você está bem.,,Ești în regulă.,Ты здоров., -Anything new?,TXT_RPLY1_SCRIPT10_D18192_ANYTH,,,,Něco nového?,Irgend etwas Neues?,,,¿Algo nuevo?,,Onko mitään uutta?,Quoi de neuf?,Valami újdonság?,,何か新しいのは?,특별한 거 없나요?,Iets nieuws?,Coś nowego?,Alguma novidade?,,Ceva nou?,Есть что-нибудь новое?, -"Yes, I've got some new hardware for you.",TXT_RYES1_SCRIPT10_D18192_YESIV,,,,"Ano, mám pro tebe novou mašinku.","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.",,貴方の為に幾つか新しいハードウェアを見つけました。,네! 사용 가능한 하드웨어가 하나 있습니다.,"Ja, ik heb wat nieuwe hardware voor je.","Tak, mam dla ciebie nowe oprogramowanie.","Sim, tenho equipamento novo pra você.",,"Da, am ceva hardware nou pentru tine.",Да. Новая аппаратура для тебя., -"Nope, I'm working on it though.",TXT_RNO1_SCRIPT10_D18192_NOPEI,,,,"Ne, ale pracuju na tom.","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.",,いえ、只今探しています。,아뇨. 아직 작업 진행 중입니다.,"Nee, maar ik ben er wel mee bezig.","Nie, jeszcze nad tym pracuję.","Não, mas estou trabalhando nisso.",,"Nu, încă lucrez la asta.","Нет, но я работаю над ним.", -"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,,,,"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.","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.",,"何か御用かい?幾つかの複雑に複合化された +I will destroy you!,TXT_RPLY0_SCRIPT10_D16676_IWILL,,,,Zničím tě!,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!,Zniszczę cię!,Eu vou destruir você!,,Te voi distruge!,Я уничтожу тебя!, +Glad to see you made it. What do you need? ,TXT_DLG_SCRIPT10_D18192_GLADT,,,,"Jsem rád, žes to zvládnul. Co bys potřeboval?","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?,"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?,"Я рад, что ты справился. Чем могу помочь?", +Heal me.,TXT_RPLY0_SCRIPT10_D18192_HEALM,,,,Potřebuju ošetřit.,Mach mich gesund.,,,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees me.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня., +"Well, lets get you fixed up.",TXT_RYES0_SCRIPT10_D18192_WELLL,,,,"Dobře, tak tě dáme dohromady.","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.","Dobra, pozbieram cię do kupy.","Ok, vamos dar um jeito em você.",,"Păi, să te aranjăm.","Ну, давай приведём тебя в порядок.", +You're fine.,TXT_RNO0_SCRIPT10_D18192_YOURE,,,,Jsi v pořádku.,Die geht es gut.,,,Estás bien.,,Olet kunnossa.,Vous allez bien.,Rendben is vagy.,Stai bene.,貴方は大丈夫です。,괜찮아 보이는데.,Je bent in orde.,Jesteś zdrowy.,Você está bem.,,Ești în regulă.,Ты здоров., +Anything new?,TXT_RPLY1_SCRIPT10_D18192_ANYTH,,,,Něco nového?,Irgend etwas Neues?,,,¿Algo nuevo?,,Onko mitään uutta?,Quoi de neuf?,Valami újdonság?,Novità?,何か新しいのは?,특별한 거 없나요?,Iets nieuws?,Coś nowego?,Alguma novidade?,,Ceva nou?,Есть что-нибудь новое?, +"Yes, I've got some new hardware for you.",TXT_RYES1_SCRIPT10_D18192_YESIV,,,,"Ano, mám pro tebe novou mašinku.","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.","Tak, mam dla ciebie nowe oprogramowanie.","Sim, tenho equipamento novo pra você.",,"Da, am ceva hardware nou pentru tine.",Да. Новая аппаратура для тебя., +"Nope, I'm working on it though.",TXT_RNO1_SCRIPT10_D18192_NOPEI,,,,"Ne, ale pracuju na tom.","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.","Nie, jeszcze nad tym pracuję.","Não, mas estou trabalhando nisso.",,"Nu, încă lucrez la asta.","Нет, но я работаю над ним.", +"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,,,,"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.","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.","何か御用かい?幾つかの複雑に複合化された フェリスのファイルにはそれだけの価値はあった スタミナインプラントの次期バージョンに 適用できる情報を少しばかり見つけたんだ。","무엇을 도와드릴까요? 페리스가 아주 복잡한 파일들을 천천히 해독하는 중입니다만, 기다리는 보람이 많이 있을 거예요. 나머지 정보를 다 해독한 뒤면 진보된 지구력 향상 이식을 받으실 수 있을 겁니다.","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.","Co mogę dla ciebie teraz zrobić? Feris @@ -9221,12 +9217,12 @@ 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ță.","Чем я могу тебе помочь? Ферис сейчас расшифровывает файлы Ордена. Это нелегко, но результат стоит того. Я уже получил кое-какие новые данные, которые помогут мне при разработке новой версии твоего импланта.", -Heal me.,TXT_RPLY0_SCRIPT10_D19708_HEALM,,,,Potřebuju ošetřit.,Mach mich gesund.,,,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료해주세요.,Genees mij.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня., -You should learn to be a little more careful.,TXT_RYES0_SCRIPT10_D19708_YOUSH,,,,Měl bys být trochu opatrnější.,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.,,もう少し慎重にやるべきでは。,몸 간수 잘하시고 싸우세요.,Je moet leren om wat voorzichtiger te zijn.,Powinieneś być bardziej ostrożny.,Você precisa aprender a tomar mais cuidado.,,Ar trebui să fii mai grijuliu.,В следующий раз тебе стоит быть поосторожнее., -When will that be ready?,TXT_RPLY1_SCRIPT10_D19708_WHENW,,,,Kdy bude hotov?,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?,,出来ているか?,이식 준비는 다 됐습니까?,Wanneer is dat klaar?,Kiedy to będzie gotowe?,Quando isso vai estar pronto?,,Când va fi gata?,Когда он будет готов?, -It's ready now. This won't take but a moment.,TXT_RYES1_SCRIPT10_D19708_ITSRE,,,,Už je hotový. Nepotrvá to ani chvilku.,"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.",,用意出来ている。すぐ終わるさ。,다 됐습니다! 이제 이식을 시작하죠!,Het is nu klaar. Dit duurt niet langer dan een moment.,Już jest gotowe. To zajęło tylko chwilę.,Já está pronto. Isso não vai demorar.,,E gata. Va dura doar un moment.,Уже готово. Это не займёт много времени..., -Soon.,TXT_RNO1_SCRIPT10_D19708_SOON,,,,Brzy.,Bald.,,Baldaŭ.,Pronto.,,Pian.,Bientôt.,Hamarosan.,,間もなくだ。,곧 완성되요.,Binnenkort.,Niedługo.,Logo logo.,,Curând.,Скоро., -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 dodatečné komponenty, které se o ni postarají a zvýší jeho výkon. Můžu pro tebe něco udělat?","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 que he encontrado un defecto en el hardware de tu implante. Feris me está ayudando a diseñar un reequipamiento que se ocupará de él y aumentará la velocidad de tu hardware un poco. ¿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?",,"インプラントハードウェアに不具合が見つかった +Heal me.,TXT_RPLY0_SCRIPT10_D19708_HEALM,,,,Potřebuju ošetřit.,Mach mich gesund.,,,Cúrame.,,Hoida minua.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료해주세요.,Genees mij.,Ulecz mnie.,Me cure.,,Bandajează-mă.,Подлечи меня., +You should learn to be a little more careful.,TXT_RYES0_SCRIPT10_D19708_YOUSH,,,,Měl bys být trochu opatrnější.,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.,Powinieneś być bardziej ostrożny.,Você precisa aprender a tomar mais cuidado.,,Ar trebui să fii mai grijuliu.,В следующий раз тебе стоит быть поосторожнее., +When will that be ready?,TXT_RPLY1_SCRIPT10_D19708_WHENW,,,,Kdy bude hotov?,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?,Kiedy to będzie gotowe?,Quando isso vai estar pronto?,,Când va fi gata?,Когда он будет готов?, +It's ready now. This won't take but a moment.,TXT_RYES1_SCRIPT10_D19708_ITSRE,,,,Už je hotový. Nepotrvá to ani chvilku.,"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.,Już jest gotowe. To zajęło tylko chwilę.,Já está pronto. Isso não vai demorar.,,E gata. Va dura doar un moment.,Уже готово. Это не займёт много времени..., +Soon.,TXT_RNO1_SCRIPT10_D19708_SOON,,,,Brzy.,Bald.,,Baldaŭ.,Pronto.,,Pian.,Bientôt.,Hamarosan.,Presto.,間もなくだ。,곧 완성되요.,Binnenkort.,Niedługo.,Logo logo.,,Curând.,Скоро., +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?","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 que he encontrado un defecto en el hardware de tu implante. Feris me está ayudando a diseñar un reequipamiento que se ocupará de él y aumentará la velocidad de tu hardware un poco. ¿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?,"Chyba znalazłem błąd w @@ -9236,12 +9232,12 @@ 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?,"Кажется, я обнаружил неполадку в устройстве твоего импланта. Ферис помогает мне в разработке модификации, которая исправит её и немного ускорит работу устройства. Чем я могу тебе помочь?", -Patch me up.,TXT_RPLY0_SCRIPT10_D21224_PATCH,,,,Potřebuju ošetřit.,Flick mich zusammen.,,,Cúrame.,,Kasaa minut takaisin kokoon.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Verbind me met elkaar.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,"Вот, прямо как новенький.", -"There, as good as new I guess.",TXT_RYES0_SCRIPT10_D21224_THERE,,,,"Tak, a jsi jako nový.","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.",,ほら、新鮮な気分だろう。,"자, 갓 태어난 것처럼 멀쩡할 겁니다!","Daar, zo goed als nieuw denk ik.",Proszę. Jak nowy. Chyba.,"Pronto. Novinho em folha, eu acho.",,"Gata, ca și nou bănuiesc.",Ты в полном порядке., -Retrofit?,TXT_RPLY1_SCRIPT10_D21224_RETRO,,,,Dovybavení?,Nachrüstsatz?,,,¿Reequipamiento?,,Jälkiasennuskappale?,Mise à jour de l'implant?,Áttervezni?,,後付け?,향상 칩 최근 버전?,Retrofit?,Ulepszenie?,Aprimoramento?,,Îmbunătățiri?,Модификация?, -"Ah, now we're cooking.",TXT_RYES1_SCRIPT10_D21224_AHNOW,,,,"Ahá, a už to jede.","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, nu zijn we aan het koken.","Ah, no i to rozumiem.","Ah, agora sim.",,"Ah, acum discutăm.",Да. Мы славно поработали над ней., -I'll have it as soon as Feris finishes it.,TXT_RNO1_SCRIPT10_D21224_ILLHA,,,,"Budu ho mít hned, co ho Feris dokončí.","Ich gebe es dir, sobald Feris fertig ist.",,,Lo tendré listo en cuanto Feris lo 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.",,完了次第フェリスから私が送ろう。,페리스가 작업을 마치는 순간 보여드리겠습니다.,Ik heb het zodra Feris het klaar heeft.,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.,"Я получу её, как только Ферис закончит.", -"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í?","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?",,"調子はどうだ?この新技術は素晴らしいものだ。 +Patch me up.,TXT_RPLY0_SCRIPT10_D21224_PATCH,,,,Potřebuju ošetřit.,Flick mich zusammen.,,,Cúrame.,,Kasaa minut takaisin kokoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Verbind me met elkaar.,Opatrz mnie.,Trate meus ferimentos.,,Bandajează-mă.,"Вот, прямо как новенький.", +"There, as good as new I guess.",TXT_RYES0_SCRIPT10_D21224_THERE,,,,"Tak, a jsi jako nový.","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.",Proszę. Jak nowy. Chyba.,"Pronto. Novinho em folha, eu acho.",,"Gata, ca și nou bănuiesc.",Ты в полном порядке., +Retrofit?,TXT_RPLY1_SCRIPT10_D21224_RETRO,,,,Doplněk?,Nachrüstsatz?,,,¿Reequipamiento?,,Jälkiasennuskappale?,Mise à jour de l'implant?,Áttervezni?,Ammodernamento?,後付け?,향상 칩 최근 버전?,Retrofit?,Ulepszenie?,Aprimoramento?,,Îmbunătățiri?,Модификация?, +"Ah, now we're cooking.",TXT_RYES1_SCRIPT10_D21224_AHNOW,,,,"Ahá, a už to jede.","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.","Ah, no i to rozumiem.","Ah, agora sim.",,"Ah, acum discutăm.",Да. Мы славно поработали над ней., +I'll have it as soon as Feris finishes it.,TXT_RNO1_SCRIPT10_D21224_ILLHA,,,,"Budu ho mít hned, co ho Feris dokončí.","Ich gebe es dir, sobald Feris fertig ist.",,,Lo tendré listo en cuanto Feris lo 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.,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.,"Я получу её, как только Ферис закончит.", +"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í?","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?","調子はどうだ?この新技術は素晴らしいものだ。 そちらのインプラントにも役立つ様な アイディアも幾つか思いついてあるぞ。 すぐ準備しよう。それとも治療か何か必要かな?","별일 없으시죠? 세상에나, 오더의 과학력은 세계 제일이군요! 이식한 칩이랑 추가 설치가 가능한데, 성능을 향상해줄 거에요. 현재 부품을 더 설계하고 있습니다. 만약 준비가 되면 불러줄게요. 아무튼, 치료가 필요하신가요?","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?","Jak się masz? Człowieku... Te nowe @@ -9251,12 +9247,12 @@ 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?","Как дела? О, среди этих новых технологий есть просто изумительные! Их можно применить при усовершенствовании твоего импланта. Я сейчас воплощаю в жизнь парочку идей, и скоро всё будет готово. Чем я могу тебе помочь? Перевязкой?", -"Yes, heal me.",TXT_RPLY0_SCRIPT10_D22740_YESHE,,,,"Ano, ošetři mě.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.",,ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, перевяжи меня.", -"All right, here you go.",TXT_RYES0_SCRIPT10_D22740_ALLRI,,,,"Dobře, to by bylo.",Alles klar soweit.,,,"Muy bien, ya está.",,"Hyvä on, tästä se lähtee.","Très bien, bous pouvez y aller.","Rendben, parancsolj.",,了解、始めましょう。,더욱 더 건강하게 치료했습니다.,"Oké, alsjeblieft.",Proszę bardzo.,"Ok, pronto.",,Gata.,Хорошо. Уже готово., -How about that new tech?,TXT_RPLY1_SCRIPT10_D22740_HOWAB,,,,Co ta nová technologie?,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?,,その新しい技術はどうだ?,세계 제일의 부품은 어떻습니까?,Hoe zit het met die nieuwe technologie?,Co z tymi nowymi technologiami?,Me fale sobre essa nova tecnologia.,,Ce zici de tehnologia aceea nouă?,Как там с новыми технологиями?, -Let me know how this works.,TXT_RYES1_SCRIPT10_D22740_LETME,,,,"Dej mi vědět, jak to funguje.","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.",,これでどんな調子か教えてくれ。,잘 작동되면 알려주시길!,Laat me weten hoe dit werkt.,Daj znać czy działa.,Me conte como funciona.,,Să-mi spui cum funcționează asta.,"Дай мне знать, если будут неполадки.", -I'm not done designing it yet.,TXT_RNO1_SCRIPT10_D22740_IMNOT,,,,Ještě s ní nejsem hotový.,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.,,まだ完成していない。,설계가 아직 끝나지 않았어요.,Ik ben nog niet klaar met het ontwerpen ervan.,Skończyłem już projektować.,Ainda não terminei de desenvolvê-la.,,Încă nu am terminat să o construiesc.,Я ещё не закончил с ними., -"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 tkáně, je to úplně nová technologie, snad to zabere. Potřebuješ ošetřit?","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?",,"戻ったか、まだ疲れてないか?なら幾らか +"Yes, heal me.",TXT_RPLY0_SCRIPT10_D22740_YESHE,,,,"Ano, ošetři mě.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, перевяжи меня.", +"All right, here you go.",TXT_RYES0_SCRIPT10_D22740_ALLRI,,,,"Dobře, to by bylo.",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.",Proszę bardzo.,"Ok, pronto.",,Gata.,Хорошо. Уже готово., +How about that new tech?,TXT_RPLY1_SCRIPT10_D22740_HOWAB,,,,Co ta nová technologie?,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?,Co z tymi nowymi technologiami?,Me fale sobre essa nova tecnologia.,,Ce zici de tehnologia aceea nouă?,Как там с новыми технологиями?, +Let me know how this works.,TXT_RYES1_SCRIPT10_D22740_LETME,,,,"Dej mi vědět, jak to funguje.","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.,Daj znać czy działa.,Me conte como funciona.,,Să-mi spui cum funcționează asta.,"Дай мне знать, если будут неполадки.", +I'm not done designing it yet.,TXT_RNO1_SCRIPT10_D22740_IMNOT,,,,Ještě s ní nejsem hotový.,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.,Skończyłem już projektować.,Ainda não terminei de desenvolvê-la.,,Încă nu am terminat să o construiesc.,Я ещё не закончил с ними., +"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?","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?","戻ったか、まだ疲れてないか?なら幾らか 良いニュースが届いた、フェリスが君の インプラント機能を増幅させる方法を見つけた。 彼がそのスペックを見せてくれたが、 @@ -9271,12 +9267,12 @@ 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ță?","Ты снова ранен? Тебе самому ещё не надоело? У меня для тебя хорошие новости: Ферис нашёл способ увеличить эффективность твоего импланта. Он дал мне схемы, и я пытаюсь подогнать имплант под твою физиологию. Я сейчас выращиваю кое-какие ткани. Раньше я никогда этого не делал, но надеюсь, что это сработает. Итак, тебе нужно лечение?", -"Yes, heal me.",TXT_RPLY0_SCRIPT10_D24256_YESHE,,,,"Ano, ošetři mě.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.",,ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, подлатай меня.", -"Done, now take care of yourself.",TXT_RYES0_SCRIPT10_D24256_DONEN,,,,"Hotovo, dávej na sebe pozor.","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.",,完了した、御気を付けて。,치료 끝. 이제 가까이서 불장난하지 마시길!,"Klaar, zorg nu voor jezelf.",Gotowe. Uważaj na siebie.,Pronto. Agora vê se toma cuidado.,,"Gata, acum ai grijă de tine.",Сделано. Береги себя., -When will you be done?,TXT_RPLY1_SCRIPT10_D24256_WHENW,,,,Kdy s tím budeš hotov?,Wann wird es fertig sein?,,,¿Cuándo habrás terminado?,,Milloin kudos on valmis?,Quand aurez-vous fini?,Mikor leszel kész?,,いつ増幅できる?,칩 조정이 언제 끝나는지요?,Wanneer ben je klaar?,Kiedy skończysz?,Quando você vai terminar?,,Când vei fi gata?,Когда он будет готов?, -"Now. Hey great, it worked!",TXT_RYES1_SCRIPT10_D24256_NOWHE,,,,"Teď. No ne, funguje to skvěle!","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!",,すぐにでも。素晴らしい、上手くいった!,"세상에나, 정말로 작동하는군요!","Nu. Hé, geweldig, het heeft gewerkt!",Już. Hej! Udało się! Działa!,"Agora. Opa, beleza! Funcionou!",,"Acum. Hei grozav, a mers!","Секунду. Отлично, он работает!", -I'm waiting on the tissue to finish its growth cycle.,TXT_RNO1_SCRIPT10_D24256_IMWAI,,,,"Čekám, než dorostou ty tkáně.","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.",,生体組織が成長しきるまで待つんだ。,조직이 다 자라날 때까지 기다리는 중입니다.,Ik wacht op het weefsel om de groeicyclus af te ronden.,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.,Подожди. Мне нужно проследить за циклом роста клеток ткани., -"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? Že ne? Je to protože u tebe fungují tak dobře. Můžu pro tebe něco udělat?","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?",,"さて、私は古い技術をバックアップして、 +"Yes, heal me.",TXT_RPLY0_SCRIPT10_D24256_YESHE,,,,"Ano, ošetři mě.","Ja, mach mich gesund.",,,"Sí, cúrame.",,"Kyllä, paranna minut.","Oui, soignez-moi.","Igen, gyógyíts fel.","Sì, curami.",ああ、治してくれ。,네. 치료해주세요.,"Ja, genees me.","Tak, ulecz mnie.","Sim, me cure.",,"Da, bandajează-mă.","Да, подлатай меня.", +"Done, now take care of yourself.",TXT_RYES0_SCRIPT10_D24256_DONEN,,,,"Hotovo, dávej na sebe pozor.","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.",Gotowe. Uważaj na siebie.,Pronto. Agora vê se toma cuidado.,,"Gata, acum ai grijă de tine.",Сделано. Береги себя., +When will you be done?,TXT_RPLY1_SCRIPT10_D24256_WHENW,,,,Kdy s tím budeš hotov?,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?,Kiedy skończysz?,Quando você vai terminar?,,Când vei fi gata?,Когда он будет готов?, +"Now. Hey great, it worked!",TXT_RYES1_SCRIPT10_D24256_NOWHE,,,,"Teď. No ne, funguje to skvěle!","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!",Już. Hej! Udało się! Działa!,"Agora. Opa, beleza! Funcionou!",,"Acum. Hei grozav, a mers!","Секунду. Отлично, он работает!", +I'm waiting on the tissue to finish its growth cycle.,TXT_RNO1_SCRIPT10_D24256_IMWAI,,,,"Čekám, než dorostou ty tkáně.","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.,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.,Подожди. Мне нужно проследить за циклом роста клеток ткани., +"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?","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?","さて、私は古い技術をバックアップして、 インプラントに更なる取り組みを試している。 マシルがそれを全員に着けるのを承認したのは 聞いたか?まだ?君が上手くやってくれたからな。 @@ -9288,12 +9284,12 @@ 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?","Я снова вернулся к старым занятиям и по-прежнему работаю над твоим имплантом. Ты знаешь, что Мэйсил теперь всем разрешил использовать импланты? Нет? Это потому, что ты так хорошо показал себя. Могу я чем-нибудь тебе помочь?", -Help me out here.,TXT_RPLY0_SCRIPT10_D25772_HELPM,,,,Pomoz mi.,Hilf mir mal.,,,Ayúdame.,,Autatko vähän.,Aidez moi.,Segíts nekem egy kicsit.,,ここで治してくれ。,나 좀 치료해줘요.,Help me hier.,Pomóż mi.,Preciso de uma ajuda aqui.,,Dă-mi o mână de ajutor.,Помоги мне вот с этим., -That's all I can do.,TXT_RYES0_SCRIPT10_D25772_THATS,,,,"To je vše, co mohu udělat.","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.,,私が出来る事はここまでだ。,좀 치료해줬습니다. 이제 어떠신가요?,Dat is alles wat ik kan doen.,To wszystko co mogę zrobić.,Isso é tudo o que posso fazer.,,Asta e tot ceea ce pot face.,"Это всё, что я могу сделать.", -New implant?,TXT_RPLY1_SCRIPT10_D25772_NEWIM,,,,Nový implantát?,Neues Implantat?,,,¿Nuevo implante?,,Uusi istute?,Un nouvel implant?,Új implantátum?,,新しいインプラントは?,새로운 이식 칩?,Een nieuw implantaat?,Nowy implant?,Implante novo?,,Implant nou?,Новый имплант?, -"Yep, my best one yet.",TXT_RYES1_SCRIPT10_D25772_YEPMY,,,,"Jo, můj zatím nejlepší.","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.",,よし、これは傑作だ。,있죠. 제 생각엔 아주 좋은 품질인 것 같아요.,"Ja, mijn beste tot nu toe.",Tak. Najlepszy jaki dotychczas zrobiłem.,Isso mesmo. O melhor que já fiz até agora.,,"Da, cel mai bun, momentan.",Да. Моё лучшее творение., -"Sorry, but you just have to wait.",TXT_RNO1_SCRIPT10_D25772_SORRY,,,,"Promiň, ještě budeš muset počkat.","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.",,すまない、だがもうすぐ出来そうだ。,시간을 좀 더 주신다면...,"Sorry, maar je moet gewoon wachten.","Wybacz, ale musisz poczekać.","Desculpe, mas você vai ter que esperar.",,"Scuze, dar trebuie să mai aștepți.","Прости, но тебе придётся подождать.", -"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 to trochu smutné, vidět můj výtvor dosáhnout vrcholu. No, alespoň budu zaneprázdněný zbytkem posádky.","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.",,"いよいよだ、フェリスが我々の保管していた +Help me out here.,TXT_RPLY0_SCRIPT10_D25772_HELPM,,,,Pomoz mi.,Hilf mir mal.,,,Ayúdame.,,Autatko vähän.,Aidez moi.,Segíts nekem egy kicsit.,Aiutami.,ここで治してくれ。,나 좀 치료해줘요.,Help me hier.,Pomóż mi.,Preciso de uma ajuda aqui.,,Dă-mi o mână de ajutor.,Помоги мне вот с этим., +That's all I can do.,TXT_RYES0_SCRIPT10_D25772_THATS,,,,"To je vše, co mohu udělat.","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.,To wszystko co mogę zrobić.,Isso é tudo o que posso fazer.,,Asta e tot ceea ce pot face.,"Это всё, что я могу сделать.", +New implant?,TXT_RPLY1_SCRIPT10_D25772_NEWIM,,,,Nový implantát?,Neues Implantat?,,,¿Nuevo implante?,,Uusi istute?,Un nouvel implant?,Új implantátum?,Nuovo impianto?,新しいインプラントは?,새로운 이식 칩?,Een nieuw implantaat?,Nowy implant?,Implante novo?,,Implant nou?,Новый имплант?, +"Yep, my best one yet.",TXT_RYES1_SCRIPT10_D25772_YEPMY,,,,"Jo, můj zatím nejlepší.","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.",Tak. Najlepszy jaki dotychczas zrobiłem.,Isso mesmo. O melhor que já fiz até agora.,,"Da, cel mai bun, momentan.",Да. Моё лучшее творение., +"Sorry, but you just have to wait.",TXT_RNO1_SCRIPT10_D25772_SORRY,,,,"Promiň, ještě budeš muset počkat.","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.","Wybacz, ale musisz poczekać.","Desculpe, mas você vai ter que esperar.",,"Scuze, dar trebuie să mai aștepți.","Прости, но тебе придётся подождать.", +"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.","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.","いよいよだ、フェリスが我々の保管していた 全てのデータから全力を尽くして編み出した、 これが最高で最後のインプラント アップグレードだ。が、私にこれ以上の創造に @@ -9305,9 +9301,9 @@ 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.","Вот и всё. Из тех данных, которыми мы располагаем, Ферису удалось вытянуть всё, что только можно. Это лучшая и последняя модификация импланта. Немного грустно видеть, что твоё творение достигло своего предела. Ну, по крайней мере, я всё ещё нужен остальной части команды.", -Could you heal me?,TXT_RPLY0_SCRIPT10_D27288_COULD,,,,Mohl bys mě ošetřit?,Kannst du mich gesund machen?,,,¿Podrías curarme?,,Voisitko hoitaa minua?,Vous pouvez me soigner?,Fel tudnál gyógyítani?,,治してくれるか?,절 치료해줄 수 있나요?,Kunt je me genezen?,Możesz mnie uleczyć?,Poderia me curar?,,Mă poți bandaja?,Вылечишь меня?, -"There, you're all set now.",TXT_RYES0_SCRIPT10_D27288_THERE,,,,"Tak, a jsi hotov.","So, das wär's dann.",,,"Ya está, listo.",,"Siinä, kaikki kunnossa.","Voilà, vous pouvez y aller.","Parancsolj, harcra kész vagy.",,これで、準備完了だ。,"자, 이제 안전할 겁니다.",Daar ben je nu helemaal klaar.,Proszę. Wszystko gotowe.,Feito. Tudo certo agora.,,"Gata, ești pregătit.",Конечно. Теперь ты в норме., -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,,,,"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í.","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.",,"正に英雄、流石です! +Could you heal me?,TXT_RPLY0_SCRIPT10_D27288_COULD,,,,Mohl bys mě ošetřit?,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?,Możesz mnie uleczyć?,Poderia me curar?,,Mă poți bandaja?,Вылечишь меня?, +"There, you're all set now.",TXT_RYES0_SCRIPT10_D27288_THERE,,,,"Tak, a jsi hotov.","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.,Proszę. Wszystko gotowe.,Feito. Tudo certo agora.,,"Gata, ești pregătit.",Конечно. Теперь ты в норме., +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,,,,"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í.","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.","正に英雄、流石です! 何か必要ですか?城の全兵器が揃っております。 弾薬が必要ならジャスティンに頼めば大丈夫ですよ",그 프론트의 인기 많은 영웅 아닌가요? 잘하셨습니다! 무엇을 도와드릴까요? 성안에서 특이하고 질 좋은 보급물자들을 긁어모아 왔어요. 만약 탄약 보급을 위해서 오신 거라면 저스틴에게 물어보세요.,"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.","Oto bohater. Dobra robota! Co mogę dla ciebie zrobić? Mamy teraz większy @@ -9315,36 +9311,36 @@ 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.","А вот и наш герой. Отлично сработано! Чем я могу тебе помочь? Теперь в нашем распоряжении всё оружие из замка, так что выбор стал побогаче. Если тебе нужны боеприпасы, обратись к Джастину: он тебе поможет.", -I'm out of bullets.,TXT_RPLY0_SCRIPT10_D28804_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Luodit on loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D28804_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,,この弾をどうぞ、無駄遣いしないように。,그렇게 계속 쏘아대면 탄약이 낭비됩니다. 여기 탄약이에요.,Hier is wat munitie voor je. Verspil het niet.,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.,Можешь взять немного. Не трать их понапрасну., -Teach me.,TXT_RPLY1_SCRIPT10_D28804_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -"Now, a few tips on the big guns.",TXT_RYES1_SCRIPT10_D28804_NOWAF,,,,"Tak jo, pár tipů, jak na velké zbraně.",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.",,では、大きい銃の扱い方を教えます。,중화기 다루는 훈련을 시작하겠습니다!,"Nu, een paar tips over de grote geweren.",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.",А теперь пара советов насчёт больших пушек., -You're not ready yet.,TXT_RNO1_SCRIPT10_D28804_YOURE,,,,Ještě nejsi připraven.,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.,,貴方の準備がまだ整ってないように思えます。,준비가 아직 안됐습니다.,Je bent nog niet klaar.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., -"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,,,,"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?","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?",,"奮闘してますか?気にしないで、 +I'm out of bullets.,TXT_RPLY0_SCRIPT10_D28804_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,Skończyły mi się naboje.,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D28804_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,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.,Можешь взять немного. Не трать их понапрасну., +Teach me.,TXT_RPLY1_SCRIPT10_D28804_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +"Now, a few tips on the big guns.",TXT_RYES1_SCRIPT10_D28804_NOWAF,,,,"Tak jo, pár tipů, jak na velké zbraně.",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.",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.",А теперь пара советов насчёт больших пушек., +You're not ready yet.,TXT_RNO1_SCRIPT10_D28804_YOURE,,,,Ještě nejsi připraven.,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.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., +"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,,,,"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?","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?","奮闘してますか?気にしないで、 ここにいるなら上手くやってるのは分かります。 どういうご用件ですか?",전쟁 상황은 어떻게 되어가나요? 상관은 없지만. 우리들이 아직 살아있는 한 물어볼 필요도 없죠. 무엇을 원하시나요?,"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?","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?","Как дела на фронте? Впрочем, неважно. Наверняка всё хорошо, раз мы ещё живы. Что я могу для тебя сделать?", -I ran out of bullets.,TXT_RPLY0_SCRIPT10_D30320_IRANO,,,,Došly mi náboje.,Mir ist die Munition ausgegangen.,,,Me he quedado sin balas.,,Minulta loppuivat luodit.,Je suis à court de munitions.,Kifogytam a lőszerből.,,弾を使い果たした。,탄약이 바닥났어요.,De kogels zijn op.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,У меня кончились патроны., -That should help.,TXT_RYES0_SCRIPT10_D30320_THATS,,,,Tohle by mělo pomoci.,Das hier sollte helfen.,,,Esto debería ayudar.,,Tämän pitäisi auttaa.,Cela devrait aider.,Ez majd segít.,,これが助けになるでしょう。,좀 도움이 될 겁니다.,Dat zou moeten helpen.,To powinno pomóc.,Isto deve ajudar.,,Asta ar trebui să ajute.,"Вот, пожалуйста.", -You've got enough ammo.,TXT_RNO0_SCRIPT10_D30320_YOUVE,,,,Máš jich dost.,Du hast genug Munition.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,弾は十分に見えます。,탄약을 충분히 소지한 것 같은데.,Je hebt genoeg munitie.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă.,Вполне достаточно., -Teach me.,TXT_RPLY1_SCRIPT10_D30320_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -"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.,"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.",,では、幾つかのコツを教えましょう。,저항군의 참된 기술들을 좀 가르쳐드리죠!,Hier zal ik je een paar trucjes van het vak laten zien.,Proszę. Oto kilka wskazówek o handlu.,"Certo, vou te mostrar alguns truques do ofício.",,"Iată, am să te învăț niște trucuri.","Давай, я покажу тебе пару секретных приёмчиков.", -You're not ready yet.,TXT_RNO1_SCRIPT10_D30320_YOURE,,,,Ještě nejsi připraven.,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.,,貴方の準備がまだ整ってないように思えます。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., -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,,,,"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.","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.",,"指導の受講か、弾薬の受け取りですか? +I ran out of bullets.,TXT_RPLY0_SCRIPT10_D30320_IRANO,,,,Došly mi náboje.,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.,Skończyły mi się naboje.,Fiquei sem munição.,,Am rămas fără gloanțe.,У меня кончились патроны., +That should help.,TXT_RYES0_SCRIPT10_D30320_THATS,,,,Tohle by mělo pomoci.,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.,To powinno pomóc.,Isto deve ajudar.,,Asta ar trebui să ajute.,"Вот, пожалуйста.", +You've got enough ammo.,TXT_RNO0_SCRIPT10_D30320_YOUVE,,,,Máš jich dost.,Du hast genug Munition.,,,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.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă.,Вполне достаточно., +Teach me.,TXT_RPLY1_SCRIPT10_D30320_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +"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.,"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.,Proszę. Oto kilka wskazówek o handlu.,"Certo, vou te mostrar alguns truques do ofício.",,"Iată, am să te învăț niște trucuri.","Давай, я покажу тебе пару секретных приёмчиков.", +You're not ready yet.,TXT_RNO1_SCRIPT10_D30320_YOURE,,,,Ještě nejsi připraven.,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.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., +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,,,,"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.","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.","指導の受講か、弾薬の受け取りですか? まだ全て終わったわけではありません。 私の袖口に若干技術を忍ばせております。","무엇을 원하시나요? 훈련? 아니면 탄약 보급? 그리고 훈련은 아직 끝난 게 아니니까 끝날 걱정도, 다칠 고민도 하지 마시길 바랍니다.",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.,"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ă.","Итак, ты пришёл за напутствием? Или тебе нужны боеприпасы? Не думай, что твоё обучение окончено. У меня ещё есть кое-какие козыри в рукаве!", -It's ammo for now.,TXT_RPLY0_SCRIPT10_D31836_ITSAM,,,,Teď jenom kvůli nábojům.,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.,,今のところ弾薬だ。,탄약이 필요하겠네요.,Het is voorlopig munitie.,Tym razem chodzi o amunicję.,No momento preciso de munição.,,Muniție pentru moment.,Мне нужны боеприпасы., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D31836_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,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.,,この弾をどうぞ、無駄遣いしないように。,"좋은 병사에겐, 좋은 품질의 탄약을.",Hier is wat munitie voor je. Verspil het niet.,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.,Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT10_D31836_YOUVE,,,,Máš jich dost.,Du hast genug Munition.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,弾は十分に見えます。,아직 당신에게 탄약이 남아있는 것 같습니다만...,Je hebt genoeg munitie.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов., -Teach me.,TXT_RPLY1_SCRIPT10_D31836_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., -Time for the advanced lessons.,TXT_RYES1_SCRIPT10_D31836_TIMEF,,,,Čas na pokročilé lekce.,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.,,上級レッスンの時間です。,심화학습을 할 시간이군요!,Tijd voor de gevorderde lessen voor gevorderden.,Czas na lekcje dla zaawansowanych.,Hora das aulas avançadas.,,Timpul pentru lecțiile avansate.,Пришло время для углублённого изучения оружия!, -You're not ready yet.,TXT_RNO1_SCRIPT10_D31836_YOURE,,,,Ještě nejsi připraven.,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.,,貴方の準備がまだ整ってないように思えます。,넌 아직 준비가 안됐어.,Je bent nog niet klaar.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., -"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,,,"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.","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.",,"さて、調子はどうですか?休憩しませんか? +It's ammo for now.,TXT_RPLY0_SCRIPT10_D31836_ITSAM,,,,Teď tu jsem jen pro náboje.,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.,Tym razem chodzi o amunicję.,No momento preciso de munição.,,Muniție pentru moment.,Мне нужны боеприпасы., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT10_D31836_HERES,,,,"Tady nějaké máš, neplýtvej s nimi.",Hier hast du welche. Verschwende sie nicht.,,,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.,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.,Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT10_D31836_YOUVE,,,,Máš jich dost.,Du hast genug Munition.,,,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.,Masz wystarczająco dużo amunicji.,Você já tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов., +Teach me.,TXT_RPLY1_SCRIPT10_D31836_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,Naucz mnie.,Me ensine.,,Învață-mă.,Обучи меня., +Time for the advanced lessons.,TXT_RYES1_SCRIPT10_D31836_TIMEF,,,,Čas na pokročilé lekce.,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.,Czas na lekcje dla zaawansowanych.,Hora das aulas avançadas.,,Timpul pentru lecțiile avansate.,Пришло время для углублённого изучения оружия!, +You're not ready yet.,TXT_RNO1_SCRIPT10_D31836_YOURE,,,,Ještě nejsi připraven.,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.,Nie jesteś jeszcze na to gotowy.,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., +"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,,,"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.","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.","さて、調子はどうですか?休憩しませんか? 貴方がまだ息をしているのが喜ばしい事です。 お気に入りの生徒が死体袋から天を仰ぐ様に なるのは嫌なのです。",이번엔 또 뭔가요? 휴식을 제대로 취하지 않는 성격인가요? 그래도 몸은 멀쩡히 움직이는 것 같군요! 그토록 가르침을 받던 우수한 제자가 사체로 돌아오면 정말 슬플 테니.,"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.","Dobra. Co tym razem? Czy ty w ogóle @@ -9352,228 +9348,228 @@ 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.,"Итак, ты справился и даже ни разу не остановился передохнуть? Рад видеть, что ты всё ещё дышишь. Мне бы не хотелось, чтобы мой лучший ученик вернулся в мешке для трупов.", -I need some more bullets.,TXT_RPLY0_SCRIPT10_D33352_INEED,,,,Potřebuju nějaké další náboje.,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.,,もっと弾が必要だ。,총알이 좀 더 필요해.,Ik heb meer kogels nodig.,Potrzebuję trochę naboi.,Preciso de mais munição.,,Am nevoie de niște gloanțe.,Мне нужны патроны., -"There, don't waste it.",TXT_RYES0_SCRIPT10_D33352_THERE,,,,"Tady máš, neplýtvej s nimi.","Hier, verschwende sie nicht.",,,"Toma, no las desperdicies.",,"Kas tässä, älä tuhlaa niitä.","Voilà, ne les gaspillez pas.","Parancsolj, ne pazarold el.",,大切にして下さいね。,여기 있습니다. 낭비하지 말고 아껴 쓰세요.,"Daar, verspil het niet.",Proszę. Nie zmarnuj ich.,Pegue. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту., -You have enough.,TXT_RNO0_SCRIPT10_D33352_YOUHA,,,,Máš jich dost.,Du hast genug.,,,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Már van elég.,,十分そうです。,지금도 충분한 것 같은데요.,Je hebt genoeg.,Masz już ich wystarczająco dużo.,Você já tem o suficiente.,,Ai destulă.,Тебе хватает., -What can you teach me?,TXT_RPLY1_SCRIPT10_D33352_WHATC,,,,Co mě můžeš naučit?,Was kannst du mir beibringen?,,,¿Qué puedes enseñarme?,,Mitä voit opettaa minulle?,Que pouvez-vous m'apprendre.,Mit tudsz tanítani?,,何か教えてくれないか?,나에게 뭘 가르쳐 줄 수 있죠?,Wat kun je me leren?,Czego możesz mnie nauczyć?,O que você tem pra me ensinar?,,Ce mă poți învăța?,Чему ты можешь меня научить?, -"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.","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.",,ぶっきらぼうにならないで、まだ成長の余地はあります。,너무 자만하지 마세요. 아직 더 배울 게 많으니까.,"Wordt niet snipperig, je hebt nog wat ruimte om te groeien.",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.",Не задирай нос. Тебе ещё есть куда расти., -Nothing until you're ready.,TXT_RNO1_SCRIPT10_D33352_NOTHI,,,,"Nic, dokud nebudeš připraven.","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.",,準備が整うまで何も出来ません。,준비가 안 된 것 같으니 나중에 배웁시다.,Niets totdat je er klaar voor bent.,Na razie nic póki nie jesteś gotowy.,Nada até que você esteja preparado.,,"Nimic, până nu ești pregătit.","Ничему, пока ты не готов.", -"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,,,,"No ne, kdopak to je? Jak se vede? Vím, že je to těžké, ale všichni si tě vážíme, věř mi.","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.",,"誰が戻って来たかについて、貴方の考えとは? +I need some more bullets.,TXT_RPLY0_SCRIPT10_D33352_INEED,,,,Potřebuju nějaké další náboje.,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.,Potrzebuję trochę naboi.,Preciso de mais munição.,,Am nevoie de niște gloanțe.,Мне нужны патроны., +"There, don't waste it.",TXT_RYES0_SCRIPT10_D33352_THERE,,,,"Tady máš, neplýtvej s nimi.","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.",Proszę. Nie zmarnuj ich.,Pegue. Não desperdice.,,"Iată, n-o risipi.",Вот. Не трать их попусту., +You have enough.,TXT_RNO0_SCRIPT10_D33352_YOUHA,,,,Máš jich dost.,Du hast genug.,,,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Már van elég.,Ne hai a sufficienza.,十分そうです。,지금도 충분한 것 같은데요.,Je hebt genoeg.,Masz już ich wystarczająco dużo.,Você já tem o suficiente.,,Ai destulă.,Тебе хватает., +What can you teach me?,TXT_RPLY1_SCRIPT10_D33352_WHATC,,,,Co mě můžeš naučit?,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?,Czego możesz mnie nauczyć?,O que você tem pra me ensinar?,,Ce mă poți învăța?,Чему ты можешь меня научить?, +"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.,"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.",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.",Не задирай нос. Тебе ещё есть куда расти., +Nothing until you're ready.,TXT_RNO1_SCRIPT10_D33352_NOTHI,,,,"Nic, dokud nebudeš připraven.","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.,Na razie nic póki nie jesteś gotowy.,Nada até que você esteja preparado.,,"Nimic, până nu ești pregătit.","Ничему, пока ты не готов.", +"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,,,,"No ne, kdopak to je? Jak se vede? Vím, že je to těžké, ale všichni si tě vážíme, věř mi.","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.","誰が戻って来たかについて、貴方の考えとは? 困難な事だとわかっています。しかし私達全員は 貴方の努力には感謝しています。","다시 돌아오다니. 어쩐 일이십니까? 견디기 힘든 고역이었겠지만, 지금 당신은 우리들을 위해 잘 싸우고 계십니다. 믿어주세요!","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.",,"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ă.","Посмотрите-ка, кто вернулся. Что у тебя стряслось? Я знаю, твои задания сложны, но, поверь, мы все ценим твои усилия.", -I've run out of bullets.,TXT_RPLY0_SCRIPT10_D34868_IVERU,,,,Došly mi náboje.,Mir ist die Munition ausgegangen.,,,Me he quedado sin balas.,,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,,弾が無くなった。,탄약이 바닥났어요.,Ik heb geen kogels meer.,,Fiquei sem munição.,,Am rămas fără gloanțe.,Мне нужны патроны., -"What else is new, here you go.",TXT_RYES0_SCRIPT10_D34868_WHATE,,,,Něco jiného nového? Tady máš.,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.",,新しい試みですか、どうぞ。,여기 탄약. 그리고 더 필요한게?,"Wat is er nog meer nieuw, alsjeblieft.",,Que novidade. Aqui está.,,"Ce mai e nou, iată.","Знаю, знаю. Вот, держи!", -You have more than I can give you.,TXT_RNO0_SCRIPT10_D34868_YOUHA,,,,"Máš víc, než kolik ti můžu dát.","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.",,今渡せる以上に持ってますよ。,내가 줄 수 있는 탄약의 양보다 큰데?,Je hebt meer dan ik je kan geven.,,Você tem o suficiente.,,Ai mai multe decât ți-aș putea oferi.,"Да у тебя их больше, чем на нашем складе.", -Teach me what you can.,TXT_RPLY1_SCRIPT10_D34868_TEACH,,,,"Uč mě, co můžeš.",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.,,可能な限り教えてくれ。,가르칠 수 있는 걸 가르쳐주세요.,Leer me wat je kunt.,,O que você pode me ensinar?,,Învață-mă ce poți.,"Научи меня, чему можешь.", -"All right, here's some pointers.",TXT_RYES1_SCRIPT10_D34868_ALLRI,,,,"Dobře, tady je pár tipů.","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.",,わかりました、貴方に幾つかやり方を教ましょう。,알겠습니다. 여기 과녁을 보여주지.,"Oké, hier zijn wat aanwijzingen.",,"Tá legal, aqui vai algumas dicas.",,"În regulă, uite niște repere.",Ну хорошо. Вот пара советов., -Not right now.,TXT_RNO1_SCRIPT10_D34868_NOTRI,,,,Zrovna teď ne.,Nicht jetzt.,,Ne nun.,Ahora no.,,Ei juuri nyt.,Pas maintenant.,Most nem érek rá.,,今はまだです。,지금은 안 돼요.,Niet op dit moment.,,Agora não.,,Nu chiar acum.,Не сейчас., -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,,,,"Copak potřebuješ? Doufám, že oplácíš Řádu to, co nám za celé ty roky udělali.","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.",,"必要な物は何ですか?私達が何年も前から感じた +I've run out of bullets.,TXT_RPLY0_SCRIPT10_D34868_IVERU,,,,Došly mi náboje.,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.,,Fiquei sem munição.,,Am rămas fără gloanțe.,Мне нужны патроны., +"What else is new, here you go.",TXT_RYES0_SCRIPT10_D34868_WHATE,,,,Něco jiného nového? Tady máš.,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.",,Que novidade. Aqui está.,,"Ce mai e nou, iată.","Знаю, знаю. Вот, держи!", +You have more than I can give you.,TXT_RNO0_SCRIPT10_D34868_YOUHA,,,,"Máš víc, než kolik ti můžu dát.","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.,,Você tem o suficiente.,,Ai mai multe decât ți-aș putea oferi.,"Да у тебя их больше, чем на нашем складе.", +Teach me what you can.,TXT_RPLY1_SCRIPT10_D34868_TEACH,,,,"Uč mě, co můžeš.",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.,,O que você pode me ensinar?,,Învață-mă ce poți.,"Научи меня, чему можешь.", +"All right, here's some pointers.",TXT_RYES1_SCRIPT10_D34868_ALLRI,,,,"Dobře, tady je pár tipů.","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.",,"Tá legal, aqui vai algumas dicas.",,"În regulă, uite niște repere.",Ну хорошо. Вот пара советов., +Not right now.,TXT_RNO1_SCRIPT10_D34868_NOTRI,,,,Zrovna teď ne.,Nicht jetzt.,,Ne nun.,Ahora no.,,Ei juuri nyt.,Pas maintenant.,Most nem érek rá.,Non adesso.,今はまだです。,지금은 안 돼요.,Niet op dit moment.,,Agora não.,,Nu chiar acum.,Не сейчас., +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,,,,"Copak potřebuješ? Doufám, že oplácíš Řádu to, co nám celé ty roky dělali.","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.,"必要な物は何ですか?私達が何年も前から感じた 多くの苦痛の味をオーダーに与えることを 願っています。",필요한 게 있습니까? 수 년 동안 고통을 안겨 온 오더 놈들에게 복수를 해줬으면 하는 바입니다. 끝날 때까지!,Wat heb je nodig? Ik hoop dat je de Orde een voorproefje geeft van het soort pijn dat we al jaren voelen.,,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.,"Что тебе нужно? Надеюсь, ты даёшь Ордену почувствовать ту боль, что мы терпели годами.", -Some ammo.,TXT_RPLY0_SCRIPT10_D36384_SOMEA,,,,Nějakou munici.,Etwas Munition.,,,Algo de munición.,,Vähän ammuksia.,Des munitions.,Valamennyi lőszer.,,弾を幾つか。,탄약 좀...,Wat munitie.,,Um pouco de munição.,,Niște muniție.,Боеприпасы., -"There you go, don't waste it.",TXT_RYES0_SCRIPT10_D36384_THERE,,,,"Tady máš, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,"Toma, no las desperdicies.",,"Ole hyvä, älä tuhlaa niitä.",Voilà pour vous. Ne les gaspillez pas.,"Parancsolj, ne pazarold el.",,はいどうぞ、無駄にしないように。,전장을 자주 누비나 보군요. 여기 탄약!,"Daar ga je, verspil het niet.",,Aqui está. Não desperdice.,,"Iată, n-o risipi.",Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT10_D36384_YOUVE,,,,Máš jí dost.,Du hast genug Munition.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,弾は十分に見えます。,당신의 남은 탄약이 눈에 보이는군요. 줄 수 없습니다!,Je hebt genoeg munitie.,,Você tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов., -Teach me.,TXT_RPLY1_SCRIPT10_D36384_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., -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.","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.",,もう少しで私の教えられる事が全てわかるはずです。,제가 가르칠 만한 훈련을 배우면 좀 똑똑해질 겁니다.,Nog een paar lessen en je weet alles wat ik je kan leren.,,Mais algumas aulas e você já saberá tudo o que consigo ensinar.,,"Câteva lecții, și vei știi tot ce știu si eu.","Ещё немного, и ты будешь знать всё, что знаю я.", -You're not ready yet.,TXT_RNO1_SCRIPT10_D36384_YOURE,,,,Ještě nejsi připraven.,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.,,貴方の準備がまだ整ってないように思えます。,훈련받기엔 가깝지만서도... 먼 것 같습니다.,Je bent er nog niet klaar voor.,,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., -"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,,,,"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?","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í, tu y yo. Se han ido tantos como tú 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?",,"私達はまだ貴方の護衛をし続けられるとは +Some ammo.,TXT_RPLY0_SCRIPT10_D36384_SOMEA,,,,Nějakou munici.,Etwas Munition.,,,Algo de munición.,,Vähän ammuksia.,Des munitions.,Valamennyi lőszer.,Un poco di munizioni.,弾を幾つか。,탄약 좀...,Wat munitie.,,Um pouco de munição.,,Niște muniție.,Боеприпасы., +"There you go, don't waste it.",TXT_RYES0_SCRIPT10_D36384_THERE,,,,"Tady máš, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,"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.",,Aqui está. Não desperdice.,,"Iată, n-o risipi.",Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT10_D36384_YOUVE,,,,Máš jí dost.,Du hast genug Munition.,,,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.,,Você tem munição suficiente.,,Ai destulă muniție.,У тебя хватает патронов., +Teach me.,TXT_RPLY1_SCRIPT10_D36384_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., +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.","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.,,Mais algumas aulas e você já saberá tudo o que consigo ensinar.,,"Câteva lecții, și vei știi tot ce știu si eu.","Ещё немного, и ты будешь знать всё, что знаю я.", +You're not ready yet.,TXT_RNO1_SCRIPT10_D36384_YOURE,,,,Ještě nejsi připraven.,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.,,Você ainda não está preparado.,,Nu ești pregătit încă.,Ты ещё не готов., +"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,,,,"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?","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í, tu y yo. Se han ido tantos como tú 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?",,"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?","Не могу поверить, что мы всё ещё живы, ты и я. За всё это время уже стольких из нас не стало. Что я могу сделать для тебя, дружище?", -I'm out of bullets.,TXT_RPLY0_SCRIPT10_D37900_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,Me he quedado sin balas.,,Minulta on luodit loppu.,Je suis à court de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., -"Here, use them to keep you in good health.",TXT_RYES0_SCRIPT10_D37900_HEREU,,,,"Tady, používej je, abys zůstal ve zdraví.","Hier, benutze sie um gesund zu bleiben,",,,"Aquí tienes, úsalas para mantenerte en buena salud.",,"Tässä, pidä niillä itsesi terveenä.","Voilà, gardez vous en bonne santé.","Parancsolj, használd őket az egészséged érdekében.",,どうぞ、これで体の調子を保って下さい。,건강하고 집중됬을 때 소모하시길.,"Hier, gebruik ze om je in goede gezondheid te houden.",,Pode pegar. Use essa munição para se manter saudável.,,"Aici, folosește-le ca să te menții în formă.","Вот. Используй их, чтобы сохранить себя.", -You have enough.,TXT_RNO0_SCRIPT10_D37900_YOUHA,,,,Máš jich dost.,Du hast genug.,,,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Van elég.,,十分に持っています。,충분히 있으면 더 안 줘요.,Je hebt genoeg.,,Você tem o suficiente.,,Ai destule.,Тебе хватает., -Teach me.,TXT_RPLY1_SCRIPT10_D37900_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., -"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.","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.",,これで全てです。これ以上は教える事がありません。,"흐음, 이게 다입니다. 훈련을 다 마쳤어요.","Nou, dat is het dan, je bent klaar. Ik kan geen les meer geven.",,"Bom, é isso. Você já sabe de tudo. Não consigo ensinar mais nada.",,"Asta e, gata, nu mai am ce să te învăț.","Что ж, это всё. Твоё обучение закончено. Больше я ничему не могу тебя научить.", -Return after Macil tells you it's time.,TXT_RNO1_SCRIPT10_D37900_RETUR,,,,"Vrať se až ti Macil řekne, že je čas.","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.",,マシルに許可を貰わないとなりません。,사령관님의 말씀을 듣고 찾아와주시길.,Keer terug nadat Macil je vertelt dat het tijd is.,,Volte depois que Macil te disser que está na hora.,,Întoarce-te după ce Macil îți spune că e vremea.,"Возвращайся, когда скажет Мэйсил.", -"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,,,,"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.","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.",,"私が教えられる事はもうありません。 +I'm out of bullets.,TXT_RPLY0_SCRIPT10_D37900_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., +"Here, use them to keep you in good health.",TXT_RYES0_SCRIPT10_D37900_HEREU,,,,"Tady, používej je, abys zůstal ve zdraví.","Hier, benutze sie um gesund zu bleiben,",,,"Aquí tienes, úsalas para mantenerte en buena salud.",,"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.",,Pode pegar. Use essa munição para se manter saudável.,,"Aici, folosește-le ca să te menții în formă.","Вот. Используй их, чтобы сохранить себя.", +You have enough.,TXT_RNO0_SCRIPT10_D37900_YOUHA,,,,Máš jich dost.,Du hast genug.,,,Tienes suficientes.,,Sinulla on tarpeeksi.,Vous en avez assez.,Van elég.,Ne hai a sufficienza.,十分に持っています。,충분히 있으면 더 안 줘요.,Je hebt genoeg.,,Você tem o suficiente.,,Ai destule.,Тебе хватает., +Teach me.,TXT_RPLY1_SCRIPT10_D37900_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Mutasd meg.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., +"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.","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.",,"Bom, é isso. Você já sabe de tudo. Não consigo ensinar mais nada.",,"Asta e, gata, nu mai am ce să te învăț.","Что ж, это всё. Твоё обучение закончено. Больше я ничему не могу тебя научить.", +Return after Macil tells you it's time.,TXT_RNO1_SCRIPT10_D37900_RETUR,,,,"Vrať se až ti Macil řekne, že je čas.","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.,,Volte depois que Macil te disser que está na hora.,,Întoarce-te după ce Macil îți spune că e vremea.,"Возвращайся, когда скажет Мэйсил.", +"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,,,,"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.","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.","私が教えられる事はもうありません。 今後新しい武器は時間が掛かるが自分のペースで 学びなさい。弾切れでなければの話ですが。",모든 훈련을 배우고 마치셨잖아요. 당신이 알아둬야 할 건 그게 전부입니다. 그 외에는 탄약이 필요하신가요?,"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.",,"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ă.","Я обучил тебя всему, что умею сам. Всему, что тебе может когда-нибудь пригодиться. Больше я ничем не могу тебе помочь... если, конечно, у тебя патроны не кончились.", -Yes I am.,TXT_RPLY0_SCRIPT10_D39416_YESIA,,,,"Ano, došly.","Ja, bin ich.",,"Jes, mi estas.","Si, eso es.",,Kyllä on.,"Oui, j'en ai besoin.",Igen.,,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",,Estou mesmo.,,Da sunt.,"Да, кончились.", -Here you go. ,TXT_RYES0_SCRIPT10_D39416_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,,どうぞ。,탄약 대령이요!,Alsjeblieft.,,Aqui está.,,Iată.,Держи., -"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,,,,"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?","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?",,"何を見つけたと思う、テレポータービーコンだ。 +Yes I am.,TXT_RPLY0_SCRIPT10_D39416_YESIA,,,,"Ano, došly.","Ja, bin ich.",,"Jes, mi estas.","Si, eso es.",,Kyllä on.,"Oui, j'en ai besoin.",Igen.,"Sì, ho bisogno di munizioni.",ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",,Estou mesmo.,,Da sunt.,"Да, кончились.", +Here you go. ,TXT_RYES0_SCRIPT10_D39416_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,탄약 대령이요!,Alsjeblieft.,,Aqui está.,,Iată.,Держи., +"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,,,,"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?","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?","何を見つけたと思う、テレポータービーコンだ。 ビーコンを使用すると信号を追跡して増援を送る ことができるぞ。必要な物はあるか?","이 녀석을 확인해보세요! 텔레포터 비컨이라는 건데, 사용해서 신호를 전송하면 병력을 보내겠습니다. 그 외에 원하는 게 있어요?","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?",,"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?","Посмотри на эту новинку: телепортационный маяк. Когда ты его включишь, мы проследим сигнал и вышлем подмогу. Итак, что я могу тебе предложить?", -Box of rockets,TXT_RPLY0_SCRIPT10_D40932_BOXOF,,,,Bednu raket,Kiste Raketen.,,,Caja de cohetes.,,Rakettilaatikko.,Boîte de roquettes.,Egy doboz rakéta kellene.,,ロケット箱,미니 미사일 한 박스,Doos met raketten,,Caixa de foguetes,,Cutie de rachete.,Коробку ракет, -There you go.,TXT_RYES0_SCRIPT10_D40932_THERE,,,,Tady máš.,Bitteschön.,,Jen.,Ahí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,,はい、どうぞ。,여기 있어!,Daar ga je.,,Aqui está.,,Iată.,Бери., -You can't afford that!,TXT_RNO0_SCRIPT10_D40932_YOUCA,,,,Tu si nemůžeš dovolit!,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.,,買うだけの余裕が無い!,돈이 부족한 것 같은데!,Dat kan je je niet betalen!,,Você não pode comprar isto!,,Nu-ți poți permite asta!,Ты не можешь себе этого позволить!, -H-E grenades.,TXT_RPLY1_SCRIPT10_D40932_HEGRE,,,,Výbušné granáty,HE-Granaten.,,,Granadas HE.,,Räjähdekranaatteja.,Grenades explosives.,Robbanó gránátot.,,HEグレネード,고폭 유탄,H-E-granaten.,,Granadas explosivas.,,Grenade.,Осколочные гранаты, -Here you go.,TXT_RYES1_SCRIPT10_D40932_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,,どうぞ。,거래 감사드립니다!,Alsjeblieft.,,Aqui está.,,Iată.,Держи., -Come back when you have enough money.,TXT_RNO1_SCRIPT10_D40932_COMEB,,,,Vrať se až budeš mít dost peněz.,"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.",,十分持ってたらまた来い。,돈이 충분할 때 다시와요.,Kom terug als je genoeg geld hebt.,,Volte quando tiver dinheiro suficiente.,,Întoarce-te când ai destui bani.,"Возвращайся, когда у тебя будут деньги.", -Energy pod,TXT_RPLY2_SCRIPT10_D40932_ENERG,,,,Energetický kokón,Energiezelle.,,,Vaina de energía,,Energia-akku.,Cellule énergétique.,Energia cella.,,エネルギーポッド,에너지 포드,Energiecapsule,,Célula de energia.,,Capsulă energetică.,Энергоячейку, -Here's your energy pod,TXT_RYES2_SCRIPT10_D40932_HERES,,,,Tady ho máš.,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.,,これがエネルギーポッドだ。,에너지 포드 한 개 대령이요!,Hier is je energiecapsule...,,Aqui está a sua célula de energia.,,Iată capsula energetică.,Вот твоя энергоячейка., -You don't have enough for that.,TXT_RNO2_SCRIPT10_D40932_YOUDO,,,,Na ten nemáš dost.,"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.",,それでは足りない。,이 물품은 비싸죠. 저도 압니다.,Daar heb je niet genoeg voor.,,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег., -Teleporter beacon,TXT_RPLY3_SCRIPT10_D40932_TELEP,,,,Teleportační maják,Teleportersignal.,,,Faro de teletransporte,,Kaukosiirrinmajakka,Antenne de téléporteur.,Teleport követő,,テレポータービーコン,텔레포터 비콘,Teleporter baken,,Sinalizador de teletransporte,,Far pentru teleportare.,Телепортационный маяк, -"Help, when and where you need it.",TXT_RYES3_SCRIPT10_D40932_HELPW,,,,Pomoc kdekoliv a kdykoliv je třeba.,"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.",,助けが必要になったら使うんだ。,위급한 상황에서만 사용하시길.,"Help, waar en wanneer je het nodig hebt.",,"Reforços, quando e onde você precisar.",,"Ajutor, acolo și când ai nevoie de el.",Теперь ты сможешь получить помощь всегда и везде., -"Sorry, no charity.",TXT_RNO3_SCRIPT10_D40932_SORRY,,,,"Promiň, nejsme charita.","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.",,すまない、チャリティーじゃないんだ。,"미안하지만, 여긴 자선단체가 아니에요.","Sorry, geen liefdadigheid.",,"Sinto muito, mas não fazemos caridade.",,"Scuze, nu e caritate.",Прости. Никакой благотворительности., -"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,,,,Teď když máme hrad pod kontrolou musíme s ním být ještě obezřetnější. Řád se pravděpodobně právě teď připravuje zaútočit.,"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.",,"城が管理下に入った今、維持させるためには +Box of rockets,TXT_RPLY0_SCRIPT10_D40932_BOXOF,,,,Bednu raket,Kiste Raketen.,,,Caja de cohetes.,,Rakettilaatikko.,Boîte de roquettes.,Egy doboz rakéta kellene.,Cassa di razzi,ロケット箱,미니 미사일 한 박스,Doos met raketten,,Caixa de foguetes,,Cutie de rachete.,Коробку ракет, +There you go.,TXT_RYES0_SCRIPT10_D40932_THERE,,,,Tady máš.,Bitteschön.,,Jen.,Ahí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,はい、どうぞ。,여기 있어!,Daar ga je.,,Aqui está.,,Iată.,Бери., +You can't afford that!,TXT_RNO0_SCRIPT10_D40932_YOUCA,,,,Tu si nemůžeš dovolit!,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!,,Você não pode comprar isto!,,Nu-ți poți permite asta!,Ты не можешь себе этого позволить!, +H-E grenades.,TXT_RPLY1_SCRIPT10_D40932_HEGRE,,,,Výbušné granáty,HE-Granaten.,,,Granadas HE.,,Räjähdekranaatteja.,Grenades explosives.,Robbanó gránátot.,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten.,,Granadas explosivas.,,Grenade.,Осколочные гранаты, +Here you go.,TXT_RYES1_SCRIPT10_D40932_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Eccole qua.,どうぞ。,거래 감사드립니다!,Alsjeblieft.,,Aqui está.,,Iată.,Держи., +Come back when you have enough money.,TXT_RNO1_SCRIPT10_D40932_COMEB,,,,Vrať se až budeš mít dost peněz.,"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.,,Volte quando tiver dinheiro suficiente.,,Întoarce-te când ai destui bani.,"Возвращайся, когда у тебя будут деньги.", +Energy pod,TXT_RPLY2_SCRIPT10_D40932_ENERG,,,,Energetický kokón,Energiezelle.,,,Vaina de energía,,Energia-akku.,Cellule énergétique.,Energia cella.,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,,Célula de energia.,,Capsulă energetică.,Энергоячейку, +Here's your energy pod,TXT_RYES2_SCRIPT10_D40932_HERES,,,,Tady ho máš.,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...,,Aqui está a sua célula de energia.,,Iată capsula energetică.,Вот твоя энергоячейка., +You don't have enough for that.,TXT_RNO2_SCRIPT10_D40932_YOUDO,,,,Na ten nemáš dost.,"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.,,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег., +Teleporter beacon,TXT_RPLY3_SCRIPT10_D40932_TELEP,,,,Teleportační maják,Teleportersignal.,,,Faro de teletransporte,,Kaukosiirrinmajakka,Antenne de téléporteur.,Teleport követő,Radiofaro per teletrasporto.,テレポータービーコン,텔레포터 비콘,Teleporter baken,,Sinalizador de teletransporte,,Far pentru teleportare.,Телепортационный маяк, +"Help, when and where you need it.",TXT_RYES3_SCRIPT10_D40932_HELPW,,,,Pomoc kdekoliv a kdykoliv je třeba.,"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.",,"Reforços, quando e onde você precisar.",,"Ajutor, acolo și când ai nevoie de el.",Теперь ты сможешь получить помощь всегда и везде., +"Sorry, no charity.",TXT_RNO3_SCRIPT10_D40932_SORRY,,,,"Promiň, nejsme charita.","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.",,"Sinto muito, mas não fazemos caridade.",,"Scuze, nu e caritate.",Прости. Никакой благотворительности., +"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,,,,"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.","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.","城が管理下に入った今、維持させるためには 更なる警戒網が必要になるだろう。オーダーは 反撃の準備をしているはずだ。",성을 공격해 점령한 이후로 화력과 병력 등을 많이 증가시킬 수 있게 되었습니다. 오더 놈들은 분명히 이를 대비한 역습을 준비하고 있을 거예요.,"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.",,"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.","Замок теперь наш, но если хотим его удержать, нужно не терять бдительности. Быть может, именно сейчас Орден готовит контратаку.", -Be careful out there.,TXT_DLG_SCRIPT10_D43964_BECAR,,,,Buď tam venku opatrný.,Sei vorsichtig da draußen.,,,Ten cuidado ahí fuera.,,Pidä varasi siellä.,Faites attention à vous.,Vigyázz magadra odakinnt.,,外は気を付けろ。,부디 조심하시길.,Wees voorzichtig daarbuiten.,,Tome cuidado.,,Ai grijă afară.,Будь настороже., -"Keep up the great work, we couldn't have done it without you.",TXT_DLG_SCRIPT10_D45480_KEEPU,,,,"Jen tak dál, bez tebe bychom to nedokázali.","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.",,"我々は貴方無くして成し遂げる事は出来なかった +Be careful out there.,TXT_DLG_SCRIPT10_D43964_BECAR,,,,Buď tam venku opatrný.,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.,,Tome cuidado.,,Ai grijă afară.,Будь настороже., +"Keep up the great work, we couldn't have done it without you.",TXT_DLG_SCRIPT10_D45480_KEEPU,,,,"Jen tak dál, bez tebe bychom to nedokázali.","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.",,Continue assim. Nós não teríamos conseguido sem você.,,"Continuă să faci treabă bună, n-am fi reușit fără tine.",Продолжай в том же духе. Без тебя мы бы не справились., -I'm the keymaster.,TXT_DLG_SCRIPT11_D0_IMTHE,,,,Já jsem tu klíčníkem.,Ich bin der Schlüsselmeister.,,,Soy el amo de llaves.,,Olen avainmestari.,Je suis le maître des clés.,Én vagyok a kulcsmester.,,僕がキーマスターだ。,전 열쇠지기에요.,Ik ben de sleutelbeheerder.,,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник., -"A lot of people would say this is a thankless and insignificant job. But it's not, in fact...",TXT_DLG_SCRIPT11_D1516_ALOTO,,,,"Většina lidí by řekla, že tohle je nevděčná a nedůležitá práce, ale není, naopak...","Eine Menge Leute würden sagen, dies sei eine undankbare Aufgabe, aber das ist es nicht, in Wirklichkeit...",,,"Mucha gente diría que éste 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...",,"皆、この仕事が報われないと思っているが +I'm the keymaster.,TXT_DLG_SCRIPT11_D0_IMTHE,,,,Já jsem tu klíčníkem.,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.,,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник., +"A lot of people would say this is a thankless and insignificant job. But it's not, in fact...",TXT_DLG_SCRIPT11_D1516_ALOTO,,,,"Většina lidí by řekla, že tohle je nevděčná a nedůležitá práce, ale není, naopak...","Eine Menge Leute würden sagen, dies sei eine undankbare Aufgabe, aber das ist es nicht, in Wirklichkeit...",,,"Mucha gente diría que éste 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....",,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...","Многие скажут, что это неблагодарная и незначительная работа, но это не так. На самом деле...", -Give me the key!,TXT_RPLY0_SCRIPT11_D1516_GIVEM,,,,Dej mi klíč!,Gib mir den Schlüssel.,,,¡Dame la llave!,,Anna minulle avain!,Donne moi la clé!,Add ide a kulcsot!,,鍵をくれ!,그냥 망할 열쇠를 줘!,Geef me de sleutel!,,Me dê a chave!,,Dă-mi cheia!,Дай мне ключ!, -"OK, but remember, I'm the keymaster.",TXT_DLG_SCRIPT11_D3032_OKBUT,,,,"Dobře, ale nezapomeň, že klíčník jsem já.","Ok, aber vergiß nicht, dass ICH der Schlüsselmeister bin.",,,"Ok, 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é, maar onthoud, ik ben de sleutelbeheerder.",,"Ok, mas lembre-se, eu sou o mestre das chaves.",,"Bine, dar ține minte, eu sunt stăpânul cheilor.","Держи, но помни: я ключник!", -"OK pal, whatever.",TXT_RPLY0_SCRIPT11_D3032_OKPAL,,,,"Jasně, kámo, klidně.","Was auch immer, Kumpel.",,,"Ok colega, lo que tú digas.",,"Joo joo, ihan sama.","Comme tu veux, mon ami.","OK öreg, nem hat meg.",,わかった、何なりと。,"그래, 알 게 뭐야...","Oké, vriend, wat dan ook.",,"Ok, amigo. Que seja.",,"Bine amice, cum spui tu.",Ага. Без проблем., -I'm the keymaster.,TXT_DLG_SCRIPT11_D4548_IMTHE,,,,Já jsem tu klíčníkem.,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.,,僕がキーマスターだ。,열쇠지기. 그게 바로 저죠!,Ik ben de sleutelbeheerder.,,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник., -Die traitor!,TXT_DLG_SCRIPT11_D6064_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,,死ね、反逆者!,"죽어라, 배신자!","Sterf, verrader.",,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", -Die traitor!,TXT_DLG_SCRIPT11_D7580_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,,死ね、反逆者!,"뒈져라, 배신자!","Sterf, verrader.",,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", -"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,,,,"Přišel ses vysmívat? I když jsme za mřížemi, dokud jsme na nohou, ty jsi poražený.","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.",,"何睨んでるんだ?この棒が俺達を囲んでる限り、 +Give me the key!,TXT_RPLY0_SCRIPT11_D1516_GIVEM,,,,Dej mi klíč!,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!,,Me dê a chave!,,Dă-mi cheia!,Дай мне ключ!, +"OK, but remember, I'm the keymaster.",TXT_DLG_SCRIPT11_D3032_OKBUT,,,,"Dobře, ale nezapomeň, že klíčník jsem já.","Ok, aber vergiß nicht, dass ICH der Schlüsselmeister bin.",,,"Ok, 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, mas lembre-se, eu sou o mestre das chaves.",,"Bine, dar ține minte, eu sunt stăpânul cheilor.","Держи, но помни: я ключник!", +"OK pal, whatever.",TXT_RPLY0_SCRIPT11_D3032_OKPAL,,,,"Jasně, kámo, klidně.","Was auch immer, Kumpel.",,,"Ok colega, lo que 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, amigo. Que seja.",,"Bine amice, cum spui tu.",Ага. Без проблем., +I'm the keymaster.,TXT_DLG_SCRIPT11_D4548_IMTHE,,,,Já jsem tu klíčníkem.,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.,,Eu sou o mestre das chaves.,,Sunt stăpânul cheilor.,Я ключник., +Die traitor!,TXT_DLG_SCRIPT11_D6064_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"죽어라, 배신자!","Sterf, verrader.",,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", +Die traitor!,TXT_DLG_SCRIPT11_D7580_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter.",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,死ね、反逆者!,"뒈져라, 배신자!","Sterf, verrader.",,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", +"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,,,,"Přišel ses nám vysmívat? I když jsme za mřížemi, dokud jsme na nohou, ty zůstáváš poražený.","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.",,"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.","Пришёл поглумиться? Пусть мы и за этими решётками, но пока мы живы, вам не победить.", -Let us out of here!,TXT_DLG_SCRIPT11_D10612_LETUS,,,,Pusť nás odsud!,Lass uns hier raus!,,,¡Sácanos de aquí!,,Päästä meidät pois täältä!,Sortez nous de là!,Engedj ki minket!,,ここから出してくれ!,우릴 여기서 내보내 줘!,Laat ons hier uit!,,Nos tire daqui!,,Scoate-ne de aici!,Выпусти нас отсюда!, -Leave me alone!,TXT_DLG_SCRIPT11_D12128_LEAVE,,,,Nech mě být!,Lass mich in Ruhe!,,,¡Déjame en paz!,,Jätä minut rauhaan!,Foutez moi la paix!,Hagyj békén!,,ほっといてくれ!,날 좀 내버려 둬!,Laat me met rust!,,Me deixe em paz!,,Lasă-mă în pace!,Оставь меня в покое!, -"What is the wisdom you seek, simple one?",TXT_DLG_SCRIPT12_D0_WHATI,,,,"Jaké moudro hledáš, jednoduchý?","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?",,迷える者よ、如何なる知識を求めに来た。,그대가 찾고 있는 지혜는 어떤 것인가? 평범한 자여?,"Wat is de wijsheid die je zoekt, eenvoudige wijsheid?",,"Qual é a sabedoria que você procura, simples criatura?",,"Ce întelepciune cauți, om simplu?","Какой мудрости ты ищешь, непосвящённый?", -The Sigil of the One God.,TXT_RPLY0_SCRIPT12_D0_THESI,,,,Pečeť Jednoho boha.,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.,,唯一神のシジルだ。,"유일신의 인장, 시질이다.",De Sigil van de Ene God.,,O Sigilo do Deus Único.,,Sigiliul Adevăratului Zeu.,Сигил Единого Бога., -"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.","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.",,"お主の持つ欠片が共鳴しているのを感受出来る。 +Let us out of here!,TXT_DLG_SCRIPT11_D10612_LETUS,,,,Pusť nás odsud!,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!,,Nos tire daqui!,,Scoate-ne de aici!,Выпусти нас отсюда!, +Leave me alone!,TXT_DLG_SCRIPT11_D12128_LEAVE,,,,Nech mě být!,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!,,Me deixe em paz!,,Lasă-mă în pace!,Оставь меня в покое!, +"What is the wisdom you seek, simple one?",TXT_DLG_SCRIPT12_D0_WHATI,,,,"Jaké moudro hledáš, jednoduchý?","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?",,"Qual é a sabedoria que você procura, simples criatura?",,"Ce întelepciune cauți, om simplu?","Какой мудрости ты ищешь, непосвящённый?", +The Sigil of the One God.,TXT_RPLY0_SCRIPT12_D0_THESI,,,,Pečeť Jednoho boha.,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.,,O Sigilo do Deus Único.,,Sigiliul Adevăratului Zeu.,Сигил Единого Бога., +"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.","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.","お主の持つ欠片が共鳴しているのを感受出来る。 二つ目の欠片は紅と黒曜の塔だ。 そこでお主を待ち構えているビショップと戦え。 その者が持つシンボルを辿れば見つかるだろう。 このトークンをキーマスターに渡せ。 魔物を討伐した後、此処へ戻るのだ。",그대에게서 시질의 조각 중 하나가 느껴지는군. 두 번째 조각은 진홍빛 흑요석 탑의 심장부에 있다. 거기서 기다리고 있는 비숍과 싸워야 한다. 그 자의 권력을 상징하는 문양을 따라가면 만날 수 있을 것이다. 열쇠지기에게 이 통행증을 전해주어라. 그리고 괴물을 처치하면 다시 나에게로 오라.,"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.",,"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.","Я чувствую один фрагмент, настроенный на тебя. Второй лежит в сердце багрово-обсидиановой башни. Там тебе предстоит сразиться с Епископом — он знает о тебе и ждёт твоего появления. Его символ власти приведёт тебя прямо к нему. Отнеси этот жетон ключнику. Срази чудовище и возвращайся ко мне. ", -I'll be back.,TXT_RPLY0_SCRIPT12_D1516_ILLBE,,,,Vrátím se.,Ich werde zurückkommen.,,Mi revenos.,Volveré.,,Tulen takaisin.,Je reviendrai.,Visszatérek még.,,すぐ戻ってくる。,금방 돌아올게.,Ik kom terug.,,Eu voltarei.,,Mă voi întoarce.,Я вернусь., -"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.","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.",,"ビショップは手強く、この使命は困難であろう。 +I'll be back.,TXT_RPLY0_SCRIPT12_D1516_ILLBE,,,,Vrátím se.,Ich werde zurückkommen.,,Mi revenos.,Volveré.,,Tulen takaisin.,Je reviendrai.,Visszatérek még.,Ritornerò.,すぐ戻ってくる。,금방 돌아올게.,Ik kom terug.,,Eu voltarei.,,Mă voi întoarce.,Я вернусь., +"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.","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.","ビショップは手強く、この使命は困難であろう。 次の欠片を手にしたら此処へ戻るのだ。 ","비숍은 만만치 않은 상대지만, 이보다 더한 일들이 기다리고 있다. 두 번째 조각을 찾고 다시 돌아오라.","Hoewel de bisschop formidabel is, is deze zoektocht gering. Keer terug naar mij als je het volgende fragment bezit.",,"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.","Каким бы страшным Епископ ни был, это задание не доставит тебе хлопот. Достань следующий фрагмент и возвращайся ко мне.", -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.","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.",,"次の挑戦はお主の精神が試されるだろう。 +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.","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.,"次の挑戦はお主の精神が試されるだろう。 三つ目の欠片はお主の指導者が所持している。 彼奴はお主の死を望むが為 戦場へ送り込んでいるのだ。",다음 도전은 그대의 정신을 시험할 것이다. 세 번째 조각은 바로 그대의 지도자가 가지고 있다. 그는 그대를 시켜서 죽였던 괴물들과 마찬가지인 존재다.,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.,,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.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу.", -Macil? A traitor?,TXT_RPLY0_SCRIPT12_D4548_MACIL,,,,Macil? Zrádce?,Macil? Ein Verräter?,,,¿Macil? ¿Un traidor?,,Macil? Petturiko?,Macil? Un traître?,Macil? Egy áruló volna?,,マシル?彼が裏切者?,마실이 배신자라고?,Macil? Een verrader?,,Macil? Um traidor?,,Macil? Un trădător?,Мэйсил? Предатель?, -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.","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.",,"彼を妄信するお主の活躍によって、 +Macil? A traitor?,TXT_RPLY0_SCRIPT12_D4548_MACIL,,,,Macil? Zrádce?,Macil? Ein Verräter?,,,¿Macil? ¿Un traidor?,,Macil? Petturiko?,Macil? Un traître?,Macil? Egy áruló volna?,Macil? Un traditore?,マシル?彼が裏切者?,마실이 배신자라고?,Macil? Een verrader?,,Macil? Um traidor?,,Macil? Un trădător?,Мэйсил? Предатель?, +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.","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.,"彼を妄信するお主の活躍によって、 彼奴の目的が果たされる間近だ。 彼奴に立ち向かい、運命を切り開くのだ。",그대의 맹목적인 믿음이 조각들을 하나하나 찾으면서 그자의 목표를 이뤄주고 있다. 그를 상대하고 구속된 운명에서 벗어나라.,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.,,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.","Твоя слепая вера приближала его к цели каждый раз, как ты находил фрагмент. Сразись с ним и исполни своё предназначение.", -"All right, it is Macil.",TXT_RPLY0_SCRIPT12_D6064_ALLRI,,,,"Tak dobře, je to 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.",,わかった、それがマシルか。,역시... 마실이였군.,"Oké, het is Macil.",,Certo. Então é o Macil.,,"Bine, Macil să fie.",Понятно. Я убью Мэйсила., -It's you I don't trust.,TXT_RPLY1_SCRIPT12_D6064_ITSYO,,,,Ale já nevěřím tobě.,"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.",,信用できん。,내가 믿지 않는 건 네놈이다.,Ik vertrouw jou niet.,,É você em quem eu não confio.,,Tu ești cel în care nu am încredere.,"Я думаю, что это ты лжешь!", -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.","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.",,"如何なる選択でも、人類は大いなる神の元で +"All right, it is Macil.",TXT_RPLY0_SCRIPT12_D6064_ALLRI,,,,"Tak dobře, je to 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.",,Certo. Então é o Macil.,,"Bine, Macil să fie.",Понятно. Я убью Мэйсила., +It's you I don't trust.,TXT_RPLY1_SCRIPT12_D6064_ITSYO,,,,Ale já nevěřím tobě.,"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.,,É você em quem eu não confio.,,Tu ești cel în care nu am încredere.,"Я думаю, что это ты лжешь!", +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.","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.",,"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.","Что бы ты ни выбрал, твой род исчезнет по воле Единого Бога.", -I'll be back when Macil's dead.,TXT_RPLY0_SCRIPT12_D7580_ILLBE,,,,"Vrátím se, až bude Macil mrtev.","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.",,マシルの死と共に戻る。,마실을 죽이고 돌아오겠다.,Ik kom terug als Macil dood is.,,Voltarei quando Macil estiver morto.,,Am să mă întorc odată ce Macil e mort.,Я вернусь после смерти Мэйсила., -I can't let that happen.,TXT_RPLY1_SCRIPT12_D7580_ICANT,,,,To nemůžu dopustit.,Das darf nicht passieren.,,,No pienso permitirlo.,,En voi antaa sen tapahtua.,Je ne peux pas vous laisser faire ça.,Nem hagyhatom ezt.,,そうはさせん。,그렇게 할 순 없어.,Dat kan ik niet laten gebeuren.,,Não posso deixar isso acontecer.,,Nu voi permite asta.,Я не могу этого допустить., -"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.,"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.",,事を措いても、時の河は永遠の先に進む。,"그대가 가만히 있어도, 시간의 강은 계속 흐를 뿐이다.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.",,"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.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.", -"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 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.",,"心に動揺が見られるな、だがお主は己の体から +I'll be back when Macil's dead.,TXT_RPLY0_SCRIPT12_D7580_ILLBE,,,,"Vrátím se, až bude Macil mrtev.","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.,,Voltarei quando Macil estiver morto.,,Am să mă întorc odată ce Macil e mort.,Я вернусь после смерти Мэйсила., +I can't let that happen.,TXT_RPLY1_SCRIPT12_D7580_ICANT,,,,To nemůžu dopustit.,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.,,Não posso deixar isso acontecer.,,Nu voi permite asta.,Я не могу этого допустить., +"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.,"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.",,"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.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.", +"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 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.","心に動揺が見られるな、だがお主は己の体から 癌を取り除いた。次の欠片は 人々を虐殺で支配するロアマスター外科医が 所持している。彼奴を止め、欠片を得るのだ。","그대 몸 안의 암 덩어리를 잘라냈건만, 심장은 여전히 뛰고 있구나. 다음은 네 종족의 도살과 지배를 책임졌던 로어마스터다. 그를 막아내면, 다음 조각은 너의 것이다.","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.",,"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.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими: Хранителя мудрости. Останови его, и следующий фрагмент твой.", -Where do I find him?,TXT_RPLY0_SCRIPT12_D10612_WHERE,,,,Kde ho najdu?,Wo finde ich ihn?,,,¿Dónde lo encuentro?,,Mistä löydän hänet?,Où puis-je le trouver?,Hol találom meg?,,そいつはどうやって見つける?,어디를 가야 그를 발견할 수 있지?,Waar vind ik hem?,,Onde encontro ele?,,Unde îl găsesc?,Где мне искать его?, -"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ě.","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.",,"我の傍にあるテレポーターの扉を開いた。 +Where do I find him?,TXT_RPLY0_SCRIPT12_D10612_WHERE,,,,Kde ho najdu?,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?,,Onde encontro ele?,,Unde îl găsesc?,Где мне искать его?, +"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ě.","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.","我の傍にあるテレポーターの扉を開いた。 それがロアマスターの元に通ずる。 彼奴に死を伝えた後、再び扉を通るがよい。","내가 로어마스터로 향하는 순간이동 장치를 열어두었다. 그 자가 죽으면, 똑같은 장치를 써서 다시 나에게 오라. \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.",,"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.","Используй телепорт за той дверью, что я только что открыл, чтобы добраться до Хранителя. Когда он умрёт, найди другой телепорт, чтобы вернуться ко мне.", -"I'll be back, with his piece!",TXT_RPLY0_SCRIPT12_D12128_ILLBE,,,,Vrátím se s jeho dílem!,"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!",,欠片を持ってすぐ戻る!,녀석의 조각을 가지고 다시 올게!,"Ik kom terug, met zijn stuk!",,"Eu voltarei, com a peça dele!",,"Mă voi întoarce, cu piesa lui.",Я достану его фрагмент!, -"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.,"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.",,事を措いても、時の河は永遠の先に進む。,"발버둥을 친다해도, 시간의 강은 계속 흐를 뿐.","De rivier van de tijd beweegt voor altijd verder, terwijl je stilstaat.",,"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.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.", -"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.","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.",,"気の毒な者よ、お主は幾千の者達が +"I'll be back, with his piece!",TXT_RPLY0_SCRIPT12_D12128_ILLBE,,,,Vrátím se s jeho dílem!,"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!",,"Eu voltarei, com a peça dele!",,"Mă voi întoarce, cu piesa lui.",Я достану его фрагмент!, +"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.,"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.",,"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.","Река времени непрестанно течёт вперёд, в то время как ты стоишь без движения.", +"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.","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.","気の毒な者よ、お主は幾千の者達が 遂げられなかった行いを果たした... お主は我にシジルの力を、唯一神の声を届けた。","애처로운 자여, 지금껏 수천 명이 이루지 못했던 일을 해내었다... 나에게 시질의 힘을, 유일신의 목소리를 전해주는구나.","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.",,"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.","Ничтожный человечишка, тебе удалось сделать то, с чем не справились тысячи... Ты принёс мне мощь Сигила, глас Единого Бога.", -I don't understand.,TXT_RPLY0_SCRIPT12_D15160_IDONT,,,,Nerozumím ti.,Ich verstehe nicht.,,Mi ne komprenas.,No entiendo.,,En ymmärrä.,Je ne comprends pas.,Nem értem.,,わからないな。,무슨 소리야?,Ik begrijp het niet.,,Eu não entendo.,,Nu înțeleg.,Я не понимаю., -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í.","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.",,"シジルは門を開き、この惑星の魂を浄化し +I don't understand.,TXT_RPLY0_SCRIPT12_D15160_IDONT,,,,Nerozumím ti.,Ich verstehe nicht.,,Mi ne komprenas.,No entiendo.,,En ymmärrä.,Je ne comprends pas.,Nem értem.,Non capisco.,わからないな。,무슨 소리야?,Ik begrijp het niet.,,Eu não entendo.,,Nu înțeleg.,Я не понимаю., +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í.","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.,"シジルは門を開き、この惑星の魂を浄化し 我に永遠の命を授け給うのだ。我はこの世の 生命力を剥ぎ取り、新たなる星への征服に 駆り出すのだ。","시질은 잠겨저 있던 문을 열고, 이 세상을 정화할 혼령을 깨울 것이며, 나에게 영생을 선사할 것이다. 내가 이 세상의 기운을 모두 쓸어 담아 새로 정복할 세계를 찾아 나설 힘을 모을 것이다.",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.,,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.,"Сигил распахнёт дверь и высвободит сущность, что очистит эту планету и дарует мне вечную жизнь. Я выкраду всю энергию этого мира и отправлюсь на завоевание следующих.", -I can't let you do that.,TXT_RPLY0_SCRIPT12_D16676_ICANT,,,,To ti nemůžu dovolit.,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.,,そんな真似はさせられないな。,네 놈의 음모를 막겠다!,Dat kan ik je niet laten doen.,,Não vou deixar você fazer isso.,,Nu te pot lăsa să faci asta.,Я не могу этого допустить., -You can if you're dead.,TXT_DLG_SCRIPT12_D18192_YOUCA,,,,"Můžeš, když zemřeš.","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ó.,,お主の破滅は免れぬぞ。,네가 죽으면 될 것이다...,Dat kan je wel als je dood bent.,,Deixará se você estiver morto.,,"Poți, dacă ești mort.","Сможешь, когда умрёшь.", -"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.","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.",,"俺達を解放しに来たのか?あいつらに +I can't let you do that.,TXT_RPLY0_SCRIPT12_D16676_ICANT,,,,To ti nemůžu dovolit.,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.,,Não vou deixar você fazer isso.,,Nu te pot lăsa să faci asta.,Я не могу этого допустить., +You can if you're dead.,TXT_DLG_SCRIPT12_D18192_YOUCA,,,,"Můžeš, když zemřeš.","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.,,Deixará se você estiver morto.,,"Poți, dacă ești mort.","Сможешь, когда умрёшь.", +"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.","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.","俺達を解放しに来たのか?あいつらに インプラントを外されたが、俺は大丈夫だ。 まだ少し留まって涎を拭き取らないとならない。","저희를 구출하기 위해서 찾아오셨나요? 그들이 제가 성실하게 일을 한 사례로 세뇌 장치를 때어갔어요. 그런데... 아직도 위험한 것 같은데, 좀 흘린 침 자국을 좀 닦아야 할 것 같아요.","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.",,"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ă.","Ты пришёл спасти нас? Я был послушным, так что они вынули мой имплант. И всё равно я вынужден оставаться тут, внизу, и подтирать слюни за дронами.", -"Yes, I'm here to free you.",TXT_RPLY0_SCRIPT14_D0_YESIM,,,,"Ano, jsem tu, abych vás osvobodil.","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.",,そうだ、助けに来た。,"그래, 난 널 구하러 왔어.","Ja, ik ben hier om je te bevrijden.",,"Sim, estou aqui para libertar vocês.",,"Da, am venit să te eliberez.","Да, я здесь, чтобы спасти вас.", -You mean it?,TXT_RYES0_SCRIPT14_D0_YOUME,,,,To myslíš doopravdy?,Wirklich?,,,¿En serio?,,Todellako?,Vraiment?,Tényleg?,,そういう意味か?,정말인가요?,Je meent het?,,Sério mesmo?,,Pe bune?,Правда?, -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. Ani náhodou!","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!",,"まだ俺は手伝うことが出来ない。 +"Yes, I'm here to free you.",TXT_RPLY0_SCRIPT14_D0_YESIM,,,,"Ano, jsem tu, abych vás osvobodil.","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.",,"Sim, estou aqui para libertar vocês.",,"Da, am venit să te eliberez.","Да, я здесь, чтобы спасти вас.", +You mean it?,TXT_RYES0_SCRIPT14_D0_YOUME,,,,To myslíš doopravdy?,Wirklich?,,,¿En serio?,,Todellako?,Vraiment?,Tényleg?,Veramente?,そういう意味か?,정말인가요?,Je meent het?,,Sério mesmo?,,Pe bune?,Правда?, +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!","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ù!,"まだ俺は手伝うことが出来ない。 トランスミッターを壊さなければバレてしまう。 そいつは上の階のフォースフィールドを越えた所 にいる。コンベアーの詰まりをチェックする だけの仕事だったが、もう辞任だな!",전송기를 파괴하기 전까지는 세뇌된 사람들을 도와줄 수가 없어요. 저 위층에 방어막에 보호받고 있는 채로 있습니다. 제 원래 업무는 광석이 끼지 않게 운반 벨트를 확인하는 거였어요... 이젠 일할 필요도 없지만!,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!,,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!","Я не могу помочь другим, пока ты не взорвёшь передатчик. Он находится за силовым полем наверху. Моя работа — проверять, не заклинило ли конвейеры. Теперь уже нет!", -"That's right, you're saved!",TXT_RPLY0_SCRIPT14_D1516_THATS,,,,"Ano, jsi zachráněn!","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.",,そうだ、救われたぞ!,당연하지. 너는 자유야!,"Dat klopt, je bent gered!",,Isso mesmo. Vocês estão salvos!,,"Așa e, ești salvat!","Да, это так! Вы спасены!", -"Oh, thank you!",TXT_RYES0_SCRIPT14_D1516_OHTHA,,,,"Oh, děkuju!","Oh, danke sehr!",,"Ho, dankon.","Oh, ¡gracias!",,"Voi, kiitos!","Oh, merci!","Oh, köszönöm!",,おう、ありがとよ!,"오, 고마워요!","Oh, dank je wel!",,"Ah, muito obrigado!",,"Oh, mulțumesc!",Ура! Спасибо тебе!, -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D3032_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!,,自由だ!!俺達は自由だ!!俺達は自由だ!!,우린 자유야! 우린 자유라고!,We zijn vrij!! We zijn vrij!! We zijn vrij!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, -Must mine more ore!,TXT_DLG_SCRIPT14_D4548_MUSTM,,,,Muset těžit další rudu!,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!,,もっと掘らねえといけねえんだ!,광석을... 캐내야 해...,Moet erts meer of meer ontginnen!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D6064_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!,,自由だ!!オレらは自由だ!!オレらは自由だ!!,프론트가 해냈다! 자유를 거의 되찾았어!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, -Must mine more ore!,TXT_DLG_SCRIPT14_D7580_MUSTM,,,,Muset těžit další rudu!,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!,,鉱石がもっと必要なんだ!,광석... 데그닌... 캔다...,Moet meer erts ontginnen!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D9096_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!,,自由だ!!私達は自由だ!!私達は自由だ!!,살았군요. 이제 저항군 기지로 향하는 일 밖엔 남지 않은 것 같아요.,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, -Must mine more ore!,TXT_DLG_SCRIPT14_D10612_MUSTM,,,,Muset těžit další rudu!,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!,,いつまで採掘しなければならない!,캐고... 캐고... 또 캔다...,Moet meer erts ontginnen!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, -We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D12128_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!,,僕らは自由だ!!僕らは自由だ!!僕らは自由だ!!,살았다! 이제 그 놈들이 죽이기 전에 도망쳐야해요!,We zijn vrij!!! We zijn vrij!!! We zijn vrij!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, -What are you doing here?,TXT_DLG_SCRIPT15_D0_WHATA,,,,Co tady děláš?,Was machst du hier?,,,¿Qué haces aquí?,,Mitä teette täällä?,Qu'est ce que vous faites ici?,Mit csinálsz itt?,,ここで何をしている?,여기서 뭘 하는거지?,Wat doe je hier?,,O que você está fazendo aqui?,,Ce cauți aici?,По какому делу ты здесь?, -Routine inspection.,TXT_RPLY0_SCRIPT15_D0_ROUTI,,,,Rutinní kontrola.,Eine Routineinspektion.,,,Inspección rutinaria.,,Rutiinitarkastus.,Inspection de routine.,Rutin ellenőrzés.,,見回りだ。,정기적 검사요.,Routine-inspectie.,,Inspeção de rotina.,,Inspecție de rutină.,Плановая проверка., -"All right, carry on.",TXT_RYES0_SCRIPT15_D0_ALLRI,,,,"Dobře, pokračuj.","In Ordnung, mach weiter.",,,"Muy bien, continúa.",,"Selvä on, jatkakaa.","D'accord, continuez.","Renben, folytasd csak.",,わかった、続けろ。,"좋아, 계속해.","Oké, ga door.",,"Muito bem, continue.",,"Bine, mergi mai departe.",Понятно. Продолжай., -"Nothing to report here. Everything is working fine. If anything goes wrong, I'll be sure to report it.",TXT_DLG_SCRIPT15_D1516_NOTHI,,,,"Tady nic k nahlášení není. Všechno funguje dobře. Pokud se něco pokazí, nahlásím to.","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.",,"報告することはない。全て順調だ。 +"That's right, you're saved!",TXT_RPLY0_SCRIPT14_D1516_THATS,,,,"Ano, jsi zachráněn!","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!",,Isso mesmo. Vocês estão salvos!,,"Așa e, ești salvat!","Да, это так! Вы спасены!", +"Oh, thank you!",TXT_RYES0_SCRIPT14_D1516_OHTHA,,,,"Oh, děkuju!","Oh, danke sehr!",,"Ho, dankon.","Oh, ¡gracias!",,"Voi, kiitos!","Oh, merci!","Oh, köszönöm!","Oh, grazie!",おう、ありがとよ!,"오, 고마워요!","Oh, dank je wel!",,"Ah, muito obrigado!",,"Oh, mulțumesc!",Ура! Спасибо тебе!, +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D3032_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, +Must mine more ore!,TXT_DLG_SCRIPT14_D4548_MUSTM,,,,Muset těžit další rudu!,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!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D6064_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, +Must mine more ore!,TXT_DLG_SCRIPT14_D7580_MUSTM,,,,Muset těžit další rudu!,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!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D9096_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, +Must mine more ore!,TXT_DLG_SCRIPT14_D10612_MUSTM,,,,Muset těžit další rudu!,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!,,Preciso minerar mais!,,Mai trebuie să minez încă o bucată de minereu.,Нужно добыть больше руды!, +We're free!! We're free!! We're free!!,TXT_DLG_SCRIPT14_D12128_WEREF,,,,Jsme volní! Jsme volní! Jsme volní!,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!!!,,Estamos livres!! Estamos livres!! Estamos livres!!,,Suntem liberi!! Suntem liberi!! Suntem liberi!!,Мы свободны! Мы свободны! Мы свободны!, +What are you doing here?,TXT_DLG_SCRIPT15_D0_WHATA,,,,Co tady děláte?,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?,,O que você está fazendo aqui?,,Ce cauți aici?,По какому делу ты здесь?, +Routine inspection.,TXT_RPLY0_SCRIPT15_D0_ROUTI,,,,Rutinní kontrola.,Eine Routineinspektion.,,,Inspección rutinaria.,,Rutiinitarkastus.,Inspection de routine.,Rutin ellenőrzés.,Ispezione ordinaria.,見回りだ。,정기적 검사요.,Routine-inspectie.,,Inspeção de rotina.,,Inspecție de rutină.,Плановая проверка., +"All right, carry on.",TXT_RYES0_SCRIPT15_D0_ALLRI,,,,"Dobře, pokračujte.","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.",,"Muito bem, continue.",,"Bine, mergi mai departe.",Понятно. Продолжай., +"Nothing to report here. Everything is working fine. If anything goes wrong, I'll be sure to report it.",TXT_DLG_SCRIPT15_D1516_NOTHI,,,,"Tady nic k nahlášení není. Všechno funguje dobře. Pokud se něco pokazí, nahlásím to.","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.",,"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.","Тут не о чём докладывать. Всё работает превосходно. Если что-нибудь пойдёт не так, я обязательно доложу об этом.", -"Sir, there was a problem earlier, but it was taken care of.",TXT_DLG_SCRIPT15_D3032_SIRTH,,,,"Pane, předtím tu byl problém, ale vyřešili jsme jej.","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.",,"上官殿、以前より問題があったが、 +"Sir, there was a problem earlier, but it was taken care of.",TXT_DLG_SCRIPT15_D3032_SIRTH,,,,"Pane, předtím tu byl problém, ale vyřešili jsme jej.","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.",,"Senhor, havia um problema antes, mas já foi resolvido.",,"Domnule, a fost o problemă adineauri, dar s-a rezolvat.","Сэр, тут была одна неполадка, но её уже устранили.", -Move along or taste metal.,TXT_DLG_SCRIPT17_D0_MOVEA,,,,"Jdi dál, nebo okus ocel.",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.",,同行か鉄を味わうかだ。,탄창으로 맞고 싶지 않으면 움직여.,Ga verder of proef metaal.,,Vá embora ou vai tomar chumbo grosso.,,Mișcă-te sau mănânci metal.,"Прочь, или отведаешь металла.", -I.D. check.,TXT_DLG_SCRIPT17_D1516_IDCHE,,,,Doklady.,Ausweisüberprüfung.,,,Comprobación de identificación.,,Henkilöllisyystarkastus.,Vérification de carte d'identité.,Igazolvány ellenőrzés.,,I.D.チェックだ。,신분증 확인.,I.D. check.,,Verificação de identidade.,,Verificare card de identitate.,Ваши документы., -"Here, I'm in a hurry.",TXT_RPLY0_SCRIPT17_D1516_HEREI,,,,"Tady, spěchám.","Hier, ich hab's eilig.",,,"Ten, tengo prisa.",,"Tässä, minulla on kiire.","Voilà, je suis pressé.","Nesze, nem érek rá.",,ほら、急いでるんだ。,여기요. 급하니 빨리 확인해주세요.,Hier heb ik haast.,,"Pegue, estou com pressa.",,"Aici, mă grăbesc.",Вот. Я тороплюсь., -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ř.,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.,,目前まで近づけるな、さっさと行け。,얼굴 앞에서 신분증 그만 흔들고 얼른 들어가.,Stop met je ID in mijn gezicht te zwaaien en ga naar binnen.,,Pare de sacudir a sua identificação e entre logo.,,Nu mai flutura cardul în fața mea și intră.,Прекрати махать своей карточкой перед моим лицом и проходи., -Nothing to see here. Move along.,TXT_DLG_SCRIPT17_D4548_NOTHI,,,,Nic k vidění. Jdi dál.,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.,,何事も無い。進め。,아무 일도 안 일어났다. 어서 움직여.,Hier is niets te zien. Ga verder.,,Nada pra ver aqui. Vá embora.,,Nimic aici. Mișcă.,Тут не на что смотреть. Проваливай., -"What a healthy specimen. You don't need my help, do you?",TXT_DLG_SCRIPT17_D6064_WHATA,,,,"Jaký zdravý exemplář! Moji pomoc nepotřebuješ, že ne?","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?",,"なんて活きの良い標本だ。 +Move along or taste metal.,TXT_DLG_SCRIPT17_D0_MOVEA,,,,"Jdi dál, nebo okus ocel.",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.,,Vá embora ou vai tomar chumbo grosso.,,Mișcă-te sau mănânci metal.,"Прочь, или отведаешь металла.", +I.D. check.,TXT_DLG_SCRIPT17_D1516_IDCHE,,,,Doklady.,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.,,Verificação de identidade.,,Verificare card de identitate.,Ваши документы., +"Here, I'm in a hurry.",TXT_RPLY0_SCRIPT17_D1516_HEREI,,,,"Tady, spěchám.","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.,,"Pegue, estou com pressa.",,"Aici, mă grăbesc.",Вот. Я тороплюсь., +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ř.,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.,,Pare de sacudir a sua identificação e entre logo.,,Nu mai flutura cardul în fața mea și intră.,Прекрати махать своей карточкой перед моим лицом и проходи., +Nothing to see here. Move along.,TXT_DLG_SCRIPT17_D4548_NOTHI,,,,Nic k vidění. Jdi dál.,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.,,Nada pra ver aqui. Vá embora.,,Nimic aici. Mișcă.,Тут не на что смотреть. Проваливай., +"What a healthy specimen. You don't need my help, do you?",TXT_DLG_SCRIPT17_D6064_WHATA,,,,"Takový zdravý exemplář! Moji pomoc nepotřebujete, že ne?","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?",,"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?","Какой прекрасный образец. Тебе не нужна моя помощь, или нужна?", -"Well, yes. Macil sent me.",TXT_RPLY0_SCRIPT17_D6064_WELLY,,,,"No, jo. Poslal mě Macil.","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.",,そうだ。マシルの使者だ。,"뭐, 그렇지. 마실이 날 보냈으니까.","Nou, ja. Macil heeft me gestuurd.",,"Bem, sim. Macil me enviou.",,Ba da. Macil m-a trimis.,"Ну, нужна. Я от Мэйсила.", -"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 chtěl nás oba nechat popravit. Tak, co pro tebe můžu udělat?","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?",,"シーッ...静かに、 +"Well, yes. Macil sent me.",TXT_RPLY0_SCRIPT17_D6064_WELLY,,,,Potřebuju. Poslal mě Macil.,"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.",,"Bem, sim. Macil me enviou.",,Ba da. Macil m-a trimis.,"Ну, нужна. Я от Мэйсила.", +"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?","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?",,"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?","Тсс... Тише, если не хочешь, чтобы нас обоих убили. Итак, чем я могу тебе помочь?", -Tell me how to find the Bishop.,TXT_RPLY0_SCRIPT17_D7580_TELLM,,,,"Řekni mi, jak najít Biskupa.","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.",,ビショップは何処か聞きたい。,비숍을 어떻게 찾아야 하는지 알려줘.,Vertel me hoe ik de bisschop kan vinden.,,Diga onde eu encontro o Bispo.,,Spune-mi cum găsesc Episcopul.,"Скажи, как мне найти Епископа.", -"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ě.","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.",,"おおぅ、そういう事だろうと思った。 +Tell me how to find the Bishop.,TXT_RPLY0_SCRIPT17_D7580_TELLM,,,,"Řekni mi, jak najít Biskupa.","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.,,Diga onde eu encontro o Bispo.,,Spune-mi cum găsesc Episcopul.,"Скажи, как мне найти Епископа.", +"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ě.","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.","おおぅ、そういう事だろうと思った。 後ろを見ろ。そこがビショップの大聖堂だ。 しかし要人以外は入れないよう フォースフィールドが張ってある、 君には通れないな。","호오오, 난 네가 그걸 물어볼 줄 알았어. 뒤를 돌아봐. 저건 비숍의 성채로 향하는 입구야. 방어막으로 덮여있는데 저걸 끌 수 있는 건 허가된 방문자뿐이야. 네가 아니라.","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.",,"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.","А-а-а, я знал, что ты спросишь об этом. Оглянись: это вход в цитадель Епископа. Он защищён силовым полем, которое отключается только для официальных посетителей, не для тебя.", -I must kill the Bishop.,TXT_RPLY0_SCRIPT17_D9096_IMUST,,,,Musím zabít Biskupa.,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.,,ビショップを殺さなければならないんだ。,난 비숍을 죽여야만 해.,Ik moet de bisschop vermoorden.,,Preciso matar o Bispo.,,Trebuie să-l omor pe Episcop.,Я должен убить Епископа., -"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.","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.",,"ああ、だろうな。先にまず複合警備施設を +I must kill the Bishop.,TXT_RPLY0_SCRIPT17_D9096_IMUST,,,,Musím zabít Biskupa.,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.,,Preciso matar o Bispo.,,Trebuie să-l omor pe Episcop.,Я должен убить Епископа., +"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.","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.","ああ、だろうな。先にまず複合警備施設を 制圧してそこにあるテレポーターを使え。 君に合った方法だと思うが、テレポーター先の 中央管理部にあるコンピューターを潰せ。 コンピューターが無けれは、フォースも無しだ。 ","아, 그렇겠지. 먼저 보안단지에 들어가서 텔레포터를 이용해. 그리고 어쩌면 이건 네 취향일지도 모르겠군. 중앙 관리소에서 컴퓨터를 파괴해. 컴퓨터도 없애고, 방어막도 없애버리라고. \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.",,"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ță.","О, не сомневаюсь. Для начала проберись в охранный комплекс и используй телепорт. И, что тебе должно больше понравиться, уничтожь компьютер в центральной администрации. Нет компьютера — нет силового поля.", -"Great, that sounds easy.",TXT_RPLY0_SCRIPT17_D10612_GREAT,,,,"Super, to zní snadně.","Großartig, das klingt doch einfach.",,,"Genial, suena fácil.",,"Loistavaa, kuulostaa helpolta.","Bien, ça à l'air facile.","Remek, ez könnyűnek hangzik.",,そりゃいい、簡単そうだな。,"좋아, 쉬운 일인 것 같군.","Geweldig, dat klinkt gemakkelijk.",,Ótimo. Isso parece fácil.,,"Grozav, sună simplu.","Здорово. Легче сказать, чем сделать.", -"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!,"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!",,"コンピューターを潰す利点はな、 +"Great, that sounds easy.",TXT_RPLY0_SCRIPT17_D10612_GREAT,,,,"Super, to zní snadně.","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.",,Ótimo. Isso parece fácil.,,"Grozav, sună simplu.","Здорово. Легче сказать, чем сделать.", +"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!,"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!,"コンピューターを潰す利点はな、 奴等の塔へ送られる情報もそれに保管されている。 それを万引き、とも言えるな?へヘッ!","컴퓨터를 파괴할 승산이 있을거야, 성채로 향하는 계획서가 있는 곳이니까. 물건 좀 빼돌려 본 적 있나? 헤헷!","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!",,"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!","В уничтожении компьютера есть ещё один плюс: планы башни хранятся там. Можно сказать, скидка на все сто? Хе-хе!", -Anything else?,TXT_RPLY0_SCRIPT17_D12128_ANYTH,,,,Ještě něco dalšího?,Noch etwas?,,,¿Algo más?,,Onko jotain muuta?,Quoi d'autre?,Valami más még?,,他にあるか?,뭐 다른건 없나?,Nog iets anders?,,Mais alguma coisa?,,Altceva?,Что-нибудь ещё?, -"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.","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.",,"そうだな、中庭の倉庫にマウラーが納品されたと +Anything else?,TXT_RPLY0_SCRIPT17_D12128_ANYTH,,,,Ještě něco dalšího?,Noch etwas?,,,¿Algo más?,,Onko jotain muuta?,Quoi d'autre?,Valami más még?,C'è dell'altro?,他にあるか?,뭐 다른건 없나?,Nog iets anders?,,Mais alguma coisa?,,Altceva?,Что-нибудь ещё?, +"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.","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.","そうだな、中庭の倉庫にマウラーが納品されたと 聞いた。その威力は相手を消滅させられる程だと。","음, 듣자 하니 성안 쪽 격납고에 마울러가 입고되었다더군. 뭐든지 날려버리는 무기 말이야. \cy흠. 이유 없이 그런 소문이 났을 리는 없을 테고... 나도 그 무기 하나만 가져다줘.","Nou ja, er wordt gezegd dat het magazijn van de bailey een zending maulers heeft ontvangen, dat is het wapen dat verdampt.",,"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ă.","Скажем так: есть слух, что склад крепости получил партию Истязателей: оружия, которое «испепеляет».", -"Is that it, now?",TXT_RPLY0_SCRIPT17_D13644_ISTHA,,,,Je to už všechno?,War es das jetzt?,,,"Con que eso es, ¿eh?",,Ja onko siinä nyt kaikki?,Vraiment?,Mi van már megint?,,それはまだあるんだな?,이게 전부지?,"Is dat het, nu?",,Só isso?,,"Asta e, deci?",Теперь всё?, -"Don't you know the meaning of the words ""get lost""?",TXT_DLG_SCRIPT17_D15160_DONTY,,,,Neznáš význam slova „zmizni“?,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?",,次の話はバレる前に'去れ'か?,"자네, “꺼져.”가 무슨 뜻인지는 알지?","Weet je niet wat de betekenis is van de woorden ""verdwalen""?",,"Você não sabe o que significa a expressão ""se manda""?",,"Nu cunoști semnificația cuvântului ""dispari""?",Ты не знаешь значения слова «исчезни»?, -Talk to Quincy first. I'm not allowed to help anyone unless he says it's ok.,TXT_DLG_SCRIPT17_D16676_TALKT,,,,Promluv si nejprve s Quincym. Já nemůžu nikomu pomáhat dokud to nepovolí.,"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 nacie a menos que 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.",,"先にクインシーと話を。彼から許可を +"Is that it, now?",TXT_RPLY0_SCRIPT17_D13644_ISTHA,,,,Je to už všechno?,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?",,Só isso?,,"Asta e, deci?",Теперь всё?, +"Don't you know the meaning of the words ""get lost""?",TXT_DLG_SCRIPT17_D15160_DONTY,,,,Neznáš význam slova „zmizni“?,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""?",,"Você não sabe o que significa a expressão ""se manda""?",,"Nu cunoști semnificația cuvântului ""dispari""?",Ты не знаешь значения слова «исчезни»?, +Talk to Quincy first. I'm not allowed to help anyone unless he says it's ok.,TXT_DLG_SCRIPT17_D16676_TALKT,,,,Promluvte si nejprve s Quincym. Já nemůžu nikomu pomáhat dokud to nepovolí.,"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 nacie a menos que 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.",,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ă.,"Сперва поговори с Куинси. Мне не позволено помогать кому-либо, пока он не разрешит.", -How how can I help you today?,TXT_DLG_SCRIPT17_D18192_HOWHO,,,,Jak ti mohu dnes pomoci?,Wie kann ich dir heute helfen?,,,¿Cómo puedo ayudarte hoy?,,Miten voin olla avuksi tänään?,Comment puis-je vous aider aujourd'hui?,Ma miben segíthetek?,,本日は何かお困りで?,오늘은 어떻게 도와드릴까요?,Hoe kan ik je vandaag helpen?,,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем могу быть полезен?, -Med patch,TXT_RPLY0_SCRIPT17_D18192_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekäärettä.,Pansement.,Ragtapasz,,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Trusă de prim-ajutor.,Бинтами, -Here's your patch.,TXT_RYES0_SCRIPT17_D18192_HERES,,,,Tady jsou.,Hier ist deine Bandage.,,,Aquí tienes tu parche.,,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,,これをどうぞ。,"의료 붕대 하나, 여기 있습니다.",Hier is je patch.,,Aqui está sua compressa.,,Aici e trusa.,Вот твой набор бинтов., -That is 15 gold my friend.,TXT_RNO0_SCRIPT17_D18192_THATI,,,,"To je patnáct zlatých, příteli.","Das macht 15 Gold, mein Freund.",,,"Son 15 de oro, amigo mío.",,"Se saisi olla 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",Az bizony 15 arany lesz barátom.,,15 ゴールド必要です。,"그건 15 골드입니다, 친구.","Dat is 15 goud, mijn vriend.",,"Custa 15 moedas de ouro, meu amigo.",,Costă 15 monezi amice.,"Они стоят 15 золотых, друг.", -Medical kit,TXT_RPLY1_SCRIPT17_D18192_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit médico,,Lääkintälaukku.,Kit médical.,Elsősegély doboz.,,医療用キット,구급 키트,Medische kit,,Kit médico,,Kit de prim-ajutor.,Аптечкой, -Here's your medical kit.,TXT_RYES1_SCRIPT17_D18192_HERES,,,,Tady je.,Hier ist dein Verbandskasten,,,Aquí tienes tu kit médico.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegélydobozod.,,こちらが 医療用キットです。,구급 키트입니다. 잘 쓰시길.,Hier is je medische uitrusting.,,Aqui está o seu kit médico,,Aici e kitul.,Вот твоя аптечка., -You're a bit low on funds for that.,TXT_RNO1_SCRIPT17_D18192_YOURE,,,,Tu si nemůžeš dovolit.,Du hast zu wenig Geld dafür.,,,Estás un poco bajo de efectivo para eso.,,Sinulla on varat hieman vähissä siihen.,Vous manquez d'argent pour ça.,Nincs elég pénzed ehhez.,,その為の資金が少し足りません。,그거 사기엔 자금이 부족한 듯.,Je hebt daar een beetje weinig geld voor.,,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств., -Field surgery kit,TXT_RPLY2_SCRIPT17_D18192_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku.,Kit de chirurgie.,Harctéri műtéti felszerelés,,手術キット,수술 키트.,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом, -"One field surgery kit, done.",TXT_RYES2_SCRIPT17_D18192_ONEFI,,,,"Jedna souprava, zde.","Eine Erste-Hilfe-Kasten, kommt sofort.",,,"Un kit quirúrgico, hecho.",,"Yksi kirurgilaukku, noin.","Un kit de chirurgie, voilà.",Egy műtő felszerelés itt is van.,,野外用手術キット一丁。,수술 키트 하나 여기있습니다.,"Eén veldoperatiekit, klaar.",,Um kit de cirurgia saindo,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи., -Come back when you have money!,TXT_RNO2_SCRIPT17_D18192_COMEB,,,,"Vrať se, až budeš mít peníze!","Komm wieder, wenn du etwas Geld hast.",,,¡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.",,余裕がある時にまたどうぞ!,돈이 좀 있을 때 돌아와요!,Kom terug als je geld hebt!,,Volte quando tiver dinheiro!,,Întoarce-te când ai destui bani!,Возвращайся с деньгами!, -What is it?,TXT_DLG_SCRIPT18_D0_WHATI,,,,Co je?,Was gibt es?,,Kio estas ĝi?,¿Qué pasa?,,Mikä on?,Vous voulez quoi?,Az meg mi?,,何事だ?,무슨 일이냐?,Wat is het?,,O que foi?,,Ce e?,Что тебе нужно?, -Just looking around.,TXT_RPLY0_SCRIPT18_D0_JUSTL,,,,Jen se poohlížím.,Ich schaue mich bloß um.,,,Solo estoy mirando.,,Ihan vain katselen.,Je fais juste un tour.,Csak nézelődök.,,見周りしている。,그냥 둘러보는 중이었습니다.,Gewoon rondkijken.,,Só dando uma olhada.,,Doar mă uit împrejur.,Просто осматриваюсь., -Just keep out of the way.,TXT_RYES0_SCRIPT18_D0_JUSTK,,,,Prostě se drž z cesty.,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.,,この先は立入禁止だ。,그럼 방해하지마.,Blijf gewoon uit de weg.,,Apenas fique fora do caminho.,,Doar nu sta în cale.,Просто не путайся под ногами., -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 vyzvednou si své nové trhače. Jestli se jim připleteš pod nohy, jsi mrtvý.","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.",,"新しいマウラーズを得たテンプル騎士団が +How how can I help you today?,TXT_DLG_SCRIPT17_D18192_HOWHO,,,,Jak vám mohu dnes pomoci?,Wie kann ich dir heute helfen?,,,¿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?,,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем могу быть полезен?, +Med patch,TXT_RPLY0_SCRIPT17_D18192_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekäärettä.,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Trusă de prim-ajutor.,Бинтами, +Here's your patch.,TXT_RYES0_SCRIPT17_D18192_HERES,,,,Tady jsou.,Hier ist deine Bandage.,,,Aquí tienes tu parche.,,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,"의료 붕대 하나, 여기 있습니다.",Hier is je patch.,,Aqui está sua compressa.,,Aici e trusa.,Вот твой набор бинтов., +That is 15 gold my friend.,TXT_RNO0_SCRIPT17_D18192_THATI,,,,"To je patnáct zlatých, příteli.","Das macht 15 Gold, mein Freund.",,,"Son 15 de oro, amigo mío.",,"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.",,"Custa 15 moedas de ouro, meu amigo.",,Costă 15 monezi amice.,"Они стоят 15 золотых, друг.", +Medical kit,TXT_RPLY1_SCRIPT17_D18192_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit médico,,Lääkintälaukku.,Kit médical.,Elsősegély doboz.,Kit medico,医療用キット,구급 키트,Medische kit,,Kit médico,,Kit de prim-ajutor.,Аптечкой, +Here's your medical kit.,TXT_RYES1_SCRIPT17_D18192_HERES,,,,Tady je.,Hier ist dein Verbandskasten,,,Aquí tienes tu kit médico.,,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.,,Aqui está o seu kit médico,,Aici e kitul.,Вот твоя аптечка., +You're a bit low on funds for that.,TXT_RNO1_SCRIPT17_D18192_YOURE,,,,Tu si nemůžete dovolit.,Du hast zu wenig Geld dafür.,,,Estás un poco bajo de efectivo para eso.,,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.,,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств., +Field surgery kit,TXT_RPLY2_SCRIPT17_D18192_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku.,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트.,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом, +"One field surgery kit, done.",TXT_RYES2_SCRIPT17_D18192_ONEFI,,,,"Jedna souprava, zde.","Eine Erste-Hilfe-Kasten, kommt sofort.",,,"Un kit quirúrgico, hecho.",,"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.",,Um kit de cirurgia saindo,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи., +Come back when you have money!,TXT_RNO2_SCRIPT17_D18192_COMEB,,,,"Vrať se, až budeš mít peníze!","Komm wieder, wenn du etwas Geld hast.",,,¡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!,,Volte quando tiver dinheiro!,,Întoarce-te când ai destui bani!,Возвращайся с деньгами!, +What is it?,TXT_DLG_SCRIPT18_D0_WHATI,,,,Co je?,Was gibt es?,,Kio estas ĝi?,¿Qué pasa?,,Mikä on?,Vous voulez quoi?,Az meg mi?,Che cos'è?,何事だ?,무슨 일이냐?,Wat is het?,,O que foi?,,Ce e?,Что тебе нужно?, +Just looking around.,TXT_RPLY0_SCRIPT18_D0_JUSTL,,,,Jen se poohlížím.,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.,,Só dando uma olhada.,,Doar mă uit împrejur.,Просто осматриваюсь., +Just keep out of the way.,TXT_RYES0_SCRIPT18_D0_JUSTK,,,,Prostě se drž z cesty.,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.,,Apenas fique fora do caminho.,,Doar nu sta în cale.,Просто не путайся под ногами., +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ý.","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.,"新しいマウラーズを得たテンプル騎士団が すぐにでもここに来る。長生きしたければ 邪魔をしようと思わない方がいい。",템플러가 곧 새 마울러를 가지러 올 거야. 그들을 방해하면 넌 죽은 목숨이야.,"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.",,"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.,"Храмовники скоро придут сюда забрать свои новые истязатели. Если попадёшься им на пути, станешь покойником.", -Maulers?,TXT_RPLY0_SCRIPT18_D1516_MAULE,,,,Trhače?,Vernichter?,,,¿Trituradores?,,Moukarit?,Des broyeurs?,Kézi fegyver?,,マウラーズ?,마울러?,Maulers?,,Desintegradores?,,Schiloditoare?,Истязатели?, -The Templar's favorite weapon.,TXT_RYES0_SCRIPT18_D1516_THETE,,,The templar's favourite weapon.,Oblíbená zbraň templářů.,Die Lieblingswaffe der Templer.,,,El arma favorita de los templarios.,,Temppeliherrojen lempiase.,L'arme favorite du templier.,A keresztesek kedvenc fegyvere.,,騎士団に人気の兵器だ。,템플러가 제일 좋아하는 무기야.,Het favoriete wapen van de Tempeliers.,,A arma favorita dos Templários.,,Arma preferată a Templierilor.,Их любимое оружие., -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,,,,"Přišly sem už předtím, 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ě.","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.",,"以前所属したばかりだ。 +Maulers?,TXT_RPLY0_SCRIPT18_D1516_MAULE,,,,Trhače?,Vernichter?,,,¿Trituradores?,,Moukarit?,Des broyeurs?,Kézi fegyver?,Mauler?,マウラーズ?,마울러?,Maulers?,,Desintegradores?,,Schiloditoare?,Истязатели?, +The Templar's favorite weapon.,TXT_RYES0_SCRIPT18_D1516_THETE,,,The templar's favourite weapon.,Oblíbená zbraň templářů.,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.,,A arma favorita dos Templários.,,Arma preferată a Templierilor.,Их любимое оружие., +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ě.","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.,"以前所属したばかりだ。 彼等は全て警備に周るだろう。 門を閉める時に見る機会があったからな。 残りの小隊が兵器を請求するまで 誰も入れる事はできない。","최신 에너지 무기지. 이 무기를 보호하기 위해서 경비가 아주 삼엄하다고. 다만 시간 날 때 맨눈으로 보기는 했지만. 모든 템플러 분대가 이것들을 집어가기 전까지는 그 누구도 절대로 만질 수도, 볼 수도 없어.",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.,,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.,"Его привезли раньше, поэтому здесь столько охраны. Я заглянул в хранилище, когда запирал его. Пока весь отряд храмовников не получит своё оружие, никому не позволено входить или выходить.", -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.,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.,,,,이곳은 중앙 관리소에 전술이나 계획을 보고하기 위한 곳이야.,Hier krijg je de plannen voor de centrale administratie.,,É aqui onde você pega os planos da administração central.,,De aici vei lua schemele pentru camera de administrare centrală.,Здесь ты добудешь схему центральной администрации., -"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.","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.",,"私がこの場所の主任者だ。 +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.,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.,,É aqui onde você pega os planos da administração central.,,De aici vei lua schemele pentru camera de administrare centrală.,Здесь ты добудешь схему центральной администрации., +"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.","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.","私がこの場所の主任者だ。 私の仕事は、ロアマスターのロボットの デザインに必要な原料パーツを生産することだ。 もしあなたが公用で来たのではないのなら、 申し訳ないが話すための時間はないのだ。","난 이곳의 책임자야. 로어마스터님의 로봇 설계를 돕기 위해 일하고 있지. 만약 공식 업무 외에 온 거라면, 바쁘니까 돌아가 줘야 되겠는걸?","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.",,"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ă.","Я здесь главный. Моя работа — изготавливать детали роботов для Хранителя мудрости. Если ты здесь не по служебным делам, то, боюсь, мне некогда с тобой болтать.", -I am on official business.,TXT_RPLY0_SCRIPT22_D0_IAMON,,,,Jsem tu kvůli oficiálním záležitostem.,Ich bin dienstlich hier.,,,Estoy por asuntos oficiales.,,Olen virallisilla asioilla.,Je suis en visite officielle.,Hivatalos ügyben jöttem.,,私は公用で来た。,공식 업무로 왔어.,Ik ben voor officiële zaken.,,Estou aqui para tratar de assuntos oficiais.,,Sunt cu treburi oficiale.,Я по служебным делам., -"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.","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.",,"ということは、ティモシーと話したのだな。 +I am on official business.,TXT_RPLY0_SCRIPT22_D0_IAMON,,,,Jsem tu kvůli oficiálním záležitostem.,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.,,Estou aqui para tratar de assuntos oficiais.,,Sunt cu treburi oficiale.,Я по служебным делам., +"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.","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.,"ということは、ティモシーと話したのだな。 彼と私は、取り返しのつかない事態に陥る前に オーダーの秘密を解き明かすために 一緒に働いてきた。もしかすると、 君は私達に手を貸せるかもしれない。 私は今、生産セクターへの扉を開いたぞ。","티모시와 이야기를 나눴구나, 그렇지? 티모시랑 같이 한발 늦기 전에 오더의 비밀을 파헤치려고 열심히 노력했지. 아마도 우리들을 도와줄 수 있을 것 같은데 말이야. 방금 제조 공간의 문을 열어놨어.","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.",,"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.","Итак, ты уже поговорил с Тимоти. Мы с ним вместе пытаемся раскрыть тайны Ордена, пока не стало слишком поздно. Возможно, ты сможешь нам помочь. Я открыл дверь в производственный сектор.", -Do you know what's inside?,TXT_RPLY0_SCRIPT22_D1516_DOYOU,,,,"Víš, co je uvnitř?",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?,,中に何があるのかを知っているのか?,그 안에 무엇이 있는지 아나?,Weet je wat er in zit?,,Você sabe o que tem lá dentro?,,Știi cumva ce e înăuntru?,"Ты знаешь, что там?", -"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.","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.",,"あの場所は極秘エリアだ。 +Do you know what's inside?,TXT_RPLY0_SCRIPT22_D1516_DOYOU,,,,"Víš, co je uvnitř?",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?,,Você sabe o que tem lá dentro?,,Știi cumva ce e înăuntru?,"Ты знаешь, что там?", +"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.","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.","あの場所は極秘エリアだ。 オーダーはある種の生物のようなものを そこで繁殖させているし、それだけではなく 私はタリスマンと呼ばれる奇妙な @@ -9581,389 +9577,389 @@ Do you know what's inside?,TXT_RPLY0_SCRIPT22_D1516_DOYOU,,,,"Víš, co je uvnit 誰もそれには近づくことが許されていないのだ。 噂では、タリスマンはほかの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.",,"É 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.","Это совершенно секретно. Во-первых, Орден разводит там каких-то... существ. Во-вторых, я своими глазами видел странный артефакт — «Талисман». К нему никого и близко не подпускают. Говорят, если объединить его с двумя другими, можно получить огромную силу.", -I suppose you want this thing?,TXT_RPLY0_SCRIPT22_D3032_ISUPP,,,,"Předpokládám, že jej chceš?","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.,,それが欲しいということか?,내 생각엔 그걸 원하나 보지?,Ik neem aan dat je dit ding wilt?,,Imagino que você quer essa coisa?,,Presupun că vrei chestia asta?,"Похоже, ты и сам хочешь этот артефакт?", -"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...","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...",,"そうではない!もし見つけたら +I suppose you want this thing?,TXT_RPLY0_SCRIPT22_D3032_ISUPP,,,,"Předpokládám, že jej chceš?","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?,,Imagino que você quer essa coisa?,,Presupun că vrei chestia asta?,"Похоже, ты и сам хочешь этот артефакт?", +"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...","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...","そうではない!もし見つけたら それは自分のものにしてくれ。もしかすれば、 それを私達をオーダーから解放するために 使えるかもしれない。幸運を祈ってはいるが、 もしあの場所に行こうとしているなら、 もっと多くの力が必要となるぞ...","아니야! 만약 네가 가질 수만 있다면, 그건 네 거야. 아마도 우리들을 탄압으로부터 구해줄 수 있겠네. 부디 행운을 빌어. 왜냐하면 많은 걸 준비 한 뒤 각오하고 들어가야 하거든.","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....",,"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...","Нет! Если ты его найдёшь, он твой. Может быть, он поможет тебе освободить нас от гнёта. Я бы пожелал тебе удачи, но, если ты пойдёшь туда, простой удачи будет недостаточно...", -What's all this about the past?,TXT_RPLY0_SCRIPT22_D4548_WHATS,,,,Cos to říkal o minulosti?,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?,,過去に何があったというんだ?,그 과거에 대해서 뭐가 어떻길레?,Wat is dit alles over het verleden?,,Que história é essa sobre o passado?,,Care e treaba cu trecutul ăsta?,Что такого творилось здесь в прошлом?, -"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, pochází z tohoto světa, velmi dávno.","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.",,"君はこの周りの廃墟群を見てきたはずだ。 +What's all this about the past?,TXT_RPLY0_SCRIPT22_D4548_WHATS,,,,Cos to říkal o minulosti?,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?,,Que história é essa sobre o passado?,,Care e treaba cu trecutul ăsta?,Что такого творилось здесь в прошлом?, +"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, pochází z tohoto světa, velmi dávno.","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.","君はこの周りの廃墟群を見てきたはずだ。 この星に衝突した彗星は、実は宇宙船だったのだ 信じられないかもしれないが、 それは遥か前のこの乱世の始まりとも言える。","주변을 돌아다니면서 각종 폐허를 봤을 거야. 믿기지는 않겠지만, 하늘에서 갑자기 추락한 혜성은 정말로 혜성이 아니라 외계인들이 타고 내려온 우주선이라는 거야. 그리고 더 놀라운 사실은, 이 녀석들은 다 이곳에서 태어났데.","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.",,"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.","Скорее всего, ты уже видел эти руины. Тот метеорит, который упал на нашу планету, — на самом деле это космический корабль. Веришь или нет, его построили на этой самой планете, давным-давно.", -"So the spectres, the One God...",TXT_RPLY0_SCRIPT22_D6064_SOTHE,,,,"Takže přízraky, Jeden bůh...","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...",,だから霊の、唯一神...,그래서 그 스펙터들과 유일신이...,"Dus de schrikbeelden, de Ene God....",,"Então os espectros, o Deus Único...",,"Deci spectrele, Adevăratul Zeu...",Так фантомы и Единый Бог..., -"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.","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.",,"奴等はかつてこの世界を支配していた生物で +"So the spectres, the One God...",TXT_RPLY0_SCRIPT22_D6064_SOTHE,,,,"Takže přízraky, Jeden bůh...","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....",,"Então os espectros, o Deus Único...",,"Deci spectrele, Adevăratul Zeu...",Так фантомы и Единый Бог..., +"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.","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.","奴等はかつてこの世界を支配していた生物で 生命力をひたすら吸収する存在だった。 古代人が辛うじて封印したが、 その過程で彼らの命は奪われた。 私が知っているのはそれだけだ。","한때 이 생물들은 이 세상을 지배했던 존재였어. 초월한 힘을 계속 유지하기 위해 온갖 생명력을 빨아먹어 왔던 거지. 태초의 사람들이 어떻게든 이 들을 봉인하긴 했지만, 많은 희생이 뒤따라야만 했지... 이게 내가 알고 있는 전부야.","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.",,"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.","Эти существа когда-то правили этим миром и стремились выжать из него все соки. Древние смогли запечатать и изгнать их, пожертвовав своими жизнями. Больше, боюсь, я ничего не знаю.", -Thanks... I'll do what I can.,TXT_RPLY0_SCRIPT22_D7580_THANK,,,,"Díky... Uvidím, co budu moct.",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.,,ありがとう...精一杯の事をしよう。,고... 고마워. 내가 할 수 있는 것을 찾아보지.,Bedankt... Ik zal doen wat ik kan.,,Obrigado... Farei o possível.,,Merci... O să fac ce pot.,"Спасибо... Я сделаю всё, что смогу.", -"Godspeed, friend.",TXT_DLG_SCRIPT22_D9096_GODSP,,,,"Zlom vaz, příteli.","Viel Erfolg, Freund.",,,"Buena suerte, amigo.",,"Onnea matkaan, ystävä.","Bonne chance, mon ami.","Isten veled, barátom.",,急ぎたまえ、同志よ。,"행운을 비네, 친구.","Goeie reis, vriend.",,"Boa sorte, amigo.",,"Noroc, prietene.","Удачи, друг.", -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 kovářem, jestli se chceš na něco zeptat. Já jenom dávám štítky na krabice.","Sprich mit dem Meister Smithy, wenn du Fragen hast. Ich versehe die Kisten nur mit Etiketten.",,,Habla con el maestro herrero si tienes preguntas. Todo lo que hago yo es etiquetar las cajas.,,"Puhu pajamestarin kanssa, jos sinulla on kysyttävää. Minä vain leimaan laatikoita.","Parlez au maître forgeron 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.,,"相談がある場合は鍛冶屋のマスターに仰って +Thanks... I'll do what I can.,TXT_RPLY0_SCRIPT22_D7580_THANK,,,,"Díky... Uvidím, co budu moct.",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.,,Obrigado... Farei o possível.,,Merci... O să fac ce pot.,"Спасибо... Я сделаю всё, что смогу.", +"Godspeed, friend.",TXT_DLG_SCRIPT22_D9096_GODSP,,,,"Zlom vaz, příteli.","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.",,"Boa sorte, amigo.",,"Noroc, prietene.","Удачи, друг.", +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 kovářem, jestli se chceš na něco zeptat. Já jenom dávám štítky na krabice.","Sprich mit dem Meister Smithy, wenn du Fragen hast. Ich versehe die Kisten nur mit Etiketten.",,,Habla con el maestro herrero si tienes preguntas. Todo lo que hago yo es etiquetar las cajas.,,"Puhu pajamestarin kanssa, jos sinulla on kysyttävää. Minä vain leimaan laatikoita.","Parlez au maître forgeron 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 de meestersmidij als je vragen hebt. Het enige wat ik doe is etiketten op de kratten plakken.,,Fale com o ferreiro-mestre se tiver dúvidas. Tudo o que eu faço aqui é colocar etiquetas nas caixas.,,Vorbește cu maestrul făurar dacă ai întrebări. Tot ce fac eu e să pun embleme pe cutii.,"Если у тебя есть какие-то вопросы, обратись к мастеру. Я просто подписываю ящики.", -"What can I get you, citizen?",TXT_DLG_SCRIPT23_D0_WHATC,,,,"Co ti mohu nabídnout, občane?","Was darf es sein, Bürger?",,,"¿Qué puedo ofrecerte, ciudadano?",,"Mitä saisi olla, asukas?","Qu'est-ce que je peux faire pour vous, citoyen?","Miben segíthetek, polgártárs?",,何が入り用だ、お客さん?,"무엇을 줄까요, 형씨?","Wat kan ik voor je halen, burger?",,"Como posso ajudá-lo, cidadão?",,"Ce pot să-ți aduc, cetățeanule?","Что я могу тебе предложить, гражданин?", -Ammo box,TXT_RPLY0_SCRIPT23_D0_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de municiones,,Ammuslaatikko,Boîte de munitions.,Lőszer doboz,,銃弾倉,돌격소총 탄약 박스,Munitiedoos,,Caixa de munição,,Cutie cu muniție,Коробку патронов, -Here's your ammo.,TXT_RYES0_SCRIPT23_D0_HERES,,,,Tady je.,Hier ist deine Munition.,,,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,,これでソチラのブツだ。,탄약을 구매해줘서 고마워요.,Hier is je munitie.,,Aqui está a sua munição.,,Aici e muniția.,Вот твои патроны., -You don't have enough for that!,TXT_RNO0_SCRIPT23_D0_YOUDO,,,,Na tu nemáš dost peněz!,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!,,そんだけの金持ってないぞ!,가격에 맞게 돈을 가져오세요!,Daar heb je niet genoeg voor!,,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег!, -Crate of missiles,TXT_RPLY1_SCRIPT23_D0_CRATE,,,,Bednu raket,Raketenkiste,,,Caja de misiles,,Ohjuslaatikko,Caisse de missiles.,Ládányi rakéta,,ミサイル箱,미니 미사일 박스,Krat van raketten,,Caixa de mísseis,,Cutie de rachete.,Коробку ракет, -"Here, citizen.",TXT_RYES1_SCRIPT23_D0_HEREC,,,,"Tady, občane.","Hier, Bürger.",,,"Toma, ciudadano.",,"Tässä, asukas.","Voilà, citoyen.","Parancsolj, polgártárs.",,どうぞ、お客さん。,여기 있습니다.,"Hier, burger.",,"Aqui, cidadão.",,"Aici, orășene.","Вот, гражданин.", -"It's 85 gold, citizen!",TXT_RNO1_SCRIPT23_D0_ITS85,,,,"Ta stojí 85 zlatých, občane!","Das macht 85 Gold, Bürger!",,,"¡Son 85 de oro, ciudadano!",,"Se maksaa 85 kolikkoa, asukas!","Cela coûte 85 pièces, citoyen!","85 arany lesz, polgártárs.",,85ゴールドだぜ、お客さん!,그건 85골드입니다.,"Het is 85 goud, burger!",,"Custa 85 moedas de ouro, cidadão!",,"E 85 de monezi, orășene!","Гражданин, это стоит 85 золотых!", -H-E grenades,TXT_RPLY2_SCRIPT23_D0_HEGRE,,,,Výbušné granáty,HE-Granaten,,,Granadas HE,,Räjähdekranaatteja,Grenades explosives.,Robbanó gránátok,,HEグレネード,고폭 유탄,H-E-granaten,,Granadas explosivas,,Grenade.,Осколочные гранаты, -Here are your grenades.,TXT_RYES2_SCRIPT23_D0_HEREA,,,,Tady jsou.,Hier sind deine Granaten.,,,Aquí tienes tus granadas.,,Tässä kranaattisi.,Voilà vos grenades.,Itt vannak a gránátaid.,,これでソチラのブツだ。,여기 유탄입니다.,Hier zijn je granaten.,,Aqui estão as suas granadas,,Aici sunt grenadele.,Забирай свои гранаты., -"They are 100 gold, friend.",TXT_RNO2_SCRIPT23_D0_THEYA,,,,"Ty stojí sto zlatých, příteli.","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.,,100ゴールドだぜ、旦那!,"그건 100 골드야, 친구.","Ze zijn 100 goud, vriend.",,"Custam 100 moedas, amigo.",,"Costă 100 de monezi, prietene.","Они по 100 золотых, друг.", -Energy pod,TXT_RPLY3_SCRIPT23_D0_ENERG,,,,Energetický kokón,Energiezelle.,,,Vaina de energía,,Energia-akku,Cellule énergetique.,Energia cella,,エネルギーポッド,에너지 포드,Energiecapsule,,Célula de energia.,,Capsulă energetică.,Энергоячейку, -Here you are.,TXT_RYES3_SCRIPT23_D0_HEREY,,,,Tady je.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,,どうぞ。,여기 있습니다.,Hier ben je dan.,,Aqui está.,,Aici este.,Получай., -"That's 135 gold, sorry.",TXT_RNO3_SCRIPT23_D0_THATS,,,,"Ten stojí 135 zlatých, je mi líto.","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.",,135ゴールドなんだ、ワリィ!,"미안하지만, 그건 135 골드입니다.","Dat is 135 goud, sorry.",,Custa 135 moedas. Sinto muito.,,"Costă 135 de monezi, scuze.",Она стоит 135 золотых. Извини., -What can I assist you with?,TXT_DLG_SCRIPT23_D1516_WHATC,,,,S čím ti mohu pomoci?,Wie kann ich dir behilflich sein?,,,¿Con qué puedo ayudarte?,,Miten voin auttaa?,Commen puis-je vous assister?,Miben segíthetek?,,何か手伝いましょうか?,어떤 걸 도와드릴까요?,Waarmee kan ik je helpen?,,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем я могу тебе помочь?, -Leather armor,TXT_RPLY0_SCRIPT23_D1516_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro,,Armură de piele,Кожаной бронёй, -Here it is citizen.,TXT_RYES0_SCRIPT23_D1516_HEREI,,,,"Tady je, občane.","Hier ist sie, Bürger.",,"Jen ĝi, civitano.","Aquí está, ciudadano.",,"Tässä on, asukas.","Voilà pour vous, citoyen.",Parancsolj.,,どうぞ、お客さん。,"여기 있어요, 형씨.",Hier is het een burger.,,"Aqui está, cidadão.",,Aici e orășene.,"Вот она, гражданин.", -There's no charity given here!,TXT_RNO0_SCRIPT23_D1516_THERE,,,,Nejsme charita!,Hier gibt es nichts umsonst!,,,¡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.",,これはチャリティーじゃない!,돈이 부족하면 다른 곳을 알아봐! 여긴 자선단체가 아니라고!,Er wordt hier geen liefdadigheid gegeven!,,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!, -Metal armor,TXT_RPLY1_SCRIPT23_D1516_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлической бронёй, -An excellent choice citizen.,TXT_RYES1_SCRIPT23_D1516_ANEXC,,,,"Výborná volba, občane.","Eine exzellente Wahl, Bürger.",,,"Excelente elección, ciudadano.",,"Erinomainen valinta, asukas.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,,良い選択です。,"탁월한 선택이십니다, 형씨.","Een uitstekende keuze, burger.",,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.", -You don't have enough for this!,TXT_RNO1_SCRIPT23_D1516_YOUDO,,,,Na to nemáš dost peněz!,Du hast nich genug Gold dafür!,,,¡No tienes suficiente para esto!,,Rahasi ei riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,,これでは足りない!,이것을 구입하기엔 돈이 부족합니다!,Je hebt hier niet genoeg voor!,,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!, -Environmental suit,TXT_RPLY2_SCRIPT23_D1516_ENVIR,,,,Ochranný oděv,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védőruha,,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитным костюмом, -Here you are.,TXT_RYES2_SCRIPT23_D1516_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Kas tässä.,Voilà pour vous.,"Itt van, parancsolj.",,どうぞ。,여기 있습니다.,Hier ben je dan.,,Aqui está.,,Aici este.,Держи., -"No money, no suit.",TXT_RNO2_SCRIPT23_D1516_NOMON,,,,Bez peněz pro oděvy nelez.,"Kein Geld, kein Anzug.",,,Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.",,金が無いならスーツは無しだ。,돈이 없다면 방호복을 줄 수 없습니다.,"Geen geld, geen pak.",,"Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.", -Something different?,TXT_RPLY3_SCRIPT23_D1516_SOMET,,,,Něco jiného?,Irgendetwas anderes?,,,¿Algo distinto?,,Jotain erilaista?,Quelque chose d'autre?,Valami mást esetleg?,,何か別のやつは?,뭔가 다른 거는?,Iets anders?,,Algo diferente?,,Ceva diferit?,Что-нибудь ещё?, -Go through the door down the hall.,TXT_RYES3_SCRIPT23_D1516_GOTHR,,,,Projdi dveřmi dole na chodbě.,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.,,ホールのドアを通るんだ。,복도를 따라 문을 향해 가보세요.,Ga door de deur aan het einde van de gang.,,Passe pela porta lá no salão.,,Intră pe ușa din josul holului.,"Дальше по коридору, за дверью.", -You must pay if you want to play.,TXT_RNO3_SCRIPT23_D1516_YOUMU,,,,"Musíš zaplatit, jestli si chceš hrát.","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.,,プレイするなら支払うべきだ。,할려면 돈을 먼저 주세요.,Je moet betalen als je wilt spelen.,,Você precisa pagar se quiser jogar.,,Trebuie să plătești dacă vrei să joci.,"Любишь играть, люби и платить!", -What can I get you?,TXT_DLG_SCRIPT23_D3032_WHATC,,,,Co ti mohu nabídnout?,Was darf es sein?,,,¿Qué puedo ofrecerte?,,Mitä teille saisi olla?,Que puis-je pour vous?,Mit adhatok?,,何をお求めで?,무엇을 드릴까요?,Wat kan ik voor je halen?,,O que gostaria?,,Ce pot să-ți aduc?,Что я могу тебе предложить?, -Leather armor,TXT_RPLY0_SCRIPT23_D3032_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro,,Armură de piele,Кожаную броню, -"Here it is, citizen.",TXT_RYES0_SCRIPT23_D3032_HEREI,,,,"Tady je, občane.","Hier ist sie, Bürger.",,"Jen ĝi, civitano.","Aquí está, ciudadano.",,"Tästä saat, asukas.","Voilà pour vous, citoyen.","Parancsolj, polgártárs.",,どうぞ、お客さん。,"적절히 입으세요, 시민.","Hier is het, burger.",,"Aqui está, cidadão.",,"Aici este, orășene.","Вот она, гражданин.", -There's no charity given here!,TXT_RNO0_SCRIPT23_D3032_THERE,,,,Nejsme charita!,Hier gibt es nichts umsonst!,,,¡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.",,これはチャリティーじゃない!,딴 데 가서 구걸하세요!,Er wordt hier geen liefdadigheid gegeven!,,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!, -Metal armor,TXT_RPLY1_SCRIPT23_D3032_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлическую броню, -An excellent choice citizen.,TXT_RYES1_SCRIPT23_D3032_ANEXC,,,,"Výborná volba, občane.","Eine exzellente Wahl, Bürger.",,,"Excelente elección, ciudadano.",,"Erinomainen valinta, asukas.","Un excellent choix, citoyen.",Kiváló választás polgártárs.,,良い選択だ。,탄탄한 게 잘 보호해준답니다.,Een uitstekende keuze voor de burger.,,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.", -You don't have enough for this!,TXT_RNO1_SCRIPT23_D3032_YOUDO,,,,Na to nemáš dost peněz!,Du hast nich genug Gold dafür!,,,¡No tienes suficiente para esto!,,Sinulla ei rahat riitä siihen!,Vous n'avez pas assez d'argent.,Nincs elég ehhez nálad!,,これでは足りない!,돈이 부족합니다. 다른 건 어떠신가요?,Je hebt hier niet genoeg voor!,,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!, -Environmental suit,TXT_RPLY2_SCRIPT23_D3032_ENVIR,,,,Ochranný oděv,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм, -Here you are.,TXT_RYES2_SCRIPT23_D3032_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,,どうぞ。,여기 받으세요!,Hier ben je dan.,,Aqui está.,,Aici este.,Держи., -"No money, no suit.",TXT_RNO2_SCRIPT23_D3032_NOMON,,,,Bez peněz pro oděvy nelez.,"Kein Geld, kein Anzug.",,,Sin dinero no hay traje.,,"Ei rahaa, ei pukua.","Pas d'argent, pas de combi.","Ha nincs pénz, nincs védőruha.",,金が無いならスーツは無しだ。,방호복을 사기엔 돈이 부족합니다.,"Geen geld, geen pak.",,"Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.", -How can I help you today?,TXT_DLG_SCRIPT23_D4548_HOWCA,,,,S čím ti mohu dnes pomoci?,Wie kann ich dir heute weiterhelfen?,,,¿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?,,本日は何の用で?,환영합니다. 뭔가 필요하신지요?,Hoe kan ik u vandaag helpen?,,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем я могу тебе помочь сегодня?, -Med patch,TXT_RPLY0_SCRIPT23_D4548_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekäärettä,Pansement.,Ragtapasz,,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Bandaj medical,Бинтами, -Here's your patch.,TXT_RYES0_SCRIPT23_D4548_HERES,,,,Tady jsou.,Hier ist deine Bandage.,,,Aquí tienes tu parche.,,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,,これが貴方のパッチです。,의료 붕대 하나. 경마한 부상에 쓰시길.,Hier is je patch.,,Aqui está sua compressa.,,Aici e bandajul.,Вот твой набор бинтов., -That is 15 gold my friend.,TXT_RNO0_SCRIPT23_D4548_THATI,,,,"Ty stojí patnáct zlatých, příteli.","Das macht 15 Gold, mein Freund.",,,"Son 15 de oro, amigo mío.",,"Se maksaa 15 kolikkoa, ystäväiseni.","15 pièces pour ça, mon ami.",15 arany lesz barátocskám.,,これは15ゴールドですよ。,15 골드가 없습니까? 유감이군요.,"Dat is 15 goud, mijn vriend.",,"Custa 15 moedas de ouro, meu amigo.",,E 15 monezi prietene.,"Они стоят 15 монет, друг.", -Medical kit,TXT_RPLY1_SCRIPT23_D4548_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit médico,,Lääkintälaukku,Kit médical.,Elsősegély doboz,,医療用キット,구급 키트,Medische kit,,Kit médico,,Kit medical,Аптечкой, -Here's your medical kit.,TXT_RYES1_SCRIPT23_D4548_HERES,,,,Tady je.,Hier ist dein Verbandskasten,,,Aquí tienes tu kit médico.,,Tässä lääkintälaukkusi.,Voilà votre kit médical.,Itt az elsősegély dobozod.,,これが貴方のキットです。,구급 키트는 아주 유용하죠. 잘 쓰시길!,Hier is je medische uitrusting.,,Aqui está o seu kit médico,,Aici e kitul medical.,Вот твоя аптечка., -Your a bit low on funds for that.,TXT_RNO1_SCRIPT23_D4548_YOURA,,,,Na tu teď nemáš dost.,Du hast zu wenig Geld dafür.,,,Estás un poco bajo de efectivo para eso.,,Rahasi eivät ihan riitä siihen.,Vous manquez d'argent pour ça.,Kevés lesz a pénzed ehhez most.,,お金が少し足りませんよ。,돈이 부족하군요. 못 줍니다!,Je hebt daar een beetje weinig geld voor.,,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств., -Field surgery kit,TXT_RPLY2_SCRIPT23_D4548_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,,手術キット,수술 키트,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом, -One field surgery kit.,TXT_RYES2_SCRIPT23_D4548_ONEFI,,,,Jedna souprava.,"Eine Erste-Hilfe-Kasten, kommt sofort.",,,Un kit quirúrgico.,,"Yksi kirurgilaukku, tässä.","Un kit de chirurgie, voilà.","Parancsolj, egy műtéti felszerelés.",,手術キット一丁。,아주 위박한 상황에 쓰시길. 여기 수술 키트입니다!,Een veldoperatiekit.,,Um kit de cirurgia.,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи., -Come back when you have money!,TXT_RNO2_SCRIPT23_D4548_COMEB,,,,"Vrať se, až budeš mít peníze!","Komm wieder, wenn du etwas Geld hast.",,,¡Vuelve cuando tengas dinero!,,"Tule takaisin, kun sinulla on rahaa!",Revenez quand vous avez des sous?,"Akkor gyere vissza, ha pénzed is lesz!",,お金が有る時にまた!,"돈이 많이 있으면 모를까, 살 수 없을겁니다!",Kom terug als je geld hebt!,,Volte quando tiver dinheiro!,,Revino când o să ai bani!,Возвращайся с деньгами!, -"Hello friend, what can I get you?",TXT_DLG_SCRIPT23_D6064_HELLO,,,,"Zdravím, příteli, co pro tebe mohu udělat?","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?",,よう旦那、何が必要だ?,좋은 하루! 뭐 필요한거라도?,"Hallo vriend, wat kan ik voor je halen?",,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?","Привет, друг. Могу я тебе что-нибудь предложить?", -Information,TXT_RPLY0_SCRIPT23_D6064_INFOR,,,,Informace,Informationen,,,Información,,Tietoa.,Des infos.,Információ,,情報,정보 있습니까?,Informatie,,Informações,,Informație,Информацию, -"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é.","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.",,"誰も工場を出入りしている所を見ていない、 +"What can I get you, citizen?",TXT_DLG_SCRIPT23_D0_WHATC,,,,"Co vám mohu nabídnout, občane?","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?",,"Como posso ajudá-lo, cidadão?",,"Ce pot să-ți aduc, cetățeanule?","Что я могу тебе предложить, гражданин?", +Ammo box,TXT_RPLY0_SCRIPT23_D0_AMMOB,,,,Krabici nábojů,Munitionsschachtel,,,Caja de municiones,,Ammuslaatikko,Boîte de munitions.,Lőszer doboz,Scatola di munizioni,銃弾倉,돌격소총 탄약 박스,Munitiedoos,,Caixa de munição,,Cutie cu muniție,Коробку патронов, +Here's your ammo.,TXT_RYES0_SCRIPT23_D0_HERES,,,,Tady je.,Hier ist deine Munition.,,,Aquí tienes tus municiones.,,Tässä ammuksesi.,Voilà vos munitions.,Itt a lőszered.,Ecco le tue munizioni.,これでソチラのブツだ。,탄약을 구매해줘서 고마워요.,Hier is je munitie.,,Aqui está a sua munição.,,Aici e muniția.,Вот твои патроны., +You don't have enough for that!,TXT_RNO0_SCRIPT23_D0_YOUDO,,,,Na tu nemáš dost peněz!,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!,,Você não tem o suficiente para isto.,,Nu ai suficiente fonduri pentru asta.,У тебя недостаточно денег!, +Crate of missiles,TXT_RPLY1_SCRIPT23_D0_CRATE,,,,Bednu raket,Raketenkiste,,,Caja de misiles,,Ohjuslaatikko,Caisse de missiles.,Ládányi rakéta,Cassa di razzi,ミサイル箱,미니 미사일 박스,Krat van raketten,,Caixa de mísseis,,Cutie de rachete.,Коробку ракет, +"Here, citizen.",TXT_RYES1_SCRIPT23_D0_HEREC,,,,"Tady, občane.","Hier, Bürger.",,,"Toma, ciudadano.",,"Tässä, kansalainen.","Voilà, citoyen.","Parancsolj, polgártárs.","Ecco qua, cittadino",どうぞ、お客さん。,여기 있습니다.,"Hier, burger.",,"Aqui, cidadão.",,"Aici, orășene.","Вот, гражданин.", +"It's 85 gold, citizen!",TXT_RNO1_SCRIPT23_D0_ITS85,,,,"Ta stojí 85 zlatých, občane!","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!",,"Custa 85 moedas de ouro, cidadão!",,"E 85 de monezi, orășene!","Гражданин, это стоит 85 золотых!", +H-E grenades,TXT_RPLY2_SCRIPT23_D0_HEGRE,,,,Výbušné granáty,HE-Granaten,,,Granadas HE,,Räjähdekranaatteja,Grenades explosives.,Robbanó gránátok,Granate ad alto potenziale esplosivo,HEグレネード,고폭 유탄,H-E-granaten,,Granadas explosivas,,Grenade.,Осколочные гранаты, +Here are your grenades.,TXT_RYES2_SCRIPT23_D0_HEREA,,,,Tady jsou.,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.,,Aqui estão as suas granadas,,Aici sunt grenadele.,Забирай свои гранаты., +"They are 100 gold, friend.",TXT_RNO2_SCRIPT23_D0_THEYA,,,,"Ty stojí sto zlatých, příteli.","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.",,"Custam 100 moedas, amigo.",,"Costă 100 de monezi, prietene.","Они по 100 золотых, друг.", +Energy pod,TXT_RPLY3_SCRIPT23_D0_ENERG,,,,Energetický kokón,Energiezelle.,,,Vaina de energía,,Energia-akku,Cellule énergetique.,Energia cella,Nucleo energetico,エネルギーポッド,에너지 포드,Energiecapsule,,Célula de energia.,,Capsulă energetică.,Энергоячейку, +Here you are.,TXT_RYES3_SCRIPT23_D0_HEREY,,,,Tady je.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Eccolo qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,,Aqui está.,,Aici este.,Получай., +"That's 135 gold, sorry.",TXT_RNO3_SCRIPT23_D0_THATS,,,,"Ten stojí 135 zlatých, je mi líto.","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.",,Custa 135 moedas. Sinto muito.,,"Costă 135 de monezi, scuze.",Она стоит 135 золотых. Извини., +What can I assist you with?,TXT_DLG_SCRIPT23_D1516_WHATC,,,,S čím vám mohu pomoci?,Wie kann ich dir behilflich sein?,,,¿Con qué puedo ayudarte?,,Miten voin auttaa?,Commen puis-je vous assister?,Miben segíthetek?,Come posso esserti utile?,何か手伝いましょうか?,어떤 걸 도와드릴까요?,Waarmee kan ik je helpen?,,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем я могу тебе помочь?, +Leather armor,TXT_RPLY0_SCRIPT23_D1516_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro,,Armură de piele,Кожаной бронёй, +Here it is citizen.,TXT_RYES0_SCRIPT23_D1516_HEREI,,,,"Tady je, občane.","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.,,"Aqui está, cidadão.",,Aici e orășene.,"Вот она, гражданин.", +There's no charity given here!,TXT_RNO0_SCRIPT23_D1516_THERE,,,,Nejsme charita!,Hier gibt es nichts umsonst!,,,¡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!,,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!, +Metal armor,TXT_RPLY1_SCRIPT23_D1516_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлической бронёй, +An excellent choice citizen.,TXT_RYES1_SCRIPT23_D1516_ANEXC,,,,"Výborná volba, občane.","Eine exzellente Wahl, Bürger.",,,"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.",,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.", +You don't have enough for this!,TXT_RNO1_SCRIPT23_D1516_YOUDO,,,,Na to nemáte dost peněz!,Du hast nich genug Gold dafür!,,,¡No tienes suficiente para esto!,,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!,,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!, +Environmental suit,TXT_RPLY2_SCRIPT23_D1516_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védőruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитным костюмом, +Here you are.,TXT_RYES2_SCRIPT23_D1516_HEREY,,,,Tady máte.,Bitteschön.,,Jen.,Aquí tienes.,,Kas tässä.,Voilà pour vous.,"Itt van, parancsolj.",Eccola qua.,どうぞ。,여기 있습니다.,Hier ben je dan.,,Aqui está.,,Aici este.,Держи., +"No money, no suit.",TXT_RNO2_SCRIPT23_D1516_NOMON,,,,Bez peněz pro oděvy nelez.,"Kein Geld, kein Anzug.",,,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.",,"Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.", +Something different?,TXT_RPLY3_SCRIPT23_D1516_SOMET,,,,Něco jiného?,Irgendetwas anderes?,,,¿Algo distinto?,,Jotain erilaista?,Quelque chose d'autre?,Valami mást esetleg?,Qualcos'altro?,何か別のやつは?,뭔가 다른 거는?,Iets anders?,,Algo diferente?,,Ceva diferit?,Что-нибудь ещё?, +Go through the door down the hall.,TXT_RYES3_SCRIPT23_D1516_GOTHR,,,,Jděte dveřmi dole na chodbě.,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.,,Passe pela porta lá no salão.,,Intră pe ușa din josul holului.,"Дальше по коридору, за дверью.", +You must pay if you want to play.,TXT_RNO3_SCRIPT23_D1516_YOUMU,,,,Chceš si hrát? Zaplať.,"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.,,Você precisa pagar se quiser jogar.,,Trebuie să plătești dacă vrei să joci.,"Любишь играть, люби и платить!", +What can I get you?,TXT_DLG_SCRIPT23_D3032_WHATC,,,,Co vám mohu nabídnout?,Was darf es sein?,,,¿Qué puedo ofrecerte?,,Mitä teille saisi olla?,Que puis-je pour vous?,Mit adhatok?,Cosa ti porto?,何をお求めで?,무엇을 드릴까요?,Wat kan ik voor je halen?,,O que gostaria?,,Ce pot să-ți aduc?,Что я могу тебе предложить?, +Leather armor,TXT_RPLY0_SCRIPT23_D3032_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero,,Nahkasuojus,Armure de cuir.,Bőr vért,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro,,Armură de piele,Кожаную броню, +"Here it is, citizen.",TXT_RYES0_SCRIPT23_D3032_HEREI,,,,"Tady je, občane.","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.",,"Aqui está, cidadão.",,"Aici este, orășene.","Вот она, гражданин.", +There's no charity given here!,TXT_RNO0_SCRIPT23_D3032_THERE,,,,Nejsme charita!,Hier gibt es nichts umsonst!,,,¡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!,,Aqui não é local de caridade!,,Nu facem caritate aici!,Я благотворительностью не занимаюсь!, +Metal armor,TXT_RPLY1_SCRIPT23_D3032_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлическую броню, +An excellent choice citizen.,TXT_RYES1_SCRIPT23_D3032_ANEXC,,,,"Výborná volba, občane.","Eine exzellente Wahl, Bürger.",,,"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.,,"Excelente escolha, cidadão.",,Excelentă alegere orășene.,"Отличный выбор, гражданин.", +You don't have enough for this!,TXT_RNO1_SCRIPT23_D3032_YOUDO,,,,Na to nemáte dost peněz!,Du hast nich genug Gold dafür!,,,¡No tienes suficiente para esto!,,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!,,Você não tem o suficiente para isto!,,Nu ai suficiente fonduri pentru asta!,У тебя недостаточно денег!, +Environmental suit,TXT_RPLY2_SCRIPT23_D3032_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм, +Here you are.,TXT_RYES2_SCRIPT23_D3032_HEREY,,,,Tady máte.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Eccoti qui.,どうぞ。,여기 받으세요!,Hier ben je dan.,,Aqui está.,,Aici este.,Держи., +"No money, no suit.",TXT_RNO2_SCRIPT23_D3032_NOMON,,,,Bez peněz pro oděvy nelez.,"Kein Geld, kein Anzug.",,,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.",,"Sem dinheiro, sem traje.",,"Niciun ban, niciun costum.","Нет денег, нет костюма.", +How can I help you today?,TXT_DLG_SCRIPT23_D4548_HOWCA,,,,S čím vám mohu dnes pomoci?,Wie kann ich dir heute weiterhelfen?,,,¿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?,,Como posso ajudá-lo hoje?,,Cu ce te pot ajuta azi?,Чем я могу тебе помочь сегодня?, +Med patch,TXT_RPLY0_SCRIPT23_D4548_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekäärettä,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Bandaj medical,Бинтами, +Here's your patch.,TXT_RYES0_SCRIPT23_D4548_HERES,,,,Tady jsou.,Hier ist deine Bandage.,,,Aquí tienes tu parche.,,Tässä kääreesi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これが貴方のパッチです。,의료 붕대 하나. 경마한 부상에 쓰시길.,Hier is je patch.,,Aqui está sua compressa.,,Aici e bandajul.,Вот твой набор бинтов., +That is 15 gold my friend.,TXT_RNO0_SCRIPT23_D4548_THATI,,,,"Ty stojí patnáct zlatých, příteli.","Das macht 15 Gold, mein Freund.",,,"Son 15 de oro, amigo mío.",,"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.",,"Custa 15 moedas de ouro, meu amigo.",,E 15 monezi prietene.,"Они стоят 15 монет, друг.", +Medical kit,TXT_RPLY1_SCRIPT23_D4548_MEDIC,,,,Lékárničku,Verbandskasten,,,Kit médico,,Lääkintälaukku,Kit médical.,Elsősegély doboz,Kit medico,医療用キット,구급 키트,Medische kit,,Kit médico,,Kit medical,Аптечкой, +Here's your medical kit.,TXT_RYES1_SCRIPT23_D4548_HERES,,,,Tady je.,Hier ist dein Verbandskasten,,,Aquí tienes tu kit médico.,,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.,,Aqui está o seu kit médico,,Aici e kitul medical.,Вот твоя аптечка., +Your a bit low on funds for that.,TXT_RNO1_SCRIPT23_D4548_YOURA,,,,Na tu nemáte dost.,Du hast zu wenig Geld dafür.,,,Estás un poco bajo de efectivo para eso.,,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.,,Você está um pouco mal de dinheiro pra isso.,,Cam puțini bani pentru aia.,Тебе на это не хватает средств., +Field surgery kit,TXT_RPLY2_SCRIPT23_D4548_FIELD,,,,Chirurgickou soupravu,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Медкомплектом, +One field surgery kit.,TXT_RYES2_SCRIPT23_D4548_ONEFI,,,,Jedna souprava.,"Eine Erste-Hilfe-Kasten, kommt sofort.",,,Un kit quirúrgico.,,"Yksi kirurgilaukku, tässä.","Un kit de chirurgie, voilà.","Parancsolj, egy műtéti felszerelés.","Un kit chirurgico, eccolo qua.",手術キット一丁。,아주 위박한 상황에 쓰시길. 여기 수술 키트입니다!,Een veldoperatiekit.,,Um kit de cirurgia.,,"Un kit chirurgical de teren, gata.",Один медкомплект. Держи., +Come back when you have money!,TXT_RNO2_SCRIPT23_D4548_COMEB,,,,"Vrať se, až budeš mít peníze!","Komm wieder, wenn du etwas Geld hast.",,,¡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!,,Volte quando tiver dinheiro!,,Revino când o să ai bani!,Возвращайся с деньгами!, +"Hello friend, what can I get you?",TXT_DLG_SCRIPT23_D6064_HELLO,,,,"Zdravím, příteli, co pro vás mohu udělat?","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?",,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?","Привет, друг. Могу я тебе что-нибудь предложить?", +Information,TXT_RPLY0_SCRIPT23_D6064_INFOR,,,,Informace,Informationen,,,Información,,Tietoa.,Des infos.,Információ,Informazioni,情報,정보 있습니까?,Informatie,,Informações,,Informație,Информацию, +"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é.,"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.",,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.","Никогда не видел, чтобы кто-нибудь приходил или уходил с фабрики. Поле всегда включено.", -"No money, no info.",TXT_RNO0_SCRIPT23_D6064_NOMON,,,,"Žádné peníze, žádné informace.","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ó.",,金が無いなら情報は無しだ。,"돈 없으면, 정보도 없다네.","Geen geld, geen informatie.",,"Sem grana, nada de informações.",,"Niciun ban, nicio informație.",Нет денег — нет сведений., -"Yes, what would you like?",TXT_DLG_SCRIPT23_D7580_YESWH,,,,"Ano, co by sis přál?","Ja, was darf es sein?",,,"Sí, ¿Qué quieres?",,"Niin, mitä saisi olla?","Oui, que voulez-vous?","Igen, milyen érdekelne?",,はい、どうしたい?,"아, 무엇을 원하는가?","Ja, wat wil je graag?",,"Sim, o que você gostaria?",,"Da, ce ai dori?",Да? Что ты хотел?, -More info.,TXT_RPLY0_SCRIPT23_D7580_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,,更なる情報,정보가 필요해요.,Meer info.,,Mais informações.,,Mai multă informație.,Ещё сведений., -The factory's built on the comet's impact site. I don't think it's by chance.,TXT_RYES0_SCRIPT23_D7580_THEFA,,,,"Továrna je postavená na místě dopadu komety. Nemyslím si, že to je náhoda.","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.,,"工場は彗星の衝突地点に建っている。 +"No money, no info.",TXT_RNO0_SCRIPT23_D6064_NOMON,,,,"Žádné peníze, žádné informace.","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.",,"Sem grana, nada de informações.",,"Niciun ban, nicio informație.",Нет денег — нет сведений., +"Yes, what would you like?",TXT_DLG_SCRIPT23_D7580_YESWH,,,,"Ano, co byste si přál?","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?",,"Sim, o que você gostaria?",,"Da, ce ai dori?",Да? Что ты хотел?, +More info.,TXT_RPLY0_SCRIPT23_D7580_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報,정보가 필요해요.,Meer info.,,Mais informações.,,Mai multă informație.,Ещё сведений., +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.","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.,,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ță.,"Фабрика была построена в кратере от падения метеорита. Не думаю, что это случайность.", -"Come on, it's a measly 5 gold.",TXT_RNO0_SCRIPT23_D7580_COMEO,,,,"No tak, je to jen pět zlatých.","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.",,頼むぜ、たった5ゴールドだぞ。,5 골드 정도 하는데 말이지.,"Kom op, het is een miezerige 5 goud.",,"Vamos lá, custa só 5 moedinhas.",,"Haide, sunt 5 bănuți amărâți.","Ну же, всего-то 5 золотых.", -"Hello again, what'll it be?",TXT_DLG_SCRIPT23_D9096_HELLO,,,,"Opět ahoj, co to bude?",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?",,また来たな、何か頼むか?,다시 만났군. 오늘은 어떤 걸?,"Hallo nogmaals, wat zal het zijn?",,Olá de novo. O que vai ser desta vez?,,"Bună din nou, ce dorești?",И снова привет. Что на этот раз?, -More info.,TXT_RPLY0_SCRIPT23_D9096_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,,更なる情報,더 많은 정보를 원해요.,Meer info.,,Mais informações.,,Mai multă informație.,Ещё информацию., -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.,"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.",,"工場はオーダーの「新審問官」が来てから +"Come on, it's a measly 5 gold.",TXT_RNO0_SCRIPT23_D7580_COMEO,,,,"No tak, chci pouhých pět zlatých.","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.",,"Vamos lá, custa só 5 moedinhas.",,"Haide, sunt 5 bănuți amărâți.","Ну же, всего-то 5 золотых.", +"Hello again, what'll it be?",TXT_DLG_SCRIPT23_D9096_HELLO,,,,"Opět zdravím, co to bude?",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?",,Olá de novo. O que vai ser desta vez?,,"Bună din nou, ce dorești?",И снова привет. Что на этот раз?, +More info.,TXT_RPLY0_SCRIPT23_D9096_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,更なる情報,더 많은 정보를 원해요.,Meer info.,,Mais informações.,,Mai multă informație.,Ещё информацию., +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.,"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.,,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.,"Фабрика закрылась, когда Орден показал своё новое страшилище — инквизитора.", -5 gold please.,TXT_RNO0_SCRIPT23_D9096_5GOLD,,,,"Pět zlatých, prosim.","5 Gold, bitte.",,,5 de oro por favor.,,"5 kolikkoa, kiitos.","5 pièces, s'il vous plaît.",5 arany lesz.,,5ゴールドかかるぜ。,먼저 5 골드를 주게나.,5 goud alsjeblieft.,,5 moedas por favor.,,5 bani te rog.,"5 золотых, пожалуйста.", -"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ň.","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.",,"知ってることはこれで全部だ。 +5 gold please.,TXT_RNO0_SCRIPT23_D9096_5GOLD,,,,"Pět zlatých, prosim.","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 moedas por favor.,,5 bani te rog.,"5 золотых, пожалуйста.", +"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.","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.",,"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.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.", -Hello.,TXT_DLG_SCRIPT23_D12128_HELLO,,,,Ahoj.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,,こんにちは。,안녕하세요.,Hallo.,,Olá.,,Salut.,Привет., -What are you doing?,TXT_RPLY0_SCRIPT23_D12128_WHATA,,,,Co tady děláš?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit csinálsz?,,何してるんだ?,뭐하는 거죠?,Wat ben je aan het doen?,,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?, -"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D12128_IMDOI,,,,"Dělám věci, vypadni!","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!",,今は立て込んでる、離れなさい!,별거 아닙니다. 방해하지 말고 저리 가세요!,"Ik doe dingen, ga weg!",,"Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!, -"Now, what can I help you with?",TXT_DLG_SCRIPT23_D13644_NOWWH,,,,"Tak, s čím ti mohu pomoci?","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?",,今手伝ってくれるか?,"자, 제가 뭘 도와드릴까요?","Nu, waar kan ik je mee helpen?",,"Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?", -Shadow armor?,TXT_RPLY0_SCRIPT23_D13644_SHADO,,,Shadow armour?,Stínové brnění?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,,シャドウアーマー?,그림자 갑옷?,Schaduw harnas?,,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?, -"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D13644_AHHTO,,,,"Áha, být slyšen, ne viděn!","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.",,ああ、声はすれど姿は見えず。,하하하... 아주 조용하고 보이지 않는 도구죠!,"Ahhh, om gehoord, maar niet gezien te worden!",,"Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!", -"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.","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.",,ここを出て、稼いでからまた来てくれ!,"저리 가, 돈이 있을 때나 여길 찾으라고요.","Ga hier weg, kom terug als je wat geld hebt.",,Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.", -"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!","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!",,"ようやく来てくれたか。 +Hello.,TXT_DLG_SCRIPT23_D12128_HELLO,,,,Ahoj.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Ciao.,こんにちは。,안녕하세요.,Hallo.,,Olá.,,Salut.,Привет., +What are you doing?,TXT_RPLY0_SCRIPT23_D12128_WHATA,,,,Co tady děláš?,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?,,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?, +"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D12128_IMDOI,,,,"Dělám věci, vypadni!","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!",,"Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!, +"Now, what can I help you with?",TXT_DLG_SCRIPT23_D13644_NOWWH,,,,"Tak, s čím ti mohu pomoci?","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?",,"Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?", +Shadow armor?,TXT_RPLY0_SCRIPT23_D13644_SHADO,,,Shadow armour?,Stínové brnění?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw harnas?,,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?, +"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D13644_AHHTO,,,,"Áha, být slyšen, ne viděn!","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!",,"Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!", +"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.","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.",,Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.", +"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!","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!","ようやく来てくれたか。 工場に入るためには鍵が必要だ。 鍵は盗んだのだが、我々の密偵が砦地下にある 地下墓所で行方不明になった。 彼を探すため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!",,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!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!", -What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D15160_WHATI,,,,"Co to je? Člověk, nebo...?",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...?,,それは一体?人間か...?,그게 뭐죠? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?, -"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á.","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.",,"いや。人間の仕業だとはとても思えない。 +What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D15160_WHATI,,,,"Co to je? Člověk, nebo...?",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.... ?,,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?, +"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á.","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.","いや。人間の仕業だとはとても思えない。 それが何であれ君は鍵を取り戻せ。 地下墓所への入り口は開けておこう。 鍵を手に入れたら、工場は採掘所の隣にある。 時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","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.",,"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ă.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!", -"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D16676_SOMET,,,,"Něco nelidského, co? Skvělý.",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.",,非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.",,"Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично., -You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D18192_YOURE,,,,Plýtváš časem i životy! Jdi!,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!,,"こうしてる間にも君は時間と人命を +"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D16676_SOMET,,,,"Něco nelidského, co? Skvělý.",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.",,"Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично., +You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D18192_YOURE,,,,Plýtváš časem i životy! Jdi!,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!,,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Шевелись!, -Can I be of more help?,TXT_DLG_SCRIPT23_D10612_CANIB,,,,Můžu ti dál pomocI?,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?,,何かお困りでも?,당신의 도움이 더 되어줄 수 있겠습니까?,Kan ik meer hulp bieden?,,Posso ajudar com mais alguma coisa?,,Pot fi mai de ajutor?,Могу ли я чем-нибудь помочь?, -More info.,TXT_RPLY0_SCRIPT23_D10612_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,,更なる情報。,정보 더 있습니까?,Meer info.,,Mais informações.,,Mai multă informație.,Информацией., -Look for Timothy. I've heard he knows some of the Order's secrets.,TXT_RYES0_SCRIPT23_D10612_LOOKF,,,,"Najdi Timothyho. Slyšel jsem, že ví nějaká tajemství Řádu.","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.",,"ティモシーを探せ。彼がオーダーの秘密を +Can I be of more help?,TXT_DLG_SCRIPT23_D10612_CANIB,,,,Můžu vám dál pomocI?,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?,,Posso ajudar com mais alguma coisa?,,Pot fi mai de ajutor?,Могу ли я чем-нибудь помочь?, +More info.,TXT_RPLY0_SCRIPT23_D10612_MOREI,,,,Další informace.,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Più informazioni.,更なる情報。,정보 더 있습니까?,Meer info.,,Mais informações.,,Mai multă informație.,Информацией., +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.","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.,,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.,"Найди Тимоти. Я слышал, он знает какие-то секреты Ордена.", -Just another 5 gold.,TXT_RNO0_SCRIPT23_D10612_JUSTA,,,,Jen dalších pět zlatých.,Nur 5 weitere Goldstücke.,,,Solo otros 5 de oro.,,Vain 5 kolikkoa lisää.,Juste 5 pièces.,Még 5 arany kell.,,たった5ゴールドだぞ。,5 골드만 주세요.,Gewoon nog eens 5 goud.,,Só mais 5 moedas.,,Alte 5 monezi.,Всего лишь ещё 5 золотых!, -"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ň.","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.",,"知ってることはこれで全部だ。 +Just another 5 gold.,TXT_RNO0_SCRIPT23_D10612_JUSTA,,,,Jen dalších pět zlatých.,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.,,Só mais 5 moedas.,,Alte 5 monezi.,Всего лишь ещё 5 золотых!, +"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.","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.",,"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.","Это всё, что я знаю. Даже у хозяев таверн заканчиваются темы для болтовни, увы.", -Hello.,TXT_DLG_SCRIPT23_D13644_HELLO,,,,Ahoj.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,,どうも。,안녕하세요.,Hallo.,,Olá.,,Salut.,Привет., -What are you doing?,TXT_RPLY0_SCRIPT23_D13644_WHATA,,,,Co tady děláš?,Was machst du?,,Kion vi faras?,¿Qué estás haciendo?,,Mitä teet?,Qu'est-ce que vous faites?,Mit művelsz?,,何してるんだ?,무슨 일을 하고 있는거죠?,Wat ben je aan het doen?,,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?, -"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D13644_IMDOI,,,,"Dělám věci, vypadni!","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!",,今は立て込んでる、離れろ!,그냥 뭘 하고 있습니다. 저리가세요!,"Ik doe dingen, ga weg!",,"Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!, -"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.","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.",,"アンタがもし時間を浪費するつもりじゃないなら +Hello.,TXT_DLG_SCRIPT23_D13644_HELLO,,,,Ahoj.,Hallo.,,Saluton.,Hola.,,Hei.,Bonjour.,Helló.,Salve.,どうも。,안녕하세요.,Hallo.,,Olá.,,Salut.,Привет., +What are you doing?,TXT_RPLY0_SCRIPT23_D13644_WHATA,,,,Co tady děláš?,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?,,O que você está fazendo?,,Ce faci?,Чем ты занимаешься?, +"I'm doing stuff, go away!",TXT_RYES0_SCRIPT23_D13644_IMDOI,,,,"Dělám věci, vypadni!","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!",,"Estou fazendo coisas, vá embora!",,"Am treabă, pleacă!",Ерундой всякой. Отвали!, +"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.","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.","アンタがもし時間を浪費するつもりじゃないなら 青の聖杯を見つけられるかどうかを確かめる。 その骨董品は俺にとって非常に価値がある。 持ってきたら協力しよう。","만약 시간이 남아돈다면, 푸른 성배를 찾아보러 가시는 게 어떤가요? 오더에 대한 제 연구가 맞아떨어진다면, 그것은 분명히 공장의 조립시설에 숨겨져 있을 겁니다. 그 보물은 더 할 말 없이 아주 진귀할 거에요. 그걸 찾아주면, 딱 맞는 보답을 해주지요.","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.",,"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.","Если тебе не жаль времени, найди синюю чашу. Я изучал Орден и узнал, что они спрятали её где-то в обрабатывающем секторе фабрики. Мне очень нужен этот артефакт. Принеси его мне, и я помогу тебе.", -"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 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.",,"青の聖杯を見つけたのか! +"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 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.",,"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.","Ты нашёл синюю чашу! Отдай её мне, и я исполню свою часть договора.", -"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D16676_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","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.",,渡そう、兎に角運が悪かった。,여기 받아요. 재수 없어 보이니까.,"Neem het, het is toch al pech.",,Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье., -"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D16676_SCREW,,,,"Jdi se vycpat, nechám si ho.","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.",,ふざけるな、俺の物だ。,"배 째시지, 이건 이제 제거에요.","Krijg de klere, ik hou het.",,"Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе., -Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D16676_THENI,,,,Pak ti nic nedám. Zmizni!,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é!,,何もやるモンは無いぞ。失せな!,이런 식으로 나가시겠다? 그럼 거래를 취소하죠. 사라지세요!,Dan geef ik je niets. Donder op!,,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!, -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 kovárnu. Informace, které jsem ti právě dal, ti pomůžou vstoupit do tajného sektoru továrny. Jeden z pracovníků kovárny ti otevře dveře.","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.",,"工場の鉄工所を探せ。俺が与えた情報は +"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D16676_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","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.",,Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье., +"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D16676_SCREW,,,,"Jdi se vycpat, nechám si ho.","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.",,"Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе., +Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D16676_THENI,,,,Pak ti nic nedám. Zmizni!,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!,,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!, +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.","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.,"工場の鉄工所を探せ。俺が与えた情報は そこの隠された区域に入る為に必要だ。 偽の作業員がドアを開けるだろう。",공장의 제련소로 찾아가세요. 제가 제공한 정보만 있으면 그곳으로 향하는 비밀구역을 쉽게 찾을 수 있을 겁니다. 제련소 직원 중 한 명이 그곳으로 향하는 문을 열 수 있어요.,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.,,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.,"Найди кузню. Сведения, которые я передал тебе, помогут тебе пройти в секретный сектор фабрики. Один из работников в кузне откроет тебе дверь.", -What can I find there?,TXT_RPLY0_SCRIPT23_D18192_WHATC,,,,Co tam můžu najít?,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?,,そこには何がある?,그곳을 어떻게 찾을 수 있죠?,Wat kan ik daar vinden?,,O que vou encontrar lá?,,Ce pot găsi acolo?,Что там находится?, -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ý!","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!",,"俺の調査では、古代の災厄がそこに隠されている +What can I find there?,TXT_RPLY0_SCRIPT23_D18192_WHATC,,,,Co tam můžu najít?,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?,,O que vou encontrar lá?,,Ce pot găsi acolo?,Что там находится?, +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ý!","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!,,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ă!,"Судя по результатам исследования, какая-то тёмная сила из далёкого прошлого. Будь осторожен!", -"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.","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.",,"その青い聖杯はどうした? +"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.","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.","その青い聖杯はどうした? 私はオーダーの遥か過去の関係について調査 していた、その骨董品が手掛かりになりそうだ。 取引しよう、聖杯をくれれば幾つか情報を渡す。","저 푸른 성배... 어떻게 찾으신 거죠? 오더와 그들의 과거를 좀 조사하던 참이었습니다. 저 보물만 있으면 아주 커다란 도움이 될 것입니다. 그 성배를 주신다면, 좋은 정보를 알려주겠습니다.","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.",,"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.","Эта синяя чаша... откуда она у тебя? Мои исследования Ордена связаны с событиями далёкого прошлого, и мне очень нужен этот артефакт. Давай заключим сделку: ты мне чашу, а я тебе — информацию.", -"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D21224_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","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.",,渡そう、兎に角運が悪かった。,"값어치도 없을 것 같은데, 그냥 가져가세요.","Neem het, het is toch al pech.",,Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье., -"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D21224_SCREW,,,,"Jdi se vycpat, nechám si ho.","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.",,ふざけるな、俺の物だ。,뭔 개소리야? 이제 이건 내 것이라고!,"Krijg de klere, ik hou hem.",,"Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе., -Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D21224_THENI,,,,Pak ti nic nedám. Zmizni!,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é!,,何もやるモンは無いぞ。失せな!,아주 좋은 기회를 다 날려버리시는군. 꺼져요!,Dan geef ik je niets. Donder op!,,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!, -"Now, what can I help you with?",TXT_DLG_SCRIPT23_D22740_NOWWH,,,,"Tak, s čím ti mohu pomoci?","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?,,今手伝ってくれるか?,"그럼, 뭘 더 도와드릴까요?","Nu, waar kan ik je mee helpen?",,"Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?", -Shadow armor?,TXT_RPLY0_SCRIPT23_D22740_SHADO,,,Shadow armour?,Stínové brnění?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,,シャドウアーマー?,그림자 갑옷?,Schaduw pantser?,,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?, -"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D22740_AHHTO,,,,"Áha, být slyšen, ne viděn!","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.",,ああ、声はすれど姿は見えず。,들켜도 당신을 계속 맞추진 못할 거요!,"Ahhh, om gehoord, maar niet gezien te worden!",,"Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!", -"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.","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.",,ここを出て、稼いでからまた来てくれ!,이 유용한 도구를 공짜로 주기엔 영 그렇군요.,"Ga hier weg, kom terug als je wat geld hebt.",,Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.", -"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!","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!",,"ようやく来てくれたか。 +"Take it, it's bad luck anyway.",TXT_RPLY0_SCRIPT23_D21224_TAKEI,,,,"Vem si ho, stejně přináší jen smůlu.","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.",,Pode pegar. Isso atrai azar de qualquer forma.,,"Ia-l, poartă ghinion oricum.",Держи. Она всё равно приносит несчастье., +"Screw you, I'm keeping it.",TXT_RPLY1_SCRIPT23_D21224_SCREW,,,,"Jdi se vycpat, nechám si ho.","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.",,"Vá se ferrar, ele é meu.",,"Du-te naibi, îl păstrez.",Пошёл ты! Я оставлю её себе., +Then I'm not giving you anything. Get lost!,TXT_RYES1_SCRIPT23_D21224_THENI,,,,Pak ti nic nedám. Zmizni!,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!,,Então não te darei nada. Se manda!,,Atunci nu îți dau nimic. Valea!,Тогда я тебе ничего не скажу. Убирайся!, +"Now, what can I help you with?",TXT_DLG_SCRIPT23_D22740_NOWWH,,,,"Tak, s čím ti mohu pomoci?","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?",,"Então, como posso ajudá-lo?",,"Acum, cu ce te pot ajuta?","Итак, чем я могу быть тебе полезен?", +Shadow armor?,TXT_RPLY0_SCRIPT23_D22740_SHADO,,,Shadow armour?,Stínové brnění?,Schattenrüstung?,,,¿Armadura de sombra?,,Varjohaarniska?,Armure des ombres?,Árnyék vért?,Armatura Ombra?,シャドウアーマー?,그림자 갑옷?,Schaduw pantser?,,Armadura das sombras?,,Armura umbrei?,Теневой бронёй?, +"Ahh, to be heard, but not seen!",TXT_RYES0_SCRIPT23_D22740_AHHTO,,,,"Áha, být slyšen, ne viděn!","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!",,"Ahh, ser ouvido mas não ser visto!",,"Ahh, să fii auzit, dar nu văzut!","Ах, чтобы быть услышанным, но не увиденным!", +"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.","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.",,Vá embora daqui. Volte quando tiver dinheiro.,,"Cară-te, întoarce-te când ai bani.","Выметайся вон. Вернёшься, когда раздобудешь наличности.", +"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!","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!","ようやく来てくれたか。 工場に入るためには鍵が必要だ。 鍵は盗んだのだが、我々の密偵が砦地下にある 地下墓所で行方不明になった。 彼を探すため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!",,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!","Хвала господу, ты добрался сюда. Тебе нужен ключ, чтобы проникнуть на фабрику. Мы выкрали его, но наш агент пропал в сети катакомб под крепостью Ордена. Чтобы разыскать его, я послал в эти туннели десять хороших бойцов, и ни один не вернулся. Там внизу что-то есть!", -What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D24256_WHATI,,,,"Co to je? Člověk, nebo...?",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...?,,それは一体?人間か...?,이게 뭐지? 사람? 아니면... ?,Wat is het? Menselijk of.... ?,,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?, -"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á.","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.",,"いや。人間の仕業だとはとても思えない。 +What is it? Human or... ?,TXT_RPLY0_SCRIPT23_D24256_WHATI,,,,"Co to je? Člověk, nebo...?",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.... ?,,O que é? É humano ou... ?,,Ce e? Uman sau... ?,Что это? Человек или...?, +"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á.","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.","いや。人間の仕業だとはとても思えない。 それが何であれ君は鍵を取り戻せ。 地下墓所への入り口は開けておこう。 鍵を手に入れたら、工場は採掘所の隣にある。 時間はあまり無いから急ぐのだ。","아냐. 사람 같은 건 절대로 아니라고. 그게 무엇이든, 당신은 어떻게든 싸워서 열쇠를 돌려받아야 합니다. 고대 무덤의 입구를 열어두겠습니다. 만약 열쇠를 얻으셨다면, 광산 옆에 있는 공장으로 향하시길 바랍니다. 시간이 얼마 남지 않았습니다!","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.",,"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ă.","Нет. Определённо нет. Что бы это ни было, ты должен сразиться с ним, чтобы заполучить ключ. Я открою вход в катакомбы. Когда добудешь его, направляйся на фабрику: она находится рядом со входом в шахты. Торопись! Дорога каждая секунда!", -"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D25772_SOMET,,,,"Něco nelidského, co? Skvělý.",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.",,非人道的な何か?流石だな。,비인간적인 녀석인가요? 좋군요.,"Iets onmenselijks, eh?, geweldig.",,"Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично., -You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D27288_YOURE,,,,Plýtváš časem i životy! Jdi!,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!,,"こうしてる間にも君は時間と人命を +"Something inhuman, eh?, great.",TXT_RPLY0_SCRIPT23_D25772_SOMET,,,,"Něco nelidského, co? Skvělý.",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.",,"Algo não-humano, é? Que ótimo.",,"Ceva inuman, ei? Grozav.",Что-то иное? Просто отлично., +You're wasting time and lives! Move!,TXT_DLG_SCRIPT23_D27288_YOURE,,,,Plýtváš časem i životy! Jdi!,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!,,Você está desperdiçando tempo e vidas! Ande logo!,,"Pierzi timp și vieți, mișcă-te!",Ты тратишь время и жизни! Вперёд!, -"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.","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. Oh, bueno, no queda 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.",,"マスターは訪問者ヲ嫌っている。 +"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.","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. Oh, bueno, no queda 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.","マスターは訪問者ヲ嫌っている。 彼ハ自分ノ仕事ヲ邪魔されないノガ良いからダ。 私ハこれカラ倉庫に新品の部品を取りに行かねば 腕と足だったカナ。オット、モウ話ス時間ハ無イ マスターが君を見つける前ニ出発しなけれバ。","주인님은 방문자들을 싫어해. 반대로 그는 남들의 방해 없이 혼자서 일을 하는 걸 아주 좋아하지. 저장고에서 재료를 꺼내서 가져다주는 나 같은 사람들을 제외하면. 한 쌍의 팔다리가 필요하다고 들었는데... 오, 이런. 이제 이야기할 시간도 없어졌네. 그가 널 찾기 전에 도망치는 게 좋을걸?","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.",,"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ă.","Хранитель не любит гостей — он предпочитает, чтобы его никто не отвлекал от работы. Он послал меня на склад за свежими частями. Рукой и ногой, кажется... Ох, нет времени на разговоры. Лучше бы тебе уйти, пока он не вернулся.", -Why's that.,TXT_RPLY0_SCRIPT27_D0_WHYST,,,,A proč?,Wieo das?,,,¿Por qué?,,Miksi?,Pourquoi donc?,Miért tennék olyat?,,何故そんなことを。,그건 왜지?,Waarom is dat.,,Por quê?,,De ce.,Почему так?, -"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!","Ich habe dir doch gesagt, dass er keine Besucher mag!",,,"Porque, ¡Te he dicho 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!",,ナゼなら、マスターは訪問されたくナイからダ!,"왜냐하면, 그가 방문자들을 싫어한다고 내가 말했으니까!","Omdat hij niet van bezoekers houdt, zei ik toch!",,"Porque, como eu já te falei, ele não gosta de visitantes!",,"Pentru că, ți-am spus, nu-i plac vizitatorii!","Потому что, как я уже сказал тебе, он не любит посетителей!", -"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ů.","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.",,"知ッテるハズだ、アンタに合う +Why's that.,TXT_RPLY0_SCRIPT27_D0_WHYST,,,,A proč?,Wieo das?,,,¿Por qué?,,Miksi?,Pourquoi donc?,Miért tennék olyat?,E perché mai?,何故そんなことを。,그건 왜지?,Waarom is dat.,,Por quê?,,De ce.,Почему так?, +"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!","Ich habe dir doch gesagt, dass er keine Besucher mag!",,,"Porque, ¡Te he dicho 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!",,"Porque, como eu já te falei, ele não gosta de visitantes!",,"Pentru că, ți-am spus, nu-i plac vizitatorii!","Потому что, как я уже сказал тебе, он не любит посетителей!", +"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ů.","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.",,"Sabe, você tem a altura perfeita para um dos uniformes de acólito.",,"Știi, eși marimea potrivită pentru o uniformă de acolit.","Знаешь, тебе бы как раз впору пошла униформа служителя.", -"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,,,,"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.","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.",,,"Oh no, no soy el verdadero Programador, él 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.","Oh no, no soy el verdadero Programador, él está escondido. Continúa a traves del área de entrenamiento de guardias, muy duro. 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, 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,,,,"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.","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.",,,"Oh no, no soy el verdadero Programador, él 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.","Oh no, no soy el verdadero Programador, él está escondido. Continúa a traves del área de entrenamiento de guardias, muy duro. 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.",,"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.","О, нет. Я не настоящий Программист. Он прячется. На твоём пути лежит зона тренировки стражи. Пройти её очень непросто. Если уцелеешь, то сможешь поговорить с ним... или убить его.", -Who are you?,TXT_RPLY0_SCRIPT31_D0_WHOAR,,,,Kdo jsi?,Wer bist du?,,,¿Quién eres?,,Kuka sinä olet?,Qui êtes vous?,Ki vagy te?,,お前は誰だ?,당신은 누구죠?,Wie ben jij?,,Quem é você?,,Cine ești?,Кто ты?, -You'll never find anything if you hang around here.,TXT_DLG_SCRIPT31_D1516_YOULL,,,,"Nic nenajdeš, když se tu budeš potloukat.","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.",,アンタがここをふらついても何も無いよ。,여기에 계속 머무르고 있으면 다 알지도 못할걸.,Je zult nooit iets vinden als je hier rondhangt.,,Você nunca vai descobrir nada se ficar por aqui.,,N-o să aflii nimic dacă pierzi timpul aici.,"Ты ничего не добьёшься, если будешь ошиваться тут.", -Piss off peasant!,TXT_DLG_SCRIPT32_D0_PISSO,,,,"Odprejskni, poddaný!","Verpiss dich, du Bauer!",,,"¡Esfúmate, campesino!",,"Suksi suohon, maallikko!","Dégage, paysan!",Takarodj a színem elől paraszt!,"Sparisci, contadino!",イラつかせるな、田吾作が!,"저리 꺼져라, 시민!",Boer boer kwaad maken!,,"Suma daqui, plebeu!",,"Valea, sărmanule!","Вали отсюда, рабочий!", +Who are you?,TXT_RPLY0_SCRIPT31_D0_WHOAR,,,,Kdo jsi?,Wer bist du?,,,¿Quién eres?,,Kuka sinä olet?,Qui êtes vous?,Ki vagy te?,E tu chi sei?,お前は誰だ?,당신은 누구죠?,Wie ben jij?,,Quem é você?,,Cine ești?,Кто ты?, +You'll never find anything if you hang around here.,TXT_DLG_SCRIPT31_D1516_YOULL,,,,"Nic nenajdeš, když se tu budeš potloukat.","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.,,Você nunca vai descobrir nada se ficar por aqui.,,N-o să aflii nimic dacă pierzi timpul aici.,"Ты ничего не добьёшься, если будешь ошиваться тут.", +Piss off peasant!,TXT_DLG_SCRIPT32_D0_PISSO,,,,"Odprejskni, poddaný!","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!,,"Suma daqui, plebeu!",,"Valea, sărmanule!","Вали отсюда, рабочий!", 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!","Stirb, kleiner Mann!",,,"¡Muere, enano!",,"Kuole, pikku mies!","Meurs, petite frappe!",,"Muori, piccolo uomo!",,죽어라. 나약한 것!,Sterf kleine man!,,"Morra, insignificante!",,"Mori, mititelule!","Сдохни, человечишка!", -Finally I can get out of this cell.,TXT_DLG_SCRIPT32_D3032_FINAL,,,,Konečně se můžu z téhle cely dostat.,Endlich kann ich aus dieser Zelle raus.,,,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.,,遂に、この独房から抜け出せる。,드디어 이 감옥에서 벗어나는구나...,Eindelijk kan ik uit deze cel komen.,,Finalmente eu posso sair desta cela.,,În sfârșit pot părăsi celula asta.,Наконец-то я могу сбежать из этой камеры!, -Why are you in here?,TXT_RPLY0_SCRIPT32_D3032_WHYAR,,,,Proč tu jsi?,Warum bist du da drin?,,,¿Por que estás aquí?,,Miksi olet täällä?,Pourquoi êtes vous ici?,Miért vagy itt bent?,,何でここにいる?,너가 왜 여기있지?,Waarom ben je hier binnen?,,Por que você está aqui?,,De ce ești închis?,Как ты здесь оказался?, -I was framed.,TXT_RYES0_SCRIPT32_D3032_IWASF,,,,Podvedli mě.,Ich wurde hereingelegt.,,,Fui incriminado.,,Minut lavastettiin.,J'ai été victime d'un coup monté.,Meggyanúsítottak.,,私は無実だ。,저는 누명을 썼어요.,Ik werd erin geluisd.,,Eu caí numa cilada.,,Am fost înscenat.,Меня подставили., -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 hat erzählt, das ich plante den Gouverneur zu ermorden. Ich könnte keiner Menschenseele etwas antun.",,,Harris dijo que estaba planeando matar al Gobernador. Yo nunca le haría daño 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.",,"ハリスに知事の暗殺を企てていると言われた。 +Finally I can get out of this cell.,TXT_DLG_SCRIPT32_D3032_FINAL,,,,Konečně se můžu z téhle cely dostat.,Endlich kann ich aus dieser Zelle raus.,,,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.,,Finalmente eu posso sair desta cela.,,În sfârșit pot părăsi celula asta.,Наконец-то я могу сбежать из этой камеры!, +Why are you in here?,TXT_RPLY0_SCRIPT32_D3032_WHYAR,,,,Proč tu jsi?,Warum bist du da drin?,,,¿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?,,Por que você está aqui?,,De ce ești închis?,Как ты здесь оказался?, +I was framed.,TXT_RYES0_SCRIPT32_D3032_IWASF,,,,Podvedli mě.,Ich wurde hereingelegt.,,,Fui incriminado.,,Minut lavastettiin.,J'ai été victime d'un coup monté.,Meggyanúsítottak.,Mi hanno incastrato.,私は無実だ。,저는 누명을 썼어요.,Ik werd erin geluisd.,,Eu caí numa cilada.,,Am fost înscenat.,Меня подставили., +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 hat erzählt, das ich plante den Gouverneur zu ermorden. Ich könnte keiner Menschenseele etwas antun.",,,Harris dijo que estaba planeando matar al Gobernador. Yo nunca le haría daño 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.,,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ă.,"Харрис сказал, что я замышлял убийство губернатора. А я и мухи не обижу!", -Be careful out there.,TXT_DLG_SCRIPT33_D0_BECAR,,,,Buď tam venku opatrný.,Sei vorsichtig dort draußen.,,,Ten cuidado ahí fuera.,,Pidä itsestäsi huoli.,Faites attention à vous.,Légy óvatos odakint.,,外は気をつけろ。,조심해.,Wees voorzichtig daarbuiten.,,Tome cuidado por aí.,,Ai grijă pe-acolo.,Будь поосторожнее., -"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,,,,"Poslyš, příteli, pomůžu ti, když ti pomůžeš mě. Dej mi pět zlatých a já ti řeknu, co vím.","Sag, mein Freund. Ich helfe dir, wenn du mir hilst. Gib mir 5 Gold und ich sage dir was ich weiß.",,,"Dime, amigo, te ayudo, si tú me ayudas. Dame 5 de oro y te digo todo 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.",,"助けてくれるなら援助する。 +Be careful out there.,TXT_DLG_SCRIPT33_D0_BECAR,,,,Buď tam venku opatrný.,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.,,Tome cuidado por aí.,,Ai grijă pe-acolo.,Будь поосторожнее., +"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,,,,"Poslyš, příteli, pomůžu ti, když ti pomůžeš mě. Dej mi pět zlatých a já ti řeknu, co vím.","Sag, mein Freund. Ich helfe dir, wenn du mir hilst. Gib mir 5 Gold und ich sage dir was ich weiß.",,,"Dime, amigo, te ayudo, si tú me ayudas. Dame 5 de oro y te digo todo 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.",,"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.","Дружище, я помогу тебе, если ты поможешь мне. Пять золотых, и я расскажу тебе всё, что знаю!", -Here's the gold.,TXT_RPLY0_SCRIPT33_D1516_HERES,,,,Tady máš to zlato.,Hier ist das Gold.,,Jen la oro.,Aquí tienes el oro.,,Tässä kulta.,Voilà votre argent.,Itt az arany.,,金はこれだ。,여기 골드입니다.,Hier is het goud.,,Tome estas moedas.,,Aici e aurul.,Вот монеты., -"If you punch someone, you won't set off the alarms.",TXT_RYES0_SCRIPT33_D1516_IFYOU,,,,"Když někoho praštíš, nespustíš alarmy.","Wenn du jemanden schlägst, wirst du keinen Alarm auslösen.",,,"Si golpeas a alguien, no activarás 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ó.",,パンチならアラームを鳴らせることはない。,"만약 네가 누군가를 주먹으로 때린다면, 알람은 울리지 않을 거야.","Als je iemand slaat, zal je het alarm niet afgaan.",,"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.","Убивай холодным оружием, тогда ты не поднимешь тревогу.", -I won't tell you anything for free!,TXT_RNO0_SCRIPT33_D1516_IWONT,,,,Zadarmo ti nic říkat nebudu!,Umsonst werde ich dir nichts sagen.,,,¡No te voy a decir nada gratis!,,En kerro mitään ilmaiseksi!,Je ne vous dirai rien gratuitement!,Nem árulok el ingyen semmit se!,,タダでは教えられないな!,무료로는 말 못 해!,Ik zal je niets gratis vertellen!,,Não te direi nada de graça!,,Nu-ți voi spune nimic pe gratis.,Бесплатно я не скажу ничего!, -I've already told you what I know.,TXT_DLG_SCRIPT33_D3032_IVEAL,,,,"Už jsem ti řekl, co vím.","Ich habe dir alles gesagt, was ich weiß.",,,Ya te he dicho lo que sé.,,"Olen jo kertonut sinulle, mitä tiedän.",Je vous ai dit tout ce que je sais.,Már elmondtam amit tudtam.,,俺が知っていることはこれで全部だ。,난 이미 내가 아는 걸 말해 줬어!,Ik heb je al verteld wat ik weet.,,Já te disse o que eu sei.,,Ți-am spus deja tot ce știu.,"Я уже сказал тебе всё, что знал.", -Hello friend. What can I get for you?,TXT_DLG_SCRIPT33_D4548_HELLO,,,,"Zdravím, příteli, co ti mohu nabídnout?","Hallo, Freund, was kann ich dir geben?",,,"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?,,どうも同士よ。何か必要か?,"안녕하십니까, 친구여. 구매하고 싶은 게 있습니까?",Hallo vriend. Wat kan ik voor je halen?,,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?",Здравствуй. Что-нибудь интересует?, -Electric bolts,TXT_RPLY0_SCRIPT33_D4548_ELECT,,,,Elektrické šípy,Elektrische Pfeile,,,Saetas eléctricas.,,Sähkönuolia,Carreaux électriques.,Elektromos nyilak,,エレクトリック ボルト,전격 볼트,Elektrische bouten,,Setas elétricas,,Bolțuri electrice,Электрические болты, -One quarrel it is.,TXT_RYES0_SCRIPT33_D4548_ONEQU,,,,Jeden toulec.,Hier hast du sie.,,,Marchando unas flechas.,,"Tässä, olkaa hyvä.",Un carquois pour vous.,Itt is van.,,クォーレル一本だ。,잔소리 없이 주겠습니다.,Eén ruzie is het.,,Está na mão.,,Aici sunt.,Один колчан., -You're broke!,TXT_RNO0_SCRIPT33_D4548_YOURE,,,,Jseš na mizině!,Du bist pleite!,,,¡Estás sin blanca!,¡Estás quebrado!,Olet peeaa!,Vous êtes à sec!,Nincs is nálad pénz!,,スッカラカンじゃないか!,돈이 한 푼도 없는 것 같은데.,Je bent blut!,,Você está sem grana!,,Ești falit!,"Друг, да ты на мели!", -Clip of bullets,TXT_RPLY1_SCRIPT33_D4548_10ROU,,,,Zásobník nábojů,10-Kugeln-Magazin,,,Cargador de balas,,Luotilipas,Chargeur de 10 cartouches.,Egy tárnyi töltény,,銃弾倉,돌격소총 탄창,Klem van kogels,,Carregador de balas,,Cartuș de gloanțe,Обойма патронов, -Here's your ammo,TXT_RYES1_SCRIPT33_D4548_HERES,,,,Tady je tvá munice.,Hier ist deine Munition.,,,Aquí tienes tu munición.,,Tässä panoksesi.,Voilà vos balles.,Itt a töltényed.,,これでアンタのブツだ。,여기 탄약입니다.,Hier is je munitie....,,Aqui está a sua munição.,,Aici e.,Вот твои патроны., -"Sorry, no money, no bullets.",TXT_RNO1_SCRIPT33_D4548_SORRY,,,,"Promiň, žádné peníze, žádné náboje.","Tut mir leid. Kein Geld, keine Munition.",,,"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.",,悪いが、金が無ければブツも無しだ。,돈 없으면 거래 못 합니다.,"Sorry, geen geld, geen kogels.",,"Desculpe. Sem grana, sem balas.",,"Scuze, niciun ban, niciun glonț.","Извини, нет денег — нет патронов!", -Ammo box,TXT_RPLY2_SCRIPT33_D4548_50ROU,,,,Krabici nábojů,50-Kugeln-Schachtel,,,Caja de municiones,,Luotilaatikko,Boîte de 50 balles.,Töltény doboz,,銃弾倉箱,돌격소총 탄약 박스,Munitiedoos,,Caixa de munição,,Cutie cu muniție,Коробка патронов, -Here you go,TXT_RYES2_SCRIPT33_D4548_HEREY,,,,Tu máš.,Bitteschön.,,Jen,Aquí tienes,,Ole hyvä.,Voilà pour vous.,Parancsolj.,,どうぞ。,거래 감사드립니다.,Alsjeblieft,,Aqui está,,Aici este,Держи., -You don't have enough gold!,TXT_RNO2_SCRIPT33_D4548_YOUDO,,,,Nemáš dost zlata!,Du hast nicht genug Gold.,,,¡No tienes suficiente oro!,,Sinulla ei ole riittävästi kultaa!,Vous n'avez pas assez d'argent.,Nincs elég aranyad.,,十分な額じゃない,골드가 충분치 않군요!,Je hebt niet genoeg goud!,,Você não tem ouro suficiente!,,Nu ai suficient aur!,У тебя недостаточно золота!, -Ammo satchel,TXT_RPLY3_SCRIPT33_D4548_AMMOS,,,,Brašnu na munici,Munitionstasche.,,,Mochila de municiones,,Ammuslaukku,Sacoche de munitions.,Lőszeres hátizsák,,弾薬鞄,탄약 배낭,Munitie tasje,,Mochila de munição,,Sac cu muniție,Ранец для боеприпасов, -"Thank you, anything else?",TXT_RYES3_SCRIPT33_D4548_THANK,,,,Děkuji. Něco dalšího?,"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?",,ありがとう。 他に何か?,좋습니다! 더 필요한 거라도?,"Bedankt, nog iets anders?",,Obrigado. Mais alguma coisa?,,"Merci, altceva?",Благодарю. Что-нибудь ещё?, -"You can't afford that, good day.",TXT_RNO3_SCRIPT33_D4548_YOUCA,,,,"To si nemůžeš dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag.,,,"No puedes permitirte eso, buen día.","No puedes pagar eso, 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.",,それを買える余裕は無い、また今度。,제공할 수 없습니다. 유감이군요.,"Dat kan je je niet betalen, goede dag.",,Você não pode comprar isto. Tenha um bom dia.,,"Nu ai bani, ziua bună.",У тебя не хватает денег. Всего доброго!, -Welcome. What may I show you?,TXT_DLG_SCRIPT33_D6064_WELCO,,,,Vítej. Co bych ti mohl nabídnout?,Willkommen. Was darf ich dir zeigen?,,,Bienvenido. ¿Qué puedo mostrarte?,,Tervetuloa. Mitä voin teille esitellä?,"Bienvenue, comment puis-je vous servir?",Üdvözöllek barátom. Mit tehetek érted?,,ようこそ、何を見ていきますか?,어서 오세요! 무엇이 필요한지?,Welkom. Wat kan ik je laten zien?,,Seja bem-vindo. O que posso lhe mostrar?,,Bună. Cu ce te pot ajuta?,Здравствуй. Что-нибудь интересует?, -Environmental suit,TXT_RPLY0_SCRIPT33_D6064_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм, -Here you are.,TXT_RYES0_SCRIPT33_D6064_HEREY,,,,"Tak, tady to je.",Bitteschön.,,,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Parancsolj.,,はい、これをどうぞ。,받으세요!,Hier ben je dan.,,Aqui está.,,Aici e.,"Хорошо, бери.", -You don't have enough money for that.,TXT_RNO0_SCRIPT33_D6064_YOUDO,,,,Na to nemáš dost peněz.,Dafür hast du nicht genug Geld.,,,No tienes suficiente dinero para eso.,,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.",,すみませんが、貴方は十分なお金を持っていません。,돈이 충분치 않아요.,Daar heb je niet genoeg geld voor.,,Você não tem dinheiro o suficiente para isto.,,N-ai suficienți bani.,"Извини, но у тебя не хватает денег.", -Leather armor.,TXT_RPLY1_SCRIPT33_D6064_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero.,,Nahkasuojus,Armure de cuir.,Bőr vért.,,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro.,,Armură de piele.,Кожаная броня, -Here you are.,TXT_RYES1_SCRIPT33_D6064_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,,これをどうぞ。,딱 맞는 치수의 갑옷이죠.,Hier ben je dan.,,Aqui está.,,Aici e.,Держи., -Perhaps some other time?,TXT_RNO1_SCRIPT33_D6064_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Tal vez en otro momento?,,Ehkä jokin toinen kerta?,Peut être une autre fois?,Talán később?,,また別の機会に?,아마 나중에 사야겠는데요?,Misschien een andere keer?,,Talvez outra hora?,,Poate altădată?,"Может, в следующий раз?", -Metal armor,TXT_RPLY2_SCRIPT33_D6064_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлическая броня, -Wear it in good health.,TXT_RYES2_SCRIPT33_D6064_WEARI,,,,Nes ho ve zdraví.,Trage sie und bleib gesund.,,,Llévala en buena salud.,,Pitäköön asu teidät terveenä.,Portez-la en bonne santé.,Használd egészséggel.,,着ると安心しますよ。,건강하게 착용하십시오.,Draag het in goede gezondheid.,,Vista com orgulho.,,Să o porți sănătos.,Носи на здоровье., -Come back when you can afford it.,TXT_RNO2_SCRIPT33_D6064_COMEB,,,,"Vrať se, až si to budeš moct dovolit.","Komme wieder, wenn du dir sie leisten kannst.",,,Vuelve cuando puedas permitírtela.,Vuelve cuando puedas pagarlo.,"Palataan asiaa, kun teillä on siihen varaa.",Revenez quand vous pouvez l'acheter.,Gyere vissza ha tellik rá.,,余裕がある時にまた。,돈이 좀 있을때 다시 찾아와주세요.,Kom terug wanneer je het je kunt veroorloven.,,Volte quando puder comprar.,,Întoarce-te când ai destui bani!,"Вернёшься, когда поднакопишь на то, что хочешь!", -How may I assist you?,TXT_DLG_SCRIPT33_D7580_HOWMA,,,,Jak ti mohu pomoci?,Womit kann ich dienen?,,,¿Cómo puedo ayudarte?,,Miten voin teitä avustaa?,Comment puis-je vous aider aujourd'hui?,Miben lehetek a segítségedre?,,何かお困りですか?,반갑습니다. 어떻게 도와드릴까요?,Hoe kan ik u helpen?,,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем могу помочь?, -Med patch,TXT_RPLY0_SCRIPT33_D7580_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekääre,Pansement.,Ragtapasz,,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Bandaj medical,Бинтами, -Here's your patch kit.,TXT_RYES0_SCRIPT33_D7580_HERES,,,,Tady je tvůj obvaz.,Hier ist deine Bandage.,,,Aquí tienes tu kit de parches.,,Tässä käärepakettisi.,Voilà votre pansement.,Itt a tapaszod.,,これをどうぞ。,저렴한 가격의 의료 붕대입니다.,Hier is je patch.,,Aqui está a sua compressa,,Aici este.,Вот они., -You need 10 gold for that.,TXT_RNO0_SCRIPT33_D7580_YOUNE,,,,Na ty potřebuješ deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitas 10 de oro para eso.,,Tarvitset sitä varten 10 kolikkoa.,Il vous faut 10 pièces pour ça.,10 aranyba kerül.,,10 ゴールド必要です。,10 골드입니다. 설마 이 만한 양의 돈이 없으신가요?,Daar heb je 10 goud voor nodig.,,Você precisa de 10 moedas para isto.,,Ai nevoie de 10 monezi pentru aia.,Тебе не хватает 10 золотых., -Field surgery kit,TXT_RPLY1_SCRIPT33_D7580_FIELD,,,,Lékárničku,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,,手術キット,수술 키트,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Аптечкой, -Thank you.,TXT_RYES1_SCRIPT33_D7580_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitoksia,Merci.,Köszönöm.,,ありがとうございます。,말 없이 주겠습니다. 거래 고마워요!,Bedankt.,,Obrigado.,,Merci.,Спасибо., -"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.","Ich wünschte, ich könnte sie verschenken, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.",,譲渡したい所ですが、25 ゴールド必要です。,25 골드만 있으면 잔소리 말고 주겠습니다.,"Ik wou dat ik ze kon weggeven, maar ze kosten 25 goud.",,"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 золотых.", -Healing,TXT_RPLY2_SCRIPT33_D7580_HEALI,,,,Ošetření,Heilung,,,Curación,,Sairaanhoitoa,Des soins.,Gyógyítás,,治療だ,치료 중.,Genezing,,Cura,,Vindecă-mă.,Медкомплектом, -There you go. Take care now.,TXT_RYES2_SCRIPT33_D7580_THERE,,,,A je to. Buď opatrný.,Bitteschön. Aber sei vorsichtiger.,,,Aquí tienes. Cúidate.,,Olkaa hyvä. Pitäkäähän nyt huoli itsestänne.,"Voilà pour vous, portez-vous-bien.",Meg is oldottam. Vigyázz magadra.,,こちらになります、お気をつけて。,치료가 끝났어. 몸 조심하라고.,Daar ga je. Pas goed op jezelf.,,Pronto. Se cuida.,,Gata. Ai grijă acum.,Пожалуйста. Береги себя!, -"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT33_D7580_WELLM,,,,Možná si můžeš dovolit nějaké obvazy?,"Naja, vielleicht kannst du dir ein paar Bandagen leisten?",,,"Bueno, ¿tal vez puedas permitirte algunos parches médicos?","Bueno, ¿tal vez puedas comprar algunos parches médicos?",Ehkä teillä olisi kuitenkin sidekääreisiin varaa?,"Eh bien, peut être pouvez-vous vous acheter quelques pansements?",Talán tellik pár tapaszra is?,,ところで、医薬パッチを買う余裕はありますか?,의료 붕대는 어떠신가요? 이 건 저렴한데.,"Nou ja, misschien kunt u zich wat medische patches veroorloven?",,"Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse medicale?","Тогда, может быть, купишь несколько бинтов?", -"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,,,,"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ší nepříplést se tomu do cesty.","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.",,"どうも余所者、この辺では見かけない顔だな。 +Here's the gold.,TXT_RPLY0_SCRIPT33_D1516_HERES,,,,Tady máš to zlato.,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.,,Tome estas moedas.,,Aici e aurul.,Вот монеты., +"If you punch someone, you won't set off the alarms.",TXT_RYES0_SCRIPT33_D1516_IFYOU,,,,"Když někoho praštíš, nespustíš alarmy.","Wenn du jemanden schlägst, wirst du keinen Alarm auslösen.",,,"Si golpeas a alguien, no activarás 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.",,"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.","Убивай холодным оружием, тогда ты не поднимешь тревогу.", +I won't tell you anything for free!,TXT_RNO0_SCRIPT33_D1516_IWONT,,,,Zadarmo ti nic říkat nebudu!,Umsonst werde ich dir nichts sagen.,,,¡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!,,Não te direi nada de graça!,,Nu-ți voi spune nimic pe gratis.,Бесплатно я не скажу ничего!, +I've already told you what I know.,TXT_DLG_SCRIPT33_D3032_IVEAL,,,,"Už jsem ti řekl, co vím.","Ich habe dir alles gesagt, was ich weiß.",,,Ya te he dicho 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.,,Já te disse o que eu sei.,,Ți-am spus deja tot ce știu.,"Я уже сказал тебе всё, что знал.", +Hello friend. What can I get for you?,TXT_DLG_SCRIPT33_D4548_HELLO,,,,"Zdravím, příteli, co ti mohu nabídnout?","Hallo, Freund, was kann ich dir geben?",,,"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?,,"Olá amigo, como posso te ajudar?",,"Bună prietene, ce pot să-ți aduc?",Здравствуй. Что-нибудь интересует?, +Electric bolts,TXT_RPLY0_SCRIPT33_D4548_ELECT,,,,Elektrické šípy,Elektrische Pfeile,,,Saetas eléctricas.,,Sähkönuolia,Carreaux électriques.,Elektromos nyilak,Dardi elettrificati ,エレクトリック ボルト,전격 볼트,Elektrische bouten,,Setas elétricas,,Bolțuri electrice,Электрические болты, +One quarrel it is.,TXT_RYES0_SCRIPT33_D4548_ONEQU,,,,Jeden toulec.,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.,,Está na mão.,,Aici sunt.,Один колчан., +You're broke!,TXT_RNO0_SCRIPT33_D4548_YOURE,,,,Jseš švorc!,Du bist pleite!,,,¡Estás sin blanca!,¡Estás quebrado!,Olet peeaa!,Vous êtes à sec!,Nincs is nálad pénz!,Sei sul lastrico!,スッカラカンじゃないか!,돈이 한 푼도 없는 것 같은데.,Je bent blut!,,Você está sem grana!,,Ești falit!,"Друг, да ты на мели!", +Clip of bullets,TXT_RPLY1_SCRIPT33_D4548_10ROU,,,,Zásobník s náboji,10-Kugeln-Magazin,,,Cargador de balas,,Luotilipas,Chargeur de 10 cartouches.,Egy tárnyi töltény,Un caricatore di proiettili,銃弾倉,돌격소총 탄창,Klem van kogels,,Carregador de balas,,Cartuș de gloanțe,Обойма патронов, +Here's your ammo,TXT_RYES1_SCRIPT33_D4548_HERES,,,,Tady je tvá munice.,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....,,Aqui está a sua munição.,,Aici e.,Вот твои патроны., +"Sorry, no money, no bullets.",TXT_RNO1_SCRIPT33_D4548_SORRY,,,,"Promiň. Žádné peníze, žádné náboje.","Tut mir leid. Kein Geld, keine Munition.",,,"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.",,"Desculpe. Sem grana, sem balas.",,"Scuze, niciun ban, niciun glonț.","Извини, нет денег — нет патронов!", +Ammo box,TXT_RPLY2_SCRIPT33_D4548_50ROU,,,,Krabici nábojů,50-Kugeln-Schachtel,,,Caja de municiones,,Luotilaatikko,Boîte de 50 balles.,Töltény doboz,Scatola di munizioni,銃弾倉箱,돌격소총 탄약 박스,Munitiedoos,,Caixa de munição,,Cutie cu muniție,Коробка патронов, +Here you go,TXT_RYES2_SCRIPT33_D4548_HEREY,,,,Tu máš.,Bitteschön.,,Jen,Aquí tienes,,Ole hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,どうぞ。,거래 감사드립니다.,Alsjeblieft,,Aqui está,,Aici este,Держи., +You don't have enough gold!,TXT_RNO2_SCRIPT33_D4548_YOUDO,,,,Nemáš dost zlaťáků!,Du hast nicht genug Gold.,,,¡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!,,Você não tem ouro suficiente!,,Nu ai suficient aur!,У тебя недостаточно золота!, +Ammo satchel,TXT_RPLY3_SCRIPT33_D4548_AMMOS,,,,Brašnu na munici,Munitionstasche.,,,Mochila de municiones,,Ammuslaukku,Sacoche de munitions.,Lőszeres hátizsák,Sacca di munizioni,弾薬鞄,탄약 배낭,Munitie tasje,,Mochila de munição,,Sac cu muniție,Ранец для боеприпасов, +"Thank you, anything else?",TXT_RYES3_SCRIPT33_D4548_THANK,,,,Děkuji. Něco dalšího?,"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?",,Obrigado. Mais alguma coisa?,,"Merci, altceva?",Благодарю. Что-нибудь ещё?, +"You can't afford that, good day.",TXT_RNO3_SCRIPT33_D4548_YOUCA,,,,"To si nemůžeš dovolit, přeji hezký den.",Das kannst du dir nicht leisten. Guten Tag.,,,"No puedes permitirte eso, buen día.","No puedes pagar eso, 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.",,Você não pode comprar isto. Tenha um bom dia.,,"Nu ai bani, ziua bună.",У тебя не хватает денег. Всего доброго!, +Welcome. What may I show you?,TXT_DLG_SCRIPT33_D6064_WELCO,,,,Vítej. Co bych ti mohl nabídnout?,Willkommen. Was darf ich dir zeigen?,,,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?,,Seja bem-vindo. O que posso lhe mostrar?,,Bună. Cu ce te pot ajuta?,Здравствуй. Что-нибудь интересует?, +Environmental suit,TXT_RPLY0_SCRIPT33_D6064_ENVIR,,,,Ochranný oblek,Schutzanzug.,,,Traje ambiental,,Ympäristösuojapuku,Combinaison Hazmat.,Védő ruha,Tuta ambientale,耐環境スーツ,환경 방호복,Beschermend Pak,,Traje de proteção,,Costum de Protecție împotriva Mediului,Защитный костюм, +Here you are.,TXT_RYES0_SCRIPT33_D6064_HEREY,,,,"Tak, tady to je.",Bitteschön.,,,Aquí tienes.,,"Tässä, olkaa hyvä.",Voilà pour vous.,Parancsolj.,Ecco a te.,はい、これをどうぞ。,받으세요!,Hier ben je dan.,,Aqui está.,,Aici e.,"Хорошо, бери.", +You don't have enough money for that.,TXT_RNO0_SCRIPT33_D6064_YOUDO,,,,Na to nemáš dost peněz.,Dafür hast du nicht genug Geld.,,,No tienes suficiente dinero para eso.,,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.,,Você não tem dinheiro o suficiente para isto.,,N-ai suficienți bani.,"Извини, но у тебя не хватает денег.", +Leather armor.,TXT_RPLY1_SCRIPT33_D6064_LEATH,,,Leather armour,Kožené brnění,Lederrüstung,,,Armadura de cuero.,,Nahkasuojus,Armure de cuir.,Bőr vért.,Armatura di cuoio,レザーアーマー,가죽 갑옷,Leren harnas,,Armadura de couro.,,Armură de piele.,Кожаная броня, +Here you are.,TXT_RYES1_SCRIPT33_D6064_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,Olkaa hyvä.,Voilà pour vous.,Parancsolj.,Ecco a te.,これをどうぞ。,딱 맞는 치수의 갑옷이죠.,Hier ben je dan.,,Aqui está.,,Aici e.,Держи., +Perhaps some other time?,TXT_RNO1_SCRIPT33_D6064_PERHA,,,,Možná někdy jindy?,Vielleicht ein anderes Mal?,,,¿Tal vez en otro momento?,,Ehkä jokin toinen kerta?,Peut être une autre fois?,Talán később?,Magari un'altra volta?,また別の機会に?,아마 나중에 사야겠는데요?,Misschien een andere keer?,,Talvez outra hora?,,Poate altădată?,"Может, в следующий раз?", +Metal armor,TXT_RPLY2_SCRIPT33_D6064_METAL,,,Metal armour,Kovové brnění,Metallrüstung,,,Armadura de metal,,Metallihaarniska,Armure de métal.,Fém vért,Armatura di metallo,メタルアーマー,강철 갑옷,Metalen harnas,,Armadura de metal,,Armură de metal,Металлическая броня, +Wear it in good health.,TXT_RYES2_SCRIPT33_D6064_WEARI,,,,Nos ho ve zdraví.,Trage sie und bleib gesund.,,,Llévala en buena salud.,,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.,,Vista com orgulho.,,Să o porți sănătos.,Носи на здоровье., +Come back when you can afford it.,TXT_RNO2_SCRIPT33_D6064_COMEB,,,,"Vrať se, až si to budeš moct dovolit.","Komme wieder, wenn du dir sie leisten kannst.",,,Vuelve cuando puedas permitírtela.,Vuelve cuando puedas pagarlo.,"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.,,Volte quando puder comprar.,,Întoarce-te când ai destui bani!,"Вернёшься, когда поднакопишь на то, что хочешь!", +How may I assist you?,TXT_DLG_SCRIPT33_D7580_HOWMA,,,,Jak ti mohu pomoci?,Womit kann ich dienen?,,,¿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?,,Como posso ajudá-lo?,,Cu ce te pot ajuta?,Чем могу помочь?, +Med patch,TXT_RPLY0_SCRIPT33_D7580_MEDPA,,,,Obvazy,Medizinische Bandage,,,Parche médico.,,Sidekääre,Pansement.,Ragtapasz,Bende,医薬パッチ,의료 붕대,Med-patch,,Compressa médica,,Bandaj medical,Бинтами, +Here's your patch kit.,TXT_RYES0_SCRIPT33_D7580_HERES,,,,Tady je tvůj obvaz.,Hier ist deine Bandage.,,,Aquí tienes tu kit de parches.,,Tässä käärepakettisi.,Voilà votre pansement.,Itt a tapaszod.,Ecco le tue bende.,これをどうぞ。,저렴한 가격의 의료 붕대입니다.,Hier is je patch.,,Aqui está a sua compressa,,Aici este.,Вот они., +You need 10 gold for that.,TXT_RNO0_SCRIPT33_D7580_YOUNE,,,,Na ty potřebuješ deset zlatých.,Dafür brauchst du 10 Gold.,,,Necesitas 10 de oro para eso.,,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.,,Você precisa de 10 moedas para isto.,,Ai nevoie de 10 monezi pentru aia.,Тебе не хватает 10 золотых., +Field surgery kit,TXT_RPLY1_SCRIPT33_D7580_FIELD,,,,Lékárničku,Erste-Hilfe-Kasten,,,Kit quirúrgico,,Kenttäkirurgilaukku,Kit de chirurgie.,Harctéri műtéti felszerelés,Kit chirurgico,手術キット,수술 키트,Veld chirurgie kit,,Kit de cirurgia,,Kit chirurgical de teren.,Аптечкой, +Thank you.,TXT_RYES1_SCRIPT33_D7580_THANK,,,,Děkuji.,Danke.,,Dankon.,Gracias.,,Kiitoksia,Merci.,Köszönöm.,Grazie.,ありがとうございます。,말 없이 주겠습니다. 거래 고마워요!,Bedankt.,,Obrigado.,,Merci.,Спасибо., +"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.","Ich wünschte, ich könnte sie verschenken, aber sie kosten 25 Gold.",,,"Ojalá pudiera regalarlos, pero cuestan 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.",,"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 золотых.", +Healing,TXT_RPLY2_SCRIPT33_D7580_HEALI,,,,Ošetření,Heilung,,,Curación,,Sairaanhoitoa,Des soins.,Gyógyítás,Ho bisogno di essere curato.,治療だ,치료 중.,Genezing,,Cura,,Vindecă-mă.,Медкомплектом, +There you go. Take care now.,TXT_RYES2_SCRIPT33_D7580_THERE,,,,A je to. Buď opatrný.,Bitteschön. Aber sei vorsichtiger.,,,Aquí tienes. Cúidate.,,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.,,Pronto. Se cuida.,,Gata. Ai grijă acum.,Пожалуйста. Береги себя!, +"Well, maybe you can afford some med patches?",TXT_RNO2_SCRIPT33_D7580_WELLM,,,,Možná si můžeš dovolit nějaké obvazy?,"Naja, vielleicht kannst du dir ein paar Bandagen leisten?",,,"Bueno, ¿tal vez puedas permitirte algunos parches médicos?","Bueno, ¿tal vez puedas comprar algunos parches médicos?",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?",,"Bem, talvez você possa comprar algumas compressas?",,"Păi, poate îți permiți niște truse medicale?","Тогда, может быть, купишь несколько бинтов?", +"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,,,,"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.","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.","どうも余所者、この辺では見かけない顔だな。 では一杯アドバイスをおごろう。 この付近が自由な発言を 許さないからって下手な真似をするなよ。 オーダーという自警団がすぐに駆けつけてくるぞ。","반갑네, 친구. 낯선 사람인 것 같은데, 조심하고 걸어 다니게나. 지금 이곳에서 꽤 많은 일이 일어났거든. 내가 하는 말을 들으면 이해가 될 걸세.","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.",,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.","Привет, дружище. Что-то я не видел тебя тут раньше. Дам тебе один совет: я бы на твоём месте был поосторожнее. Сейчас здесь такое творится, что лучше не высовываться.", -Information,TXT_RPLY0_SCRIPT33_D9096_INFOR,,,,Informace,Informationen,,Informoj,Información,,Tietoa.,Des infos.,Információ.,,情報,정보를 줘.,Informatie,,Informações,,Informație,Есть новости?, -The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT33_D9096_THESE,,,,Stoky ukrývají víc než jen krysy a roboty.,Die Kanalisation hat mehr zu bieten als Ratten und Roboter.,,,Las alcantarillas tienen más que 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.,,他は...下水道には鼠やロボが沢山だ。,"하수도엔 쥐도 있고, 오물도 있고, 그 중 위험한 로봇들도 있다네.",In het riool zijn meer dan alleen ratten en robots te vinden.,,Os esgotos abrigam mais do que ratos e robôs.,,Canalele găzduiesc mai mult decât roboți și șobolani.,В канализации водятся не только крысы и роботы., -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, 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?",,"ちょっと男はお金を稼ぐんだ。 +Information,TXT_RPLY0_SCRIPT33_D9096_INFOR,,,,Informace,Informationen,,Informoj,Información,,Tietoa.,Des infos.,Információ.,Informazioni,情報,정보를 줘.,Informatie,,Informações,,Informație,Есть новости?, +The sewers hold more than just rats and robots.,TXT_RYES0_SCRIPT33_D9096_THESE,,,,Stoky ukrývají víc než jen krysy a roboty.,Die Kanalisation hat mehr zu bieten als Ratten und Roboter.,,,Las alcantarillas tienen más que 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.,,Os esgotos abrigam mais do que ratos e robôs.,,Canalele găzduiesc mai mult decât roboți și șobolani.,В канализации водятся не только крысы и роботы., +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, 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?","ちょっと男はお金を稼ぐんだ。 あなたはこれらのジョーカーがうまく傾くと 思いますか?",먹고 살려면 돈이 필요하다네. 이 손님들은 팁도 안 준다니까!,"Hé, een man moet wat geld verdienen. Denk je dat deze grappenmakers een goede fooi geven?",,"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?,"Заработай немного денег, парень. Или ты думаешь, что все эти шутники щедро платят?", -"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?","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?",,"また戻ってね? +"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?","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?","また戻ってね? まあ、少なくともあなたは自分の肌を 損なわないようにするのに十分知っています。 私は今あなたのために何ができますか?","다시 돌아온 건가? 뭐, 자기 몸 간수 잘하고 살아 돌아왔기에 망정이지. 뭘 원하나?","Weer terug, hè? Nou ja, je weet tenminste genoeg om je eigen huid intact te houden. Wat kan ik nu voor je doen?",,"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?","Снова ты? Ну что ж, ты хотя бы знаешь, как шкуру сберечь. Что я могу тебе предложить?", -More info,TXT_RPLY0_SCRIPT33_D10612_MOREI,,,,Další informace,Mehr Informationen.,,,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,,話のネタ。,그 외의 정보를 줘.,Meer info,,Mais informações.,,Mai multă informație,Расскажи больше, -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.,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.,,知事は俺達に自由はないと思い出させる象徴さ。,모렐 총독은 부정하고 짜증 나는 오더의 정권의 예야.,De gouverneur is een eenvoudige herinnering aan de invloed van de Orde.,,O governador é um simples lembrete da influência da Ordem.,,Guvernatorul e o simplă reamintire a influenței Ordinului.,Губернатор — живое напоминание о власти Ордена., -Come back if you change your mind.,TXT_RNO0_SCRIPT33_D10612_COMEB,,,,"Vrať se, pokud změníš názor.","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.,,気が変わったら戻ってきな。,마음이 바뀌면 돌아와주게나.,Kom terug als u van gedachten verandert.,,Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся., -"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 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.",,"所で、アンタは死に行かない人達に +More info,TXT_RPLY0_SCRIPT33_D10612_MOREI,,,,Další informace,Mehr Informationen.,,,Más información,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,그 외의 정보를 줘.,Meer info,,Mais informações.,,Mai multă informație,Расскажи больше, +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.,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.,,O governador é um simples lembrete da influência da Ordem.,,Guvernatorul e o simplă reamintire a influenței Ordinului.,Губернатор — живое напоминание о власти Ордена., +Come back if you change your mind.,TXT_RNO0_SCRIPT33_D10612_COMEB,,,,"Vrať se, pokud změníš názor.","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.,,Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся., +"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 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...","所で、アンタは死に行かない人達に 聞き回ってる様だが。悪いことは言わねえ、 あんまし死に急ぐんじゃねえぞ。","아주 오래 살아서 배짱이 두둑한가, 다시 돌아와 줬구먼! 나야말로 괜찮다네. 이 주정부리들 보다 자네랑 대화하는 게 그나마 낫지.","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.",,"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.","Да, для человека, который прожил так долго, ты задаёшь многовато вопросов. Впрочем, это неплохо: я бы скорее предпочёл говорить с кем-то вроде тебя, чем с местными.", -More info.,TXT_RPLY0_SCRIPT33_D12128_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,,話のネタ。,더 많은 정보를 줘.,Meer info.,,Mais informações.,,Mai multă informație.,Говори дальше., -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íš.","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.",,オーダーは見えてる以上に強大だ。,여기저기 퍼지는 소문보다 오더가 지키는 비밀이 더 깊숙하다네.,De Orde heeft meer te bieden dan wat er hier gebeurt.,,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.,"Орден — нечто большее, чем кажется.", -Come back if you change your mind.,TXT_RNO0_SCRIPT33_D12128_COMEB,,,,"Vrať se, pokud změníš názor.","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.",,気が変わったら戻ってきな。,생각이 바뀌면 다시 돌아오게나.,Kom terug als je van gedachten verandert.,,Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся., -"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.","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.",,"これはこれは親友、心得の瓶は切らしてるぞ。 +More info.,TXT_RPLY0_SCRIPT33_D12128_MOREI,,,,Další informace,Mehr Informationen.,,,Más información.,,Lisää tietoa.,Plus d'infos.,Több információ.,Altre informazioni,話のネタ。,더 많은 정보를 줘.,Meer info.,,Mais informações.,,Mai multă informație.,Говори дальше., +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íš.","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.,,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.,"Орден — нечто большее, чем кажется.", +Come back if you change your mind.,TXT_RNO0_SCRIPT33_D12128_COMEB,,,,"Vrať se, pokud změníš názor.","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.,,Volte quando mudar de idéia.,,Întoarce-te dacă te răzgândești.,Передумаешь — возвращайся., +"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.","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.",,"É 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.","Это всё, дружище. Кладезь мудрости исчерпан. Я и так рассказал тебе больше, чем следовало.", -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,,,,"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.","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 jugetes... cuando estás sin blanca. Haz algunos recados para mi y conseguirás más de lo que puedas gastarte. Te haré un hombre rico.,Difícil comprarse nuevos jugetes... cuando estás quebrado. Haz algunos encargos para mi y conseguirás más de lo que puedas gastarte. Te haré 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.",,"新しい玩具も買えないぐらい...貧しそうだな +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,,,,"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.","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 jugetes... cuando estás sin blanca. Haz algunos recados para mi y conseguirás más de lo que puedas gastarte. Te haré un hombre rico.,Difícil comprarse nuevos jugetes... cuando estás quebrado. Haz algunos encargos para mi y conseguirás más de lo que puedas gastarte. Te haré 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.,,"É 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.,"Трудновато покупать игрушки, когда нет и гроша за душой... Выполни одно заданьице для меня, и ты заработаешь столько, сколько в твоих карманах сроду не водилось. Ты будешь богатым!", -I got nothing better to do.,TXT_RPLY0_SCRIPT33_D15160_IGOTN,,,,Nemám nic lepšího na práci.,Ich habe nichts besseres zu tun.,,,No tengo nada mejor que hacer.,,Ei minulla parempaakaan tekemistä ole.,Je n'ai rien de mieux à faire.,Nincs jobb dolgom úgy sem.,,何もしないよりはいいか。,저는 할 것이 아무것도 없어요.,Ik heb niets beters te doen.,,Não tenho nada melhor pra fazer.,,N-am nimic mai bun de făcut.,Заманчивое предложение., -No thanks.,TXT_RPLY1_SCRIPT33_D15160_NOTHA,,,,"Ne, díky.","Nein, danke.",,Ne dankon.,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,,いらない。,아뇨 괜찮습니다.,"Nee, bedankt.",,"Não, obrigado.",,Nu merci.,"Нет, спасибо.", -Nobody walks away from me!,TXT_RYES1_SCRIPT33_D15160_NOBOD,,,,Ode mě nikdo neodchází!,Niemand sagt Nein zu mir.,,,¡Nadie pasa de mí!,¡Nadie se aleja 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!,,俺から逃げられると思ってるのか!,그 누구도 나를 거절할 수 없어!,Niemand loopt weg van mij!,,Ninguém me ignora!,,Nimeni nu scapă de mine!,От меня ещё никто не уходил!, -"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.",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.",,"良い判断だ。川沿いにある オーダーの聖域 は +I got nothing better to do.,TXT_RPLY0_SCRIPT33_D15160_IGOTN,,,,Nemám nic lepšího na práci.,Ich habe nichts besseres zu tun.,,,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.,,Não tenho nada melhor pra fazer.,,N-am nimic mai bun de făcut.,Заманчивое предложение., +No thanks.,TXT_RPLY1_SCRIPT33_D15160_NOTHA,,,,"Ne, díky.","Nein, danke.",,Ne dankon.,No gracias.,,Ei kiitos.,Non merci.,Nem kösz.,No grazie.,いらない。,아뇨 괜찮습니다.,"Nee, bedankt.",,"Não, obrigado.",,Nu merci.,"Нет, спасибо.", +Nobody walks away from me!,TXT_RYES1_SCRIPT33_D15160_NOBOD,,,,Ode mě nikdo neodchází!,Niemand sagt Nein zu mir.,,,¡Nadie pasa de mí!,¡Nadie se aleja 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!,,Ninguém me ignora!,,Nimeni nu scapă de mine!,От меня ещё никто не уходил!, +"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.",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.,"良い判断だ。川沿いにある オーダーの聖域 は あいつらの非公式の拷問室だ。 中には黄金の聖杯が隠してある。 そいつを持ってくれば報酬をやるぜ。 ",좋은 선택이야. 강가 근처에 있는 성소가 바로 오더의 비공식적인 고문실이야. 그리고 그 안에는 숨겨진 금색 성배가 있지. 넌 그것을 훔치고 여기 선술집으로 와서 보상을 받으면 돼.,"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.",,"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.","Правильный выбор. В святилище Ордена у реки — там у них негласная камера пыток — спрятана золотая чаша. Ты крадёшь её, возвращаешься ко мне в таверну и получаешь свою награду.", -How am I supposed to do that?,TXT_RPLY0_SCRIPT33_D16676_HOWAM,,,,Jak to mám udělat?,Wie soll ich das anstellen?,,,¿Cómo se supone que hago eso?,,Miten minä muka sen teen?,Comment est-ce que je suis sensé faire ça?,Hogyan kéne ezt véghezvinnem?,,どうすればいいんだ?,어떻게 하면 되나요?,Hoe moet ik dat doen?,,Como vou conseguir fazer isso?,,Cum ar trebui să fac asta?,Как мне это сделать?, -Let me think about it.,TXT_RPLY1_SCRIPT33_D16676_LETME,,,,Nech mě o tom popřemýšlet.,Lass mich darüber nachdenken.,,,Déjame pensarlo.,,Anna minun pohtia asiaa.,Laissez-moi y réfléchir.,Hadd gondolkozzak.,,ちょっと考えとく。,좀 생각해 보겠습니다.,Laat me erover nadenken.,,Vou pensar sobre isso.,,Lasă-mă să mă gândesc.,Я подумаю над твоим предложением., -"Sorry, no second chances. Oh, guards, kill him!",TXT_RYES1_SCRIPT33_D16676_SORRY,,,,"Promiň, žádné druhé šance. A, stráže, zabte ho!","Keine zweite Chance. Oh Wachen, tötet ihn.",,,"Lo siento, no hay segundas oportunidades. Oh, 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!",,"残念、次はねえよ。おぅガードの旦那、 +How am I supposed to do that?,TXT_RPLY0_SCRIPT33_D16676_HOWAM,,,,Jak to mám udělat?,Wie soll ich das anstellen?,,,¿Cómo se supone que hago 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?,,Como vou conseguir fazer isso?,,Cum ar trebui să fac asta?,Как мне это сделать?, +Let me think about it.,TXT_RPLY1_SCRIPT33_D16676_LETME,,,,Nech mě o tom popřemýšlet.,Lass mich darüber nachdenken.,,,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.,,Vou pensar sobre isso.,,Lasă-mă să mă gândesc.,Я подумаю над твоим предложением., +"Sorry, no second chances. Oh, guards, kill him!",TXT_RYES1_SCRIPT33_D16676_SORRY,,,,"Promiň, žádné druhé šance. A, stráže, zabte ho!","Keine zweite Chance. Oh Wachen, tötet ihn.",,,"Lo siento, no hay segundas oportunidades. Oh, 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!",,"Sinto muito, nada de segundas chances. Ah, guardas, matem-no!",,"Oh, nicio altă șansă. Gardienilor, omorâți-l.","Нет, никакого второго шанса. Эй, стража, убейте его.", -"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ě.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,,"Toma una ballesta, solo apunta derecho y -- ¡splat! --. Recuerda, toma la copa bonita y ven 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.",,"このクロスボウを使いな、狙いを定めて +"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ě.","Hier ist eine Armbust, einfach gerade zielen und --Platsch--. Denk dran, schnapp dir den schicken Kelch und dann ab zur Taverne.",,,"Toma una ballesta, solo apunta derecho y -- ¡splat! --. Recuerda, toma la copa bonita y ven 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.",,"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ă.",Вот арбалет — просто прицеливаешься и «шлеп!» Запомни — хватаешь чашку и возвращаешься в таверну., -I'll see you there.,TXT_RPLY0_SCRIPT33_D18192_ILLSE,,,,Uvidíme se tam.,Wir sehen uns dort.,,,Te veré allí.,,Tapaan sinut siellä.,Je vous y verrais.,Ott találkozunk.,,また会おう。,거기서 보자고.,Ik zie je daar.,,Te vejo lá.,,Ne vedem acolo.,Я вернусь с чашей., -"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!","Worauf wartest du noch? Keine Sorge, ich kümmere mich um die Leichen. Bring mir den Kelch.",,,"¿Qué estás esperando? No te preocupes, me desharé de los cuerpos, ¡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.",,"何ボーっとしてんだ? 心配すんな、 +I'll see you there.,TXT_RPLY0_SCRIPT33_D18192_ILLSE,,,,Uvidíme se tam.,Wir sehen uns dort.,,,Te veré allí.,,Tapaan sinut siellä.,Je vous y verrais.,Ott találkozunk.,Ci vediamo lì.,また会おう。,거기서 보자고.,Ik zie je daar.,,Te vejo lá.,,Ne vedem acolo.,Я вернусь с чашей., +"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!","Worauf wartest du noch? Keine Sorge, ich kümmere mich um die Leichen. Bring mir den Kelch.",,,"¿Qué estás esperando? No te preocupes, me desharé de los cuerpos, ¡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!",,"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.",Чего ты ждёшь? Не беспокойся: я сам избавлюсь от трупов. Просто принеси мне чашу!, -Guards! Kill the traitor!,TXT_DLG_SCRIPT33_D21224_GUARD,,,,Stráže! Zabte toho zrádce!,Wächter! Tötet den Verräter!,,,¡Guardias! ¡Maten al traidor!,,Vartijat! Tappakaa petturi!,Gardes! Tuez ce traître!,Őrök! Öljétek meg az árulót!,,ガード! 裏切者を殺せ!,경비! 반역자를 죽여라!,Bewakers! Dood de verrader!,,Guardas! Matem esse traidor!,,"Gardieni, omorâți trădătorul!",Стража! Убейте предателя!, -"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, 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.",,"よう。アンタが何を考えてるかわかるぜ、 +Guards! Kill the traitor!,TXT_DLG_SCRIPT33_D21224_GUARD,,,,Stráže! Zabte toho zrádce!,Wächter! Tötet den Verräter!,,,¡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!,,Guardas! Matem esse traidor!,,"Gardieni, omorâți trădătorul!",Стража! Убейте предателя!, +"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, 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à.","よう。アンタが何を考えてるかわかるぜ、 まるで罠だと。 俺には暴れん坊みたいな芸当出来ねえしな。 おう、カップを巡って大騒ぎだろうなこりゃ、 怖い怖い。 だったら準備しな、金と名誉は、約束通り。 この鍵を取ったら知事が報酬を与えるだろうな。","이봐, 무슨 생각을 하는지 알겠어. 확실히 뭔가 꾸며 놓은 것 같다는 거. 난 훌륭한 학살 기계에게 그런 짓을 할 사람이 아니야. 휴... 그깟 컵 가지고. 이상해. 아무튼 준비해, 골드와 영광을. 이 열쇠를 총독에게 가져다주면 보상해 줄 거야.","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.",,"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.","Слушай, я знаю, о чём ты думаешь. Ты думаешь, что это подстава. Но я бы никогда не сделал этого с такой машиной для убийств, как ты, правда-правда. Тем более, ради какой-то чаши. А теперь, тебя ждут золото и слава, как я и обещал. Возьми этот ключ, губернатор лично наградит тебя.", -"Great, I can't wait!",TXT_RPLY0_SCRIPT33_D22740_GREAT,,,,"Skvělý, nemůžu se dočkat!","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!",,そりゃいいな、待ち遠しい!,좋았어! 기다릴 수 없는걸?,"Geweldig, ik kan niet wachten!",,"Ótimo, mal posso esperar!",,"Grozav, abia aștept.",Прекрасно. Мне уже не терпится!, -"No chalice, no money!",TXT_RNO0_SCRIPT33_D22740_NOCHA,,,,"Žádný kalich, žádný prachy!","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!",,聖杯が無いなら、金も無しだ!,성배가 없다면 돈도 없어!,"Geen kelk, geen geld!",,"Sem cálice, sem dinheiro!",,"Niciun potir, niciun ban!",Нет чаши — нет денег!, -"I'll keep the chalice, thanks.",TXT_RPLY1_SCRIPT33_D22740_ILLKE,,,,"Nechám si ten kalich, díky.","Ich behalte den Kelch, danke.",,,"Me quedaré el caliz, gracias.",,"Pidän kalkin, kiitos.","Je le garde, merci.","Inkább megtartom a serleget, kösz.",,聖杯は頂く、じゃあな。,"내가 성배를 가지고 있을게, 고마워.","Ik bewaar de kelk, bedankt.",,"Vou ficar com o cálice, obrigado.",,"Păstrez potirul, merci.","Спасибо, но я оставлю чашу себе.", -Keep it? I think not!,TXT_RYES1_SCRIPT33_D22740_KEEPI,,,,Necháš? Nemyslím si!,"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!,,頂く? 有り得ねえな!,가지고 있겠다고? 내 생각은 아닌데?,Bewaren? Ik denk van niet!,,Ficar com o cálice? Acho que não!,,Păstrezi? Ba nu cred!,Оставишь себе? Ещё чего!, -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í.,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.,,何突っ立ってんだ? 知事に報酬を受けて来いよ。,꾸물거리지 말고 총독을 만나. 그가 너를 보답해줄 거야.,Waar wacht je nog op? De gouverneur zelf zal je belonen.,,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.,Чего ты ждёшь? Губернатор лично наградит тебя., -Die traitor! ,TXT_DLG_SCRIPT33_D25772_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter!",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,,くたばれ裏切者が!,죽어라. 배신자!,Sterf de verrader!,,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", -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?","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?,,"それで、お前が聖杯を盗んだ愚か者か? +"Great, I can't wait!",TXT_RPLY0_SCRIPT33_D22740_GREAT,,,,"Skvělý, nemůžu se dočkat!","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!",,"Ótimo, mal posso esperar!",,"Grozav, abia aștept.",Прекрасно. Мне уже не терпится!, +"No chalice, no money!",TXT_RNO0_SCRIPT33_D22740_NOCHA,,,,"Žádný kalich, žádný prachy!","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!",,"Sem cálice, sem dinheiro!",,"Niciun potir, niciun ban!",Нет чаши — нет денег!, +"I'll keep the chalice, thanks.",TXT_RPLY1_SCRIPT33_D22740_ILLKE,,,,"Nechám si ten kalich, díky.","Ich behalte den Kelch, danke.",,,"Me quedaré el caliz, 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.",,"Vou ficar com o cálice, obrigado.",,"Păstrez potirul, merci.","Спасибо, но я оставлю чашу себе.", +Keep it? I think not!,TXT_RYES1_SCRIPT33_D22740_KEEPI,,,,Necháš? Nemyslím si!,"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!,,Ficar com o cálice? Acho que não!,,Păstrezi? Ba nu cred!,Оставишь себе? Ещё чего!, +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í.,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.,,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.,Чего ты ждёшь? Губернатор лично наградит тебя., +Die traitor! ,TXT_DLG_SCRIPT33_D25772_DIETR,,,,"Zemři, zrádče!","Stirb, Verräter!",,,"¡Muere, traidor!",,"Kuole, petturi!","Meurs, traître!",Halál rád áruló!,Muori traditore!,くたばれ裏切者が!,죽어라. 배신자!,Sterf de verrader!,,"Morra, traidor!",,Mori trădătorule!,"Умри, предатель!", +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?","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?,"それで、お前が聖杯を盗んだ愚か者か? 私は反賊としてお前を逮捕するつもりだ... そうすればオーダーでの地位が上がる。 無意味な駒だと思うか? ",그래서 네가 그 성배를 훔친 바보로군? 반군 절도범으로 체포해주지... 오더에서의 내 위치도 올리는 겸. 모르는 사이에 장물아비가 된 기분이 어떤가?,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?,,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?,"Так это ты тот недоумок, что украл чашу? Я передам тебя Ордену, как вора повстанцев... Это укрепит мои отношения с ним. Каково чувствовать себя безмозглой пешкой?", -It sucks!,TXT_RPLY0_SCRIPT33_D27288_ITSUC,,,,Je to na hovno!,Scheiße!,,Ĝi aĉas!,¡Apesta!,,Ihan perseestä!,Quelle merde!,Ez szopás!,,クソが!,기분이 아주 좆같아.,Het is klote!,,É uma merda!,,Nașpa!,Чтоб ты сдох!, -For you it does.,TXT_RYES0_SCRIPT33_D27288_FORYO,,,,Pro tebe určitě.,Du steckst ganz tief drin.,,,"Para ti, sí.",,"Kyllä, sinun tilanteesi.","Pour vous, en effet.",...és a bráner rossz végén vagy.,,私もそう思う。,더한 기분이 들게 해주지.,Voor jou wel.,,"Pra você, é mesmo.",,"Pentru tine, într-adevăr este.",Скоро сдохнешь ты., -Harris promised me money!,TXT_RPLY1_SCRIPT33_D27288_HARRI,,,,Harris mi slíbil peníze!,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 beloofde me geld!,,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!, -Too bad. The only thing you're getting is death!,TXT_RYES1_SCRIPT33_D27288_TOOBA,,,,"Smůla. Jediné, co dostaneš, je smrt!",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.",,残念だな、お前にやれるものは死のみだ!,안됐네. 넌 여기서 죽게 될테니까!,Jammer. Het enige wat je krijgt is de dood!,,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ce vei primi e moarte!,"Увы. Всё, что ты получишь, — это смерть!", -We're going to kill you!,TXT_DLG_SCRIPT33_D28804_WEREG,,,,Zabijeme tě!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,,お前をぶっ殺す!,우린 널 죽일 거야!,We gaan je vermoorden!,,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!, -Get out of here!,TXT_DLG_SCRIPT33_D30320_GETOU,,,,Vypadni odsud!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,,ここから立ち去れ!,여길 나가!,Maak dat je hier wegkomt!,,Saia daqui!,,Valea!,Убирайся отсюда!, -We're going to kill you!,TXT_DLG_SCRIPT33_D31836_WEREG,,,,Zabijeme tě!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,,お前をぶっ殺す!,널 죽이는걸 즐길테다.,We gaan je vermoorden!,,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!, -Get out of here!,TXT_DLG_SCRIPT33_D33352_GETOU,,,,Vypadni odsud!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,,ここから立ち去れ!,여기서 뭐하는 거야? 꺼져!,Maak dat je wegkomt!,,Saia daqui!,,Valea!,Убирайся отсюда!, -"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,,,,"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ý.","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.",,"旧市庁舎の下で、 +It sucks!,TXT_RPLY0_SCRIPT33_D27288_ITSUC,,,,Je to na hovno!,Scheiße!,,Ĝi aĉas!,¡Apesta!,,Ihan perseestä!,Quelle merde!,Ez szopás!,È uno schifo!,クソが!,기분이 아주 좆같아.,Het is klote!,,É uma merda!,,Nașpa!,Чтоб ты сдох!, +For you it does.,TXT_RYES0_SCRIPT33_D27288_FORYO,,,,Pro tebe určitě.,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.,,"Pra você, é mesmo.",,"Pentru tine, într-adevăr este.",Скоро сдохнешь ты., +Harris promised me money!,TXT_RPLY1_SCRIPT33_D27288_HARRI,,,,Harris mi slíbil peníze!,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!,,O Harris prometeu me pagar!,,Harris mi-a promis bani!,Харрис обещал мне деньги!, +Too bad. The only thing you're getting is death!,TXT_RYES1_SCRIPT33_D27288_TOOBA,,,,"Smůla. Jediné, co dostaneš, je smrt!",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!,,Que pena. A única coisa que você vai receber é a morte!,,Păcat. Tot ce vei primi e moarte!,"Увы. Всё, что ты получишь, — это смерть!", +We're going to kill you!,TXT_DLG_SCRIPT33_D28804_WEREG,,,,Zabijeme tě!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,우린 널 죽일 거야!,We gaan je vermoorden!,,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!, +Get out of here!,TXT_DLG_SCRIPT33_D30320_GETOU,,,,Vypadni odsud!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여길 나가!,Maak dat je hier wegkomt!,,Saia daqui!,,Valea!,Убирайся отсюда!, +We're going to kill you!,TXT_DLG_SCRIPT33_D31836_WEREG,,,,Zabijeme tě!,Wir werden euch töten!,,,¡Vamos a matarte!,,Tapamme sinut!,On va te buter!,Megölünk!,Adesso ti ammazziamo!,お前をぶっ殺す!,널 죽이는걸 즐길테다.,We gaan je vermoorden!,,Nós vamos te matar!,,Te vom omorâ!,Готовься к смерти!, +Get out of here!,TXT_DLG_SCRIPT33_D33352_GETOU,,,,Vypadni odsud!,Verschwinde von hier!,,,¡Sal de aquí!,,Häivy täältä!,Sortez de là!,Pusztulj innen!,Fuori di qui!,ここから立ち去れ!,여기서 뭐하는 거야? 꺼져!,Maak dat je wegkomt!,,Saia daqui!,,Valea!,Убирайся отсюда!, +"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,,,,"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ý.","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.","旧市庁舎の下で、 私たちにとって何という完璧な場所です。 秩序は彼らが私たちを消滅させたと考 えていますが、それがすべてだったのは あなたが不注意になったときに起こり得ることを 私たちに思い出させるものです。","정말 경치 좋지? 이 박살 난 시청 주변에서. 오더 놈들이 우리들을 전멸했다고 자랑하는데, 우리들이 힘을 모아서 복수하기 전까진 그렇게 놓아두는 게 좋을 것 같아.","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.",,"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.","Здесь, под городской ратушей, такое чудесное место для нашей базы! Орден думает, что мы разгромлены, но мы всего лишь усвоили урок о цене беспечности.", -"Talk to Macil, he'll be able to help you.",TXT_DLG_SCRIPT34_D1516_TALKT,,,,Promluv si s Macilem. On ti pomůže.,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.",,マシルと話すんだ。彼から援助が得られるはず。,"마실 사령관님에게 말해, 그가 널 도울 수 있을 거야.","Praat met Macil, hij zal je kunnen helpen.",,Fale com o Macil. Ele vai poder te ajudar.,,"Vorbește cu Macil, el te poate ajuta.",Обратись к Мэйсилу. Он поможет тебе., -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,,,,"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.","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.",,"私はマシルがオーダーを転覆させる計画を +"Talk to Macil, he'll be able to help you.",TXT_DLG_SCRIPT34_D1516_TALKT,,,,Promluv si s Macilem. On ti pomůže.,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.",,Fale com o Macil. Ele vai poder te ajudar.,,"Vorbește cu Macil, el te poate ajuta.",Обратись к Мэйсилу. Он поможет тебе., +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,,,,"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.","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.,"私はマシルがオーダーを転覆させる計画を 持っていると聞いた。そうだと良かったが。 我々は一度大敗し全滅しかけた。",마실 사령관이 또 다른 작전을 준비한데. 그전에 일어났던 대참사보다 훨씬 나은 작전이었으면 좋겠는데. 운이 나쁘면 많은 병력을 잃어버릴 것 같아.,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.,,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.,"Я слышал, что Мэйсил готовит новую операцию после провала предыдущей. Она должна быть крайне успешной. После второго такого провала мы уже не оправимся.", -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.,"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.,,"ここの樽は捨てられていた物で +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.,"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.",,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.,"Несколько таких бочек, сброшенных в их водоснабжение, причинят немало неприятностей.", -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,,,,"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?","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?",,,Estoy trabajando en algo que nos dará una ventaja. Aumentará tu aguante y te pondrá a tope. 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?",,"私は研究にも取り組んでいる。貴方のスタミナを +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,,,,"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?","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?",,,Estoy trabajando en algo que nos dará una ventaja. Aumentará tu aguante y te pondrá a tope. 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?,,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?,"Я работаю кое над чем, что может нам пригодиться. Оно увеличит твою выносливость и улучшит самочувствие. Я уже исправил почти все дефекты. Или тебе нужно что-то ещё?", -Patch me up.,TXT_RPLY0_SCRIPT34_D6064_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., -"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,君、滅茶苦茶だな。なんとかしよう。,가능한 한 아프지 않게 치료하겠습니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.",,"Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.", -Stamina implant?,TXT_RPLY1_SCRIPT34_D6064_STAMI,,,,Implantát pro výdrž?,Ausdauerimplantat?,,,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,,Implante de resistência?,,Implant de rezistență?,Выносливостный имплант?, -"All right, this won't take but a moment.",TXT_RYES1_SCRIPT34_D6064_ALLRI,,,,"Dobře, tohle potrvá jen chvilku.","Alles klar, das haben wir sofort.",,,"Muy bien, esto solo 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.",,大丈夫、すぐ終わります。,많이 걸리진 않을거에요...,"Oké, dit duurt maar een momentje.",,"Ok, isso não vai demorar.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.", -It's not done yet.,TXT_RNO1_SCRIPT34_D6064_ITSNO,,,,Ještě není hotový.,Es ist noch nicht soweit.,,,Aún no está listo.,,Se ei ole valmis vielä.,Ce n'est pas encore terminé.,Még nincs kész.,,まだ完成していません。,연구가 진행중입니다. 나중에.,Het is nog niet klaar.,,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов., -"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?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Hey, estoy trabajando en una versión actualizada de tu implante. ¿Hay algo que pueda hacer por ti?",,"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?,,"どうも、私は今最新版のインプラントに +Patch me up.,TXT_RPLY0_SCRIPT34_D6064_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Hoida minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., +"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,"Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.", +Stamina implant?,TXT_RPLY1_SCRIPT34_D6064_STAMI,,,,Implantát pro výdrž?,Ausdauerimplantat?,,,¿Implante de aguante?,,Kuntoistute?,Implant d'endurance?,Állóképesség implantátum?,Impianto stamina?,スタミナインプラント?,지구력 향상 이식?,Stamina implantaat?,,Implante de resistência?,,Implant de rezistență?,Выносливостный имплант?, +"All right, this won't take but a moment.",TXT_RYES1_SCRIPT34_D6064_ALLRI,,,,"Dobře, tohle potrvá jen chvilku.","Alles klar, das haben wir sofort.",,,"Muy bien, esto solo 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.",,"Ok, isso não vai demorar.",,"În regulă, va dura doar un moment.","Отлично, это займёт всего пару секунд.", +It's not done yet.,TXT_RNO1_SCRIPT34_D6064_ITSNO,,,,Ještě není hotový.,Es ist noch nicht soweit.,,,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.,,Ainda não terminei.,,Încă nu e gata.,Он ещё не готов., +"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?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Hey, estoy trabajando en una versión actualizada de tu implante. ¿Hay algo que pueda hacer por ti?",,"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?",,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?","Я работаю над улучшенной версией твоего импланта. А пока, что-нибудь ещё?", -Patch me up.,TXT_RPLY0_SCRIPT34_D7580_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., -Well at least you're seeing action.,TXT_RYES0_SCRIPT34_D7580_WELLA,,,,"No, alespoň jsi v akci.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Bueno, al menos ves algo de acción.",,"No, ainakin näet toimintaa.","Eh bien, au moins vous en voyez, de l'action.",Legalább ér valami izgalom.,,少なくとも行動を起こしているのです。,이제 마음껏 움직여보세요.,"Nou ja, je ziet in ieder geval actie.",,"Bem, pelo menos está tendo um pouco de ação.",,"Pă, măcar tu ai parte de niște acțiune.","Что ж, зато ты участвуешь в операциях.", -Implant upgrade?,TXT_RPLY1_SCRIPT34_D7580_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,,Versão aprimorada do implante?,,Upgrade la implant?,Улучшение импланта?, -"Good thing, never can be too safe.",TXT_RYES1_SCRIPT34_D7580_GOODT,,,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Alles klar, das haben wir sofort.",,,"Cosa buena, nunca se puede estar seguro del todo.",,"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.",,良いことだ、安全すぎることはない。,위험 할 때도 있으니 지금 고치겠습니다.,"Goede zaak, kan nooit te veilig zijn.",,Boa ideia. Segurança nunca é demais.,,"Bine zis, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.", -"I'm almost finished, but not quite.",TXT_RNO1_SCRIPT34_D7580_IMALM,,,,"Už je skoro hotový, ale ne úplně.",Es ist noch nicht soweit.,,,"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",,もうすぐ出来上がる、それほど掛からない。,거의 완성했는데... 아마도 다음 시간에?,"Ik ben bijna klaar, maar niet helemaal.",,Está quase pronto.,,"Sunt aproape gata, dar nu chiar.",Я почти закончил. Ещё немного., -"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?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Muy bien, esto es todo. Casi tengo todo funcionando perfectamente. Hubo algunos problemas restantes para arreglar, ¿necesitas alguna otra cosa?",,"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?",,"大丈夫、全て順調だ。残っていた問題も +Patch me up.,TXT_RPLY0_SCRIPT34_D7580_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Pistä minut kuntoon.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., +Well at least you're seeing action.,TXT_RYES0_SCRIPT34_D7580_WELLA,,,,"No, alespoň jsi v akci.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Bueno, al menos ves 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.",,"Bem, pelo menos está tendo um pouco de ação.",,"Pă, măcar tu ai parte de niște acțiune.","Что ж, зато ты участвуешь в операциях.", +Implant upgrade?,TXT_RPLY1_SCRIPT34_D7580_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?,,Versão aprimorada do implante?,,Upgrade la implant?,Улучшение импланта?, +"Good thing, never can be too safe.",TXT_RYES1_SCRIPT34_D7580_GOODT,,,,"Dobrá věcička, nikdy si nemůžeš být moc jistý.","Alles klar, das haben wir sofort.",,,"Cosa buena, nunca se puede estar seguro del todo.",,"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.",,Boa ideia. Segurança nunca é demais.,,"Bine zis, nu poți fi niciodată prea sigur.","Очень советую, ни в чём нельзя быть уверенным до конца.", +"I'm almost finished, but not quite.",TXT_RNO1_SCRIPT34_D7580_IMALM,,,,"Už je skoro hotový, ale ne úplně.",Es ist noch nicht soweit.,,,"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.",,Está quase pronto.,,"Sunt aproape gata, dar nu chiar.",Я почти закончил. Ещё немного., +"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?","He, ich arbeite an einer verbesserten Version deines Implantats. Gibt es sonst etwas, das ich für dich tun kann?",,,"Muy bien, esto es todo. Casi tengo todo funcionando perfectamente. Hubo algunos problemas restantes para arreglar, ¿necesitas alguna otra cosa?",,"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?",,"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?","Итак, тут оставалась пара проблем, но теперь всё работает почти идеально. Что-нибудь ещё?", -Patch me up.,TXT_RPLY0_SCRIPT34_D9096_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., -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?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,¿Qué has intentado hacer? ¿Encabezonarte con un cruzado?,¿Qué has intentado hacer? ¿Pelear cabeza a cabeza contra 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?,,"今度は何を始めるんだ? +Patch me up.,TXT_RPLY0_SCRIPT34_D9096_PATCH,,,,Dej mě do hromady.,Flick mich zusammen.,,,Cúrame.,,Paikkaa minut.,Soignez moi.,Gyógyíts fel.,Curami.,治療してほしい。,치료가 필요합니다.,Patch me op.,,Trate meus ferimentos.,,Bandajează-mă.,Перебинтуй меня., +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?,"Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,¿Qué has intentado hacer? ¿Encabezonarte con un cruzado?,¿Qué has intentado hacer? ¿Pelear cabeza a cabeza contra 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?,,O que andou tentando fazer? Sair na porrada com um Cruzado?,,Ce ai încercat să faci? Dai cap în cap cu un Cruciat?,"Ты что, бился один на один с крестоносцем?", -Implant upgrade?,TXT_RPLY1_SCRIPT34_D9096_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?.,,Aprimoramento de implante?,,Upgrade la implant?,Улучшение импланта?, -That should do it for you.,TXT_RYES1_SCRIPT34_D9096_THATS,,,,Tohle by mělo fungovat.,"Alles klar, das haben wir sofort.",,,Esto te debería servir.,,Eiköhän tällä ala tepsiä.,Ca devrait faire l'affaire.,Ez szerintem megteszi.,,今取り掛かっている。,도움이 좀 될 거에요.,Dat zou het voor je moeten doen.,,Isso deve funcionar pra você.,,Asta ar trebui să fie suficient.,Вот оно., -Let me run some more tests first.,TXT_RNO1_SCRIPT34_D9096_LETME,,,,Ještě ho musím dál otestovat.,Es ist noch nicht soweit.,,,Déjame hacer algunas pruebas primero.,,Anna minun ajaa muutamia kokeita ensin.,Laissez moi faire quelques tests d'abord.,Hadd futtassak pár tesztet.,,もう少しテストしてからにしよう。,시험단계를 좀 거치고 예기할게요.,Laat me eerst nog wat testen doen.,,Só deixa eu fazer mais alguns testes.,,Lasă-mă să fac niște teste mai întâi.,Дай мне ещё времени на тесты., -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í?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,,Eso es todo lo que puedo hacer con el implante por ahora. ¿Qué tal una cura?,,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?,,"インプラントはこれ以上ない程完成した。 +Implant upgrade?,TXT_RPLY1_SCRIPT34_D9096_IMPLA,,,,Vylepšení implantátu?,Implantatsupgrade?,,,¿Mejora de implante?,,Istutteen päivitys?,Mise à jour de l'implant?,Implantátum fejlesztés?,Aggiornamento dell'impianto?,インプラント アップグレード?,지구력 업그레이드?,Implantaat upgrade?.,,Aprimoramento de implante?,,Upgrade la implant?,Улучшение импланта?, +That should do it for you.,TXT_RYES1_SCRIPT34_D9096_THATS,,,,Tohle by mělo fungovat.,"Alles klar, das haben wir sofort.",,,Esto te debería servir.,,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.,,Isso deve funcionar pra você.,,Asta ar trebui să fie suficient.,Вот оно., +Let me run some more tests first.,TXT_RNO1_SCRIPT34_D9096_LETME,,,,Ještě ho musím dál otestovat.,Es ist noch nicht soweit.,,,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.,,Só deixa eu fazer mais alguns testes.,,Lasă-mă să fac niște teste mai întâi.,Дай мне ещё времени на тесты., +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í?","Das ist alles, was ich im Moment mit dem Implantat machen kann. Vielleicht etwas medizinische Versorgung?",,,Eso es todo lo que puedo hacer con el implante por ahora. ¿Qué tal una cura?,,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?,,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?,Пока что я больше ничего не могу сделать с имплантом. Как насчёт лечения?, -Yeah.,TXT_RPLY0_SCRIPT34_D10612_YEAH,,,,Jo.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,,ああ。,그래.,Ja.,,Sim.,,Da.,Давай., -"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,君、滅茶苦茶だな。なんとかしよう。,치료가 다 끝났습니다. 다 의료기술 덕입니다.,"Jongen, je bent een echte puinhoop. Ik zal zien wat ik kan doen.",,"Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.", -What can I do for you?,TXT_DLG_SCRIPT34_D12128_WHATC,,,,Co pro tebe můžu udělat?,Was kann ich für dich tun?,,,¿Qué puedo hace por ti?,,Mitä voin tehdä sinulle?,Que puis-je faire pour vous?,Mit tehetek érted?,,それで何か用か?,무엇을 도와줄까.,Wat kan ik voor je doen?,,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?, -I'm out of bullets.,TXT_RPLY0_SCRIPT34_D12128_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on luodit loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D12128_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco 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.,,無駄遣いするなよ。,조금만 주겠습니다. 재고가 모자라거든요.,Hier is wat munitie voor je. Verspil het niet.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., -Teach me.,TXT_RPLY1_SCRIPT34_D12128_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., -"All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT34_D12128_ALLRI,,,,"Dobře, ukážu ti pár rad.","Alles klar, ich zeige dir ein paar Kniffe.",,,"Muy bien, te daré algunos pequeños 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.,,わかった、幾つかやり方を教えよう。,좋습니다. 움직이는 과녁을 쏘세요!,"Oké, ik zal je gewoon een paar kleine tips laten zien.",,"Ok, vou te dar algumas dicas.",,"În regulă, am să-ți arăt niște repere.",Хорошо. Покажу тебе пару приёмов., -You're not ready yet.,TXT_RNO1_SCRIPT34_D12128_YOURE,,,,Ještě nejsi připravený.,Du bist noch nicht so weit.,,,Aún no estás listo.,,Et ole vielä valmis.,Vous n'êtes pas encore prêt.,Nem állsz még készen.,,そっちの準備がまだ整ってないようだな。,당신은 아직 준비가 안됐어요.,Je bent nog niet klaar.,,Você não está preparado ainda.,,Nu ești pregătit încă.,Ты ещё не готов., -Back again? What do you need?,TXT_DLG_SCRIPT34_D13644_BACKA,,,,Zase zpátky? Co potřebuješ?,Scxhon zurück? Was brauchst du?,,,¿De vuelta otra vez? ¿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?,,もう戻ったか?何が必要だ?,다시 왔군요. 무엇이 필요하죠?,Weer terug? Wat heb je nodig?,,Já voltou? O que precisa?,,Te-ai întors? Ce mai dorești?,Ты вернулся? Что тебе нужно?, -I'm out of bullets.,TXT_RPLY0_SCRIPT34_D13644_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me quedan balas.,,Minulta on ammukset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 바닥났어요.,Ik heb geen kogels meer.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D13644_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco de munición. No la gastes.,,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.,,この弾を使え、無駄遣いするなよ。,"적을 사살하려면, 역시 탄약을 소진해야만 하죠. 여기 탄약입니다.",Hier is wat munitie voor je. Verspil het niet.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT34_D13644_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌어. 다 소진하고 찾아오세요.,Je hebt genoeg munitie.,,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя их достаточно., -Teach me.,TXT_RPLY1_SCRIPT34_D13644_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., -"All right, this should keep you going for a while.",TXT_RYES1_SCRIPT34_D13644_ALLRI,,,,"Dobře, tohle by ti mělo pomoct.","Alles klar, das sollte fürs erste reichen.",,,"Muy bien, esto te mantendrá a punto durante un tiempo.",,"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.",,わかった、これで長くやり合えるだろう。,"여기, 적병 일부를 충분히 죽일 수 있을 만큼의 탄약입니다.","Oké, dit zou je een tijdje op de been moeten houden.",,"Ok, isso deve te ajudar por enquanto.",,"Bine, asta ar trebui să te ajute o vreme.","Хорошо, это не раз спасёт тебе жизнь.", -"Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT34_D13644_SORRY,,,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,,"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.",,すまないが、できない。マシルの命令だ。,마실 사령관님의 명령입니다. 그럴 수는 없어요.,"Sorry, dat kan niet. Ik volg gewoon de orders van Macil op.",,Desculpe mas não posso. Só estou seguindo as ordens do Macil.,,"Scuze, nu pot. Eu doar umez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.", -"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.","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.",,,"Bueno ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a tener en mis manos esas nuevas armas que hemos capturado. En cuanto termine con ellas, podré 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.",,"弾薬と訓練、どっちの用件だ? +Yeah.,TXT_RPLY0_SCRIPT34_D10612_YEAH,,,,Jo.,Ja.,,Jes.,Sí.,,Kyllä.,Ouais.,Igen.,Sì.,ああ。,그래.,Ja.,,Sim.,,Da.,Давай., +"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.","Mann, du siehst aber gar nicht gut aus. Mal sehen, was ich machen kann.",,,"Chico, estás hecho un desastre. Veré que 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.",,"Rapaz, você está arrebentado. Verei o que posso fazer.",,"Băiete, ești un dezastru. O să văd ce pot face.","Ты просто месиво. Посмотрим, что я смогу сделать.", +What can I do for you?,TXT_DLG_SCRIPT34_D12128_WHATC,,,,Co pro tebe můžu udělat?,Was kann ich für dich tun?,,,¿Qué puedo hace 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?,,Como posso te ajudar?,,Ce pot face pentru tine?,Чем я могу тебе помочь?, +I'm out of bullets.,TXT_RPLY0_SCRIPT34_D12128_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D12128_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco 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.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., +Teach me.,TXT_RPLY1_SCRIPT34_D12128_TEACH,,,,Uč mě.,Unterrichte mich.,,,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., +"All right, I'll just show you a few little pointers.",TXT_RYES1_SCRIPT34_D12128_ALLRI,,,,"Dobře, ukážu ti pár rad.","Alles klar, ich zeige dir ein paar Kniffe.",,,"Muy bien, te daré algunos pequeños 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.",,"Ok, vou te dar algumas dicas.",,"În regulă, am să-ți arăt niște repere.",Хорошо. Покажу тебе пару приёмов., +You're not ready yet.,TXT_RNO1_SCRIPT34_D12128_YOURE,,,,Ještě nejsi připravený.,Du bist noch nicht so weit.,,,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.,,Você não está preparado ainda.,,Nu ești pregătit încă.,Ты ещё не готов., +Back again? What do you need?,TXT_DLG_SCRIPT34_D13644_BACKA,,,,Zase zpátky? Co potřebuješ?,Scxhon zurück? Was brauchst du?,,,¿De vuelta otra vez? ¿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?,,Já voltou? O que precisa?,,Te-ai întors? Ce mai dorești?,Ты вернулся? Что тебе нужно?, +I'm out of bullets.,TXT_RPLY0_SCRIPT34_D13644_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,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.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились патроны., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D13644_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco de munición. No la gastes.,,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.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT34_D13644_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,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.,,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя их достаточно., +Teach me.,TXT_RPLY1_SCRIPT34_D13644_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., +"All right, this should keep you going for a while.",TXT_RYES1_SCRIPT34_D13644_ALLRI,,,,"Dobře, tohle by ti mělo pomoct.","Alles klar, das sollte fürs erste reichen.",,,"Muy bien, esto te mantendrá a punto durante un tiempo.",,"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.",,"Ok, isso deve te ajudar por enquanto.",,"Bine, asta ar trebui să te ajute o vreme.","Хорошо, это не раз спасёт тебе жизнь.", +"Sorry, can't. I'm just following Macil's orders.",TXT_RNO1_SCRIPT34_D13644_SORRY,,,,"Promiň, nemůžu. Řídím se rozkazy od Macila.","Tut mir leid, aber ich kann nicht. Ich folge nur Macils Befehlen.",,,"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.",,Desculpe mas não posso. Só estou seguindo as ordens do Macil.,,"Scuze, nu pot. Eu doar umez ordinele lui Macil.","Увы, не могу. Я подчиняюсь Мэйсилу.", +"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.","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.",,,"Bueno ¿qué va a ser?, ¿balas o entrenamiento? No puedo esperar a tener en mis manos esas nuevas armas que hemos capturado. En cuanto termine con ellas, podré 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.","弾薬と訓練、どっちの用件だ? 奪った新しい武器が届くのを待ち切れないです。 少しの訓練でデカい復讐を。",탄약보급? 훈련? 가능하면 모두 다 가능합니다! 그리고 방금 수송된 무기들을 만져보고 싶습니다. 조사가 끝난 뒤에는 모두가 특수 훈련을 받을 수 있을 거에요.,"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.",,"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.","Что теперь, патроны или тренировка? Мне не терпится опробовать это новое трофейное оружие. Чуть-чуть тренировки, и они за всё заплатят.", -I'm out of ammo.,TXT_RPLY0_SCRIPT34_D15160_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me queda minicion.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились боеприпасы., -Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D15160_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco 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.,,この弾をどうぞ、無駄遣いしないように。,조금 나눠주도록 하겠습니다. 부디 낭비하지 마시길.,Hier is wat munitie voor je. Verspil het niet.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., -You've got enough ammo.,TXT_RNO0_SCRIPT34_D15160_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,Tienes suficiente munición.,,Sinulla on riittävästi ammuksia.,Vous avez assez de munitions.,Van elég lőszered.,,もう十分に弾を持ってるようだぞ。,충분한 탄약을 가졌군...,Je hebt genoeg munitie.,,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя хватает патронов., -Teach me.,TXT_RPLY1_SCRIPT34_D15160_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., -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.","OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,,OK. Toma lo que has aprendido y muéstrales a los de la Orden el camino 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!",,"オーケー、ここで学んだ事を生かして +I'm out of ammo.,TXT_RPLY0_SCRIPT34_D15160_IMOUT,,,,Došly mi náboje.,Ich habe keine Munition mehr.,,,No me queda minicion.,,Minulta on panokset loppu.,Je suis à cours de munitions.,Kifogytam a lőszerből.,Ho finito le munizioni.,弾切れだ。,탄약이 떨어졌어요.,Ik heb geen munitie meer.,,Estou sem munição.,,Nu mai am gloanțe.,У меня кончились боеприпасы., +Here's some ammo for you. Don't waste it.,TXT_RYES0_SCRIPT34_D15160_HERES,,,,"Tady máš nějakou munici, neplýtvej s ní.",Hier hast du welche. Verschwende sie nicht.,,,Aquí tienes un poco 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.,,Leve esta munição. Não desperdice.,,Iată niște muniție. N-o irosi.,Можешь взять немного. Не трать их понапрасну., +You've got enough ammo.,TXT_RNO0_SCRIPT34_D15160_YOUVE,,,,Vždyť jich máš dost.,Du hast genug.,,,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.,,Você já tem munição suficiente.,,Ai suficientă muniție.,У тебя хватает патронов., +Teach me.,TXT_RPLY1_SCRIPT34_D15160_TEACH,,,,Uč mě.,Unterrichte mich.,,Instruu min.,Enséñame.,,Kouluta minua.,Apprenez-moi.,Taníts.,Dammi dell'altro addestramento.,教えてくれ。,가르쳐 줘.,Leer het me.,,Me ensine.,,Învață-mă.,Обучи меня., +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.","OK. Nutze, was du hier gelernt hast um diesen Tölpeln vom Orden den Weg in die Hölle zu zeigen.",,,OK. Toma lo que has aprendido y muéstrales a los de la Orden el camino 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. 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.","Запоминай внимательно, покажешь этим прихвостням Ордена быструю дорогу в ад.", -"Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT34_D15160_COMEB,,,,"Přijď někdy jindy, až řekne Macil.","Komm wieder, wenn Macil dir Bescheid gibt.",,,"Vuelve más tarde, cuando Macil diga que es 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.",,マシルの命令を受けてから、また来い。,마실 사령관님이 준비되었다고 말했을 때 와주세요.,"Kom later terug, als Macil zegt dat het tijd is.",,"Volte mais tarde, quando o Macil disser que é hora.",,"Revin-o mai încolo, când Macil zice că e timpul.","Приходи позже, когда прикажет Мэйсил.", -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.","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.",,,"Te he enseñado todo lo que puedo de momento. Dame algo de tiempo para poner esas nuevas armas a punto. Eso es, a menos que estés sin balas.",,"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.",,"私が教えられる事はもう無い。 +"Come back later, when Macil says it's time.",TXT_RNO1_SCRIPT34_D15160_COMEB,,,,"Přijď někdy jindy, až řekne Macil.","Komm wieder, wenn Macil dir Bescheid gibt.",,,"Vuelve más tarde, cuando Macil diga que es 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.",,"Volte mais tarde, quando o Macil disser que é hora.",,"Revin-o mai încolo, când Macil zice că e timpul.","Приходи позже, когда прикажет Мэйсил.", +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.","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.",,,"Te he enseñado todo lo que puedo de momento. Dame algo de tiempo para poner esas nuevas armas a punto. Eso es, a menos que estés sin balas.",,"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.,,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.,Пока что я не могу научить тебя ничему новому. Дай мне время разобраться в этом новом оружии. Или у тебя закончились патроны?, -Yes I am.,TXT_RPLY0_SCRIPT34_D16676_YESIA,,,,"Ano, potřebuju.","Ja, bin ich.",,"Jes, mi estas.",Eso mismo.,,Kyllä on.,"En effet, je le suis.",Igen.,,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",,"Sim, eu estou.",,Da sunt.,"Да, закончились.", -Here you go.,TXT_RYES0_SCRIPT34_D16676_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,,どうぞ。,여기요!,Alsjeblieft.,,Aqui está.,,Aici sunt.,Держи., -"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,,,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,,"No te lies a tiros en el pueblo, activarás las alarmas y empezarán a enviar guardias desdel 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.",,"街の中で銃をバンバン撃ったりするんじゃないぞ +Yes I am.,TXT_RPLY0_SCRIPT34_D16676_YESIA,,,,"Ano, potřebuju.","Ja, bin ich.",,"Jes, mi estas.",Eso mismo.,,Kyllä on.,"En effet, je le suis.",Igen.,Sì che mi servono.,ああ、そうだ。,알겠습니다. 그럼 탄약이라도?,"Ja, dat ben ik wel.",,"Sim, eu estou.",,Da sunt.,"Да, закончились.", +Here you go.,TXT_RYES0_SCRIPT34_D16676_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,Aquí tienes.,,"Tässä, ole hyvä.",Voilà pour vous.,Parancsolj.,Ecco qua.,どうぞ。,여기요!,Alsjeblieft.,,Aqui está.,,Aici sunt.,Держи., +"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,,,,Ať tě nenapadne střílet ve městě. Spustil bys poplach a přivolal stráže z hradu.,"Fang nicht an, hier in der Stadt herumzuballern. Wenn du hier den Alarm auslöst, senden sie gleich die Truppen aus der Burg.",,,"No te lies a tiros en el pueblo, activarás las alarmas y empezarán a enviar guardias desdel 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.",,"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.","Когда будешь в городе, не стреляй направо и налево. Если ты поднимешь тревогу, они вызовут подкрепление из замка.", -"Welcome, we can always use more help.",TXT_DLG_SCRIPT34_D19708_WELCO,,,,"Vítej, pomoc se nám vždycky hodí.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,,"Bienvenido, siempre nos viene bien algo 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.",,ようこそ、我々が貴方の助けに成ります。,어서 오세요. 당신 같은 사람에게는 많은 도움이 필요합니다!,"Welkom, we kunnen altijd meer hulp gebruiken.",,Seja bem-vindo. Qualquer ajuda também é sempre bem-vinda.,,"Bun-venit, ajutorul e bine-venit oricând.",Добро пожаловать. Нам всегда пригодится помощь., -"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,,,,"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é.","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!",,,"Cuando aún estaba en acción tuvimos la oportunidad de examinar un acólito antes de que llegaran los refuerzos, 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.",,"私がまだ活動していた時、我々が増援に +"Welcome, we can always use more help.",TXT_DLG_SCRIPT34_D19708_WELCO,,,,"Vítej, pomoc se nám vždycky hodí.","Willkommen, wir können immer etwas Hilfe gebrauchen.",,,"Bienvenido, siempre nos viene bien algo 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.",,Seja bem-vindo. Qualquer ajuda também é sempre bem-vinda.,,"Bun-venit, ajutorul e bine-venit oricând.",Добро пожаловать. Нам всегда пригодится помощь., +"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,,,,"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é.","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!",,,"Cuando aún estaba en acción tuvimos la oportunidad de examinar un acólito antes de que llegaran los refuerzos, 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.",,"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.","Пока я был в оперативной группе, нам удалось вскрыть одного из служителей, прежде чем прибыло подкрепление. Так вот, они не люди.", -"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT34_D22740_WERET,,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,,"Estamos intentando encontrar donde están los mecanismos de la puerta del castillo, pero por ahora no hemos tenido 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.",,"我々は城門のメカニズムが何処にあるか +"We're trying to find where the castle gate mechanisms are, but so far we've had no luck.",TXT_DLG_SCRIPT34_D22740_WERET,,,,"Snažíme se zjistit, kde jsou mechanismy hradní brány, ale zatím jsme nic nenašli.","Wir versuchen herauszufinden, von wo das Burgtor kontrolliert wird, aber bisher hatten wir kein Glück.",,,"Estamos intentando encontrar donde están los mecanismos de la puerta del castillo, pero por ahora no hemos tenido 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.",,"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.","Мы пытаемся найти механизм управления воротами замка, но пока безуспешно. ", -"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,,,,"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.","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.",,,"Que no te atrapen. He oído historias de terror sobre lo que hacen con nuestra gente despues de estar encarcelados. Símplemente desaparecen, ni rastro, 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.",,"決して捕まるな。投獄されると奴等が +"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,,,,"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.","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.",,,"Que no te atrapen. He oído historias de terror sobre lo que hacen con nuestra gente despues de estar encarcelados. Símplemente desaparecen, ni rastro, 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.",,"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ă.,"Не дай себя схватить. Я слышал ужасные истории о том, что они делают с арестованными. Те просто исчезают... без следа.", -"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,,,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a jdi. Jsou rychlí a suroví.","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,,"Un consejo, si ves algún soldadito de la Orden, da la vuelta y corre. En especial no me gustan los Saqueadores, ¡esas cosas son jodidamente rápidas!",,"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.",,"伝えておく、オーダーの錫兵は +"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,,,,"Dám ti radu: Jestli někdy uvidíš jednoho z plecháčků Řádu, otoč se a jdi. Jsou rychlí a suroví.","Hier ist ein guter Rat, falls du jemals einen dieser Zinnsoldaten des Ordens vorbeigehen siehst. Sie sind schnell und brutal. ",,,"Un consejo, si ves algún soldadito de la Orden, da la vuelta y corre. En especial no me gustan los Saqueadores, ¡esas cosas son jodidamente rápidas!",,"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!",,"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!","Небольшой совет: если увидишь «оловянных солдатиков» Ордена, сворачивай в другую сторону. Я особенно не люблю похитителей — эти твари довольно быстрые!", -"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,,,,"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.","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 de 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!",,"ようこそ、ここは我々の僅かな希望が集まる +"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,,,,"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.","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 de 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.","ようこそ、ここは我々の僅かな希望が集まる 最後の場所だ。オーダーへと立ち向かう意思を 持っているのは我々くらいだ。 ここには素晴らしい頭脳を持つ学者たち、 @@ -9971,84 +9967,84 @@ Here you go.,TXT_RYES0_SCRIPT34_D16676_HEREY,,,,Tady máš.,Bitteschön.,,Jen.,A だがしかし、我々には問題解決に優れた者、 つまり私達の力となる者が足りていないんだ。 我々に手を貸してくれ。","희미한 희망에 빛에 온 것을 환영합니다. 우리만이 오더를 처치할 자유의지를 가지고 있지요. 우수한 과학력에, 뛰어난 실력을 소유한 부대도 있으니까 말입니다. 하지만, 우리들에게도 부족한 게 하나 있습니다. 바로 시련을 해결해 줄 해결사죠. 부디 도와주세요.","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.",,"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.","Добро пожаловать в последний оплот надежды. Только мы обладаем свободной волей, чтобы противостоять Ордену. С нами лучшие учёные умы, и у нас есть много толковых людей, но нам не хватает одного-единственного, э... «разрешителя проблем», который поможет нам получить необходимое преимущество.", -What will I need to do? ,TXT_RPLY0_SCRIPT34_D27288_WHATW,,,,Co budu muset udělat?,Was muss ich tun?,,,¿Qué necesito hacer?,,Mitä minun tarvitsee tehdä?,Que dois-je faire?,Mit kell tennem?,,何をしたらいい?,무엇을 해야하죠?,Wat moet ik doen?,,O que preciso fazer?,,Ce trebuie să fac?,Что я должен сделать?, -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ě.,"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.",,"我々の援護だ。我々が奴等のテクノロジーを +What will I need to do? ,TXT_RPLY0_SCRIPT34_D27288_WHATW,,,,Co budu muset udělat?,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?,,O que preciso fazer?,,Ce trebuie să fac?,Что я должен сделать?, +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ě.,"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à.,"我々の援護だ。我々が奴等のテクノロジーを 盗むのを手伝って欲しい。同胞の解放の為だ。 イカレた奴等と戦闘する必要がある。 正義を取り戻すため君には危険の伴う任務を 受けてほしいのだ。","우릴 도와주세요. 놈들의 기술을 훔치고, 붙잡힌 동료들을 구출하고, 오더의 미치광이들을 타도하기 위해서 말이죠. 그리고 진실 어린 희망을 위해서 이렇게 묻는 겁니다.",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.,,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.,Помочь нам. Помочь нам украсть их технологии. Освободить наших товарищей. Сразиться с этими извращёнными психопатами и убить их. Рискнуть своей жизнью ради правого дела., -I'm with you!,TXT_RPLY0_SCRIPT34_D28804_IMWIT,,,,Jsem s tebou!,Ich bin dabei.,,,¡Estoy contigo!,,Olen kanssanne!,Je suis avec vous!,Veletek vagyok!,,同意した!,함께 하겠습니다!,Ik sta achter je!,,Estou com vocês!,,Sunt cu tine!,Хорошо! Я с вами!, -"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.","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.",,"いいぞ、今後もブラックバードが君のガイドを +I'm with you!,TXT_RPLY0_SCRIPT34_D28804_IMWIT,,,,Jsem s tebou!,Ich bin dabei.,,,¡Estoy contigo!,,Olen kanssanne!,Je suis avec vous!,Veletek vagyok!,Sono con te!,同意した!,함께 하겠습니다!,Ik sta achter je!,,Estou com vocês!,,Sunt cu tine!,Хорошо! Я с вами!, +"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.","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.","いいぞ、今後もブラックバードが君のガイドを 務める。彼女は君に感心しているようだぞ。 君たちの二人で、オーダーと その人間離れした手下たちが持っている秘密を 暴いてもらいたい。 奴等の基地に潜り込んで、倒すんだ。","감사드립니다! 블랙버드가 당신을 위해 계속 안내를 할 것입니다. 같이 행동한다면 오더의 흉측한 비밀들을 밝혀내고, 그들의 잔혹한 존재들을 응징할 수 있을 겁니다. 우리들의 이해심 밑에 공포를 인도하는 그들의 숨겨진 존재가 있죠. 그곳으로 들어가서, 물리치세요.",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.,,"Ó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.",Хорошо. Чёрный дрозд останется твоим проводником. Она тебе несколько симпатизирует. Вместе вы раскроете секреты Ордена и его бесчеловечных слуг. За этим ужасом стоит нечто лежащее далеко за пределами нашего понимания. Проникни на их территорию и ударь по ним как следует!, -Let me at 'em!,TXT_RPLY0_SCRIPT34_D30320_LETME,,,,Pusť mě na ně!,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!,,任せろ!,저만 믿으세요!,Laat me naar ze toe!,,Pode deixar!,,Lasă-mă să pun mâna pe ei!,Я им покажу!, -That's the spirit.,TXT_RYES0_SCRIPT34_D30320_THATS,,,,Tak se mi to líbí.,Das ist die richtige Einstellung.,,,Ese es el espíritu.,,Niin sitä pitää.,J'aime entendre ça.,Ez a beszéd!,,良い心掛けだ。,좋은 마음가짐입니다.,Dat is de geest.,,Esse é o espírito.,,Ăsta e spiritul.,Правильный настрой., -Welcome friend!,TXT_DLG_SCRIPT34_D31836_WELCO,,,,"Vítej, příteli!","Wilkommen, Freund.",,"Bonvenon, amiko!",¡Bienvenido amigo!,,"Tervetuloa, ystävä!","Bievenue, notre ami!",Üdvözöllek barátom.,,よく来た、同志!,"어서오세요, 친구여!",Welkom vriend!,,"Seja bem-vindo, amigo!",,Bun-venit prietene!,"Добро пожаловать, друг!", +Let me at 'em!,TXT_RPLY0_SCRIPT34_D30320_LETME,,,,Pusť mě na ně!,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!,,Pode deixar!,,Lasă-mă să pun mâna pe ei!,Я им покажу!, +That's the spirit.,TXT_RYES0_SCRIPT34_D30320_THATS,,,,Tak se mi to líbí.,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.,,Esse é o espírito.,,Ăsta e spiritul.,Правильный настрой., +Welcome friend!,TXT_DLG_SCRIPT34_D31836_WELCO,,,,"Vítej, příteli!","Wilkommen, Freund.",,"Bonvenon, amiko!",¡Bienvenido amigo!,,"Tervetuloa, ystävä!","Bievenue, notre ami!",Üdvözöllek barátom.,Benvenuto amico!,よく来た、同志!,"어서오세요, 친구여!",Welkom vriend!,,"Seja bem-vindo, amigo!",,Bun-venit prietene!,"Добро пожаловать, друг!", ,,Random dialogue,,,,,,,,,,,,,,,,,,,,, -Please don't hurt me.,TXT_RANDOM_PEASANT_01,,,,"Neubližuj mi, prosím.",Bitte tu mir nicht weh.,,Bonvolu ne vundi min.,Por favor no me haga daño.,,"Pyydän, älä vahingoita minua.","S'il vous plaît, laissez-moi tranquille.",Kérlek ne bánts!,Ti prego non farmi male.,私を傷つけないでくれ。,목숨만은 살려줘.,Doe me alsjeblieft geen pijn.,,"Por favor, não me machuque.",,Te rog nu mă răni.,"Пожалуйста, не трогай меня.", -"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.","Falls du mir was antun willst, ich bin den Aufwand nicht wert.",,,"Si está tratando de hacerme daño, 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.","Sembra che tu voglia farmi del male, ma davvero, non ne valgo lo sforzo.","もしお前が私に暴力を振るいたいなら間違いだ、 +Please don't hurt me.,TXT_RANDOM_PEASANT_01,,,,"Neubližuj mi, prosím.",Bitte tu mir nicht weh.,,Bonvolu ne vundi min.,Por favor no me haga daño.,,"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.,,"Por favor, não me machuque.",,Te rog nu mă răni.,"Пожалуйста, не трогай меня.", +"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.","Falls du mir was antun willst, ich bin den Aufwand nicht wert.",,,"Si está tratando de hacerme daño, 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.",,"Se pretende me machucar, te digo que não valerá a pena.",,"Dacă vrei să mă rănești, nu merit efortul.","Если ты хочешь ударить меня, то я не стою твоих усилий.", -I don't know anything.,TXT_RANDOM_PEASANT_03,,,,O ničem nevím.,Ich weiß nichts.,,,No se nada.,,En tiedä mitään.,Je ne sais rien.,Én semmit sem tudok.,Non so nulla.,私は何も知らないんだ。,난 정말 아무것도 몰라.,Ik weet niets.,,Eu não sei de nada.,,Nu știu nimic.,Я ничего не знаю., +I don't know anything.,TXT_RANDOM_PEASANT_03,,,,O ničem nevím.,Ich weiß nichts.,,,No se nada.,,En tiedä mitään.,Je ne sais rien.,Én semmit sem tudok.,Non so niente.,私は何も知らないんだ。,난 정말 아무것도 몰라.,Ik weet niets.,,Eu não sei de nada.,,Nu știu nimic.,Я ничего не знаю., Go away or I'll call the guards!,TXT_RANDOM_PEASANT_04,,,,"Jdi pryč, nebo zavolám stráže!",Hau ab oder ich rufe die Wachen!,,,¡Vete o llamaré 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!,,Vá embora antes que eu chame os guardas!,,Pleacă sau voi chema gardienii!,"Уходи, или я позову стражу!", -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.","Manchmal wünsche ich mir, dass diese Rebellen ihren Unsinn stoppen würden.",,,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 parar con este absurdo.,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 che tutti questi ribelli imparassero semplicemente a stare al loro posto e la smettessero con tutte queste fesserie.,"反乱軍がこんな出鱈目な状態をひっくり返すのを +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.","Manchmal wünsche ich mir, dass diese Rebellen ihren Unsinn stoppen würden.",,,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 parar con este absurdo.,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.,,À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.,"Иногда мне хочется, чтобы все эти повстанцы просто поняли своё место и прекратили эту пустую возню.", "Just leave me alone, OK?",TXT_RANDOM_PEASANT_06,,,,"Prostě mě nech být, jasný?","Lass mich bitte in Ruhe, ok?",,,"Déjame en paz, ¿vale?","Déjame solo, ¿de acuerdo?","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é?",,"Apenas me deixe em paz, ok?",,"Doar lasă-mă în pace, OK?","Просто оставь меня в покое, хорошо?", "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ů.","Ich bin nicht ganz sicher, aber manchmal kommt es mir vor, als kenne ich diese Ministranten.",,,"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.",,"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.","Я не уверен, но порой мне кажется, что я узнаю некоторых служителей.", 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.,Der Orden hat hier alles ziemlich gut unter Kontrolle.,,,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.,,A Ordem mantém tudo trancado a sete chaves.,,Ordinul a încuiat cam tot ce se poate pe aici.,Орден держит тут всё под замком., -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.",Das sind niemals nur Sicherheitskräfte.,,,No hay manera de que esto sea sólo 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.,,Não tem como isso ser apenas um força de segurança.,,Sub nicio formă nu e asta doar o forță de securitate.,Без разрешения стражей порядка и шагу ступить нельзя., +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.",Das sind niemals nur Sicherheitskräfte.,,,No hay manera de que esto sea sólo 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.,,Não tem como isso ser apenas um força de segurança.,,Sub nicio formă nu e asta doar o forță de securitate.,Без разрешения стражей порядка и шагу ступить нельзя., 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á.","Ich habe gehört, dass der Orden sehr beunruhigt über die Aktionen der Front ist.",,,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.,,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.,"Я слыхал, что Орден серьёзно обеспокоен действиями повстанцев в этом районе.", -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.,Niemals wird sich der Orden gegen uns stellen!,,,No hay forma de que la orden aguante contra nosotros.,No hay forma de que la orden se levante 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 esiste che l'Ordine possa mettersi contro di noi.,オーダーが私達に立ち向かえるはずはない。,오더 녀석들이 우리를 이길 가능성은 전혀 없어.,De Orde zal op geen enkele manier tegen ons ingaan.,,Nao ha como a Ordem ficar contra a gente.,,Nicio șansă ca Ordinul să ni se opună.,Ордену никак не устоять против нас., +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.,Niemals wird sich der Orden gegen uns stellen!,,,No hay forma de que la orden aguante contra nosotros.,No hay forma de que la orden se levante 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.,,Nao ha como a Ordem ficar contra a gente.,,Nicio șansă ca Ordinul să ni se opună.,Ордену никак не устоять против нас., 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.,Wir sind zum großen Schlag bereit. Macils Plane werden bald umgesetzt.,,,Estamos casi listos para atacar. Los planes de Macil están cayendo en su lugar.,Estamos casi listos para atacar. Los planes de Macil se están cayendo en su lugar.,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.,,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.,Мы почти готовы атаковать. Планы Мэйсила становятся ясны., -"We're all behind you, don't worry.",TXT_RANDOM_REBEL_03,,,,"Všichni stojíme za tebou, neboj.","Wir stehen zu dir, keine Sorge.",,,"Todos estamos detrás de ti, no te preocupes.",,"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, ti copriamo tutti le spalle.",後ろは見ているぞ、気にするな。,걱정 마. 무슨 일이 있어도 우리가 지켜줄게!,"We staan allemaal achter je, maak je geen zorgen.",,"Estamos todos te protegendo, não se preocupe.",,"Suntem toți în spatele tău, nu te teme.",Не беспокойся. Мы сразу за тобой., -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. Roztaví tě na šrot!,Komm diesen großen Robotern nicht zu nahe. Die schmelzen dich zu Schrott ein.,,,No te acerques tanto a uno de esos robots grandes. ¡Podrían derretirte para 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 stare troppo vicino a uno di quei grossi robot. Ti potrebbero sciogliere per i rottami!,"デカブツには近づくなよ。スクラップみたいに +"We're all behind you, don't worry.",TXT_RANDOM_REBEL_03,,,,"Všichni stojíme za tebou, neboj.","Wir stehen zu dir, keine Sorge.",,,"Todos estamos detrás de ti, no te preocupes.",,"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.",,"Estamos todos te protegendo, não se preocupe.",,"Suntem toți în spatele tău, nu te teme.",Не беспокойся. Мы сразу за тобой., +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!,Komm diesen großen Robotern nicht zu nahe. Die schmelzen dich zu Schrott ein.,,,No te acerques tanto a uno de esos robots grandes. ¡Podrían derretirte para 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!,,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!,Держись подальше от этих больших роботов. Они и мокрого места от тебя не оставят!, -"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!","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!",,"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 sarà schiacciato!","栄光の日は我々に訪れる、 +"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!","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!",,"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!",,"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.,Близок день нашего триумфа. Скоро наши враги будут уничтожены!, -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.","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 metterti troppo comodo. Ci sta ancora il nostro lavoro ritagliato per noi.,"あまり気楽でいるな。 +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.","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.,,Não fique muito confortável. Ainda temos trabalho a fazer.,,Nu te fă prea comfortabil. Încă mai avem treabă de făcut.,Не расслабляйся. У нас по-прежнему хватает дел., 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 nennt dich unsere neue Hoffnung. Vergiss das nicht.,,,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 disse que você é a nova esperança. Lembre-se disso.,,Macil spune că tu ești speranța. Ține minte asta.,"Мэйсил говорит, что на тебя сейчас вся надежда. Имей это в виду.", -"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.","Wenn wir diese Scharlatane entmachtet haben, können wir unsere Welt endlich neu aufbauen.",,,"Una vez que hayamos eliminado a estos charlatanes, podremos reconstruir este mundo como debe ser.","Una vez que hayamos bajado a estos charlatanes, podremos 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 che eliminiamo questi ciarlatani, potremo ricostruire questo mondo a come dovrebbe essere.","我々が一度こんな酷いハッタリを負かせば、 +"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.","Wenn wir diese Scharlatane entmachtet haben, können wir unsere Welt endlich neu aufbauen.",,,"Una vez que hayamos eliminado a estos charlatanes, podremos reconstruir este mundo como debe ser.","Una vez que hayamos bajado a estos charlatanes, podremos 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.",,"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.","Когда мы свергнем этих шарлатанов, то сможем воссоздать этот мир таким, каким он должен быть.", "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.","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 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.",,"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ă.","Помни, ты сражаешься не только за себя, но и за каждого здесь и снаружи.", -"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!","Solange nur einer von uns steht, werden wir gewinnen.",,,"Mientras uno de nosotros siga en pie, ganaremos.",,"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é ci sarà uno di noi in piedi, vinceremo.",我々が一人でも立っていれば、それが勝利。,"우리 중 한 명이 남아있는 한, 이길 수 있어.","Zolang één van ons nog staat, zullen we winnen.",,"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.","Пока хотя бы один из нас ещё дышит, мы непобедимы.", -"Move along, peasant.",TXT_RANDOM_AGUARD_01,,,,"Jdi dál, poddaný.","Beweg dich, Bauer!",,,"Muévete, plebeyo.",,"Jatka matkaa, maallikko.","Barre-toi, paysan!","Mozgás, paraszt. Egy kettő.","Spostati, contadino.",立ち去れ、百姓。,"어서 움직여, 이 자식아.","Ga verder, boer.",,"Continue andando, plebeu.",,"Mișcă, sărmanule.","Проходи, рабочий.", +"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!","Solange nur einer von uns steht, werden wir gewinnen.",,,"Mientras uno de nosotros siga en pie, ganaremos.",,"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.",,"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.","Пока хотя бы один из нас ещё дышит, мы непобедимы.", +"Move along, peasant.",TXT_RANDOM_AGUARD_01,,,,"Jdi dál, poddaný.","Beweg dich, Bauer!",,,"Muévete, plebeyo.",,"Jatka matkaa, maallikko.","Barre-toi, paysan!","Mozgás, paraszt. Egy kettő.","Muoviti, cittadino.",立ち去れ、百姓。,"어서 움직여, 이 자식아.","Ga verder, boer.",,"Continue andando, plebeu.",,"Mișcă, sărmanule.","Проходи, рабочий.", "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.",Folge dem wahren Glauben und du wirst verstehen.,,,"Sigue la fe verdadera, sólo entonces empezarás 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.",,Siga a verdadeira fé. Só então você começará a entender.,,"Urmează crezul adevărat, doar atunci vei începe să înțelegi.",Следуй истинной вере. Только тогда ты начнёшь понимать., Only through death can one be truly reborn.,TXT_RANDOM_AGUARD_03,,,,Pouze skrz smrt lze dosáhnout znovuzrození.,Nur durch den Tod kann man wirklich wiedergeboren werden.,,,Sólo 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.,,Somente através da morte que alguem poderá renascer de verdade.,,Doar prin moarte poate cineva să fie renăscut cu adevărat.,Истинное перерождение возможно только через смерть., I'm not interested in your useless drivel.,TXT_RANDOM_AGUARD_04,,,,Nezajímají mě tvoje žvásty.,Dein nutzloses Geschwafel interessiert mich nicht.,,,No estoy interesado en tu charlatanería.,No estoy interesado en tus inútiles tonterías.,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.,,Não estou interessado em ouvir as suas bobagens inúteis.,,Nu sunt interesat de lipsa ta de sens.,Мне неинтересна твоя пустая болтовня., -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.","Wenn ich mich mit dir unterhalten wollte, hätte ich dir das gesagt.",,,Si hubiera querido hablar contigo te lo habría 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, lo avrei fatto.",話があったらこちらからする。,대화하고 싶었으면 내가 먼저 말을 걸었겠지. 안 그래?,"Als ik met je had willen praten, had ik je dat gezegd.",,"Se eu quisesse falar com você, eu teria te dito.",,Dacă voiam să vorbim ți-aș fi spus.,"Если бы я хотел поговорить с тобой, то сказал бы об этом.", -Go and annoy someone else!,TXT_RANDOM_AGUARD_06,,,,Jdi otravovat někoho jiného!,Bitte nerve jemand anderen.,,,¡Ve a molestar a otro!,,Mene ärsyttämään jotakuta toista!,Va ennuyer quelqu'un d'autre!,Menj és idegesíts valaki mást!,Vattene a scocciare qualcun altro!,あまりイライラさせるな!,귀찮게 하지 말고 가서 딴 녀석이랑 놀아!,Ga iemand anders irriteren!,,Vá incomodar outra pessoa!,,Du-te și enervează pe altul.,Иди и надоедай кому-нибудь другому!, +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.","Wenn ich mich mit dir unterhalten wollte, hätte ich dir das gesagt.",,,Si hubiera querido hablar contigo te lo habría 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.",,"Se eu quisesse falar com você, eu teria te dito.",,Dacă voiam să vorbim ți-aș fi spus.,"Если бы я хотел поговорить с тобой, то сказал бы об этом.", +Go and annoy someone else!,TXT_RANDOM_AGUARD_06,,,,Jdi otravovat někoho jiného!,Bitte nerve jemand anderen.,,,¡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!,,Vá incomodar outra pessoa!,,Du-te și enervează pe altul.,Иди и надоедай кому-нибудь другому!, Keep moving!,TXT_RANDOM_AGUARD_07,,,,Nezastavuj se!,Beweg dich!,,,¡Sigue tu camino!,,Ala laputtaa!,Bouge!,Mozgás!,Continua a muoverti!,立ち去れ!,여어 움직여라!,Blijf in beweging!,,Continue andando!,,Continuă să mergi!,Иди куда шёл!, -"If the alarm goes off, just stay out of our way!",TXT_RANDOM_AGUARD_08,,,,"Jestli se vyhlásí poplach, jdi nám z cesty!","Wenn der Alarm losgeht, steh uns nicht im Weg!",,,"¡Si la alarma se activa, sólo 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!",,"Se o alarme disparar, não fique no nosso caminho!",,"Dacă alarma e declanșată, pur și simplu nu ne sta în cale.","Если поднимется тревога, не попадайся нам под ноги!", +"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!","Wenn der Alarm losgeht, steh uns nicht im Weg!",,,"¡Si la alarma se activa, sólo 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!",,"Se o alarme disparar, não fique no nosso caminho!",,"Dacă alarma e declanșată, pur și simplu nu ne sta în cale.","Если поднимется тревога, не попадайся нам под ноги!", 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.,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.,,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.,,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ă.,"Орден очистит этот мир и положит начало новой эре! ", -"Problem? No, I thought not.",TXT_RANDOM_AGUARD_10,,,,"Nějaký problém? Ne, není.","Hast du Probleme? Nein, ich glaube nicht.",,,"¿Algún problema? No, no lo creo.",,"Jokin ongelma? Ei, niin arvelinkin.",Un problème? Je pense que non.,Baj van? Nem? Én is így gondoltam.,Un problema? Non ci ho pensato.,問題か? そうは思わないが。,문제가 있다고? 자. 이제 없지?,"Probleem? Nee, ik dacht van niet.",,Algum problema? Imaginei que não.,,"Probleme? Nu, așa credeam și eu.",Что-то не так? Нет? Я так и думал., +"Problem? No, I thought not.",TXT_RANDOM_AGUARD_10,,,,"Nějaký problém? Ne, není.","Hast du Probleme? Nein, ich glaube nicht.",,,"¿Algún problema? No, no lo creo.",,"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.",,Algum problema? Imaginei que não.,,"Probleme? Nu, așa credeam și eu.",Что-то не так? Нет? Я так и думал., Alms for the poor?,TXT_RANDOM_BEGGAR_01,,,,Almužnu pro chudáka?,Almosen für die Armen.,,,¿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?,,Uma ajuda para os pobres?,,Ceva pentru ce-i sărmani?,У тебя не найдётся мелочи для бедняка?, -"What are you looking at, surfacer?",TXT_RANDOM_BEGGAR_02,,,,"Na co koukáš, nadzemníku?","Wonach suchst du, Oberflächler?",,,"¿Que estas mirando, prejuicioso?",,"Mitä tuijotat, maanpintalainen?","Tu regarde qui, habitant de la surface?","Mit nézel, felszínlakó?","Cosa stai guardando, essere di superficie?",何ジロジロ見てる、地上人。,"어딜 보고 있는 겁니까, 지상인씨?","Waar kijk je naar, oppervlaktebewoner? ",,"Tá olhando o quê, habitante da superfície?",,La ce te uiți?,"Что уставился, незнакомец?", -"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 hast nichts zu Essen übrig, oder?",,,"¿No tendría algo de comida, verdad?",,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, giusto?",余ってる食べ物とかはないよな?,남은 식량 가지고 있습니까? 부디 있다고 말해주세요... 제발...,"Je zou toch geen extra eten hebben, of wel?",,"Por acaso você não tem comida sobrando, tem?",,"Nu ai mâncare în plus, nu-i așa?",У тебя случайно не найдётся немного лишней еды?, -You surface people will never understand us.,TXT_RANDOM_BEGGAR_04,,,,Vy lidi z povrchu nás nikdy nepochopíte.,Ihr Oberflächenleute werdet uns nie verstehen.,,,Ustedes gente de la superficie nunca podrán entendernos.,,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.,Poi persone di superficie non ci comprenderete mai.,"お前みたいな地上の連中には俺らのことなんて +"What are you looking at, surfacer?",TXT_RANDOM_BEGGAR_02,,,,"Na co koukáš, nadzemníku?","Wonach suchst du, Oberflächler?",,,"¿Que estas 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? ",,"Tá olhando o quê, habitante da superfície?",,La ce te uiți?,"Что уставился, незнакомец?", +"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 hast nichts zu Essen übrig, oder?",,,"¿No tendría algo de comida, verdad?",,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?",,"Por acaso você não tem comida sobrando, tem?",,"Nu ai mâncare în plus, nu-i așa?",У тебя случайно не найдётся немного лишней еды?, +You surface people will never understand us.,TXT_RANDOM_BEGGAR_04,,,,Vy lidi z povrchu nás nikdy nepochopíte.,Ihr Oberflächenleute werdet uns nie verstehen.,,,Ustedes gente de la superficie nunca podrán entendernos.,,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.,,Vocês da superfície nunca nos entenderão.,,Voi oamenii de la suprafață nu veți înțelege niciodată.,"Вы, люди с поверхности, никогда не поймёте нас.", "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, 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.","衛兵共は俺らを見つけられない。 あのバカどもは俺らがここに居ることすら 知らないんだぞ。","하, 저 멍청한 경비들은 우리가 이 밑에 숨어있다는 걸 모르죠!","Ha, de bewakers kunnen ons niet vinden. Die idioten weten niet eens dat we bestaan.",,"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ă.","Ха! Эта глупая стража никогда не найдёт нас. Они даже не знают, что мы существуем.", -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.","Eines Tages werden alle, die nicht dem Orden dienen, sich uns anschließen.",,,"Un día, todos excepto aquellos que sirvan a la Orden serán forzados 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 a partecipare.","そのうち、オーダーに仕える者を除いて +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.","Eines Tages werden alle, die nicht dem Orden dienen, sich uns anschließen.",,,"Un día, todos excepto aquellos que sirvan a la Orden serán forzados 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.",,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.,"Однажды всем, кто не служит Ордену, придётся присоединиться к нам.", -"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ář.","Glotz nur, aber irgendwann wirst du auch so aussehen.",,,"Observe ahora, pero esté seguro que esta podría ser su 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.","Guardaci pure, ma lo sai che un giorno questa sarà la tua faccia.","今ジロジロ見てたみたいだが、 +"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ář.","Glotz nur, aber irgendwann wirst du auch so aussehen.",,,"Observe ahora, pero esté seguro que esta podría ser su 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.",,"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.","Смотри сколько влезет, но знай, что когда-нибудь так будет выглядеть и твоё лицо.", -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!,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ù scocciante di un essere di superficie con un attitudine!,腹立たしい地上人の態度は悩みの種だ!,버릇없는 지상인 보다 더 짜증 나는 건 없을 거예요!,Er is niets vervelender dan een verharder met een houding!,,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!,"Ничто так не выводит из себя, как болтун с поверхности!", +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!,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!,,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!,"Ничто так не выводит из себя, как болтун с поверхности!", 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.,Der Orden wird eure armselige Front auseinandernehmen.,,,La Orden acabará fácilmente con 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.,,A Ordem vai dar um jeito em vocês da Frente.,,Ordinul va face preș din Frontul tău.,Орден быстро расправится с твоим бессильным сопротивлением., -"Watch yourself, surfacer. We know our enemies!",TXT_RANDOM_BEGGAR_10,,,,"Dávej si pozor, nadzemníku. Známe své nepřátele!","Pass nur auf, Oberflächler. Wir kennen unsere Feinde.",,,"Mírese a si mismo, superficial. ¡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, essere di superficie. Conosciamo i nostri nemici!",気を付けろ、地上人。敵はアンタを知ってるぞ。,"조심하시오, 지상인. 우리는 적이 누군지 알고 있으니!","Let op jezelf, surfacer. Wij kennen onze vijanden!",,"Cuidado, ô da superficie. Nós sabemos quem são os nossos inimigos!",,"Ai grijă, omule de la suprafață! Ne cunoaștem inamicii.","Поосторожнее, человек с поверхности. Мы знаем, кто наш враг!", -We are the hands of fate. To earn our wrath is to find oblivion!,TXT_RANDOM_PGUARD_01,,,,Jsme rukami osudu. Získat si náš hněv je jako upadnout v zapomnění!,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!,"運命は我々の手の中だ。 +"Watch yourself, surfacer. We know our enemies!",TXT_RANDOM_BEGGAR_10,,,,"Dávej si pozor, nadzemníku. Známe své nepřátele!","Pass nur auf, Oberflächler. Wir kennen unsere Feinde.",,,"Mírese a si mismo, superficial. ¡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!",,"Cuidado, ô da superficie. Nós sabemos quem são os nossos inimigos!",,"Ai grijă, omule de la suprafață! Ne cunoaștem inamicii.","Поосторожнее, человек с поверхности. Мы знаем, кто наш враг!", +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í!,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!,,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!,Мы длани судьбы. Прогневить нас означает встретить забвение!, 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!,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! ","オーダーは浅ましく腐敗した世界を @@ -10056,234 +10052,234 @@ The Order will cleanse the world of the weak and corrupt!,TXT_RANDOM_PGUARD_02,, Obey the will of the masters!,TXT_RANDOM_PGUARD_03,,,,Podrob se vůli svých pánů!,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!,,Obedeça a lei dos mestres!,,Supune-te voinței stăpânilor!,Подчинись воле хозяев!, Long life to the brothers of the Order!,TXT_RANDOM_PGUARD_04,,,,Nechť žijí naši bratři Řádu!,Lang lebe die Brüder des Ordens.,,,¡Larga vida a 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!,,Vida longa aos irmãos da Ordem!,,Viață lungă fraților Ordinului!,Да здравствуют братья Ордена!, 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.",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.,,Livre arbítrio é uma ilusão para os fracos.,,Voința liberă e o iluzie care leagă mințile slabe.,"Свободная воля — лишь иллюзия, созданная для управления слабыми духом.", -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ě!,"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 camminare quel percorso!,"力は栄光への道だ。 +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ě!,"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!,,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!,Сила — путь к величию. Вступить в ряды Ордена означает пойти этим путём!, -"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!",Nimm deinen Platz unter den Gerechten ein. ,,,"Tome su lugar entre los justos, ¡Únase 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, entra con noi!",正義は我等と共に在る、参加せよ!,"우리는 참됐으며 구원을 받았느니라, 함께 기도하면 두려울 것이 없을지니!","Neem je plaats in tussen de rechtvaardigen, sluit je aan bij ons!",,Tenha o seu lugar entre os justos. Junte-se a nós!,,Alătură-te celor drepți!,Займи своё место среди праведных. Присоединись к нам!, -The Order protects its own.,TXT_RANDOM_PGUARD_08,,,,Řád si své lidi chrání.,Der Orden beschützt seine Jünger.,,,La Orden protege a los suyos.,La Orden se protege a los suyos.,Veljeskunta puolustaa omiaan.,L'ordre protège les siens.,A Rend a magáét védi.,L'ordine protegge se stesso.,オーダーは我々を守護している。,오더는 신들을 향한 기도로 거룩하여짐이니라.,De Orde beschermt zijn discipelen. ,,A Ordem protege os seus discípulos.,,Ordinul îi protejează pe cei loiali.,Орден защищает своих., -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.,Ministranten? Die müssen erst noch die volle Macht des Ordens erfahren.,,,¿Acólitos? Ellos aún no han visto la gloria de nuestra 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 vedere la gloria piena dell'Ordine.,"アコライト? +"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!",Nimm deinen Platz unter den Gerechten ein. ,,,"Tome su lugar entre los justos, ¡Únase 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!",,Tenha o seu lugar entre os justos. Junte-se a nós!,,Alătură-te celor drepți!,Займи своё место среди праведных. Присоединись к нам!, +The Order protects its own.,TXT_RANDOM_PGUARD_08,,,,Řád si své lidi chrání.,Der Orden beschützt seine Jünger.,,,La Orden protege a los suyos.,La Orden se 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. ,,A Ordem protege os seus discípulos.,,Ordinul îi protejează pe cei loiali.,Орден защищает своих., +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.,Ministranten? Die müssen erst noch die volle Macht des Ordens erfahren.,,,¿Acólitos? Ellos aún no han visto la gloria de nuestra 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.,,Acólitos? Eles ainda não viram toda a glória da Ordem.,,Acoliți? Încă nu au văzut gloria Ordinului.,Служители? Им ещё только предстоит узреть подлинное величие Ордена., -"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.","Wenn du noch einen Hauch von Ehre hast, wirst du dem Orden beitreten.",,,"Si hay algo de honor dentro de esa patética cáscara de cuerpo, podrás entrar a los brazos de la Orden.",,"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'è ancora un onore dentro quel guscio patetico di corpo, entrerai nelle braccia dell'Ordine.","その哀れな肉体の殻でも名誉の為ならば、 +"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.","Wenn du noch einen Hauch von Ehre hast, wirst du dem Orden beitreten.",,,"Si hay algo de honor dentro de esa patética cáscara de cuerpo, podrás entrar a los brazos de la Orden.",,"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.",,"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.","Если внутри этой бренной телесной оболочки есть хоть капля чести, ты присоединишься к Ордену.", Bye!,TXT_RANDOMGOODBYE_1,,,,Tak ahoj!,Tschüss!,,Ĝis!,¡Adiós!,,Näkemiin!,Au revoir!,Szervusz!,Ciao!,じゃあな!,안녕!,Dag!,,Tchau!,,Pa!,Пока!, "Thanks, bye!",TXT_RANDOMGOODBYE_2,,,,"Díky, ahoj!","Danke, tschüss!",,"Dankon, ĝis!","Gracias, ¡Adiós!",,"Kiitos, hei!","Merci, au revoir!","Köszi, szia!","Grazie, ciao!",どうも、じゃあ!,그렇군요. 그럼 안녕히!,"Bedankt, tot ziens!",,Obrigado. Até mais!,,"Merci, pa!","Спасибо, пока!", See you later!,TXT_RANDOMGOODBYE_3,,,,Uvidíme se později!,Bis später!,,Ĝis la revido!,¡Nos vemos!,,Nähdään!,A plus tard!,Később találkozunk!,Ci vediamo dopo!,また今度!,다음에 봐요!,Tot ziens!,,Até logo!,,Ne vedem mai încolo!,До встречи!, ,,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, 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!",,"もしもし? 司令部、comユニットが起動されました。 +"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, 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ユニットが起動されました。 ...からビジュアルとサウンドを受け取っています ...誰かが...ちょっと、今そこから出て行ってください ...そして聖杯を捨ててください!","여보세요? 본부, 통신기가 막 작동되기 시작했다... 지금 어떤... 사람의 모습이 보이는데... 이봐, 거기서 당장 나와... 그리고 성배를 버려!","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!",,"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!","Алло? Штаб, передатчик только что включился... Я принимаю звук и картинку от... кого-то... Эй, ты, беги оттуда, сейчас же... и брось чашу!", -"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,,,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Dostala jsem rozkaz tě přivést te 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 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, esta unidad de comunicación me dice que eres 100% humano. Se me ha ordenado hacerte entrar, hablamos en confianza. Traicióname y paga. Oh, 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.",,"聞こえるか、この無線機がアナタは100%人間だと判断した。 +"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,,,,"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 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, esta unidad de comunicación me dice que eres 100% humano. Se me ha ordenado hacerte entrar, hablamos en confianza. Traicióname y paga. Oh, 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%人間だと判断した。 私はアナタを信頼して良いとみて連れて来るよう命じられた、 反乱への報酬は期待して良いわ。ああ、それと、私の名はブラックバードよ。","잘 들어, 이 통신기에 따르면 넌 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.",,"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.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ", -"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 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.",,"聞いて、このcom-unitはあなたが100%人間だということを教えてくれます。 +"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 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. 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....",,"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.","Слушай — судя по этому передатчику, ты на сто процентов человек. Ты можешь присоединиться к нам, и мы должны доверять друг другу. Небольшое тебе испытание: в особняке губернатора есть огнемёт. Достань его, и я покажу тебе дорогу к нам.", -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,,,,"Zamiř ke staré radnici. Macil nechal postavit tunel, který nám dovoluje se dostat dovnitř a ven bez vědomí akolytů.","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.",,"旧市庁舎に入る。そこにはマシルがアコライトに関わる者を欺く為の +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,,,,"Zamiř ke staré radnici. Macil nechal postavit tunel, který nám dovoluje se dostat dovnitř a ven bez vědomí akolytů.","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.,,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.,"Отправляйся к старой ратуше. Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.", -"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,,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,,"Ve por la puerta a tu izquierda, y luego a tu 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.",,"すぐ左のドアを通り、右のドアから小部屋に入るんだ。 +"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,,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,,"Ve por la puerta a tu izquierda, y luego a tu 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.",,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.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.", -"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.","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. Ya no es seguro, nos han descubierto. Mata a todos los robots grandes, los 'Cruzados' y te guiaré a nosotros.","No entres en el ayuntamiento. Ya no es seguro, fuimos descubiertos. Mata a los robots gigantes, 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.",,"町にいるフロントへの武器供給者であるイラールの元を訪ねる。 +"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.","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. Ya no es seguro, nos han descubierto. Mata a todos los robots grandes, los 'Cruzados' y te guiaré a nosotros.","No entres en el ayuntamiento. Ya no es seguro, fuimos descubiertos. Mata a los robots gigantes, 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.",,"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.","Не ходи к ратуше. Наше убежище было разгромлено, теперь там небезопасно. Перебей этих больших роботов, «крестоносцев», и я покажу тебе дорогу к нам. ", -"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.","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.",,"私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 +"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.","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.",,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.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.", -"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.","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.",,"私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 +"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.","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.",,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.","Дверь возле оружейного магазина откроется, когда все крестоносцы будут уничтожены. На складе ты найдёшь телепорт. Используй его — он доставит тебя к нам.", -"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.","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.",,,"저 거대한 '크루세이더' 로봇들을 최대한 처리해. 상황이 정리되면, 내가 너를 마실에게 데려다줄게.","Dood zoveel mogelijk van de grote robots, kruisvaarders, als je kunt. Als je klaar bent, begeleid ik je naar Macil...",,"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.","Убей столько больших роботов, — крестоносцев, — сколько сможешь. Когда закончишь, я приведу тебя к Мэйсилу.", -"Go through the door, and talk to Macil.",TXT_ILOG9,,strifeteaser,,Projdi dveřmi a promluv si s Macilem.,Geh durch die Tür und rede mit Macil.,,,"Ve por la puerta, y habla con 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.",,ダーウィンを始末したら耳を知事に渡す。,저 문을 지나서 마실하고 대화를 해봐.,"Ga door de deur, en praat met Macil.",,Passe pela porta e fale com o Macil.,,Intră pe ușă și du-te la Macil.,Обратись к Мэйсилу. Он за этой дверью., -"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,,,,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.,Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. ,,,"Encuentra la intervención eléctrica en la red principal, y apágala. Trae algo de vuelta al gobernador como prueba. Encuentra a MacGuffin, y habla con él.",Encuentra la intervención eléctrica de la red principal y elimínala. Trae una prueba de vuelta al gobernador. 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.",,"電力盗用の場所を見つけ、それを止める。 +"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.","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...",,"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.","Убей столько больших роботов, — крестоносцев, — сколько сможешь. Когда закончишь, я приведу тебя к Мэйсилу.", +"Go through the door, and talk to Macil.",TXT_ILOG9,,strifeteaser,,Projdi dveřmi a promluv si s Macilem.,Geh durch die Tür und rede mit Macil.,,,"Ve por la puerta, y habla con 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.",,Passe pela porta e fale com o Macil.,,Intră pe ușă și du-te la Macil.,Обратись к Мэйсилу. Он за этой дверью., +"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,,,,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.,Finde die Stromanzapfung und schalte sie ab. Bringe einen Beweis zum Gouverneur. Finde MacGuffin und rede mit ihm. ,,,"Encuentra la intervención eléctrica en la red principal, y apágala. Trae algo de vuelta al gobernador como prueba. Encuentra a MacGuffin, y habla con él.",Encuentra la intervención eléctrica de la red principal y elimínala. Trae una prueba de vuelta al gobernador. 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.,,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.",Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди МакГаффина и поговори с ним., -"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,,,,"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.","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.",,,"Encuentra la intervención eléctrica en la red principal, y apágala. Trae algo de vuelta al gobernador como prueba. Encuentra a MacGuffin, y habla con él. Está arriba junto a la planta de tratamiento de aguas residuales, en el 'hoyo vagabundo', bajando las escaleras.","Encuentra la intervención eléctrica de la red principal y elimínala. Trae una prueba de vuelta al gobernador. Encuentra a MacGuffin y habla con él. Se encuentra en la planta de tratamiento de aguas residuales, en el 'agujero vagabundo', bajando las 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"".",,"電力盗用の場所を見つけ、それを止める。 +"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,,,,"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.","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.",,,"Encuentra la intervención eléctrica en la red principal, y apágala. Trae algo de vuelta al gobernador como prueba. Encuentra a MacGuffin, y habla con él. Está arriba junto a la planta de tratamiento de aguas residuales, en el 'hoyo vagabundo', bajando las escaleras.","Encuentra la intervención eléctrica de la red principal y elimínala. Trae una prueba de vuelta al gobernador. Encuentra a MacGuffin y habla con él. Se encuentra en la planta de tratamiento de aguas residuales, en el 'agujero vagabundo', bajando las 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.",,"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.","Найди нелегальное подключение к линии электропередачи и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства. Найди МакГаффина и поговори с ним. Он возле очистного сооружения, в «бомжевой норе», вниз по лестнице.", -"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,,,,"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.","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 a los circuitos de interferencia que usamos para ocultar nuestra base a la Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ahora! Luego, vuelve con el gobernador y dale el acoplador roto.","¡Idiota! Quitaste la energía a los circuitos de interferencia que utilizamos para que la Orden no vea nuestra base. Dirígete al ayuntamiento y saca al equipo de escaneo. Luego, ve 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.",,"馬鹿者! お前はオーダーから我々の基地を隠す妨害回路を +"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,,,,"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.","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 a los circuitos de interferencia que usamos para ocultar nuestra base a la Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ahora! Luego, vuelve con el gobernador y dale el acoplador roto.","¡Idiota! Quitaste la energía a los circuitos de interferencia que utilizamos para que la Orden no vea nuestra base. Dirígete al ayuntamiento y saca al equipo de escaneo. Luego, ve 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.","馬鹿者! お前はオーダーから我々の基地を隠す妨害回路を 壊してしまった!市庁舎に調査隊が向かった、今すぐ片付けろ! ",이 멍청이야! 우리 기지를 오더로부터 은폐시켜주는 교란 장치의 동력을 끊어버렸잖아. 당장 시청으로 가서 탐색반들을 쓸어버려! 그다음에 총독에게 부서진 장치를 전해줘.,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.,,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!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее! Затем вернись к губернатору и отдай ему повреждённую муфту.", -"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,,,,"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.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen. Bring ihm den Stromabnehmer.",,,"OK, ¡'no te fies de nadie' es el nombre del juego! Consigamos ese pase de la prisión del gobernador. Llévale el acoplador roto.","OK, ¡'no confíes en nadie' es el nombre del juego! Consigamos ese pase de la prision del gobernador. Llévale el acoplador roto.","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, ""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,,,,"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.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen. Bring ihm den Stromabnehmer.",,,"OK, ¡'no te fies de nadie' es el nombre del juego! Consigamos ese pase de la prisión del gobernador. Llévale el acoplador roto.","OK, ¡'no confíes en nadie' es el nombre del juego! Consigamos ese pase de la prision del gobernador. Llévale el acoplador roto.","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, ""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.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму. Отнеси ему повреждённую муфту.", -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,,,,"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.",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 paso! El gobernador es un mentiroso. Ese es nuestro acoplador de energía. Lo estamos usando para ocultar nuestra base a la Orden. Llévale de vuelta este acoplador roto y consigamos ese pase.,¡Buena movida! El gobernador es un mentiroso. Ese es nuestro acoplador de energía. Lo estamos utilizando para esconder nuestra base de la Orden. Llévale este acoplador roto y consigamos 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.",,"良い判断だ! 知事は嘘を付いている。 +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,,,,"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.",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 paso! El gobernador es un mentiroso. Ese es nuestro acoplador de energía. Lo estamos usando para ocultar nuestra base a la Orden. Llévale de vuelta este acoplador roto y consigamos ese pase.,¡Buena movida! El gobernador es un mentiroso. Ese es nuestro acoplador de energía. Lo estamos utilizando para esconder nuestra base de la Orden. Llévale este acoplador roto y consigamos 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.,,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.","Отличный ход! Губернатор — лжец. Это наше подключение к силовой линии. Мы используем его, чтобы скрывать местоположение нашей базы от Ордена. Отнеси повреждённую муфту губернатору и получи пропуск.", -Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG18,,,,"Použij dozorcův klíč k dostání se do bloku s celami a najdi způsob, jak osvobodit vězně.","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 Director para entrar a los bloques de celdas y encontrar una manera 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.",,"ワーデンの鍵で刑務所の独房区域に入って +Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG18,,,,"Použij dozorcův klíč k dostání se do bloku s celami a najdi způsob, jak osvobodit vězně.","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 Director para entrar a los bloques de celdas y encontrar una manera 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.,,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.,"Используй ключ тюремщика, чтобы пройти к камерам. Найди способ освободить пленников.", -Find a way to free the prisoners. Find a way to open the hand scanner switch.,TXT_ILOG19,,,,"Najdi způsob, jak osvobodit vězně. Najdi způsob, jak aktivovat skener otisků ruky.","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 abrir el interruptor de escáner de mano.,Encuentra una manera de liberar a los prisioneros. Encuentra una forma de abrir el switch de escaneo de manos.,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.",,"囚人を解放する方法を見つける。 +Find a way to free the prisoners. Find a way to open the hand scanner switch.,TXT_ILOG19,,,,"Najdi způsob, jak osvobodit vězně. Najdi způsob, jak aktivovat skener otisků ruky.","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 abrir el interruptor de escáner de mano.,Encuentra una manera de liberar a los prisioneros. Encuentra una forma de abrir el switch de escaneo de manos.,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.,,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.,Найди способ освободить пленников. Найди способ открыть замок со сканером отпечатка руки., -Find a way to free the prisoners. Use the judge's hand to operate the hand scanner switch.,TXT_ILOG20,,,,"Najdi způsob, jak osvobodit vězně. Použij soudcovu ruku k aktivaci skeneru otisků ruky.","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 el interruptor de escáner de mano.,Encuentra una manera de liberar a los prisioneros. Utiliza la mano del juez para operar el switch de escaneo de manos.,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.",,"囚人を解放する方法を見つける。 +Find a way to free the prisoners. Use the judge's hand to operate the hand scanner switch.,TXT_ILOG20,,,,"Najdi způsob, jak osvobodit vězně. Použij soudcovu ruku k aktivaci skeneru otisků ruky.","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 el interruptor de escáner de mano.,Encuentra una manera de liberar a los prisioneros. Utiliza la mano del juez para operar el switch de escaneo de manos.,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.,,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.,"Найди способ освободить пленников. Используй руку судьи, чтобы открыть замок со сканером отпечатка руки.", -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,,,,"Jen tak dál, příteli, dobrá práce. Skoč na teleportér, dostane tě to zpět na základnu.","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.,Que forma de avanzar amigo mío. Buen trabajo liberando a los prisioneros. Entra en alguno de los teleportes 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.",,"よくやった相棒。囚人を解放できたのは良い働きだ。 +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,,,,"Jen tak dál, příteli, dobrá práce. Skoč na teleportér, dostane tě to zpět na základnu.","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.,Que forma de avanzar amigo mío. Buen trabajo liberando a los prisioneros. Entra en alguno de los teleportes 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.",,"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ă.,"Так держать, дружище. Ты отлично поработал и освободил пленников. Прыгай в любой телепорт, и он вернёт тебя на базу.", -"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.","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. Ve a visitar a Worner, un espía que reclutamos en el almacén de la estación eléctrica.","Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Visita a Worner, un espía que reclutamos en el almacén de la Estación 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.",,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止めろ。 +"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.","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. Ve a visitar a Worner, un espía que reclutamos en el almacén de la estación eléctrica.","Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Visita a Worner, un espía que reclutamos en el almacén de la Estación 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.",,"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.","Уничтожь кристалл, питающий энергосеть Ордена, от которой работают их щиты. Встреться с Уорнэром, нашим шпионом, на складе электростанции.", -Let's get lost. There's more fun to come.,TXT_ILOG24,,,,"Ztraťme se, za chvíli tu bude víc srandy.",Lass uns verschwinden. Hier wird's gleich ungemütlich.,,,Perdámonos. Hay más diversion por venir.,Vamos a perdernos. Aún hay más diversión por venir.,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.,,迷子になったら、もっと楽しめるぞ。,어서 여길 떠나자. 녀석들이 오기 전에 말이야.,Laten we verdwalen. Er komt nog meer plezier.,,Então se manda. Tem mais diversão por vir.,,Să ne pierdem. O să mai fie distracții.,Давай-ка исчезнем отсюда. Скоро начнётся веселье., -"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,,,,"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.","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 de oro y algo de entrenamiento. Despues de visitarlo, ve al médico en el pueblo para ganar fuerza.","Una aventura más antes de que el comando se sienta listo para atacar el castillo. Macil le dijo a Irale que te de algo de oro y entrenamiento. Después de visitarlo, ve al médico en el pueblo para obtener 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.",,"もう一つの任務をこなす前に戦力の増強が必要と考えられる。 +Let's get lost. There's more fun to come.,TXT_ILOG24,,,,"Ztraťme se, za chvíli tu bude víc srandy.",Lass uns verschwinden. Hier wird's gleich ungemütlich.,,,Perdámonos. Hay más diversion por venir.,Vamos a perdernos. Aún hay más diversión por venir.,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.,,Então se manda. Tem mais diversão por vir.,,Să ne pierdem. O să mai fie distracții.,Давай-ка исчезнем отсюда. Скоро начнётся веселье., +"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,,,,"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.","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 de oro y algo de entrenamiento. Despues de visitarlo, ve al médico en el pueblo para ganar fuerza.","Una aventura más antes de que el comando se sienta listo para atacar el castillo. Macil le dijo a Irale que te de algo de oro y entrenamiento. Después de visitarlo, ve al médico en el pueblo para obtener 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ù.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 マシルがイラールを介して資金と訓練の手配をしてくれるので会いなさい。 それと近所のメディックも支援してくれるわ。",본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그리고 마을 병원에 가서 근력을 키워달라고 해.,"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.",,"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ță.","Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. После встречи с ним, посети городского медика.", -"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.","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 governador.","Visita a Irale y al médico del pueblo para obtener oro y entrenamiento, luego encuentra las alcantarillas. Dirígete a través del río enfrente de 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.",,"イラールとメディックを尋ねて資金と訓練を受け、下水道に向かうんだ。 +"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.","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 governador.","Visita a Irale y al médico del pueblo para obtener oro y entrenamiento, luego encuentra las alcantarillas. Dirígete a través del río enfrente de 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.",,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.","Зайди к Ирэйлу и городскому медику за золотом и обучением, потом спустись в канализацию. Иди вдоль берега реки, спуск прямо напротив особняка губернатора.", -"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_ILOG28,,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že to je jak barvité, tak přesné.","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.","Buscamos a Weran, quién se llama a sí mismo el Rey de las Ratas. Estoy segura que es descriptivo y colorido.","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á.",,"誰が呼んだかラットキングのウェランを探すんだ。 +"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_ILOG28,,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že to je jak barvité, tak přesné.","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.","Buscamos a Weran, quién se llama a sí mismo el Rey de las Ratas. Estoy segura que es descriptivo y colorido.","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.",,"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.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.", -"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,,,,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.,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. Al fondo hay una entrada secreta a las alcantarillas. Los controles de la puerta están ahí abajo, en algún lugar. Destrúyelos.","Llévale las partes del lanzallamas a Irale. Drena el tanque de recuperación. En la parte inferior hay una entrada oculta a las alcantarillas. Los controles de la puerta están ahí abajo, en alguna parte. Destruyelos.",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.,,"火炎放射器の部品をイラールに持っていく。 +"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,,,,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.,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. Al fondo hay una entrada secreta a las alcantarillas. Los controles de la puerta están ahí abajo, en algún lugar. Destrúyelos.","Llévale las partes del lanzallamas a Irale. Drena el tanque de recuperación. En la parte inferior hay una entrada oculta a las alcantarillas. Los controles de la puerta están ahí abajo, en alguna parte. Destruyelos.",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.",,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.","Отнеси детали огнемёта Ирэйлу. Слей жидкость из бака для переработки. На его дне скрытый вход в канализацию. Механизм управления воротами где-то там, внизу. Сломай его.", -"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,,,,"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.",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! 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.",,"司令官、彼はやったぞ! +"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,,,,"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.",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! 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.",,"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.","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились! Возвращайся на базу Сопротивления.", -"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,,,,"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.","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 escondido en un templo en el subnivel, y también otro que al final de un largo pasillo.","Únete al asalto en el castillo. Encuentra y saca al programador. Tenemos informes contradictorios sobre su ubicación. Uno dice que está en una sala de computadora, otro que se esconde en un templo en el sub-nivel y uno más que está 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.",,"城に向かう突撃部隊に参加してプログラマーを探し出せ。 +"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,,,,"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.","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 escondido en un templo en el subnivel, y también otro que al final de un largo pasillo.","Únete al asalto en el castillo. Encuentra y saca al programador. Tenemos informes contradictorios sobre su ubicación. Uno dice que está en una sala de computadora, otro que se esconde en un templo en el sub-nivel y uno más que está 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.",,"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.","Присоединись к атаке на замок. Найди и уничтожь Программиста. Наши сведения о его местонахождении противоречивы. Одни говорят, что он в компьютерной комнате, другие — что он укрывается в подземном храме, а третьи — что он в конце длинного коридора.", -Find the Programmer and kill him.,TXT_ILOG45,,,,Najdi Programátora a zabij ho.,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.,,プログラマーを見つけて殺せ。,프로그래머를 찾아서 죽여.,Zoek de Programmeur en vermoord hem.,,Encontre o Programador e mate-o.,,Găsește Programatorul și ucide-l.,Найди Программиста и убей его., -"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.","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.",,"オラクルに会いシジルの欠片の場所を尋ねろ。 +Find the Programmer and kill him.,TXT_ILOG45,,,,Najdi Programátora a zabij ho.,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.,,Encontre o Programador e mate-o.,,Găsește Programatorul și ucide-l.,Найди Программиста и убей его., +"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.","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.","オラクルに会いシジルの欠片の場所を尋ねろ。 オラクルは町外れの国境地帯にいる。 川の向こうにある城を目指しアーチウェイを左に曲がるのだ。","오라클을 찾아서 다른 시질 조각이 어디에 있는지 물어봐. 오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","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.",,"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ă.","Найди Оракула и спроси его про другие фрагменты Сигила. Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.", -"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.","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.","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.",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.",,"オラクルに会いシジルの欠片の場所を尋ねろ。 +"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.","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.","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.",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.",,"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ș.","Найди Оракула и спроси его про другие фрагменты Сигила. Храм Оракула расположен в пограничье, на окраине города.", -"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,,,,"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.","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 y 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.","Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. Obtén tu recompensa y ve con el médico y el entrenador de armas para obtener salúd y entrenamiento. El templo del Oráculo está en las fronteras, a las afueras de la ciudad.",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.",,"オラクルに会いシジルの欠片の場所を尋ねろ。 +"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,,,,"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.","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 y 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.","Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. Obtén tu recompensa y ve con el médico y el entrenador de armas para obtener salúd y entrenamiento. El templo del Oráculo está en las fronteras, a las afueras de la ciudad.",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.",,"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.,"Найди Оракула и спроси его про другие фрагменты Сигила. Возьми свою награду и зайди к медику и инструктору по стрельбе. Храм Оракула находится в пограничье, на окраине города.", -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,,,,"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ť.","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.,Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. Aquí está. Estoy grabando todo. No es que no tenga fé en que vas a sobrevivir. Solo es 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.",,"オラクルに会いシジルの欠片の場所を尋ねろ。 +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,,,,"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ť.","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.,Busca al Oráculo y pregúntale acerca de las otras piezas del Emblema. Aquí está. Estoy grabando todo. No es que no tenga fé en que vas a sobrevivir. Solo es 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.,,"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.","Найди храм Оракула и спроси его про другие фрагменты Сигила. Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Сигил.", -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,,,,"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.","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 se encuentra en el corazón e la torre carmesí y obsidiana. Ahí encontrarás al Obispo. El Obispo es 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í deberás encontrar al Obispo. El Obispo es el líder militar de la Orden. Acabamos con él y anotamos doble. Lleva el símbolo 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.",,"二つ目の欠片は深紅と黒曜石の塔にある。そこでビショップを見つけろ。 +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,,,,"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.","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 se encuentra en el corazón e la torre carmesí y obsidiana. Ahí encontrarás al Obispo. El Obispo es 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í deberás encontrar al Obispo. El Obispo es el líder militar de la Orden. Acabamos con él y anotamos doble. Lleva el símbolo 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.,"二つ目の欠片は深紅と黒曜石の塔にある。そこでビショップを見つけろ。 ビショップはオーダーの軍事指揮官だ。奴を討ち破り欠片を手に入れろ。 国境地帯のキーマスターにオラクルのトークンを見せよ。",두 번째 시질 조각은 진홍빛 흑요석 탑에 숨어있는 비숍에게 있어. 비숍은 그들의 잔혹한 군사 지도자이지. 거기에 녀석이 있을 거야. 그를 죽이면 두 배로 이득이 갈 거야. 이 통행증을 들고 접경지 안의 열쇠지기에게로 가봐.,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.,,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.,Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты сразишься с Епископом. Епископ — военный лидер Ордена. От его убийства мы выигрываем вдвойне. Отнеси жетон Оракула ключнику в пограничье., -"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,,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem? Najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","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.","El Obispo estará fuertemente resguardado, así que, ¿Porque no robamos el uniforme de un guardia y nos mezclamos? Localiza al Obispo. Una vez que lo destruyas, regresa 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.",,"ビショップのいる場所の警備は厳重なので、 +"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,,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem? Najdi Biskupa. Až ho zabiješ, vrať se k Věštci.","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.","El Obispo estará fuertemente resguardado, así que, ¿Porque no robamos el uniforme de un guardia y nos mezclamos? Localiza al Obispo. Una vez que lo destruyas, regresa 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.",,"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.","Похоже, что Епископа неплохо охраняют, так что почему бы нам не стянуть униформу и прокрасться внутрь? Найди Епископа. После того, как ты уничтожишь его, возвращайся к Оракулу.", -"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,,,,"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.","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. Trabaja allí. Después, 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. Dirijámonos al hospital. Él trabaja ahí. Después, localiza al Obispo y destruyelo. Cuando esté muerto, regresa 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.",,"要塞の中に情報提供者がいるという話を聞いた。 +"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,,,,"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.","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. Trabaja allí. Después, 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. Dirijámonos al hospital. Él trabaja ahí. Después, localiza al Obispo y destruyelo. Cuando esté muerto, regresa 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.",,"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.","Мне только что сказали, что у нас есть информатор внутри крепости. Идём к госпиталю — он работает там. Затем найди Епископа и убей его. После его смерти вернись к Оракулу.", -"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,,,,"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.",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.",,"諦めないで。これでいいんだ。真っ直ぐ行こう。 +"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,,,,"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.",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","諦めないで。これでいいんだ。真っ直ぐ行こう。 中央管理室のテレポーターに入りコンピューターコアを破壊せよ。 それはビショップのフォースフィールドを殺せる。 ビショップも殺したらオラクルの元へ戻れ。",포기하지 마. 이제 거의 다 왔어. 저 텔레포터를 올라타서 관리소로 가서 컴퓨터 중심부를 파괴해. 방어막을 완전히 꺼버리고 비숍을 죽일 수 있을 거야. 그를 파괴하고 오라클에게 찾아가 봐.,"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.",,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.","Не падай духом. Вот оно. Прямо впереди. Прыгай в телепорт к центральной администрации и уничтожь центральный компьютер. Это отключит силовое поле на входе в башню Епископа. После его смерти, возвращайся к Оракулу.", -"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,,,,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.,"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 volarlo. Eso debería ocuparse del campo de fuerza. Volvamos a la muralla, luego derechos a la torre y al Obispo.","Muy Impresionante. Vamos a volarlo. Eso debería de encargárse del campo de fuerza. Luego regresemos al Patio, luego 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.",,"あら、見事な物ね。是非とも火薬を献上しましょう。 +"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,,,,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.,"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 volarlo. Eso debería ocuparse del campo de fuerza. Volvamos a la muralla, luego derechos a la torre y al Obispo.","Muy Impresionante. Vamos a volarlo. Eso debería de encargárse del campo de fuerza. Luego regresemos al Patio, luego 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.",,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.","Очень впечатляюще. Давай взорвём. Это должно избавить нас от проблем с силовым полем. Возвращаемся во внутренний двор, затем к башне и Епископу.", -"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.","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, 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.","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.","ブラボー!新たなるシジルの欠片だ! ビショップの体から出てきたあの奇妙な幽体を見た? 以前に何処かで見た気がするけど?",브라보! 두 번째 시질 조각을 얻었어! 그나저나 비숍 몸에서 튀어나왔던 검은 물체 봤어? 전에 본 적이 있나? 오라클에게 돌아가자.,"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! 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.","Браво, ещё один фрагмент Сигила! Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше? Давай вернёмся к Оракулу.", -"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í.","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.",,"ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという +"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í.","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.",,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ă.","Мне доложили, что спектральная энергия, найденная нами возле Епископа, также исходит от Оракула. Будь начеку.", -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 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 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 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.,,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.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец. Давай вернёмся к Оракулу.", -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.,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.,,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 +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.,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!,,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.,Очередной фрагмент Сигила. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне. Давай возвращаться к Оракулу!, -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 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.",,"貴方はもはや完全なシジルの力を行使できるわけね。 +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 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.,,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.,"Теперь ты владеешь мощью завершённого Сигила. Мы уже близко — давай покончим с этим. Посмотрим, что же охранял Хранитель мудрости.", -"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.","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.",,"まあ予言なんてそんなものでしょ。 +"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.","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.",,"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.","Да, это превзошло все наши ожидания. Успокойся, Мэйсил вызывает нас назад. Давай выбираться отсюда.", -"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.","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 magético y explosivo, justo para apagar campos de fuerza. Obtengamos esa llave de las catacumbas, y luego derechos a las minas a por algo de mineral.","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. Obtengamos esa llave de las Catacumbas y luego vayamos a las minas 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.",,"工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +"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.","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 magético y explosivo, justo para apagar campos de fuerza. Obtengamos esa llave de las catacumbas, y luego derechos a las minas a por algo de mineral.","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. Obtengamos esa llave de las Catacumbas y luego vayamos a las minas 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.","工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 デグニン石は綺麗だが可燃性で、フォースフィールドを消すにはうってつけよ。 そこへのキーを地下墓所から取り、鉱山に向かおう。","공장은 광산 옆에 있어. 아마도 릭터는 데그닌 갱도를 예기한 것 같아. 데그닌 광석은 폭발성이 있는 자기력이 감도는 물질이야. 방어막을 끌 중요한 도구이기도 하지. 고대 무덤에서 그 열쇠를 얻고, 광석을 얻을 광산으로 향하자.","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.",,"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.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ из катакомб, а потом спустись в шахты за рудой.", -"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ý.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo 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.","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. Obtengamos esa llave de las Catacumbas y luego vayamos a las minas por algo de mineral. Estas deben ser las ruinas 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.",,"工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +"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ý.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo 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.","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. Obtengamos esa llave de las Catacumbas y luego vayamos a las minas por algo de mineral. Estas deben ser las ruinas 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 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.",,"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.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Достань ключ в катакомбах, а потом спустись за рудой. Должно быть, именно эти руины искали агенты Рихтера. Будь осторожен.", -"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 předměstí a pak do dolů. Potřebujeme rudu.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo para apagar campos de fuerza. Amigo, lo que sea contra lo que estamos luchando, es más que sólo la Orden. Volvamos a los comunes y luego derechos a las minas. Necesitamos mineral.","La Fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo para apagar campos de fuerza. Amigo mío, sea lo que sea con lo que estamos pelando, es algo más que solo la Orden. Regresemos a los comunes, luego vayamos 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.",,"工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +"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.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo para apagar campos de fuerza. Amigo, lo que sea contra lo que estamos luchando, es más que sólo la Orden. Volvamos a los comunes y luego derechos a las minas. Necesitamos mineral.","La Fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo para apagar campos de fuerza. Amigo mío, sea lo que sea con lo que estamos pelando, es algo más que solo la Orden. Regresemos a los comunes, luego vayamos 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 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.",,"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.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Друг мой, с чем бы мы не сражались, это нечто большее, чем просто Орден. Вернись назад в поселение и спустись в шахты. Нам нужна руда.", -"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.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo para apagar campos de fuerza. Sin bajar la guardia, busca depósitos de mineral.","La Fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo 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.",,"工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +"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.","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. Richter debe referirse a las minas de Degnin. El mineral Degnin es magético y explosivo, justo para apagar campos de fuerza. Sin bajar la guardia, busca depósitos de mineral.","La Fábrica está junto a las minas. El mineral Degnin es magnético y explosivo, justo 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. Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.",,"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.","Вход на фабрику — рядом со спуском в шахты. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. Поищи залежи руды, но не теряй бдительности!", -"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í!","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.",,"警戒を緩めることなく、鉱石の堆積所を探しましょう。 +"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í!","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.","警戒を緩めることなく、鉱石の堆積所を探しましょう。 ここの精神の乏しい労働者達は、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.",,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.","Поищи залежи руды, но не теряй бдительности. Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Если мы уничтожим передатчик, они свободны.", -"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.","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.","La Fábrica está junto a las minas. Sin bajar la guardia, busca depósitos de mineral. Mi sugerencia es, aventar el mineral al campo de fuerza y luego hacerlo estallar, la compresión que resulte debería crear una manta magnética 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.",,"工場は鉱山の隣にあるわ。警戒を緩めることなく、鉱石の堆積所を探しましょう。 +"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.","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.","La Fábrica está junto a las minas. Sin bajar la guardia, busca depósitos de mineral. Mi sugerencia es, aventar el mineral al campo de fuerza y luego hacerlo estallar, la compresión que resulte debería crear una manta magnética 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.","工場は鉱山の隣にあるわ。警戒を緩めることなく、鉱石の堆積所を探しましょう。 私の案はフォースフィールドの近くに鉱石を置き撃って爆発させる方法よ。 その結果、圧縮されていた磁場の反動で光を打ち消すわ。","공장은 광산 옆에 있어. 자신을 지킬 준비 단단히 하고, 캔 광석을 두는 곳을 찾아. 조언을 찾는다면, 광석을 방어막에 가까이 놔둔 뒤 쏴봐. 광석이 커다란 자기장을 만들 테고, 방어막을 완전히 무력화 시킬 거야.","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.",,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.","Вход на фабрику — рядом со спуском в шахты. Поищи залежи руды, но не теряй бдительности. Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.", -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!,"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!,Ahora vamos a la Fábrica. Sal de las minas y no puedes perderla. ¡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!",,"工場へ今すぐ入ろう。鉱山の出口はすぐわかる。 +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!,"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!,Ahora vamos a la Fábrica. Sal de las minas y no puedes perderla. ¡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!,,"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!","Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход. Найди эту машину и останови её!", -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!","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!,Estoy leyendo distorsiones neuronales masivas adelante. Creo que la hemos encontrado. ¡Entremos y desactivé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!,,重い神経波歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아. 어서 들어가서 꺼버리자!,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we hem gevonden hebben. Laten we naar binnen gaan en de machine stilleggen!,,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.","Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер. Войди и останови его!", -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!","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!,¡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!",,"今まで見てきたことについて考えている! +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!","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!,Estoy leyendo distorsiones neuronales masivas adelante. Creo que la hemos encontrado. ¡Entremos y desactivé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!,,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.","Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер. Войди и останови его!", +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!","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!,¡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!,"今まで見てきたことについて考えている! 奴は人の内部から出てくる...それについて考えたくないわ。 この恐怖を打ち消すんだ!",이렇게 끔찍한 모습을 보게 되다니! 멀쩡한 사람이 저곳에 들어갔다 나온 모습을... 차마 생각하기도 싫어. 저 경악스러운 것을 파괴해!,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!,,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!,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом. Покончи с этим кошмаром!", -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 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'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 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.,"オラクルが正しかった。マシルはイカれていたなんて。 彼は故意に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.,,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.,"Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов! Давай вернёмся и выясним, что происходит.", -"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ě.","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.",,"リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 +"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ě.","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.",,"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.","За фабрикой находится «лаборатория», и мы засекли характерную энергию фрагмента Сигила, исходящую оттуда. Вернись на фабрику и сделай ещё один шаг к нашему освобождению.", -"Find the Bishop and destroy him! Once he's dead, return to the Oracle.",TXT_ILOG120,,,,"Najdi Biskupa a znič ho! Až ho zabiješ, vrať se k Věštci.","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.","¡Encuentra al Obispo y destruyelo! Cuando 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.",,ビショップを見つけて殺したらオラクルの元へ戻れ。,비숍을 찾아서 그를 파괴해! 시질 조각을 얻은 뒤 오라클에게 돌아가.,"Vind de bisschop en vernietig hem! Als hij dood is, keer je terug naar het Orakel.",,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.","Найди Епископа и уничтожь его! После, вернись к Оракулу.", -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ě.","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.,,"ロアマスター研究所は開いたばかりのテレポーターを越えた先だ。 +"Find the Bishop and destroy him! Once he's dead, return to the Oracle.",TXT_ILOG120,,,,"Najdi Biskupa a znič ho! Až ho zabiješ, vrať se k Věštci.","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.","¡Encuentra al Obispo y destruyelo! Cuando 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.",,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.","Найди Епископа и уничтожь его! После, вернись к Оракулу.", +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ě.","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.,,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.,"Телепорт, который ты нашёл, приведёт тебя в лабораторию Хранителя мудрости. Давай узнаем, о чём он там бормотал, и сделаем ещё один шаг к освобождению.", -"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,,,,"No tak, dostaňme se sakra odsud. Silové pole je kaput, jdeme do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","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.",,"頼むからこんな所さっさと出よう。 +"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,,,,"No tak, dostaňme se sakra odsud. Silové pole je kaput, jdeme do Biskupovy věže. Až ho zabiješ, vrať se k Věštci.","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.","頼むからこんな所さっさと出よう。 フォースフィールドは切った、ビショップの塔へ向かおう。 ビショップを殺したらオラクルの元へ戻れ。 ","이제 이곳을 당장 떠나. 방어막이 꺼졌으니! 비숍의 성으로 이동해서 비숍을 죽이고, 오라클을 만나러 가.","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.",,"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.","Ну же, двигаем отсюда. Силовое поле отключено, пора двигаться к башне Епископа. Когда он умрёт, возвращайся к Оракулу.", -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.,"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 adentro. Tráeselo a Harris en la taberna.,Encuentra el santuario por el río. Roba el Cáliz de adentro. Tráelo con Harris a la taverna.,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.,,"川沿いの 聖域 を探し、中にある聖杯を盗む。 +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.,"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 adentro. Tráeselo a Harris en la taberna.,Encuentra el santuario por el río. Roba el Cáliz de adentro. Tráelo con Harris a la taverna.,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.,,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ă.,Найди святилище возле реки. Проникни туда и выкради чашу. Принеси её Харрису в таверну., -Find the Governor. Talk to him about your reward.,TXT_ILOG1002,,,,Najdi guvernéra. Promluv si s ním o své odměně.,Finde den Gouverneur. Rede mit ihm über deine Belohnung.,,,Encuentra al Gobernador. Háblale sobre tu recompensa.,Encuentra al gobernador. Habla con él acerca de tú 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.,,知事を探せ。彼と話して報酬を貰う。,총독을 만나서 보상에 대해 예기해.,Vind de Gouverneur. Spreek met hem over je beloning.,,Encontre o Governador. Fale com ele sobre a sua recompensa.,,Găsește Guvernatorul. Vorbește cu el despre recompensa ta.,Найди губернатора. Обсуди с ним свою награду., -"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,,,,Najdi svatyni u řeky. Uvnitř je držen jakýsi Beldin. Umlč ho a přines Rowanovi jeho prsten jako důkaz.,Finde das Heiligtum am Fluss. Dort drinnen wird jemand namens Beldin festgehalten. Bringe ihn zum Schweigen und gebe Rowan seinen Ring als Beweis.,,,"Encuentra el santuario junto al río. Dentro alguien llamado Beldin está retenido. Siléncialo, y tráe de vuelta su anillo a Rowan como prueba.",Encuentra el santuario por el río. Adentro alguien llamado Beldin está retenido. Cállalo 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.",,"川沿いの 聖域 を探せ。中にいるベルディンと +Find the Governor. Talk to him about your reward.,TXT_ILOG1002,,,,Najdi guvernéra. Promluv si s ním o své odměně.,Finde den Gouverneur. Rede mit ihm über deine Belohnung.,,,Encuentra al Gobernador. Háblale sobre tu recompensa.,Encuentra al gobernador. Habla con él acerca de tú 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.,,Encontre o Governador. Fale com ele sobre a sua recompensa.,,Găsește Guvernatorul. Vorbește cu el despre recompensa ta.,Найди губернатора. Обсуди с ним свою награду., +"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,,,,Najdi svatyni u řeky. Uvnitř je držen jakýsi Beldin. Umlč ho a přines Rowanovi jeho prsten jako důkaz.,Finde das Heiligtum am Fluss. Dort drinnen wird jemand namens Beldin festgehalten. Bringe ihn zum Schweigen und gebe Rowan seinen Ring als Beweis.,,,"Encuentra el santuario junto al río. Dentro alguien llamado Beldin está retenido. Siléncialo, y tráe de vuelta su anillo a Rowan como prueba.",Encuentra el santuario por el río. Adentro alguien llamado Beldin está retenido. Cállalo 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.","川沿いの 聖域 を探せ。中にいるベルディンと 呼ばれている捕獲された者を見つけ彼を黙らせる。 指輪をロワンに渡す。","강 근처에 있는 성소를 찾아서 벨딘이라는 사람을 찾고, 입을 다물게 해. 그 후에 그의 반지를 얻어서 로완에게 그를 죽였다고 증명해.","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.",,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ă.,"Найди святилище возле реки. Внутри содержится пленник по имени Белдин. Заставь его замолчать, и принеси его кольцо Роуэну в качестве доказательства.", -Find the location of the Front and talk to Macil.,TXT_ILOG1004,,,,Najdi umístění Fronty a promluv si s Macilem.,Finde die Basis der Front und rede mit Macil.,,,Encuentra la localización del Frente y habla con 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.",,フロントの場所を見つけ、マシルと会話する。,프론트의 기지를 찾아서 마실과 대화해봐.,Zoek de locatie van het Front en praat met Macil.,,Ache a localização da Frente e fale com o Macil.,,Găsește locația Frontului și vorbește cu Macil.,Найди базу Сопротивления и поговори с Мэйсилом., -"Go down the stairs, find and talk to Macil.",TXT_ILOG1005,,,,Jdi dolů po schodech a najdi a promluv si s Macilem.,Geh die Treppe runter und rede mit Macil.,,,"Baja por las escaleras, encuentra y habla con Macil.","Baja 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.",,階段を降り、マシルと会話する。,계단 밑으로 내려가서 마실과 대화해봐.,"Ga de trap af, zoek en praat met 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.","Спустись на этаж ниже, найди Мэйсила и поговори с ним.", -"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,,,,"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.","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á detrás de la puerta junto a la tienda de armas. Luego, usa la llave que te dió Macil para hablar con el Gobernador.","Visita a Irale, el proveedor de armamento del Frente. Está detrás de la puerta junto a la tienda de armas. Luego, usa la llave que te dió 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.",,"町にいるフロントへの武器供給者であるイラールの元を訪ねる。 +Find the location of the Front and talk to Macil.,TXT_ILOG1004,,,,Najdi umístění Fronty a promluv si s Macilem.,Finde die Basis der Front und rede mit Macil.,,,Encuentra la localización del Frente y habla con 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.,,Ache a localização da Frente e fale com o Macil.,,Găsește locația Frontului și vorbește cu Macil.,Найди базу Сопротивления и поговори с Мэйсилом., +"Go down the stairs, find and talk to Macil.",TXT_ILOG1005,,,,Jdi dolů po schodech a najdi a promluv si s Macilem.,Geh die Treppe runter und rede mit Macil.,,,"Baja por las escaleras, encuentra y habla con Macil.","Baja 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.",,"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.","Спустись на этаж ниже, найди Мэйсила и поговори с ним.", +"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,,,,"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.","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á detrás de la puerta junto a la tienda de armas. Luego, usa la llave que te dió Macil para hablar con el Gobernador.","Visita a Irale, el proveedor de armamento del Frente. Está detrás de la puerta junto a la tienda de armas. Luego, usa la llave que te dió 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.",,"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.","Посети Ирэйла, поставщика оружия Сопротивления в городе. Он за следующей после оружейного магазина дверью. Затем, воспользуйся ключом, который тебе дал Мэйсил, чтобы поговорить с губернатором.", -"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof.",TXT_ILOG1007,,,,Najdi stáčedlo energie na síti a vypni jej. Přines guvernérovi něco zpět jako důkaz.,Finde die Energieanzapfung und schalte sie aus. Bringe dem Gouverneur irgend etwas als Beweis.,,,Encuentra la intervención de la red principal y desactívala. Trae algo de vuelta al Gobernador como prueba.,Encuentra la intervención de la red principal y desactívala. Regresa con una prueba con el Gobernador.,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.",,"電力盗用の場所を見つけ、それを止める。 +"Find the power tap on the mains, and shut it off. Bring something back to the Governor as proof.",TXT_ILOG1007,,,,Najdi stáčedlo energie na síti a vypni jej. Přines guvernérovi něco zpět jako důkaz.,Finde die Energieanzapfung und schalte sie aus. Bringe dem Gouverneur irgend etwas als Beweis.,,,Encuentra la intervención de la red principal y desactívala. Trae algo de vuelta al Gobernador como prueba.,Encuentra la intervención de la red principal y desactívala. Regresa con una prueba con el Gobernador.,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.",,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.,Найди нелегальное подключение к энергосети и выведи его из строя. Принеси что-нибудь губернатору в качестве доказательства., -"Find Derwin in the warehouse of the power station. Kill him, and bring Mourel his ear.",TXT_ILOG1008,,,,Najdi Derwina ve skladu elektrárny. Zabij ho a přines Mourelovi jeho ucho.,Finde Derwin im Lagerhaus des Kraftwerks. Töte ihn und bringe Mourel sein Ohr.,,,"Encuentra a Derwin en el almacén de la estación eléctrica. Mátalo, y tráele su oreja a Mourel.",Encuentra a Derwin en el almacén de la Estación Eléctrica. Mátalo y táele a Mourel su oreja.,"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.",,"発電所の倉庫にいるダーウィンを見つける。 +"Find Derwin in the warehouse of the power station. Kill him, and bring Mourel his ear.",TXT_ILOG1008,,,,Najdi Derwina ve skladu elektrárny. Zabij ho a přines Mourelovi jeho ucho.,Finde Derwin im Lagerhaus des Kraftwerks. Töte ihn und bringe Mourel sein Ohr.,,,"Encuentra a Derwin en el almacén de la estación eléctrica. Mátalo, y tráele su oreja a Mourel.",Encuentra a Derwin en el almacén de la Estación Eléctrica. Mátalo y táele a Mourel su oreja.,"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.",,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.,Найди Дервина на складе электростанции. Убей его и принеси Морелу его ухо., -"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,,,,"Použij propustku od Mourela pro vstup do vězení. Uvnitř si promluv s dozorčím Montagem. Najdi způsob, jak vysvobodit vězně.","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.","Usa el pase que Mourel te dió para entrar en la prisión. Una vez dentro, habla con el Director Montag. Encuentra una manera 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.",,"モーレルからもらった刑務所の許可証を使って入る。 +"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,,,,"Použij propustku od Mourela pro vstup do vězení. Uvnitř si promluv s dozorčím Montagem. Najdi způsob, jak vysvobodit vězně.","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.","Usa el pase que Mourel te dió para entrar en la prisión. Una vez dentro, habla con el Director Montag. Encuentra una manera 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.",,"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.","Используй пропуск, полученный у Морела, чтобы пройти в тюрьму. Когда ты будешь внутри, поговори с тюремщиком Монтагом. Найди способ освободить пленников.", -Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG1010,,,,"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ě.","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 Director para entrar en los bloques de celdas y encuentra una manera 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.",,ワーデンから鍵を奪って内部に入れ。,"간수장의 열쇠를 써서 감옥 안으로 진입하고, 수감자들을 풀어줄 방법을 찾아봐.",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.,,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.,"Используй ключ тюремщика, чтобы пройти к камерам, и найди способ освободить пленников.", -"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,,,,"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š.","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. Ve a visitar a Worner, un espía que reclutamos en el almacén de la estación eléctrica. No te olvides de visitar al médico y el entrenador de armas antes de irte","Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Visita a Worner, un espía que reclutamos en el almacén de la Estación Eléctrica. No olvides visitar al médico y el entrenador de armas antes de irte.","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.",,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 +Use the Warden's key to get into the prison cell blocks and find a way to free the prisoners.,TXT_ILOG1010,,,,"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ě.","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 Director para entrar en los bloques de celdas y encuentra una manera 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.,,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.,"Используй ключ тюремщика, чтобы пройти к камерам, и найди способ освободить пленников.", +"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,,,,"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š.","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. Ve a visitar a Worner, un espía que reclutamos en el almacén de la estación eléctrica. No te olvides de visitar al médico y el entrenador de armas antes de irte","Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Visita a Worner, un espía que reclutamos en el almacén de la Estación Eléctrica. No olvides visitar al médico y el entrenador de armas antes de irte.","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.",,"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.","Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Поговори с Уорнэром, шпионом Сопротивления, на складе электростанции. Не забудь перед уходом посетить медика и инструктора по стрельбе.", -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,,,,"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.",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 rede eléctrica que alimenta los escudos de la Orden. Usa la identificación para entrar a la estación eléctrica. Quizas quieras comprobar el cuarto de almacenamiento encima de Worner.,Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Usa la Identificación para entrar a la Estación Eléctrica. Quizás quieras revisar el cuarto de almacenaje arriba 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.",,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 +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,,,,"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.",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 rede eléctrica que alimenta los escudos de la Orden. Usa la identificación para entrar a la estación eléctrica. Quizas quieras comprobar el cuarto de almacenamiento encima de Worner.,Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Usa la Identificación para entrar a la Estación Eléctrica. Quizás quieras revisar el cuarto de almacenaje arriba 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.,,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.,"Уничтожь кристалл, питающий энергосеть, от которой работают щиты Ордена. Пройди на электростанцию по удостоверению. Возможно, ты захочешь проверить склад на втором этаже, о котором говорил Уорнэр.", -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,,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi za Ketrickem u jádra.","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 rede eléctrica que alimenta los escudos de la Orden. Habla con Ketrick en el área del núcleo.,Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Ve a hablar 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.",,"送電網を動かしているパワークリスタルを破壊してオーダーのシールドを止める。 +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,,,,"Znič energetický krystal, který napájí elektrickou síť, kterou jsou poháněné štíty Řádu. Jdi za Ketrickem u jádra.","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 rede eléctrica que alimenta los escudos de la Orden. Habla con Ketrick en el área del núcleo.,Destruye el cristal de poder que impulsa la red eléctrica que abastece los escudos de la Orden. Ve a hablar 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.,,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.,"Уничтожь кристалл, питающий энергосеть Ордена и их щиты. Поговори с Кетриком возле реактора.", -"Destroy the power crystal. Go talk to Ketrick, bring the walkway up using the switches, then use this id for the elevator.",TXT_ILOG1014,,,,"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.",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.","Destruye el cristal de poder. Ve a hablar con Ketrick, levanta el pasaje usando los switches, luego, usa está identificación para el elevador.",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.",,"パワークリスタルを破壊してオーダーのシールドを止める。 +"Destroy the power crystal. Go talk to Ketrick, bring the walkway up using the switches, then use this id for the elevator.",TXT_ILOG1014,,,,"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.",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.","Destruye el cristal de poder. Ve a hablar con Ketrick, levanta el pasaje usando los switches, luego, usa está identificación para el elevador.",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.",,"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.","Уничтожь кристалл. Поговори с Кетриком, пройди наверх с помощью переключателей, затем используй удостоверение для доступа к лифту.", -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.","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 trae de vuelta a Weran el uniforme del guardia.,Encuentra la entrada al pueblo que la Orden ha guardado. Abre la puerta y trae el uniforme del guardia de regreso a Weran.,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.",,"オーダーが封鎖している町への入り口を見つける。 +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.","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 trae de vuelta a Weran el uniforme del guardia.,Encuentra la entrada al pueblo que la Orden ha guardado. Abre la puerta y trae el uniforme del guardia de regreso a Weran.,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.,,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.,"Найди выход в город, охраняемый Орденом. Открой дверь и принеси униформу стражника Уэрану.", -"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.,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.,,"火炎放射器の部品をイラールに持っていく。 +"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.,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.",,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.",Отнеси детали огнемёта Ирэйлу. Найди дверь техобслуживания канализации. Найди бак для переработки и слей из него жидкость. На его дне находится потайной вход в стоки. Где-то за ним находится механизм управления воротами., -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.","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.,,"城内への突撃部隊に加入し、プログラマーを探す。 +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.","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.,,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.,Присоединись к атаке на замок. Найди и убей Программиста. Посети медика и инструктора по стрельбе. Не жалей золота: битва будет чертовски жаркой., -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.,"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.",,"偽プログラマーから貰ったキーを使って本物がいるはずの砦を開く。 +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.,"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.,,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.,"Используй ключ, полученный от фальшивого Программиста, чтобы открыть вход в цитадель. Скорее всего, именно там прячется настоящий Программист. Найди и убей его.", -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,,,,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.,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.",,"オラクルに会いシジルの欠片について尋ねる。 +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,,,,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.,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.,,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.,Найди Оракула и спроси у него про другие фрагменты Сигила. Возьми свою награду и посети медика и инструктора по стрельбе., -"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.","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.",,"二つ目の欠片は深紅と黒曜石の塔の中心部にある。そこのビショップを討伐せよ。 +"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.","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.",,"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.,"Второй фрагмент лежит в сердце багрово-обсидиановой башни. Там ты встретишь Епископа, который ожидает тебя. Отнеси жетон Оракула ключнику в пограничье. Когда уничтожишь Епископа, возвращайся к Оракулу.", -"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,,,,"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.","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.",,"二つ目の欠片は深紅と黒曜石の塔の中心部にある。そこのビショップを討伐せよ。 +"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,,,,"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.","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.",,"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.","Найди багрово-обсидиановую башню. Используй пропуск, полученный у ключника, чтобы войти внутрь. Там ты должен найти Епископа. Когда уничтожишь его, возвращайся к Оракулу.", -"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,,,,"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.","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.","Encuentra el complejo de seguridad, pelea através de ahí y usa el teleporte a la Central de Administración. Destruye el núcleo en la Central de Administración. Esto desactivará el campo de fuerza en la torre del Obispo. Una vez que 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.",,"複合警備所を見つけ、そこを制圧し中央管理所へのテレポーターを使う。 +"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,,,,"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.","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.","Encuentra el complejo de seguridad, pelea através de ahí y usa el teleporte a la Central de Administración. Destruye el núcleo en la Central de Administración. Esto desactivará el campo de fuerza en la torre del Obispo. Una vez que 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.",,"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.","Найди охранный комлекс, пробейся внутрь и используй телепорт до центральной администрации. Уничтожь компьютер. Это должно отключить силовое поле башни Епископа. Когда убьёшь Епископа, возвращайся к Оракулу.", -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.","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.",,"次の挑戦は己の精神が試される。三つ目の欠片は我々のリーダーが保持している。 +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.","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.,,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.,"Следующее задание испытает силу твоего духа. Третий фрагмент у вашего лидера. Он сам — один из тех, кого вы убиваете по его приказу. Сразись с ним и исполни своё предназначение.", -"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ý.","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.",,"三つ目の欠片を持つのはオラクルだ。あいつが裏切者だ。 +"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ý.","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.",,É 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.",Третий фрагмент хранится у Оракула. Так и кто же из нас предатель? Вернись к Оракулу и расправься с ним. Доложи мне о его смерть., -"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 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.",,"己の癌は切除したが動揺は隠せないままだ。 +"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 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.",,"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.","Ты вырезал опухоль из своего тела, но твоё сердце всё ещё бьётся. Теперь тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой.", -"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ě.","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.",,"次の欠片は人々を虐殺で支配する外科医... +"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ě.","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.",,"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.","Тебе предстоит найти вивисектора, который вскрывает твоих людей и управляет ими — Хранителя мудрости. Останови его, и следующий фрагмент твой. Используй открытый мной телепорт, чтобы добраться до него. Когда он умрёт, найди другой телепорт и вернись ко мне.", -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 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.",,"貴方は賢い判断をした。三つ目の欠片は我々のリーダーが保持している。 +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 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.,"貴方は賢い判断をした。三つ目の欠片は我々のリーダーが保持している。 貴方の胸中に隠れているものを払い彼の元に戻る。 ",좋은 판단이야. 세 번째 시질 조각은 마실이 가지고 있어. 그를 죽여서 조각을 얻은 뒤 오라클에게 돌아와.,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.,,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.,"Мудрый выбор. Третий фрагмент у вашего лидера. Уничтожь то, что закралось в твоё сердце, и возвращайся ко мне.", -"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 předměstí u vodopádů. Řekne ti, jak zastavit tuto ohavnost.","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.",,"我等はオーダーが人々をサイボーグ兵に改造しつつある事を発見した。 +"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.","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à.","我等はオーダーが人々をサイボーグ兵に改造しつつある事を発見した。 これが行われている施設を見つけ永久に停止させる。 コモンズの滝近くにいるリヒターに会い、この残虐な行為を止める方法を聞く。","오더가 우리 사람들을 생체병기로 개조한다는 사실을 알았어. 끔찍한 일이 일어나는 이 시설을 찾아서 작동을 중단시켜, 영원히! 폭포와 가까운 식당가에 있는 릭터를 찾아서 어떻게 하면 중단시킬 수 있는지를 물어봐.","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.",,"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.","Мы выяснили, что Орден превращает наших людей в биомеханических солдат. Найди фабрику, где это происходит, и закрой её, навсегда! Найди Рихтера в поселении Ордена, возле водопада — он расскажет тебе, как остановить эти зверства.", -"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 předměstím. 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ů.","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.",,"工場に入るにはキーが必要だ。持っていた代理人はコモンズの地下墓所にはいない。 +"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ů.","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.","工場に入るにはキーが必要だ。持っていた代理人はコモンズの地下墓所にはいない。 何処かへ連れて行かれたと思われる。それが何であれキーを見つけなければならない。 キーを手に入れたら工場の隣の鉱山に向かう。","공장으로 들어가기 위해서는 열쇠가 필요해. 열쇠를 훔치기는 했지만, 소유했던 요원이 식당가 밑 고대 무덤 안에서 행방불명 되었데. 우리 병사들을 끌고 가는 무언가가 있는 것 같아. 그게 무엇이든, 파괴해서 열쇠를 얻어. 그리고 광산 옆에 있는 공장을 열쇠로 열어서 들어가.","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.",,"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.","Тебе нужен ключ, чтобы проникнуть на фабрику. Мы украли один, но наш агент пропал без вести в катакомбах под поселением. Там, внизу, сидит что-то, что убивает наших людей. Что бы это ни было, тебе придётся сразиться с ним. Когда заполучишь ключ, вход на фабрику рядом со спуском в шахты.", -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.,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.,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.",,聖域でチャリスを探しバーの二階にいるハリスに渡す,"성소에 있는 성배를 찾은 뒤, 선술집에 있는 헤리스에게 전달해.",Vind de kelk in de kapel van het heiligdom en breng hem naar Harris boven in de taverne.,,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ă.,Найди чашу в святилище и принеси её Харрису на второй этаж таверны., -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.,Finde die Villa des Gouverneurs und rede mit ihm über deine Belohnung.,,,Encuentra la mansión del Gobernador y habla con el Gobernador para obtener tu recompensa,Encuentra la mansión del Gobernador y habla con él para obtener tú 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.",,知事のマンションで知事と話し報酬を得る,총독의 거주지를 찾은 뒤 총독을 만나서 보상에 대해 예기해.,Zoek het herenhuis van de Gouverneur en praat met de Gouverneur om je beloning te krijgen.,,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.,Пройди в особняк губернатора и обсуди с Морелом своё вознаграждение., -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ě.","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 haz ganado 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.",,"おめでとう!私達は貴方に感謝している。 +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.,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.,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.,,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ă.,Найди чашу в святилище и принеси её Харрису на второй этаж таверны., +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.,Finde die Villa des Gouverneurs und rede mit ihm über deine Belohnung.,,,Encuentra la mansión del Gobernador y habla con el Gobernador para obtener tu recompensa,Encuentra la mansión del Gobernador y habla con él para obtener tú 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.,,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.,Пройди в особняк губернатора и обсуди с Морелом своё вознаграждение., +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ě.","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 haz ganado 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.,,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ă.,"Поздравляем! Ты заслужил нашу благодарность. Зайди к медику и инструктору по стрельбе, и они подготовят тебя к тому, что ждёт тебя впереди. Теперь ты можешь свободно передвигаться по нашей базе.", ,,Strife characters,,,,,,,,,,,,,,,,,,,,, @@ -10295,10 +10291,10 @@ Prison Guard,TXT_SPEAKER_PRISON_GUARD,,,,Vězeňská stráž,Gefängniswache,,,G Justin,TXT_SPEAKER_JUSTIN,,,,,,,,,,,,,,ジャスティン,저스틴,,,,,,Джастин, Macil,TXT_SPEAKER_MACIL,,,,,,,,,,,,,,マシル,마실,,,,,,Мэйсил, Assistant,TXT_SPEAKER_ASSISTANT,,,,Asistent,Assistent,,,Asistente,Asistente,Avustaja,,Asszisztens,Assistente,アシスタント,조수,Assistent,Asystent,Assistente,,Asistent,Ассистент, -Key Master,TXT_SPEAKER_KEY_MASTER,,,,Klíčník,Schlüsselmeister,,,Amo de Llaves,Maestro de Llaves,Avainmestari,Maître des Clés,Kulcsmester,Maestro di chiavi,キーマスター,열쇠지기,Zeer belangrijke Meester,Klucznik,Mestre das Chaves,,Stăpân al Cheilor,Ключник, -Bodyguard,TXT_SPEAKER_BODYGUARD,,,,Osobní stráž,Leibwächter,,,Guardaespaldas,Guardaespaldas,Henkivartija,Garde du corps,Testőr,Guardia del corpo,ボディガード,경호원,Lijfwacht,Ochroniarz,Guarda-costas,,Pază de Corp,Телохранитель, +Key Master,TXT_SPEAKER_KEY_MASTER,,,,Klíčník,Schlüsselmeister,,,Amo de Llaves,Maestro de Llaves,Avainmestari,Maître des Clés,Kulcsmester,Mastro delle chiavi,キーマスター,열쇠지기,Zeer belangrijke Meester,Klucznik,Mestre das Chaves,,Stăpân al Cheilor,Ключник, +Bodyguard,TXT_SPEAKER_BODYGUARD,,,,Osobní stráž,Leibwächter,,,Guardaespaldas,Guardaespaldas,Henkivartija,Garde du corps,Testőr,Guardia del corpo,ボディガード,경호원,Lijfwacht,Ochroniarz,Guarda-costas,,Gardă de Corp,Телохранитель, Interrogator,TXT_SPEAKER_INTERROGATOR,"Intended to appear in MAP01 of the Strife teaser, but does not spawn.",,,Vyslýchač,Befrager,,,Interrogador,Interrogador,Kuulustelija,Interrogateur,Kihallgató,Interrogatore,,심문자,Ondervrager,Śledczy,Interrogador,,Interogator,Дознаватель, -Warden Montag,TXT_SPEAKER_WARDEN_MONTAG,,,,Dozorce Montag,Direktor Montag,,,Carcelero Montag,Director Montag,Vankilanjohtaja Montag,Gardien Montag,Montag börtönigazgató,Guardiano Montag,モンターグ刑務所長,몬탕 간수장,Directeur Montag,Naczelnik Montag,Carcereiro Montag,,Directorul Montag,Тюремщик Монтаг, +Warden Montag,TXT_SPEAKER_WARDEN_MONTAG,,,,Dozorce Montag,Direktor Montag,,,Carcelero Montag,Director Montag,Vankilanjohtaja Montag,Gardien Montag,Montag börtönigazgató,Direttore Montag,モンターグ刑務所長,몬탕 간수장,Directeur Montag,Naczelnik Montag,Carcereiro Montag,,Directorul Montag,Тюремщик Монтаг, Richter,TXT_SPEAKER_RICHTER,,,,,,,,,,,,,,リヒター,릭터,,,,,,Рихтер, Macil's Advisor,TXT_SPEAKER_MACIL_S_ADVISOR,,,,Macilův rádce,Macils Berater,,,Consejero de Macil,Consejero de Macil,Macilin neuvonantaja,Conseiller de Macil,Macil tanácsosa,Consigliere di Macil,マシルの補佐官,마실의 조언자,Macil's adviseur,Doradca Macila,Conselheiro de Macil,,Sfetnicul lui Macil,Советник Мэйсила, Judge Wolenick,TXT_SPEAKER_JUDGE_WOLENICK,,,,Soudce Wolenick,Richter Wolenick,,,Juez Wolenick,Juez Wolenick,Tuomari Wolenick,Juge Wolenick,Wolenick bíró,Giudice Wolenick,ウォレニック裁判官,울레닉 판사,Rechter Wolenick,Sędzia Wolenick,Juiz Wolenick,,Judecătorul Wolenick,Судья Уолник, @@ -10339,13 +10335,13 @@ Security Comple,TXT_SPEAKER_SECURITY_COMPLE,"Intended to appear in MAP19, but do Computer Tech,TXT_SPEAKER_COMPUTER_TECH,,,,Počítačový technik,Computertechniker,,,Ingeniero Informático,Ingeniero Informático,Tietokoneteknikko,Technicien Informatique,Számítógép Tech,Tecnico Informatico,機械技術者,컴퓨터 기술자,Computertechniek,Technik Komputerowy,Técnico de Informática,,Tehnician Calculatoare,Компьютерный техник, MacGuffin,TXT_SPEAKER_MACGUFFIN,,,,,,,,,,,,,,マクガフィン,맥거핀,,,,,,МакГаффин, Arion,TXT_SPEAKER_ARION,,,,,,,,,,,,,,アリオン,아리온,,,,,,Арион, -Dock Worker,TXT_SPEAKER_DOCK_WORKER,,,,Dělník v docích,Dockarbeiter,,,Trabajador del Muelle,Trabajador del Muelle,Ahtaaja,Docker,Dokk munkás,Operaio Portuale,港湾労働者,항구 일꾼,Dokwerker,Pracownik Doku,Operário da Doca,,Muncitor Docuri,Рабочий дока, +Dock Worker,TXT_SPEAKER_DOCK_WORKER,,,,Přístavní dělník,Dockarbeiter,,,Trabajador del Muelle,Trabajador del Muelle,Ahtaaja,Docker,Dokk munkás,Operaio Portuale,港湾労働者,항구 일꾼,Dokwerker,Pracownik Doku,Operário da Doca,,Muncitor Docuri,Рабочий дока, Irale,TXT_SPEAKER_IRALE,,,,,,,,,,,,,,イラール,이롤리,,,,,,Ирэйл, Core Guard,TXT_SPEAKER_CORE_GUARD,,,,Stráž jádra,Wache,,,Guardia del Núcleo,Guardia del Núcleo,Ytimenvartija,Garde du cœur,Mag Őr,Guardia del Cuore,コア ガード,코어 경비병,Kernwacht,Strażnik Rdzenia,Guarda do Núcleo,,Gardian Nucleu,Страж ядра, -Sewer Guard,TXT_SPEAKER_SEWER_GUARD,,,,Stráž stok,Kanalisationswächter,,,Guardia de la Alcantarilla,Guardia de la Alcantarilla,Viemärinvartija,Garde des égouts,Kanális Őr,Guardia della Fogna,下水道ガード,하수도 보초병,Rioolwacht,Strażnik Kanałów,Guarda do Esgoto,,Gardian Canal,Страж канализации, +Sewer Guard,TXT_SPEAKER_SEWER_GUARD,,,,Kanální stráž,Kanalisationswächter,,,Guardia de la Alcantarilla,Guardia de la Alcantarilla,Viemärinvartija,Garde des égouts,Kanális Őr,Guardia della Fogna,下水道ガード,하수도 보초병,Rioolwacht,Strażnik Kanałów,Guarda do Esgoto,,Gardian Canal,Страж канализации, Technician,TXT_SPEAKER_TECHNICIAN,,,,Technik,Techniker,,,Técnico,Técnico,Teknikko,Technicien,Technikus,Tecnico,技術者,기술자,Technicus,Technik,Técnico,,Tehnician,Техник, Guard,TXT_SPEAKER_GUARD,,,,Stráž,Wache,,,Guardia,Guardia,Vartija,Garde,Őr,Guardia,ガード,경비병,Bewaker,Strażnik,Guarda,,Gardian,Стражник, -Peasant,TXT_SPEAKER_PEASANT,,,,Rolník,Einwohner,,,Campesino,Campesino,Asukas,Paysan,Jobbágy,Contadino,庶民,민간인,Boer,Kmiot,Cidadão,,Sărman,Работник, +Peasant,TXT_SPEAKER_PEASANT,,,,Rolník,Einwohner,,,Campesino,Campesino,Maallikko,Paysan,Jobbágy,Cittadino,庶民,민간인,Boer,Kmiot,Cidadão,,Sărman,Работник, Armorer,TXT_SPEAKER_ARMORER,,,Armourer,Kovář,Waffenmeister,,,Armero,Armero,Asemestari,Armurier,Fegyverkovács,Armiere,兵器係,병기공,Pantser,Płatnerz,Forjador de Armaduras,,Armurier,Бронник, Beldin,TXT_SPEAKER_BELDIN,,,,,,,,,,,,,,ベルディン,벨딘,,,,,,Белдин, Gerard,TXT_SPEAKER_GERARD,,,,,,,,,,,,,,ジェラルド,제랄드,,,,,,Джерард, @@ -10353,25 +10349,25 @@ Governor Mourel,TXT_SPEAKER_GOVERNOR_MOUREL,,,,Guvernér Mourel,Gouverneur Moure 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,,,,"Kometa bez varování narazila do naší planety. Ztratili jsme svůj ráj během jediného, brutálního úderu.",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.,,"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ă.,"Никто не ожидал, что на нашу планету обрушится метеорит. Земной рай был разрушен единственным безжалостным ударом.", -"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 milióny lidí. Ukázalo se, že to byli ti šťastnější.","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.","彗星の衝突によりウィルスが世界中に放たれ、数えきれないほどの人々が死んだ。 +The comet struck our planet without warning. We lost our paradise in a single violent stroke.,TXT_SUB_INTRO1,,,,"Kometa bez varování narazila do naší planety. Jediným, brutálním úderem jsme přišli o náš ráj.",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.,,"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ă.,"Никто не ожидал, что на нашу планету обрушится метеорит. Земной рай был разрушен единственным безжалостным ударом.", +"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ší.","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.",,"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.","Удар метеорита выпустил вирус, который пронёсся по землям и истребил миллионы людей. Умершие оказались счастливчиками.", -"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,,,,"Protože ti, kteří nezemřeli, se stali lidskými mutanty. Někteří se proměnili ve fanatiky, kteří v hlavě slyšeli hlas zlého boha, a začali si říkat „Řád“.","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"".","死ななかった人々は、人間から変異して別の物となった。 +"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“.","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.",,"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"".","Выжившие сформировали уродливое подобие прежнего общества. Некоторые услышали голос зловещего бога и стали фанатиками, называющими себя «Орденом».", -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.","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.,"その神の声を聞き取れなかった私達は苦しんだ挙げ句、 +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.","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.,"その神の声を聞き取れなかった私達は苦しんだ挙げ句、 この無慈悲な狂人どもに仕えるのを強いられた。 そして奴等は、私達のどんな武器とも比べ物にならないほど強力な兵器を持っているのだ。","신의 목소리를 듣지 못하는 자들은 끔찍한 고통에 시달렸고, 우리가 가진 어떤 무기들보다 강력한 무장을 한 이 무자비한 광신도들을 강제로 섬기게 되었다.","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.",,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.,"Другие — те, кто не слышал этого голоса, — терпели лишения. Их заставили прислуживать этим безжалостным психопатам, чьё оружие превосходило любое наше.", -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 nechat je žít jako zvířata v neutrvajícím strachu o naše životy.","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.","奴等は女性や子供を殺害していくため、私達はそういった人々を地下に隠さなければならなかった。 +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.","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.,,"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.","Они истребляют наших женщин и детей, и нам приходится прятать их в подземелье. Мы живём в постоянном страхе за свою жизнь, как животные.", -"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,,,,"Objevují se však nesouhlasné šepoty. Pokud se uspořádáme, můžeme porazit naše pány? Kradou se zbraně, cvičí se vojáci. Zrodilo se hnutí: Zrodilo se z věčného sváru!","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 allenati i soldati. È nato un movimento: nato da un eterno conflitto!","だが不満のささやきは常にある。もし私達が力を合わせれば、 +"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!","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!",,"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ță!","Но шёпот недовольства растёт. Сможем ли мы свергнуть их господство, если объединимся? Мы крадём их оружие, и наши бойцы проходят подготовку. Движение родилось — родилось из борьбы длиною в жизнь!", -"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ě?","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 leggi?","フロントの兵士たちよ、聞きたまえ! 彼がすべてを終わらせたのだ。 +"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ě?","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?",,"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?","Внимание, всем войскам Фронта! Он справился! Всё кончено! Солдат Чёрного дрозда покончил со злом! Ордена больше нет! Чёрный дрозд, как слышите?", -"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.","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 eroe galante. Tutto il combattimento è cessato. La tua vittoria ci consentirà di creare un vaccino per estirpare il virus dai nostri corpi.","あなたが勝つことは分かっていたわ、私の勇敢なヒーロー。 +"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.","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.","あなたが勝つことは分かっていたわ、私の勇敢なヒーロー。 全ての戦いは終結した。あなたがもたらした勝利のおかげで、 私達の体からウィルスを根絶するためのワクチンを作ることができる。","나의 용감한 영웅이 이길 줄 알았어. 모든 싸움이 끝이 났고, 당신의 승리 덕분에 우리 몸에 남은 바이러스를 퇴치할 백신을 만들 수 있을 거야.","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.",,"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.","Я знала, что ты победишь, мой отважный герой. Война окончена. Твоя победа позволила нам создать вакцину против вируса.", "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 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.","あなたはこの星を救い、そして自由を取り戻した。さあ、 @@ -10381,170 +10377,170 @@ They destroy our women and children so that we must hide them underground and li まだ不安と疑念に満ちている。","그래, 악은 이제 사라졌어. 하지만 우리의 불확실한 앞날은 여전히 근심의 먹구름으로 가득 찼지.","Ja, het kwaad was weg, maar onze toekomst was onzeker en vertroebeld met twijfel.",,"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.","Да, зло было повержено, но наше будущее было туманно и омрачено тенью сомнений...", 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.","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.,,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.,"Десятилетия потребуются, чтобы исцелить наших людей от вируса... если нам удастся просуществовать так долго.", -"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.","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 l'unica cosa che volevamo: ci ha lasciato senza speranza.","あの邪悪な存在が何を求めていたかはともかく、 +"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.","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.",,"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ță.","Чего бы зло ни желало, оно отняло у нас то, в чём мы нуждались больше всего — оно лишило нас надежды.", -"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 síreninu píseň smrti a začali tančit.",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 mortale, portandoci a ballare assieme.","センティエント・ウィルスは私達を津波のように襲い、 +"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.",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.",,"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.","Эпидемия захлестнула нас подобно гигантской волне, лишив рассудка каждого. Мы услышали сладкую песнь смерти и подчинились ей.", -"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 rozmnožování, vyhladilo naše rodiny.",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.","この邪悪な存在は人間たちの命と繁殖能力を奪い去り、 +"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.",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.",,"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.","Зло истребляло в нас всё человеческое. Не задумываясь о завтрашнем дне, оно перерабатывало целые семьи.", "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.","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.,,"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.","Настал день, когда зло ушло. Не осталось ничего, чем оно могло бы питаться. Мы вымерли.", -"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,,,,"Genetické mutace způsobené virem nejenže pokřivily mysli Řádu, ale také způsobily rozklad jejich těl.","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 turbava la psiche dell'Ordine, ma portava i loro corpi a decomporre.","ウィルスからもたらされた遺伝子変異はオーダーの者たちの精神だけではなく、 +"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,,,,"Genetické mutace způsobené virem nejenže pokřivily mysli Řádu, ale také způsobily rozklad jejich těl.","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.",,"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.","Генетические мутации, которые возникали из-за вируса, не только извращали психику членов Ордена, но и вызывали гниение их тел.", "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.","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.",,"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.","Орден обнаружил, что биомеханические улучшения — единственный способ поддержания их численного превосходства при отсутствии деторождения.", -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ž lidi, ale věříme, že jejich kolektivní vědomí je řízené z jednoho zdroje...","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 così tanto che molte delle truppe che vediamo sono più macchine che uomini, ma noi crediamo che la loro coscienza collettiva è controllata da una sola fonte...","彼らの肉体へのダメージは深刻で、我らが遭遇した兵士たちは人間と言うよりは +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...","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....",,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ă...,"Гниение распространялось, поэтому большинство их солдат скорее машины, чем люди. Но мы полагаем, что их коллективное сознание управляется из единого центра...", -"...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.","...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 Acoliti. Distruggi il Programmatore, e noi potremmo rendere inefficiente i soldati dell'Ordine con un colpo solo. Ma attento: rapporti nostri dicono che può vaporizzare gli aggressori.","その者の名はプログラマーだ。 +"...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.","...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.",,"...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.","...Программистом — создателем ИИ, контролирующего служителей. Уничтожь Программиста, и мы разделаемся с войсками Ордена одним ударом. Но осторожнее — нам докладывали, что он умеет... испепелять нападающих.", "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,,,,"Útržky poskládané z Programátorových souborů nám říkají, že Řád uctívá inteligentní zbraň. Říkají jí „Pečeť“.","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"".",,"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"".","Мы собирали информацию по крупицам из обрывков файлов Программиста и выяснили, что Орден поклоняется разумному оружию. Они называют его «Сигилом».", -"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.","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つだ。 +"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.","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.",,"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.","Тот фрагмент, что ты подобрал и активировал, — один из пяти. Он использует мощь, которую черпает из жизненных сил владельца. Пока ты жив, она подвластна тебе.", -"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: Vysaje tě to.","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 usarlo, ma ad un costo: ti prosciugherà in pieno.","君を気絶させた衝撃は、シジルの欠片が脈拍と脳波を同期させた際に起こした様だ。 +"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.","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.",,"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.","Ты потерял сознание, потому что фрагмент Сигила подстраивался под тебя, под твоё сердцебиение и мозговые ритмы. Теперь ты сможешь им пользоваться, но он будет взымать свою плату, иссушая тебя.", 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.,"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.,,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.,Один фрагмент — уже немалая сила. Пять фрагментов будут опустошающей силой. Их владелец получит полную власть над планетой., -"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,STRIFE1.WAD: MAP02,,,"Poslyš, tento komunikátor mi říká, že jsi na sto procent člověkem. Dostala jsem rozkaz tě přivést te 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 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, esta unidad de comunicación me dice que eres 100% humano. Se me ha ordenado hacerte entrar, hablamos en confianza. Traicióname y paga. Oh, 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.",,"聞こえるか、この無線機がアナタは100%人間だと判断した。 +"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,STRIFE1.WAD: MAP02,,,"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 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, esta unidad de comunicación me dice que eres 100% humano. Se me ha ordenado hacerte entrar, hablamos en confianza. Traicióname y paga. Oh, 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.",,"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.","Слушай — судя по этому передатчику, ты на сто процентов человек. Я получила приказ показать тебе дорогу к нам. Как видишь, тебе доверяют, но если предашь меня — пожалеешь. И да, обращайся ко мне «Чёрный дрозд». ", -"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,STRIFE1.WAD: MAP02,,,"Zamiř ke staré radnici. Když ji Řád vybombardoval, Macil nechal postavit tunel, který nám dovoluje se dostat dovnitř a ven bez vědomí akolytů.","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.",,"旧市庁舎に向かうんだ。オーダーに爆撃された後 +"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,STRIFE1.WAD: MAP02,,,"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.","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.",,"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.","Отправляйся к старой ратуше. После того, как Орден взорвал её, Мэйсил построил там туннель, который позволяет нам входить и выходить без ведома служителей.", -"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,STRIFE1.WAD: MAP02,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,,"Ve por la puerta a tu izquierda, y luego a tu 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. Mond neki, hogy aranyra van szükséged.",,"すぐ左のドアを通り、右のドアから小部屋に入るんだ。 +"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,STRIFE1.WAD: MAP02,,,"Projdi dveřmi nalevo a pak napravo. Hlídač se jmenuje Geoff. Řekni mu, že potřebuješ zlato.","Geh durch die linke Tür, dann durch die rechte. Der Wächter heißt Geoff. Sag ihm du brauchst Gold.",,,"Ve por la puerta a tu izquierda, y luego a tu 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. 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.",,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.","Пройди за левую дверь, затем иди направо. Стражника зовут Джефф. Скажи ему, что тебе нужно золото.", -"Irale is the Front's ""fixer"". He's behind the unmarked door next to the weapons shop.",TXT_SUB_LOG5,STRIFE1.WAD: MAP03,,,Irale je „dealer“ Fronty. Je za neoznačenými dveřmi vedle obchodu se zbraněmi.,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á detrás de la puerta sin marcar 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 is the Front's ""fixer"". He's behind the unmarked door next to the weapons shop.",TXT_SUB_LOG5,STRIFE1.WAD: MAP03,,,Irale je „kutil“ Fronty. Je za neoznačenými dveřmi vedle obchodu se zbraněmi.,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á detrás de la puerta sin marcar 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 é 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.",Ирэйл — «наладчик» Сопротивления. Ты найдёшь его за дверью без вывески возле оружейного магазина., -Remember: kill with stealth instead of force. You won't set off the alarms.,TXT_SUB_LOG6,STRIFE1.WAD: MAP02,,,Pamatuj: Zabíjej potichu. Nespustíš poplach.,Denk daran: Töte lautlos und du wirst den Alarm nicht auslösen.,,,"Recuerda: mata con sigilo, no con fuerza, y no activarás 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.",,覚えておいて:静かに殺す時はナイフか毒矢だ。警報を鳴らすと厄介なことになる。,기억해: 소음 없이 조용히 죽여. 그럼 경보를 울리지 않을 테니까.,Onthoud: dood met heimelijke in plaats van met geweld. Je laat de alarmen niet afgaan.,,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.,"Запомни: убивай бесшумно, не лезь на рожон, и ты не поднимешь тревогу.", -"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,STRIFE1.WAD: MAP02,,,"O guvernérovi vím jen to, že sympatizuje s oběma stranami. Tady je jeho rádoby „sídlo“.","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"".",,"私が知事について知っていることは、町の中央で双方を遊ばせてる様だ。 +Remember: kill with stealth instead of force. You won't set off the alarms.,TXT_SUB_LOG6,STRIFE1.WAD: MAP02,,,Pamatuj: Zabíjej potichu. Nespustíš poplach.,Denk daran: Töte lautlos und du wirst den Alarm nicht auslösen.,,,"Recuerda: mata con sigilo, no con fuerza, y no activarás 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.,,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.,"Запомни: убивай бесшумно, не лезь на рожон, и ты не поднимешь тревогу.", +"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,STRIFE1.WAD: MAP02,,,"O guvernérovi vím jen to, že se snaží uhrávat sympatie obou stran. Tohle je jeho rádoby „sídlo“.","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"".",,"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"".","Я знаю о губернаторе только то, что он пытается подыграть обеим сторонам, оставаясь посередине. Вот его так называемый «особняк».", -Ugh. The dregs of humanity have certainly found a home.,TXT_SUB_LOG8,,,,Fuj. Spodina lidstva si rozhodně našla domov.,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. De bezinksels van de mensheid hebben zeker een thuis gevonden.,,Urgh. A escória da humanidade certamente encontrou um lar.,,Ugh. Scursurile umanității și-au găsit o casă cu siguranță.,Фу. Самое место для отбросов человечества., -Calling Mourel sleazy is paying him a compliment. He's mongrel turd on a stick.,TXT_SUB_LOG9,STRIFE1.WAD: MAP02,,,"Nazývat Mourela slizákem by mu lichotilo, svinský parchant jeden podělaný.","Mourel als 'verschlagen' zu bezeichnen wäre, ihm ein Kompliment zu machen. Er ist ein Haufen Hundescheiße.",,,Llamar a Mourel sucio 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.,,"モーレルにとって汚職議員は誉め言葉だ。 +Ugh. The dregs of humanity have certainly found a home.,TXT_SUB_LOG8,,,,Fuj. Spodina lidstva si rozhodně našla domov.,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.,,Urgh. A escória da humanidade certamente encontrou um lar.,,Ugh. Scursurile umanității și-au găsit o casă cu siguranță.,Фу. Самое место для отбросов человечества., +Calling Mourel sleazy is paying him a compliment. He's mongrel turd on a stick.,TXT_SUB_LOG9,STRIFE1.WAD: MAP02,,,"Nazývat Mourela slizákem by mu lichotilo, svinský parchant jeden prohnilý.","Mourel als 'verschlagen' zu bezeichnen wäre, ihm ein Kompliment zu machen. Er ist ein Haufen Hundescheiße.",,,Llamar a Mourel sucio 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.,,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ăț.,"Назвать Моурела подлым, значит сделать ему комплимент. Кусок дерьма на палочке...", -We need to speak with someone who knows the old town and where this coupling is. Command says: find MacGuffin. ,TXT_SUB_LOG10,STRIFE1.WAD: MAP02,,,"Musíme si promluvit s někým, kdo zná staré město a kde se tahle spojka nalézá. Vedení říká najít MacGuffina.","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.",,"我々は何処にあるかについてはオールドタウンに知っている者がいる。 +We need to speak with someone who knows the old town and where this coupling is. Command says: find MacGuffin. ,TXT_SUB_LOG10,STRIFE1.WAD: MAP02,,,"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.","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.,,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.,"Нам нужен кто-то, кто знает старый город и может подсказать, где эта муфта. В штабе говорят, что тебе поможет МакГаффин.", -"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,STRIFE1.WAD: MAP02,,,"Najdeš ho na místě, kterému zdvořile říkají „zadnice“. Jdi přes chodník u čističky a sejdi schody.","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 educadamente se llama el ""hoyo 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.",,"彼は行儀よく'バムホール'と呼ばれる場所に居る。 +"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,STRIFE1.WAD: MAP02,,,"Najdeš ho na místě, kterému zdvořile říkají „zadnice“. Jdi přes chodník u čističky a sejdi schody.","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 educadamente se llama el ""hoyo 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.",,"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.","Он в том месте, что вежливо называют «бомжевая нора». Пройди к очистным сооружениям и спустись по лестнице.", -Take your time with this mission. I can't get intel on this from Command.,TXT_SUB_LOG12,STRIFE1.WAD: MAP02,,,Dej si s touhle misí na čas. Nemůžu z velení dostat žádné informace.,Nimm dir Zeit für diese Mission. Ich erhalte keine Informationen aus der Kommandozentrale.,,,Tómate tu tiempo en esta misión. No puedo obtener inteligencia en esto del 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.,,この任務は時間が掛かりそうだ。私は司令部からこれ以上の情報は得る事は出来ない。,느긋하게 수행해도 좋아. 본부에도 이 정보를 모으는 데 문제가 있데.,Neem je tijd met deze missie. Ik kan hier geen informatie over krijgen van de Commandant.,,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.,Не торопись с выполнением этого задания. Я не могу получить разведданные от штаба., +Take your time with this mission. I can't get intel on this from Command.,TXT_SUB_LOG12,STRIFE1.WAD: MAP02,,,Dej si s touhle misí na čas. Nemůžu z velení dostat žádné informace.,Nimm dir Zeit für diese Mission. Ich erhalte keine Informationen aus der Kommandozentrale.,,,Tómate tu tiempo en esta misión. No puedo obtener inteligencia en esto del 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.,,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.,Не торопись с выполнением этого задания. Я не могу получить разведданные от штаба., "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,"STRIFE1.WAD: MAP02 -(If the player destroys the 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!","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 a los circuitos de interferencia que usamos para ocultar nuestra base a la Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ahora!",¡Idiota! Quitaste la energía a los circuitos de interferencia que utilizamos para que la Orden no vea nuestra base. Dirígete al ayuntamiento y saca al equipo de escaneo.,"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!",,"馬鹿者!お前はオーダーから我々の基地を隠す妨害回路を壊してしまった! +(If the player destroys the 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!","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 a los circuitos de interferencia que usamos para ocultar nuestra base a la Orden. Dirígete al ayuntamiento y elimina al equipo de escaneo, ¡ahora!",¡Idiota! Quitaste la energía a los circuitos de interferencia que utilizamos para que la Orden no vea nuestra base. Dirígete al ayuntamiento y saca al equipo de escaneo.,"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!",,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!","Идиот! Ты обесточил генератор радиопомех, с помощью которого мы скрывали местоположение нашей базы от Ордена. Возвращайся к ратуше и уничтожь разведывательную группу как можно скорее!", "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,"STRIFE1.WAD: MAP02 -(If all blue acolytes in the town hall that appear after destroying the Front’s power coupling are killed)",,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen und die Gefangenen befreien.",,,"OK, ¡""no te fies de nadie"" es el nombre del juego! Consigamos ese pase del Gobernador y liberemos 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, ""Vertrouw niemand"" is de naam van het spel! Laten we die pas van de gouverneur halen en die gevangenen vrijlaten.",,"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.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму и освободим пленников.", -Good move! The Governor is a lousy liar. That's our power coupling. Now let's get that pass.,TXT_SUB_LOG15,STRIFE1.WAD: MAP02,,,"Dobrý tah! Guvernér je mizerný lhář, tohle je naše spojka. Pojďme si pro tu propustku.",Das war klasse! Der Gouverneur ist ein lausiger Lügner. Das war unsere Anzapfung. Nun lass uns den Pass holen.,,,¡Buen paso! El gobernador es un mentiroso. Ese es 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ő.,,"良い判断よ!知事は粗末な嘘を付いている。 +(If all blue acolytes in the town hall that appear after destroying the Front’s power coupling are killed)",,,"Dobře, „Nevěř nikomu“ je motto hry! Pojďme od guvernéra dostat tu propustku a osvoboďme ty vězně.","Ok, „Trau keinem“ heißt dieses Spiel. Lass uns den Gefängnispass vom Gouverneur holen und die Gefangenen befreien.",,,"OK, ¡""no te fies de nadie"" es el nombre del juego! Consigamos ese pase del Gobernador y liberemos 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, ""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.","Что ж, эта игра называется «не верь никому»! Давай получим у губернатора пропуск в тюрьму и освободим пленников.", +Good move! The Governor is a lousy liar. That's our power coupling. Now let's get that pass.,TXT_SUB_LOG15,STRIFE1.WAD: MAP02,,,"Dobrý tah! Guvernér je mizerný lhář, tohle je naše spojka. Tak si pojďme pro tu propustku.",Das war klasse! Der Gouverneur ist ein lausiger Lügner. Das war unsere Anzapfung. Nun lass uns den Pass holen.,,,¡Buen paso! El gobernador es un mentiroso. Ese es 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.,,"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.,Отличный ход! Губернатор — мерзкий лжец. Это наше подключение к силовой линии. Теперь получи пропуск., -The warehouse is in the power station. Let's make this short and sweet.,TXT_SUB_LOG16,STRIFE1.WAD: MAP02,,,Skladiště je uvnitř elektrárny. Pojďme to udělat čistě a krátce.,Das Lagerhaus ist im Kraftwerk. Lass uns das schnell erledigen.,,,El almacén está en la estación 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.,,倉庫は発電所にある。さっさと済ませよう。,창고는 발전소 근처에 있어. 어서 신속하고 죽여주게 끝내자.,Het magazijn is in de energiecentrale. Laten we dit kort en bondig houden.,,O depósito fica na usina de energia. Vamos fazer isso bem rápido.,,Depozitul e în stația de energie. Scurt și dulce.,Речь идёт о складе в электростанции. Давай сделаем это быстро и с огоньком., -I never thought I'd break into prison...,TXT_SUB_LOG17,STRIFE1.WAD: MAP02,,,"Nikdy by mě nenapadlo, že se budu vkrádat do vězení...","Ich hätte nie gedacht, in ein Gefängnis einzubrechen...",,,Nunca pensé que me fugaría adentro de 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...",,刑務所にお勤めになるなぞ考えた事もないぞ...,"감옥을 뚫고 들어가다니, 생각도 못 했는데?",Ik had nooit gedacht dat ik zou inbreken in de gevangenis....,,Nunca achei que eu invadiria uma prisão...,,N-am crezut că o să intru într-o închisoare...,"Никогда не думала, что приду в тюрьму добровольно...", -Guess there's no free lunch. Time to lock and load.,TXT_SUB_LOG18,STRIFE1.WAD: MAP05,,,Holt nic není zadarmo. Nabij zbraň a jdi do toho.,Es gibt wohl keine freie Mahlzeit. Ran an die Action.,,,Supongo que no hay comida gratis. Tiempo para 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.,,まあタダでは済まないか。派手に暴れてやれ。,급식 먹을 시간은 없겠네. 요리할 시간이야.,Ik denk dat er geen gratis lunch is. Tijd om te sluiten en te laden.,,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.,"Что ж, бесплатный сыр бывает только в мышеловке. Оружие к бою! ", -"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,STRIFE1.WAD: MAP05,,,"Dobrá. Uspokojil jsi guvernéra, rozmetal dozorčího... Vypadá to, že teď budeme muset provést menší chirurgický zákrok.","Ok, du hast den Gouverneur zufriedengestellt, den Direktor abgemetzelt... Und jetzt sieht es aus als ob eine kleine Operation nötig ist.",,,"OK. Has satisfecho al Gobernador, despedazado al Carcelero... 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.",,"よし、知事は喜ばせ刑務所長はぶちのめした... +The warehouse is in the power station. Let's make this short and sweet.,TXT_SUB_LOG16,STRIFE1.WAD: MAP02,,,"Skladiště je uvnitř elektrárny. Pojďme na to, ať to máme rychle za sebou.",Das Lagerhaus ist im Kraftwerk. Lass uns das schnell erledigen.,,,El almacén está en la estación 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.,,O depósito fica na usina de energia. Vamos fazer isso bem rápido.,,Depozitul e în stația de energie. Scurt și dulce.,Речь идёт о складе в электростанции. Давай сделаем это быстро и с огоньком., +I never thought I'd break into prison...,TXT_SUB_LOG17,STRIFE1.WAD: MAP02,,,"Nikdy by mě nenapadlo, že se budu vkrádat do vězení...","Ich hätte nie gedacht, in ein Gefängnis einzubrechen...",,,Nunca pensé que me fugaría adentro de 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....,,Nunca achei que eu invadiria uma prisão...,,N-am crezut că o să intru într-o închisoare...,"Никогда не думала, что приду в тюрьму добровольно...", +Guess there's no free lunch. Time to lock and load.,TXT_SUB_LOG18,STRIFE1.WAD: MAP05,,,Holt nic není zadarmo. Nabij zbraň a jdi do toho.,Es gibt wohl keine freie Mahlzeit. Ran an die Action.,,,Supongo que no hay comida gratis. Tiempo para 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.,,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.,"Что ж, бесплатный сыр бывает только в мышеловке. Оружие к бою! ", +"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,STRIFE1.WAD: MAP05,,,"Dobrá. Uspokojil jsi guvernéra, rozmetal dozorčího... Vypadá to, že teď budeme muset provést menší operaci.","Ok, du hast den Gouverneur zufriedengestellt, den Direktor abgemetzelt... Und jetzt sieht es aus als ob eine kleine Operation nötig ist.",,,"OK. Has satisfecho al Gobernador, despedazado al Carcelero... 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.",,"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.","Хорошо. Ты доставил удовольствие губернатору, забрызгал стены мозгами тюремщика... Теперь нам предстоит небольшое хирургическое вмешательство.", -Oh you cut off his hand! And I thought you were a nice guy... kinda. Let's go.,TXT_SUB_LOG20,STRIFE1.WAD: MAP05,,,"Oh, tys mu uříznul ruku! A já myslela že jsi hodný chlap... jakž takž. Pojďme.","Oh, du hast seine Hand abgeschnitten! Und ich dachte du wärest ein netter Typ... oder so. Lass uns gehen.",,,¡Oh le cortaste la mano! Y yo creía que eras un buen tío... más o menos. 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.",,"おいおい手を切り取ったのかよ! +Oh you cut off his hand! And I thought you were a nice guy... kinda. Let's go.,TXT_SUB_LOG20,STRIFE1.WAD: MAP05,,,"Oh, tys mu uříznul ruku! A já myslela že jsi hodný chlap... jakž takž. Pojďme.","Oh, du hast seine Hand abgeschnitten! Und ich dachte du wärest ein netter Typ... oder so. Lass uns gehen.",,,¡Oh le cortaste la mano! Y yo creía que eras un buen tío... más o menos. 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.",,"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.,"О ч-чёрт, ты отрезал ему руку! Я думала, ты добрый парень... в некотором роде. Ладно, не бери в голову.", -"Way to go, my friend. Jump on one of the teleporters and it will bring you back to base.",TXT_SUB_LOG21,STRIFE1.WAD: MAP05,,,"Jen tak dál, příteli. Skoč na teleportér, dostane tě zpět na základnu.",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.,Que forma de avanzar amigo mío. Entra en alguno de los teleportes 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.",,行きましょう、相棒。牢屋奥のテレポーターに飛び込めば基地にすぐ着くわ。,"정말 잘했어, 친구. 저 텔레포터들 중 하나를 타면 기지로 복귀할 수 있을 거야.","Goed gedaan, mijn vriend. Spring op een van de teleporters en het brengt je terug naar de basis.",,"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ă.,"Так держать, дружище. Прыгай в любой телепорт, и он вернёт тебя на базу.", -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 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 is een spion die we in het magazijn van de centrale hebben gerekruteerd.,,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.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.", -"Word from the boss is stand back when you whack the crystal, or else you'll end up mesquite-flavored too.",TXT_SUB_LOG23,STRIFE1.WAD: MAP04,,,"Velení radí, aby ses držel dál až rozbiješ krystal, jinak taky skončíš jako pečínka.","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.",,"上司が言うには、クリスタルを破壊する瞬間には隠れる必要があるな、 +"Way to go, my friend. Jump on one of the teleporters and it will bring you back to base.",TXT_SUB_LOG21,STRIFE1.WAD: MAP05,,,"Jen tak dál, příteli. Skoč na teleportér, dostane tě zpět na základnu.",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.,Que forma de avanzar amigo mío. Entra en alguno de los teleportes 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.",,"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ă.,"Так держать, дружище. Прыгай в любой телепорт, и он вернёт тебя на базу.", +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 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 é 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.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.", +"Word from the boss is stand back when you whack the crystal, or else you'll end up mesquite-flavored too.",TXT_SUB_LOG23,STRIFE1.WAD: MAP04,,,"Velení radí, aby ses držel dál až rozbiješ krystal, jinak taky skončíš jako pečínka.","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.",,"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.","Босс говорит, чтобы ты держался подальше от кристалла, когда он рванёт. Иначе тебя тоже прожарит до хрустящей корочки.", -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,STRIFE1.WAD: MAP02,,,"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 kvůli síle.","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 de 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.",,"もう一つの任務をこなす前に戦力の増強が必要と考えられる。 +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,STRIFE1.WAD: MAP02,,,"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.","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 de 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ù.","もう一つの任務をこなす前に戦力の増強が必要と考えられる。 マシルがイラールを介して資金と訓練の手配をしてくれるので会いなさい。 それと近所のメディックも支援してくれるわ。","본부가 공성전을 진행하기 전에 한 가지 해야 할 일이 있어. 마실이 이롤리에게 골드랑 훈련을 제공해달라고 부탁했대. 그다음에는, 마을 병원에 가서 근력을 키워달라고 해.",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.,,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ță.,"Ещё одно приключение, и штаб будет уверен в успешности атаки на замок. Мэйсил поручил Ирэйлу выплатить тебе награду и дать пару уроков. И зайди на всякий случай к медику.", -"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,STRIFE1.WAD: MAP02,,,"Řá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.","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.,,"オーダーは封鎖した城内が安全だと思っている。大した自信だな! +"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,STRIFE1.WAD: MAP02,,,"Řá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.","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.",,"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.","Орден думает, что замок неприступен. Большая ошибка! Он будет лёгкой добычей, когда ты откроешь врата. Спустись в канализацию, чтобы найти механизм. Иди вдоль берега реки — спуск прямо напротив особняка губернатора.", -"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,STRIFE1.WAD: MAP02,,,"Dobře, skoč tady dolů. Obyvatelé kanálů jsou příšerní mutanti, ale pomocí jejich sítě tunelů mají přístup k informacím. Podrž si nos... Jdeme dolů.","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.",,,"OK, agáchate por aquí. 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, 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,STRIFE1.WAD: MAP02,,,"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, 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.",,,"OK, agáchate por aquí. 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, 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.","Да, это здесь. Обитатели канализации — жуткие уроды, но они знают все секреты благодаря своим системам туннелей. Зажми нос — мы спускаемся!", -"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_SUB_LOG28,STRIFE1.WAD: MAP06,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že to je jak barvité, tak přesné.",,,,,,"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.",,"ウェランを探すんだ、誰が呼んだかラットキングでもある。 +"We're looking for Weran, who calls himself the Rat King. I'm sure it's descriptive as well as colorful.",TXT_SUB_LOG28,STRIFE1.WAD: MAP06,,,"Hledáma Werana, který si říká Krysí král. Jsem si jistá, že je to jak barvité, tak přesné.",,,,,,"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.",,"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.","Нам нужен Уэран — он называет себя Крысиным королём. Уверена, прозвище так же емко, как и красочно.", -"Oh, yuck. I don't even want to think about what you are stepping in!",TXT_SUB_LOG29,STRIFE1.WAD: MAP06,,,"Ó, fuj, nechci ani pomýšlet na to, do čeho teď šlapeš!","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, ja. Ik wil er niet eens aan denken wat je doet!",,"Argh, eca. Não quero nem saber no que você está pisando!",,"Oh, yuck. Nu vreau să știu în ce calci!","Ох, фу. Даже знать не хочу, во что ты наступил!", -Just what I need. More brown goo!,TXT_SUB_LOG30,STRIFE1.WAD: MAP06,,,"Přesně, co potřebuju. Další hnědá břečka!","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.,,万事休すだ。更に茶色いモノだ!,"또 시궁창이라니, 정말 보기 좋네!",Precies wat ik nodig heb. Meer bruine drab!,,Justo o que eu precisava. Mais meleca marrom!,,Exact ce îmi trebuie. Mai multă mâzgă maro!,"То, что надо. Ещё больше коричневой жижи!", -"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é!","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.,,,저기야! 저게 워렌이 열어줬으면 하는 문일 거야.,"Hé, kijk! Ik denk dat dat de deur is die Weran op een kier wil hebben!",,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!","О, смотри! Похоже, это та самая дверь, которую хочет приоткрыть Уэран!", -"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í.","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.,,,"눈 감아! 보고 싶지 않아! 오, 너무 늦었네... 역겨워. 전혀 사람 몸 같지 않던데, 대체 오더가 무슨 짓을 한 거지? 본부에 이걸 보고해야겠어.","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.",,"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.,"Зажмурься! Я не хочу это видеть! Ох, уже поздно... Какая дрянь. Это даже не выглядит как человеческое тело. Что творит этот Орден! Я немедленно доложу в штаб.", -Why can't we do a mission in a field of flowers for once?,TXT_SUB_LOG33,STRIFE1.WAD: MAP06,,,Nemůžeme někdy mít misi na poli plném kvítí?,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?,,どうして私達は綺麗な場所で一度でも任務遂行が出来ないんだ?,왜 우리는 딱 한 번이라도 꽃밭에서 작전을 수행할 수 없는 걸까?,Waarom kunnen we niet een keer een missie doen in een bloemenveld?,,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ă?,Ну почему наши задания не могут разворачиваться на цветочном лугу?, -I hate to say it but this reminds me of home. I'm underground not that far from here.,TXT_SUB_LOG34,STRIFE1.WAD: MAP06,,,"Říká se mi to těžko, ale tohle mi připomíná domov. Jsem v podzemí ne tak daleko odsud.","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.",,"言いたくないが私の家の事を思い出させるわ。 +"Oh, yuck. I don't even want to think about what you are stepping in!",TXT_SUB_LOG29,STRIFE1.WAD: MAP06,,,"Ó, fuj, nechci ani pomýšlet na to, do čeho teď šlapeš!","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!",,"Argh, eca. Não quero nem saber no que você está pisando!",,"Oh, yuck. Nu vreau să știu în ce calci!","Ох, фу. Даже знать не хочу, во что ты наступил!", +Just what I need. More brown goo!,TXT_SUB_LOG30,STRIFE1.WAD: MAP06,,,"Přesně, co potřebuju. Další hnědá břečka!","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!,,Justo o que eu precisava. Mais meleca marrom!,,Exact ce îmi trebuie. Mai multă mâzgă maro!,"То, что надо. Ещё больше коричневой жижи!", +"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é!","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!",,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!","О, смотри! Похоже, это та самая дверь, которую хочет приоткрыть Уэран!", +"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í.","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.",,"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.,"Зажмурься! Я не хочу это видеть! Ох, уже поздно... Какая дрянь. Это даже не выглядит как человеческое тело. Что творит этот Орден! Я немедленно доложу в штаб.", +Why can't we do a mission in a field of flowers for once?,TXT_SUB_LOG33,STRIFE1.WAD: MAP06,,,Nemůžeme někdy mít misi na poli plném kvítí?,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?,,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ă?,Ну почему наши задания не могут разворачиваться на цветочном лугу?, +I hate to say it but this reminds me of home. I'm underground not that far from here.,TXT_SUB_LOG34,STRIFE1.WAD: MAP06,,,"Říká se mi to těžko, ale tohle mi připomíná domov. Jsem v podzemí ne tak daleko odsud.","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.",,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.,"Не хотела говорить, но это место напоминает мне о доме. Сейчас я в подземелье, которое не так уж далеко отсюда.", -"Don't ask me where we are. I'm lost, too. Sorry.",TXT_SUB_LOG35,STRIFE1.WAD: MAP06,,,"Neptej se mě, kde jsme. Taky jsem ztracená. Promiň.","Frag mich nicht, wo wir sind, ich habe keine Ahnung. Tut mir leid.",,,No me preguntes donde estamos. Yo también me he perdido. Lo siento.,,"Ä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.",,今いる場所について私に聞かないでくれ。私も迷った。すまない。,"여기가 어딘지 묻지 마. 나도 길을 잃었거든, 미안해.",Vraag me niet waar we zijn. Ik ben ook verdwaald. Sorry.,,Não me pergunte onde estamos. Já me perdi. Desculpe.,,"Numă întreba unde suntem, și eu sunt pierdut. Scuze.","Даже не спрашивай, где мы. Я сама не знаю, извини.", -That brick... Didn't we pass that brick? No...,TXT_SUB_LOG36,STRIFE1.WAD: MAP06,,,Ta cihla... Neminuli jsme tamtu cihlu? Ne...,Der Stein... Sind wir nicht an dem Stein vorbeigekommen? Nein...,,,Ese ladrillo... ¿No pasamos por ese ladrillo? 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...,,あの煉瓦...前通ったレンガか?いや...,저 벽... 아까 저 벽을 지나가지 않았던가? 아닌데...,Die steen.... Hebben we die steen niet gepasseerd? Nee....,,Aquele tijolo... Já não passamos daquele tijolo? Não...,,Cărpmida aceea... Nu am trecut de ea? Nu...,Этот кирпич... Разве мы здесь не были? Нет..., -"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! ",TXT_SUB_LOG37,STRIFE1.WAD: MAP06,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme!",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íganel 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!",,"司令官、彼はやったぞ! +"Don't ask me where we are. I'm lost, too. Sorry.",TXT_SUB_LOG35,STRIFE1.WAD: MAP06,,,"Neptej se mě, kde jsme. Taky jsem ztracená. Promiň.","Frag mich nicht, wo wir sind, ich habe keine Ahnung. Tut mir leid.",,,No me preguntes donde estamos. Yo también me he perdido. Lo siento.,,"Ä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.,,Não me pergunte onde estamos. Já me perdi. Desculpe.,,"Numă întreba unde suntem, și eu sunt pierdut. Scuze.","Даже не спрашивай, где мы. Я сама не знаю, извини.", +That brick... Didn't we pass that brick? No...,TXT_SUB_LOG36,STRIFE1.WAD: MAP06,,,Ta cihla... Neminuli jsme tamtu cihlu? Ne...,Der Stein... Sind wir nicht an dem Stein vorbeigekommen? Nein...,,,Ese ladrillo... ¿No pasamos por ese ladrillo? 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....,,Aquele tijolo... Já não passamos daquele tijolo? Não...,,Cărpmida aceea... Nu am trecut de ea? Nu...,Этот кирпич... Разве мы здесь не были? Нет..., +"Command, he's done it! The gates are open. Send in the shock troops and tell Macil we're coming in! ",TXT_SUB_LOG37,STRIFE1.WAD: MAP06,,,"Velení, dokázal to! Brány jsou otevřené. Pošlete tam úderníky a řekněte Macilovi, že přicházíme!",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íganel 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!",,"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!","Штаб, он выполнил задание! Ворота открыты. Посылайте ударный отряд и доложите Мэйсилу, что мы пробились!", -"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,STRIFE1.WAD: MAP07,,,"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ň.","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 computadoras, otro que está en un torreón y otro más menciona un pasillo largo. Lo siento.",,"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.",,"プログラマーの居場所について矛盾する報告もあるわ。 +"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,STRIFE1.WAD: MAP07,,,"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ň.","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 computadoras, otro que está en un torreón y otro más menciona un pasillo largo. Lo siento.",,"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.",,"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.","Наши сведения о местонахождении Программиста противоречивы. Одни говорят, что он в компьютерной комнате, другие, что он укрывается в цитадели, а третьи, что он в конце длинного коридора. Извини.", -"Ah, it's good to be on the offensive again. Give 'em hell, guys!",TXT_SUB_LOG39,STRIFE1.WAD: MAP07,,,"Á, je to fajn být zase na straně ofenzívy. Jen jim dejte, chlapi!","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, het is goed om weer in de aanval te zijn. Geef ze de hel, jongens!",,"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!","Наконец-то, мы снова переходим в наступление! Всыпьте им как следует, парни!", -This looks good. Computers... Programmer... What do you think?,TXT_SUB_LOG40,STRIFE1.WAD: MAP07,,,Tohle vypadá dobře. Počítače... Programátor... Co myslíš?,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?,,"これは良い。コンピューター... +"Ah, it's good to be on the offensive again. Give 'em hell, guys!",TXT_SUB_LOG39,STRIFE1.WAD: MAP07,,,"Á, je to fajn být zase na straně ofenzívy. Jen jim dejte, chlapi!","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, é 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!","Наконец-то, мы снова переходим в наступление! Всыпьте им как следует, парни!", +This looks good. Computers... Programmer... What do you think?,TXT_SUB_LOG40,STRIFE1.WAD: MAP07,,,Tohle vypadá dobře. Počítače... Programátor... Co myslíš?,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?,,Isto parece bom. Computadores... Programador... O que você acha?,,Arată bine. Calculatoare... Programator... Ce zici?,"Похоже, это здесь. Компьютеры... Программист... Что скажешь?", -This must be the long hallway. Either that or my sense of scale is shot to hell.,TXT_SUB_LOG41,STRIFE1.WAD: MAP07,,,"Tohle musí být ta dlouhá chodba. Buď, a nebo už špatně vidím.","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.",,この長い廊下に違いない。それか私のスケール感とどちらかが撃ち落されるな。,"여기가 바로 긴 복도겠네. 아주 길다고 생각해, 아니면 내 머리가 이상하겠지.",Dit moet de lange gang zijn. Of dat of mijn gevoel voor schaalvergroting is naar de hel geschoten.,,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ă.","Должно быть, длинный коридор — это здесь. Ну или у меня всё плохо с глазомером.", -"This is all the hallmarks of a temple of evil. Severe architecture, big banner... I'd say bingo!",TXT_SUB_LOG42,STRIFE1.WAD: MAP07,,,"Tohle jsou všechno puncy chrámu zla - hrubá architektura, velký prapor... řekla bych, že 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.",,"これら全部悪の神殿の特徴だ。重苦しい建築物、デカいバナー... +This must be the long hallway. Either that or my sense of scale is shot to hell.,TXT_SUB_LOG41,STRIFE1.WAD: MAP07,,,"Tohle musí být ta dlouhá chodba. Buď, a nebo už špatně vidím.","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.,,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ă.","Должно быть, длинный коридор — это здесь. Ну или у меня всё плохо с глазомером.", +"This is all the hallmarks of a temple of evil. Severe architecture, big banner... I'd say bingo!",TXT_SUB_LOG42,STRIFE1.WAD: MAP07,,,"Tohle jsou všechno puncy chrámu zla - hrubá architektura, velký prapor... řekla bych, že 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!",,"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!","Всё это очень похоже на зловещий храм. Строгая архитектура, огромное знамя... Да, это определённо он!", -This is the almighty Programmer? No way!,TXT_SUB_LOG43,,,,Tohle je ten všemocný Programátor? To není možné!,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!,,,저게 위대한 프로그래머라고? 말도 안 돼!,Dit is de almachtige programmeur? Echt niet!,,Esse é o Programador todo-poderoso? Tá de sacanagem comigo!,,Ăsta e marele Programator? Nici vorbă!,Вот это — всемогущий Программист? Быть не может!, -"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ř.","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é lo que 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.,,,이젠 누가 맞는 건지 생각이 전혀 안나. “성채”라고 말하는 곳은 분명히 저 왼쪽에 있는 커다란 건물일 거야. 그런데 그곳으로 어떻게 들어가야 하지?,"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.",,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.","Не знаю, кому и верить. По-моему, «Цитаделью» можно назвать только ту уродливую громадину слева. Но как туда попасть, я понятия не имею.", +This is the almighty Programmer? No way!,TXT_SUB_LOG43,,,,Tohle je ten všemocný Programátor? To není možné!,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!,,Esse é o Programador todo-poderoso? Tá de sacanagem comigo!,,Ăsta e marele Programator? Nici vorbă!,Вот это — всемогущий Программист? Быть не может!, +"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ř.","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é lo que 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.",,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.","Не знаю, кому и верить. По-моему, «Цитаделью» можно назвать только ту уродливую громадину слева. Но как туда попасть, я понятия не имею.", "When the going gets weird, the weird get going. Watch yourself.",TXT_SUB_LOG45,"STRIFE1.WAD: MAP09 -(Appears to be a reference to Hunter S. Thompson’s quote, “When the going gets weird, the weird turn pro.”)",,,"Když to chce jít divně, divno jde dál. Dávej si na sebe pozor.",Die ganze Sache kommt mir spanisch vor. Pass auf dich auf.,,,La cosa se está poniendo fea. Ten 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.,,怪しい状況では怪しい影が映る。気を付けて。,"상황이 이상해지면, 이상한 일이 계속 일어난다니까... 부디 조심해.","Als het gaat raar wordt, gaat het vreemde aan de slag. Kijk uit.",,A coisa tá ficando feia. Toma cuidado.,,"Cand lucrurile devin ciudate, ai grija.","Если видишь, что что-то не так, остановись и подумай. Будь осторожен.", -"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.","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.",,,"오라클은 도시 외곽에 있는 접경지 근처에 있어. 강을 넘은 뒤, 성 쪽으로 향하고 아치 밑의 통로를 통해 왼쪽으로 이동해.","Het Orakel woont in de grensgebieden, net buiten de stad. Steek de rivier over, ga naar het kasteel en ga linksaf door de poort.",,"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ă.","Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.", -The Oracle is a supposedly sympathetic high priest who operates outside the Order.,TXT_SUB_LOG47,STRIFE1.WAD: MAP02,,,"Věštec je údajně sympatizující velekněz, operující mimo samotný Řád.","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.",,オラクルはオーダーとは別の活動をしている同情的な大司祭よ。,"오라클은 인류에 동정을 가지고 있다고 하고, 오더의 바깥에서 활동하는 대사제야.",Het Orakel is een zogenaamd sympathieke hogepriester die buiten de Orde opereert.,,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.","Похоже, этот Оракул — сочувствующий Сопротивлению верховный жрец, который действует без ведома Ордена.", -"The Oracle's temple is in the Borderlands, on the outskirts of town.",TXT_SUB_LOG48,STRIFE1.WAD: MAP10,,,"Věštcův chrám je v pohraničí, na okraji města.","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.,,オラクルの寺院は町の郊外にある国境地帯の西側にあるわ。,오라클은 도시 외곽에 있는 접경지 근처에 있어.,"De tempel van het Orakel staat in de grensstreek van Nederland, aan de rand van de stad.",,"O tempo do Oráculo está nas fronteiras, fora da cidade.",,"Templul Oracolului e în Mărginime, la ieșirea din oraș.","Храм Оракула находится в пограничье, на окраине города.", -The Order has taken our beautiful planet and turned it into a dump.,TXT_SUB_LOG49,STRIFE1.WAD: MAP11,,,Řád vzal naši krásnou planetu a proměnil ji ve skládku.,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.",,オーダーは我々の立つこの惑星を奪い、それをゴミへと変えた。,오더가 이 이쁘고 푸른 행성을 완전 쓰레기장으로 만들어버렸어...,De Orde heeft onze mooie planeet in beslag genomen en er een vuilnisbelt van gemaakt.,,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.,Орден превратил нашу прекрасную планету в помойку., -"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,STRIFE1.WAD: MAP11,,,"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ť.","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.",,"ここよ。私は全て記録している、貴方が生き残れる可能性が無いわけではなく、 +(Appears to be 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.,Die ganze Sache kommt mir spanisch vor. Pass auf dich auf.,,,La cosa se está poniendo fea. Ten 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.",,A coisa tá ficando feia. Toma cuidado.,,"Cand lucrurile devin ciudate, ai grija.","Если видишь, что что-то не так, остановись и подумай. Будь осторожен.", +"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.","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.",,"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ă.","Резиденция Оракула находится в пограничье, сразу за городской чертой. Пересеки реку, иди в сторону крепости и сверни налево, пройдя через арку.", +The Oracle is a supposedly sympathetic high priest who operates outside the Order.,TXT_SUB_LOG47,STRIFE1.WAD: MAP02,,,"Věštec je údajně sympatizující velekněz, operující mimo samotný Řád.","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.,,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.","Похоже, этот Оракул — сочувствующий Сопротивлению верховный жрец, который действует без ведома Ордена.", +"The Oracle's temple is in the Borderlands, on the outskirts of town.",TXT_SUB_LOG48,STRIFE1.WAD: MAP10,,,"Věštcův chrám je v pohraničí, na okraji města.","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.",,"O tempo do Oráculo está nas fronteiras, fora da cidade.",,"Templul Oracolului e în Mărginime, la ieșirea din oraș.","Храм Оракула находится в пограничье, на окраине города.", +The Order has taken our beautiful planet and turned it into a dump.,TXT_SUB_LOG49,STRIFE1.WAD: MAP11,,,Řád vzal naši krásnou planetu a proměnil ji ve skládku.,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.,,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.,Орден превратил нашу прекрасную планету в помойку., +"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,STRIFE1.WAD: MAP11,,,"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ť.","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.",,"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.","Так. Я всё записываю на плёнку. Это не потому, что я не верю, что ты уцелеешь. Просто мы не можем позволить Ордену заполучить Сигил.", -"You are brave, my comrade. I'm proud to be along for the ride.",TXT_SUB_LOG51,STRIFE1.WAD: MAP12,,,"Jsi statečný, můj příteli. Jsem pyšná, že u tohohle můžu být.","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.",,貴方は勇敢で、私の同志。貴方に就けた事を私は誇りに思ってるわ。,"넌 정말 용맹해, 동지. 너랑 같이 일할 수 있는 게 정말 자랑스러워.","Je bent dapper, mijn kameraad. Ik ben er trots op dat ik meega voor de rit.",,"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.","Я хотела сказать тебе, что ты очень храбрый. Я так счастлива, что мне с тобой по пути.", +"You are brave, my comrade. I'm proud to be along for the ride.",TXT_SUB_LOG51,STRIFE1.WAD: MAP12,,,"Jsi statečný, můj příteli. Jsem pyšná, že u tohohle můžu být.","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.",,"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.","Я хотела сказать тебе, что ты очень храбрый. Я так счастлива, что мне с тобой по пути.", 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.,Kannst du mal kurz warten? Mir wird etwas übel.,,,¿Puedes parar un segundo? Me estoy mareando un poco.,,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.,,ちょっと待ってもらえる?少しばかりうんざりしてるわ。,잠깐만 멈춰줄래? 속이 울렁거려...,Kun je even pauzeren? Ik word een beetje ziek.,,Pode parar por um minuto? Estou ficando com enjôo.,,Poți să te opreși un moment? Mi se face rău.,Мы можем остановиться на секунду? Что-то мне дурно., -Why do we have to spend so much time underground? I've seen underground.,TXT_SUB_LOG53,STRIFE1.WAD: MAP12,,,Proč musíme tolik času strávit v podzemí? Podzemí jsem viděla.,Warum müssen wir so viel Zeit im Untergrund verbringen.? Ich kenne den Untergrund.,,,¿Por que tenemos que pasar tanto tiempo bajo tierra? 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.,,何故私達は地下に長居せねばならないの?地下はもうわかったから。,왜 지하에서 시간을 낭비해야 되는 거지? 난 이미 지하에 있다고.,Waarom moeten we zoveel tijd onder de grond doorbrengen? Ik heb ondergronds gezien.,,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.,Почему нам приходится проводить кучу времени под землёй? Я на десять лет вперед насмотрелась на подземелья., -Are we really supposed to trust a guy whose inner sanctum is green?,TXT_SUB_LOG54,STRIFE1.WAD: MAP12,,,"Fakt máme věřit chlápkovi, jehož svatyně je zelená?","Sollen wir wirklich einem Typen vertrauen, dessen Räume grün sind?",,,¿Realmente tenemos que fiarnos de un tipo cuyo gran santuario 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?",,聖域内部と全身が緑色の者を信用するべきなの?,성소가 더럽게 초록색인데 이 녀석을 정말 믿어야 해?,Moeten we echt vertrouwen hebben in een man wiens innerlijke heiligdom groen is?,,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?,"Мы точно можем доверять парню, чьи внутренние покои зелёного цвета?", -Crimson and Obsidian? Why can't he say red and black.,TXT_SUB_LOG55,STRIFE1.WAD: MAP12,,,Karmíno-obsidiánová? Proč nemůže říct černo-červená?,Purpur und Obsidian? Warum kann er nicht Rot und Schwarz sagen?,,,¿Carmesí y obsidiana? Por que no puede 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.",,深紅と黒曜石?何故彼は赤と黒と言わないの。,진홍빛 흑요석? 빨간 검은색이라고 말하면 어디 덧나나?,Crimson en Obsidian? Waarom kan hij niet rood en zwart zeggen.,,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.,Багрово-обсидиановая? Почему бы не сказать просто — «красно-чёрная»!, -"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,STRIFE1.WAD: MAP11,,,"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.","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 sus espías y está al cargo de controlarnos. Nos lo cargamos y ganamos dos puntos.",,"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.",,"ビショップはオーダーの軍事指揮官よ。 +Random comment when the player dies with Classic Mode turned off",,,Mohl by ses na chvíli zastavit? Bude mi zle.,Kannst du mal kurz warten? Mir wird etwas übel.,,,¿Puedes parar un segundo? Me estoy mareando un poco.,,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.,,Pode parar por um minuto? Estou ficando com enjôo.,,Poți să te opreși un moment? Mi se face rău.,Мы можем остановиться на секунду? Что-то мне дурно., +Why do we have to spend so much time underground? I've seen underground.,TXT_SUB_LOG53,STRIFE1.WAD: MAP12,,,Proč musíme tolik času strávit v podzemí? Podzemí jsem viděla.,Warum müssen wir so viel Zeit im Untergrund verbringen.? Ich kenne den Untergrund.,,,¿Por que tenemos que pasar tanto tiempo bajo tierra? 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.,,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.,Почему нам приходится проводить кучу времени под землёй? Я на десять лет вперед насмотрелась на подземелья., +Are we really supposed to trust a guy whose inner sanctum is green?,TXT_SUB_LOG54,STRIFE1.WAD: MAP12,,,"Fakt máme věřit chlápkovi, jehož svatyně je zelená?","Sollen wir wirklich einem Typen vertrauen, dessen Räume grün sind?",,,¿Realmente tenemos que fiarnos de un tipo cuyo gran santuario 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?,,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?,"Мы точно можем доверять парню, чьи внутренние покои зелёного цвета?", +Crimson and Obsidian? Why can't he say red and black.,TXT_SUB_LOG55,STRIFE1.WAD: MAP12,,,Karmíno-obsidiánová? Proč nemůže říct červeno-černá?,Purpur und Obsidian? Warum kann er nicht Rot und Schwarz sagen?,,,¿Carmesí y obsidiana? Por que no puede 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.,,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.,Багрово-обсидиановая? Почему бы не сказать просто — «красно-чёрная»!, +"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,STRIFE1.WAD: MAP11,,,"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.","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 sus espías y está al cargo de controlarnos. Nos lo cargamos y ganamos dos puntos.",,"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.",,"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.","Епископ — военный лидер Ордена. Он обучает их тактике, управляет их шпионами и жаждет контроля над нами. От его убийства мы выигрываем вдвойне.", -The Bishop is going to be heavily guarded so why don't we swipe a uniform and blend in?,TXT_SUB_LOG57,STRIFE1.WAD: MAP11,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem?","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.",,ビショップのいる場所の警備は厳重なので、奴等の制服を盗み紛れ込む方が良いのでは?,"비숍은 군사 지도자니까, 삼엄한 경비에 의해 지켜질 거야. 그러니 전투복을 입고 잠입하는 게 어때?","De bisschop zal zwaar bewaakt worden, dus waarom vegen we er niet een uniform overheen en mengen we ons in de bisschop?",,"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?,"Похоже, что Епископа неплохо охраняют. Предлагаю стянуть униформу и прокрасться внутрь.", -"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.","Bittr 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.",,,"우리가 이길 수만 있다면, 축제 분위기 나게 장식할 사람을 부를 거야.","Herinner me eraan, we winnen dit ding en ik zal een decorateur inschakelen.",,"Não deixa eu esquecer, depois de vencermos vou chamar um decorador.",,"Adu-mi aminte, câștigăm și chem să ne decoreze.","Напомни мне позвать декоратора после того, как мы победим.", -"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,STRIFE1.WAD: MAP17,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam.","Ich habe gerade gehört, dass wir einen Informanten in der Festung haben. Geh rüber um Hospital, dort arbeitet er.",,,"Acaban de decirme que tenemos un informante dentro de la fortaleza. Vayamos a lo que llaman el hospital, trabaja allí.",,"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.",,"要塞の中に情報提供者がいるという話を聞いた。 +The Bishop is going to be heavily guarded so why don't we swipe a uniform and blend in?,TXT_SUB_LOG57,STRIFE1.WAD: MAP11,,,"Biskup bude silně strážen, co takhle sebrat uniformu a splynout s davem?","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?",,"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?,"Похоже, что Епископа неплохо охраняют. Предлагаю стянуть униформу и прокрасться внутрь.", +"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.","Bittr 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.",,"Não deixa eu esquecer, depois de vencermos vou chamar um decorador.",,"Adu-mi aminte, câștigăm și chem să ne decoreze.","Напомни мне позвать декоратора после того, как мы победим.", +"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,STRIFE1.WAD: MAP17,,,"Právě jsem dostala zprávu, že máme v pevnosti informátora. Měli bychom zamířit k nemocnici, pracuje tam.","Ich habe gerade gehört, dass wir einen Informanten in der Festung haben. Geh rüber um Hospital, dort arbeitet er.",,,"Acaban de decirme que tenemos un informante dentro de la fortaleza. Vayamos a lo que llaman el hospital, trabaja allí.",,"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.",,"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.","Мне только что сказали, что у нас есть информатор внутри крепости. Нам нужно место, которое они называют госпиталем — он работает там.", -"Grab the plans and knock out the computer, ok?",TXT_SUB_LOG60,STRIFE1.WAD: MAP17,,,"Seber plány a znič počítač, dobře?","Nimm die Plane und schalte den Computer aus, ok?",,,"Recoge los planos y derriba la computadora, ¿ok?",,"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?",,計画を奪いにコンピューターを破壊する、いけるわね?,계획서를 집고 컴퓨터를 파괴해. 간단하지?,"Pak de plannen en sla de computer eruit, oké?",,"Pegue os planos e destrua o computador, ok?",,"Ia planurile și distruge calculatorul, ok?","Хватаем планы и ломаем компьютер, лады?", +"Grab the plans and knock out the computer, ok?",TXT_SUB_LOG60,STRIFE1.WAD: MAP17,,,"Seber plány a znič počítač, dobře?","Nimm die Plane und schalte den Computer aus, ok?",,,"Recoge los planos y derriba la computadora, ¿ok?",,"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é?",,"Pegue os planos e destrua o computador, ok?",,"Ia planurile și distruge calculatorul, ok?","Хватаем планы и ломаем компьютер, лады?", "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.","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.",,大丈夫、次は血のバケツをぶち撒けない方法を試した方がいい。,"이런... 비꼬는 건 아닌데, 다음번엔 유혈사태를 일으키지 않고 일을 해결해보자.","Oké, ik klaag niet, maar de volgende keer kunnen we misschien de manier proberen waarop dat geen emmers bloed is.",,"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.","Я не жалуюсь, но, может, в следующий раз попробуем не проливать реки крови?", -"We've been through endless hallways before, but I swear, these walls are moving as we pass.",TXT_SUB_LOG62,STRIFE1.WAD: MAP19,,,"Už jsme předtím byli v nekonečných chodbách, ale přísahám, že tyhle stěny se hýbou.","Wir sind ja schon durch endlose Flure gegangen, aber ich könnte schwören, dass sich die Wände hier bewegen.",,,"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.",,"以前に私達は無限へ通じる玄関を通ったかと思うが、誓おう、 +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.","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.",,"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.","Я не жалуюсь, но, может, в следующий раз попробуем не проливать реки крови?", +"We've been through endless hallways before, but I swear, these walls are moving as we pass.",TXT_SUB_LOG62,STRIFE1.WAD: MAP19,,,"Už jsme předtím byli v nekonečných chodbách, ale přísahám, že tyhle stěny se hýbou.","Wir sind ja schon durch endlose Flure gegangen, aber ich könnte schwören, dass sich die Wände hier bewegen.",,,"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.",,"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.,"Мы уже повидали достаточно бесконечных коридоров, но я готова поклясться: эти стены передвигаются, когда мы на них не смотрим.", -"Well, you gotta figure. Military leader equals lots of bad guys.",TXT_SUB_LOG63,STRIFE1.WAD: MAP16,,,"No, mělo by ti to dojít. Armádní vůdce rovná se hodně padouchů.",Das war ja klar. Militärischer Anführer bedeutet jede Menge Bösewichte.,,,"Bueno, quien lo iba a pensar. 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.",,さて、貴方はフィギュアを得た。軍隊指揮者は大勢の悪人に匹敵するわ。,이거 정말 뻔하네. 군대 우두머리의 심복들은 다 난폭하고 둔하지.,"Nou ja, je moet het wel beseffen. Militair leider is gelijk aan veel slechteriken.",,"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.",Сам понимаешь. Военный лидер — всё равно что куча плохих парней., -Don't give up. This is it. Straight ahead.,TXT_SUB_LOG64,STRIFE1.WAD: MAP19,,,"Nevzdávej se, tohle je ono. Jdi rovně.",Gib nicht auf. Direkt voraus.,,,No te rindas. Esto es. 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.,,諦めないで。これでいいんだ。真っ直ぐ行こう。,포기하지 마. 거의 다 왔어. 가까이 왔다고.,Geef niet op. Dit is het. Rechtdoor.,,Não desista. Esta é a hora. Siga reto adiante.,,Nu te da bătut. Asta e. Drept înainte.,Не падай духом. Вот оно. Впереди., -"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ä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.",,,다음엔 편의점 같은 건물에 들러서 그냥 방향을 묻자.,De volgende keer stoppen we bij een tankstation en vragen we de weg.,,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.,В следующий раз остановимся на заправке и спросим дорогу., -Oh no! More bells and whistles and nasty guys chasing us.,TXT_SUB_LOG66,STRIFE1.WAD: MAP19,,,"Ale ne! Další fešné vymoženosti a padouši, co nás pronásledují.",Oh nein. Noch mehr Lärm und Bösewichte auf unseren Fersen.,,,Oh no! 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 nee! Nog meer toeters en bellen en vervelende jongens die ons achterna zitten.,,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!,"О, нет! Ещё больше свистелок, перделок и плохих парней, которые за нами гонятся.", -"You know, from the outside, this place looks tiny.",TXT_SUB_LOG67,STRIFE1.WAD: MAP15,,,Zvenku tohle místo vypadalo drobounké.,Von außen sieht das hier irgendwie mickrig aus.,,,"Sabes, por fuera, este sitio parece enano.",,"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.",,外から見ると、此処は小さいみたいね。,"궁금한 게 있는데, 왜 안에 들어가면 커지는 걸까?","Weet je, van buitenaf ziet deze plek er klein uit.",,"Sabe, vendo de longe esse lugar parece minúsculo.",,"Știi, din afară, locul ăsta arată mărunt.","Знаешь, снаружи это место кажется крошечным.", -"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!,"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.",,,네 주변에 적이 포착됐어. 그냥 쳐다보지 말고 어떻게든 해봐.,"Ik krijg een nieuwe vijandelijke lezing. Niet stoppen en staren, maar ze gewoon verspillen.",,"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.","Вижу врагов. Не стой столбом, мочи их!", -"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ízko.","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.",,私はフォースフィールドが憎いわ。遮断させるスイッチが近くにあるはずだわ。,이런 방어막들 정말 싫다니까. 저걸 끌 스위치를 찾아봐. 가까이에 있을 거야.,"Ik haat deze krachtvelden. Zoek naar de afsluitschakelaar, die moet in de buurt zijn.",,"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.","Ненавижу эти силовые поля. Поищи выключатель, он где-то неподалёку.", +"Well, you gotta figure. Military leader equals lots of bad guys.",TXT_SUB_LOG63,STRIFE1.WAD: MAP16,,,"No, dává to smysl. Armádní vůdce rovná se hodně padouchů.",Das war ja klar. Militärischer Anführer bedeutet jede Menge Bösewichte.,,,"Bueno, quien lo iba a pensar. 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.",,"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.",Сам понимаешь. Военный лидер — всё равно что куча плохих парней., +Don't give up. This is it. Straight ahead.,TXT_SUB_LOG64,STRIFE1.WAD: MAP19,,,"Nevzdávej se, tohle je ono. Jdi rovně.",Gib nicht auf. Direkt voraus.,,,No te rindas. Esto es. 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.,,Não desista. Esta é a hora. Siga reto adiante.,,Nu te da bătut. Asta e. Drept înainte.,Не падай духом. Вот оно. Впереди., +"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ä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.,,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.,В следующий раз остановимся на заправке и спросим дорогу., +Oh no! More bells and whistles and nasty guys chasing us.,TXT_SUB_LOG66,STRIFE1.WAD: MAP19,,,"Ale ne! Další fešné vymoženosti a zmetci, co nás pronásledují.",Oh nein. Noch mehr Lärm und Bösewichte auf unseren Fersen.,,,Oh no! 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.,,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!,"О, нет! Ещё больше свистелок, перделок и плохих парней, которые за нами гонятся.", +"You know, from the outside, this place looks tiny.",TXT_SUB_LOG67,STRIFE1.WAD: MAP15,,,Zvenku tohle místo vypadalo drobounké.,Von außen sieht das hier irgendwie mickrig aus.,,,"Sabes, por fuera, este sitio parece enano.",,"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.",,"Sabe, vendo de longe esse lugar parece minúsculo.",,"Știi, din afară, locul ăsta arată mărunt.","Знаешь, снаружи это место кажется крошечным.", +"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!,"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.",,"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.","Вижу врагов. Не стой столбом, мочи их!", +"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.","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.",,"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.","Ненавижу эти силовые поля. Поищи выключатель, он где-то неподалёку.", "Ooh, very impressive. Let's blow it up!",TXT_SUB_LOG70,"STRIFE1.WAD: MAP15 -(After pressing the switch to reveal the computer)",,,"Ó, velmi působivé. Co to nechat vybouchnout?","Oh, sehr imposant. Jag ihn hoch!",,,"Ooh, muy impresionante. Vamos a volarlo!",,"Oo, aika vaikuttava. Posautetaan se!","Oooh, très impressionant! Faisons tout péter!",Felettébb lenyűgöző. Robbantsuk is fel!,,あら、見事な物ね。是非とも火薬を献上しましょう。,"오우, 정말 이쁘네! 이제 터뜨리자!","Ooh, heel indrukwekkend. Laten we hem opblazen!",,"Oohh, que impressionante! Vamos detoná-lo.",,"ooh, foarte impresionant. Să-l aruncăm în aer!",Очень впечатляюще. Давай взорвём!, -"Jump on the teleporter, let's blow this pop stand.",TXT_SUB_LOG71,,,,Skoč na teleportér a odpalme tenhle stánek se zmrzlinou.,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.",,,텔레포터를 타고 이 놀이터를 벗어나자.,"Spring op de teleporter, laten we deze popstandaard opblazen.",,"Entre no teletransportador, vamos explodir este muquifo.",,"Sari în teleportor, să aruncăm în aer totul.",Прыгай в телепорт. Пора валить отсюда., -"Wait, the Oracle said we would know him by his symbol of power. Are you thinking what I'm thinking?",TXT_SUB_LOG72,STRIFE1.WAD: MAP16,,,"Počkat, Věštec říkal, že ho poznáme podle jeho symbolu moci. Myslíš na to samé, co já?","Warte, das Orakel sagte wir würden ihn an seinem Machtsymbol erkennen. Denkst du, was ich denke?",,,"Espera, el Oráculo dice que lo reconoceríamos por su símbolo de poder. ¿Piensas 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?",,"ちょっと待って、オラクルは私達に彼のシンボルを辿ればわかると述べたか。 +(After pressing the switch to reveal the computer)",,,"Ó, velmi působivé. Co to nechat vybouchnout?","Oh, sehr imposant. Jag ihn hoch!",,,"Ooh, muy impresionante. Vamos a volarlo!",,"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!",,"Oohh, que impressionante! Vamos detoná-lo.",,"ooh, foarte impresionant. Să-l aruncăm în aer!",Очень впечатляюще. Давай взорвём!, +"Jump on the teleporter, let's blow this pop stand.",TXT_SUB_LOG71,,,,Skoč na teleportér a odpalme tenhle stánek se zmrzlinou.,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.",,"Entre no teletransportador, vamos explodir este muquifo.",,"Sari în teleportor, să aruncăm în aer totul.",Прыгай в телепорт. Пора валить отсюда., +"Wait, the Oracle said we would know him by his symbol of power. Are you thinking what I'm thinking?",TXT_SUB_LOG72,STRIFE1.WAD: MAP16,,,"Počkat, Věštec říkal, že ho poznáme podle jeho symbolu moci. Myslíš na to samé, co já?","Warte, das Orakel sagte wir würden ihn an seinem Machtsymbol erkennen. Denkst du, was ich denke?",,,"Espera, el Oráculo dice que lo reconoceríamos por su símbolo de poder. ¿Piensas 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?",,"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?","Подожди — Оракул сказал, что мы найдём его по символу власти. Ты думаешь о том же, о чём и я?", -"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ě.,"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.",,,"저놈들은 도움이 되는 생각을 가지고 있기는 한데, 다 쓸데없이 망치고 있어.","Deze jongens hebben een decoratief idee dat werkt, en ze hebben het gewoon doodgeslagen.",,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.,"У этих ребят была отличная идея декора, но они загубили её на корню.", +"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ě.,"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.",,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.,"У этих ребят была отличная идея декора, но они загубили её на корню.", 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?","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?,,"ビショップの体から出てきたあの奇妙な幽体を見た? +(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?","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?,,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?,"Видел тот странный фантом, вышедший из тела Епископа? Где я могла видеть такое раньше?", -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 říkají tvoje instinkty?","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?",,,심판의 시간이야. 시질 두 조각을 모았으니 본부로 돌아가자. 이제 너의 본능은 무슨 해답을 내놓을까?,"Oordeel roep tijd. Nu we twee stukken hebben, willen we misschien terug naar de basis. Wat zegt je instinct je?",,"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?,, -"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 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í.","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.,,"ビショップにもあったスペクトラルエネルギーがオラクルにも宿っているという +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?","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?",,"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?,, +"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í.","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.",,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.","Мне доложили, что от Оракула исходит та же энергия, что и от того фантома, которого мы видели у Епископа. Будь начеку!", -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? 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? Een deel van deze puinhoop? Ik weet niet wat ik moet denken. Ik hoop dat je de juiste beslissing neemt.,,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ă.,"Мэйсил? Замешан в этом дерьме? Я даже не знаю, что и думать. Я надеюсь, ты сделаешь правильный выбор.", -"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.","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.",,,"마실은 프론트를 위해 싸워온 사람이라 의심할 수가 없어. 저 못난이가 거짓말을 하는 걸까? 모르지만, 난 너 만을 믿어.","Vertrouw ik Macil, die zijn leven heeft geriskeerd voor het Front, of een lelijke spook? Ik weet het niet. Maar jij vertrouw ik.",,"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.","Кому верить: Мэйсилу, который не щадил своей жизни ради Сопротивления, или какому-то уродливому пугалу? Не знаю. Но я доверяю тебе. ", +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? 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.,,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ă.,"Мэйсил? Замешан в этом дерьме? Я даже не знаю, что и думать. Я надеюсь, ты сделаешь правильный выбор.", +"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.","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.",,"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.","Кому верить: Мэйсилу, который не щадил своей жизни ради Сопротивления, или какому-то уродливому пугалу? Не знаю. Но я доверяю тебе. ", 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 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ó.,,"リヒターが指揮官の任を引き継いだ。マシルはずっと私達を騙していたなんて。 +(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 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.,,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.,"Рихтер принял на себя командование нашими силами. Похоже, что Мэйсил обманывал всех нас с самого начала. На самом деле он был предан Ордену. Подлец.", -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ů.",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é.",,威風堂々とした玄関ね。でも私達が調べるのは別の階よ。慎重にね。,또 전형적인 멋진 입구네. 하지만 우리가 찾는 것은 또 다른 구역에 있어. 밑으로 향해.,Vervloekt indrukwekkende toegangsweg. Maar wat we zoeken is op een ander niveau. Hoofd naar beneden.,,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.,Этот чёртов фасад впечатляет! Но нам нужно на другой этаж. Не высовывайся!, -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.,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.,,残念だな。我々の技術が拷問の為だけに浪費されるとは。,비극적이야. 우리 기술이 생명을 살리는 데 쓰이기는 커녕 고문하는 데 쓰이고 있잖아.,Wat jammer. Onze technologie wordt verspild aan marteling in plaats van leven.,,É 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ță.,"Какой кошмар. Наша технология используется для пыток, а не для жизни.", -"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.","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.",,うぬぼれが酷いな、あいつらの寺院はデカいバナーが目に付く。,"고통을 더하자면, 자기네 신전에 커다란 기를 세웠어.","Tevergeefs als de hel, markeren ze hun tempels met grote spandoeken.",,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.","Они спесивы до ужаса, раз украшают свои храмы большими флагами.", +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ů.",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.,,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.,Этот чёртов фасад впечатляет! Но нам нужно на другой этаж. Не высовывайся!, +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.,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.,,É 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ță.,"Какой кошмар. Наша технология используется для пыток, а не для жизни.", +"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.","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.",,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.","Они спесивы до ужаса, раз украшают свои храмы большими флагами.", 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ě.,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.,,"更なるシジルの欠片だ。私達の自由にまた一歩近づいたわ。 +(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ě.,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.,,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.,Очередной фрагмент Сигила. Теперь мы ещё на шаг ближе к освобождению. А ты — ещё на шаг ближе ко мне., -"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.","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.",,"この形状を見た所、解除するには完成したシジルを持って、ちっこい台座に乗るんだわ。 +"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.","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.",,"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.","Судя по всему, открыть этот замок сможет только завершённый Сигил. Что-то мне подсказывает, что мы достигли конца радуги!", You wield the power of the complete Sigil. What do you say we go get some closure.,TXT_SUB_LOG85,"STRIFE1.WAD: MAP12 @@ -10554,57 +10550,57 @@ OR 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, jít s tím vším skončit?","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, hogy rövidre zárjuk a dolgokat.",,"貴方はもはや完全なシジルの力を行使できるわけね。 +(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 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.,,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?,Теперь ты владеешь мощью завершённого Сигила. Мы уже близко — давай покончим с этим., -"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.","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.,,いい気分でしょ、私の英雄。栄光を受け入れる準備をしなさい。,"석양이 지고 있어, 나의 영웅. 영광을 누릴 준비해!","Hoog middaguur, mijn held. Bereid je voor om de glorie te omarmen.",,"Chegou a hora, meu herói. Se prepare para abraçar a glória.",,"Timpul pentru glorie, eroul meu.","Самое время, мой герой! Ты будешь купаться в славе.", +"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.","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.",,"Chegou a hora, meu herói. Se prepare para abraçar a glória.",,"Timpul pentru glorie, eroul meu.","Самое время, мой герой! Ты будешь купаться в славе.", "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 předpovědi. Počkat, Macil nás volá zpět. Vypadněme odsud vcelku.","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.",,"まあ予言なんてそんなものでしょ。 +(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.","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.",,"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.","Да, это превзошло все наши ожидания. Подожди — Мэйсил вызывает нас назад. Давай выбираться отсюда.", -"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.","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.",,,미안. 피칠갑을 한 너의 모습을 보느라 할 말을 잃었어. 그냥 마실에게로 돌아가자.,"Het spijt me, na tot aan mijn heupen in bloed kan ik nu niets geestigs bedenken om te zeggen. Laten we teruggaan naar 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.",, -"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.","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 magético y explosivo, justo para apagar campos de fuerza. ","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.",,"工場は鉱山の隣にあるわ。リヒターはデグニン鉱山とも呼んでいる。 +"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.","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.",,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.",, +"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.","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 magético y explosivo, justo para apagar campos de fuerza. ","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.",,"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.","Вход на фабрику — рядом со спуском в шахты. Рихтер, должно быть, имел в виду шахты Дегнина. Дегнинская руда магнитна и взрывоопасна — то, что надо, если хочешь отключить силовое поле. ", -"Mines, catacombs, sewers... What a first date!",TXT_SUB_LOG90,STRIFE1.WAD: MAP13,,,"Doly, kobky, stoky... skvělé první rande!","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!",,鉱山、地下墓所、下水道...とんだ初デートだな!,"광산, 고대 묘지, 하수도. 데이트하기엔 딱 맞는 장소들이네!","Mijnen, catacomben, rioleringen.... Wat een eerste afspraakje!",,"Minas, catacumbas, esgotos... Que belo primeiro encontro!",,"Mine, catacombe, canale... Ce întâlnire!","Шахты, катакомбы, канализации... Замечательное первое свидание!", -"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.","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.",,"リヒターがもっと具体的な部分に触れてくれて欲しいが。 +"Mines, catacombs, sewers... What a first date!",TXT_SUB_LOG90,STRIFE1.WAD: MAP13,,,"Doly, kobky, stoky... skvělé první rande!","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!",,"Minas, catacumbas, esgotos... Que belo primeiro encontro!",,"Mine, catacombe, canale... Ce întâlnire!","Шахты, катакомбы, канализации... Замечательное первое свидание!", +"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.","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.",,"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.,"Я надеялась, что Рихтер будет чуть более конкретным. Ладно, давай посмотрим, что там.", -"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.","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.",,"私が思うに...ああ、クソ。 +"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.","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.",,"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.","Я думаю, мы... О, чёрт. Я понятия не имею, где мы.", -"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!","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!",,"ここがリヒターのエージェントが探していた遺跡のはず。 +"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!","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!",,"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!,"Возможно, это те самые руины, которые искали агенты Рихтера... Осторожно! Крестоносцы!", -"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, 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!",,,"으윽, 이게 재생하기 시작했어. 내가 토하기 전에 파괴해!","Ugh, het probeert te regenereren. Blast het voordat ik overgeven!",,"Argh, está tentando se regenerar. Detona essa coisa antes que eu vomite!",,"Ugh, încearcă să se regenereze. Aruncă-l în aer înainte să vomit.","О-о, оно пытается восстановиться. Добей его, пока меня не стошнило!", -"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ů!","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!",,"友よ、私達が戦う相手が何であろうとも、オーダー以上のものはない。 +"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, 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!",,"Argh, está tentando se regenerar. Detona essa coisa antes que eu vomite!",,"Ugh, încearcă să se regenereze. Aruncă-l în aer înainte să vomit.","О-о, оно пытается восстановиться. Добей его, пока меня не стошнило!", +"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ů!","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!",,"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!","Друг мой, с чем бы мы ни сражались, это нечто большее, чем просто Орден. К шахтам!", -"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.,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.",,警戒を緩めることなく、鉱石の堆積所を探しましょう。,"조심해가면서, 그들이 캔 광석을 두는 곳을 찾아.","Zonder je waakzaamheid te laten verslappen, zoek je naar ertsafzettingen.",,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.","Поищи залежи руды, но не теряй бдительности!", -"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í!","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.",,"これら精神の乏しい労働者達は、シナプス機能をRCインプラントで妨害している。 +"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.,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.",,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.","Поищи залежи руды, но не теряй бдительности!", +"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í!","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!",,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!,"Эти несчастные души — дроны. Сигнал, поступающий на импланты, полностью подавляет их сознание. Давай уничтожим передатчик и освободим их!", -"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.","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.,,"司令官は送信機がフォースフィールドに守られていると言っていた。 +"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.","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.",,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ă.","Штаб говорит, что передатчик защищён силовым полем. Ты освободишь дронов и испытаешь руду — одним выстрелом двух зайцев!", -"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.","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.",,"私の案はフォースフィールドの近くに鉱石を置き撃って爆発させる方法よ。 +"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.","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.,,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.","Мой план: бросить руду поближе к силовому полю и взорвать её. Взрыв создаст магнитное поле, которое накроет электронику и отрубит её.", -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.,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.,,今すぐ工場へ向かおう。鉱山を出たら見逃すなよ!,이제 공장으로 향하자. 광산을 나가면 더 재밌는 모험이 펼쳐질 거야!,Nu naar de fabriek. Verlaat de mijnen en je kunt het niet missen!,,"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.,"Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход!", -"Sorry, hero, this is all new to me.",TXT_SUB_LOG101,STRIFE1.WAD: MAP20,,,"Promiň, hrdino, tohle všechno je pro mě nové.","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.",,ごめんなさい、これは初耳なの。,"미안, 영웅 친구... 이런 곳은 처음 봐.","Sorry, held, dit is allemaal nieuw voor mij.",,"Foi mal, meu herói, tudo isso é novo pra mim.",,"Scuze, eroule, asta e nou pentru mine.","Извини, герой. Для меня это всё в новинку.", -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.","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.,,重い神経波の歪曲が直に届いたわ。私達はそれを見つけたという事よ。,앞쪽에서 거대한 신경교란 파장이 감지되고 있어. 우리가 찾아낸 것 같아.,Ik lees enorme neurale golfvervormingen van rechtdoor. Ik denk dat we het gevonden hebben.,,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.,"Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер.", -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 viděli všechno! Dovnitř jdou jako lidé a ven vyjdou... ani na to nechci myslet.","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.",,"今まで見てきたことについて考えている! +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.,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!,,"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.,"Теперь — на фабрику. Выйди из шахты, и ты сразу увидишь вход!", +"Sorry, hero, this is all new to me.",TXT_SUB_LOG101,STRIFE1.WAD: MAP20,,,"Promiň, hrdino, tohle všechno je pro mě nové.","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.",,"Foi mal, meu herói, tudo isso é novo pra mim.",,"Scuze, eroule, asta e nou pentru mine.","Извини, герой. Для меня это всё в новинку.", +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.","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.,,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.,"Я вижу мощный источник помех прямо по курсу. Похоже, мы нашли конвертер.", +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.","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.,,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.,"А я-то думала, что хуже уже не будет! Они входят людьми, а выходят... Не хочу даже думать об этом.", -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é!,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!,,"オラクルが正しかった。マシルはイカれていたなんて。 +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é!,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!,"オラクルが正しかった。マシルはイカれていたなんて。 彼は故意に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!,,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!,Оракул сказал правду: Мэйсил озверел. Он намеренно послал двести человек на верную смерть. Я жажду мести! За убитых и за живых мертвецов!, -"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? 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? Geïnfecteerd en met een Sigil stuk. Al die jaren van geloof in hem, in de oorzaak. En waarvoor?",,"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? 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? 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? 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?","Мэйсил? Заражённый... И у него фрагмент Сигила. Всё эти годы я верила ему, верила в нашу миссию. А теперь?", "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 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.",,"リヒターの報告では我々が破壊した工場は'研究所'に繋がっていて、 +(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 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.",,"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.","Рихтер сообщает, что за разрушенной нами фабрикой лежит «лаборатория», и мы засекли характерную энергию фрагмента Сигила, исходящую оттуда. Возвращайся на фабрику — сделаем ещё один шаг к нашему освобождению.", -Who dares to defy me and enter my fortress? A worthless human? Face me and die!,TXT_SUB_LOG120,STRIFE1.WAD: MAP16,,,Kdo se to opovažuje mi vzdorovat a vkročit do mé pevnosti? Bezcenný člověk? Postav se mi a zemři!,Wer wagt es mir zu trotzen und meine Festung zu betreten? Ein wertloser Mensch? Stelle dich mir und stirb!,,,¿Quien se atreve a desafiarme y entrar en 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!",,"我に歯向かう為に敢えて私の要塞に来たのか?無価値な人間よ? +Who dares to defy me and enter my fortress? A worthless human? Face me and die!,TXT_SUB_LOG120,STRIFE1.WAD: MAP16,,,Kdo se to opovažuje mi vzdorovat a vkročit do mé pevnosti? Bezcenný člověk? Postav se mi a zemři!,Wer wagt es mir zu trotzen und meine Festung zu betreten? Ein wertloser Mensch? Stelle dich mir und stirb!,,,¿Quien se atreve a desafiarme y entrar en 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!,,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!,Кто смеет бросать мне вызов и вторгаться в мою крепость? Жалкий человечишка? Сразись со мной и умри!, -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 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.,,我を殺すことはできまい。貴様は人間。そして私は人間を超えし者だ。,"이 몸은 너에게 사살 당할 수 없다. 이 몸은 초월한 존재, 인간 따위를 넘었기에!",Je kunt me niet doden. Je bent gewoon een mens. En ik ben meer dan een mens.,,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.","Тебе не убить меня. Ты всего лишь человек. А я нечто большее, чем человек!", +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 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.,,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.","Тебе не убить меня. Ты всего лишь человек. А я нечто большее, чем человек!", "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š! - Ten hajzl má další díl Pečeti.","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! -Tällä kahjolla on toinen Sinetin osanen.","Pas de mort: la vie éternelle et plus, bien plus! Cela est mon but: cyborgs, moitié chair, moitié acier, un tout pour servir le Seul Dieu. Vous ne servez pas? Vous mourrez! Ce dégénéré a une autre pièce du Sigil.","Semmi halál, halhatatlanság és még sok más. Sok-sok más! A következő a feladatom: kiborgok gyártása, félig ember félig gép aki az Egy Igaz Istent szolgálja. Te nem Őt szolgálod? Akkor meglakolsz! Ennél a pancsernél van egy pecsét darab.",,"不死、更に永遠の命なぞない! +Tällä kahjolla on toinen Sinetin osanen.","Pas de mort: la vie éternelle et plus, bien plus! Cela est mon but: cyborgs, moitié chair, moitié acier, un tout pour servir le Seul Dieu. Vous ne servez pas? Vous mourrez! Ce dégénéré a une autre pièce du Sigil.","Semmi halál, halhatatlanság és még sok más. Sok-sok más! A következő a feladatom: kiborgok gyártása, félig ember félig gép aki az Egy Igaz Istent szolgálja. Te nem Őt szolgálod? Akkor meglakolsz! Ennél a pancsernél van egy pecsét darab.","Nessuna morte, vita eterna ed altro ancora. Molto altro! Questo è il mio compito: cyborg, metà carne, metà acciaio, tutti per servire l'Unico Dio. Tu non lo servi! Tu muori! Questo imbecille ha un altro pezzo del Sigillo.","不死、更に永遠の命なぞない! これが私の任務だ:サイボーグ達、半人間半機械、全ては唯一神に従うため。 お前は従わないと?では死ね!この愚か者がシジルの欠片を持っている。","영생, 불사, 뛰어난 지능, 이 몸은 많은 걸 지니고 있소! 강화인간, 생채병기, 반신반체, 오더를 위하여 더욱이 연구해야 하오. 이 몸의 의지에 반역하는 것이라면, 사라지시오! \cy이 미친놈은 시질 조각을 가지고 있어.","Geen dood, eeuwig leven en meer. Veel meer! Dit is mijn taak: cyborgs, half vlees, half staal, half staal, allemaal om de Ene God te dienen. Jullie dienen niet? Je sterft! @@ -10614,7 +10610,7 @@ Esse imbecil possui outra peça do Sigilo.",,"Nu moarte, viață eternă, și ma ", "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! 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 un idiota come te per ridarmi la libertà. Il tuo patetico pianeta è nelle mie mani, e tu presto rimpiangerai di essere nato.","ハッハッハ!ようこそ。私はこの瞬間を待ってイタ。 +(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! 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! 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!","Ха-ха! Приветствую. Я так долго ждала! Я ждала, что идиот вроде тебя освободит меня. Эта крошечная планета моя, и сейчас ты пожалеешь, что родился на свет!", @@ -10624,7 +10620,7 @@ I'm sick of this mystical double talk.",TXT_SUB_LOG129,STRIFE1.WAD: MAP27,,,"- P 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. Estoy cansado de habladuría mística.",,"Totuus löytyy ainoastaan maailmankaikkeuden yleistahdosta. Lankeat polvillesi Totisen Jumalan, Yhden Valon, edessä. Liity minuun, ja täytän Sinetin. Olen korviani myöten täynnä tätä mystistä hölynpölyä.","La vérité se trouve seulement dans la volonté universelle. Vous allez vous prosterner devant le Seul Dieu, la Seule Lumière. Rejoins-moi et je complèterai le Sigil. -J'en ai eu assez de ce charabia mystique.","Az igazság az univerzum akaratától függ. Térdre fogsz rogyni az Egy Igaz isten, az Egy Fény előtt. Csatlakozz hozzám, és összerakjuk a Pecsétet. Elegem van a misztikus dupla értelmű tanmesékből.","La verità è solo nella volontà universale. Ti inchinerai all'unico Dio, la sola luce. Vieni con me e io completerò il Sigillo. +J'en ai eu assez de ce charabia mystique.","Az igazság az univerzum akaratától függ. Térdre fogsz rogyni az Egy Igaz isten, az Egy Fény előtt. Csatlakozz hozzám, és összerakjuk a Pecsétet. Elegem van a misztikus dupla értelmű tanmesékből.","La verità è solo nella volontà universale. Ti inchinerai all'Unico Dio, la sola luce. Vieni con me e io completerò il Sigillo. Ne ho abbastanza di questo mistico messaggio senza senso.","真実は普遍的な意志でしか見つけられない。 お前は唯一神の前に跪くのだ、希望の光よ。 私の元に着き、シジルを完成させるのだ。この神秘的な戯言もうんざりする。","초월적인 힘을 가짐으로써 진정한 진실을 찾을 수가 있소. 당신은 이 세계의 유일신, 진정한 빛의 막강함에 의해 무릎을 꿇을 것이오. 종지부를 피하려면 시질을 건네고, 우리를 따르시오! @@ -10638,85 +10634,85 @@ Já estou cansada de toda essa ladainha mística.",,"Adevărul poate fi găsit d 我ノ詭謀ヲ截チ何世紀ニモワタル望ミヲ脅カシタ。 ダガマダ終ワリデハナイ、キサマニ憑キ意志ヲヒネリ出セバ... ","그대... 짐의 명령을 거부하고, 많은 것을 빼앗았고, 수 백 년 동안의 욕망을 위협했느니라. 그러나 짐은, 그대를 침식하여 짐의 의지에 복종하도록 만들 것이니라...","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....",,"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...","Ты... Ты разгромил мой Орден, прорвался через мои ловушки и сделал столетия ожидания напрасными. Но тебе не победить — я заражу тебя и подчиню своей воле!", -"Sounds like a dream job, doesn't it?",TXT_SUB_LOG200,,,,"Zní jako práce snů, ne?","Hört sich wie ein Traumjob an, nicht wahr?",,,"¿Parece un trabajo ideal, verdad?",,Eikö kuulostakin unelmapestiltä?,"Le job de vos rêves, non?","Úgy tűnik mint egy álam meló, ugye?",,,바라던 일 같네. 그렇지 않아?,"Klinkt als een droombaan, nietwaar?",,"Parece ser o emprego ideal, não é mesmo?",,"Sună a vis, nu?",, -"You've seen too much. Ice him, Macil!",TXT_SUB_LOG201,,,,"Viděl jsi moc. Zab ho, Macile!","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!,,,"넌 많은 걸 봤어. 얼려버려, 마실!","Je hebt te veel gezien. Ijs hem, Macil!",,"Você já viu demais. Acaba com ele, Macil!",,"Ai văzut prea mult. Îngheață-l, Macil!",, +"Sounds like a dream job, doesn't it?",TXT_SUB_LOG200,,,,"Zní jako práce snů, ne?","Hört sich wie ein Traumjob an, nicht wahr?",,,"¿Parece un trabajo ideal, verdad?",,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?",,"Parece ser o emprego ideal, não é mesmo?",,"Sună a vis, nu?",, +"You've seen too much. Ice him, Macil!",TXT_SUB_LOG201,,,,"Viděl jsi moc. Zab ho, Macile!","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!",,"Você já viu demais. Acaba com ele, Macil!",,"Ai văzut prea mult. Îngheață-l, 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ä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.,,今度は、私の言う事を聞きなさいよ。,"다음번엔, 내 말을 좀 들어. ",Volgende keer luister je naar me.,,"Da próxima vez, você vai me ouvir.",,"Data viitoare, o să mă asculți.",, -"Ugh, these post-apocalyptic prices...",TXT_SUB_LOG203,,,,"Uf, tyhle postapokalyptické ceny...","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, deze post-apocalyptische prijzen....",,"Urgh, esses preços pós-apocalípticos...",,"Ugh, prețurile ăstea post-apocaliptice...",, -Take the big one. He won't stop you.,TXT_SUB_LOG204,,,,Vem si toho velkého. Nezastaví tě.,"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.,,,커다란 놈을 막아. 둔하니까.,Neem de grote. Hij zal je niet tegenhouden.,,Leve o grandão. Ele não vai te deter.,,"Ia-l pe cel mare, nu te va opri.",, -Don't dawdle. Straight ahead!,TXT_SUB_LOG205,,,,Neloudej se. Jdi rovně!,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!,,,꾸물거리지 말고 빨리 움직여야 해! ,Niet treuzelen. Rechtdoor!,,Não pare. Siga adiante!,,Nu te lenevi. Drept în față!,, -You ever notice how these corridors look the same?,TXT_SUB_LOG206,,,,"Všimnul sis, jak všechny to chodby vypadají stejně?","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?",,,갈 때마다 보이는 복도가 다 똑같다고 생각해본 적 있어? ,Heb je ooit gemerkt hoe deze gangen er hetzelfde uitzien?,,Você já reparou como esses corredores parecem todos iguais?,,Nu observi cum coridoarele ăstea arată mereu la fel?,, -"Hey, sometimes I have to guess too!",TXT_SUB_LOG207,,,,"Hej, já taky musím někdy hádat!","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.,,,"야, 어쩔 때는 나도 추측을 해본다고! ","Hé, soms moet ik ook raden!",,"Ei, as vezes tenho que adivinhar também!",,"Hei, uneori și eu ghicesc!",, -"Oh, and watch out for the alarm.",TXT_SUB_LOG208,,,,"Oh, a dávej pozor na alarm.","Oh, und achte auf den Alarm.",,,"Oh, 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, en kijk uit voor het alarm.",,"Ah, e cuidado com o alarme.",,"Oh, și ai grijă la alarmă!",, +Random comment when the player dies with Classic Mode turned off",,,Příště budeš poslouchat mě.,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.,,"Da próxima vez, você vai me ouvir.",,"Data viitoare, o să mă asculți.","Будешь знать, как меня не слушать.", +"Ugh, these post-apocalyptic prices...",TXT_SUB_LOG203,,,,"Uf, tyhle postapokalyptické ceny...","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....",,"Urgh, esses preços pós-apocalípticos...",,"Ugh, prețurile ăstea post-apocaliptice...",, +Take the big one. He won't stop you.,TXT_SUB_LOG204,,,,Rozdej si to s tím velkým. Nezastaví tě.,"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.,,Leve o grandão. Ele não vai te deter.,,"Ia-l pe cel mare, nu te va opri.",, +Don't dawdle. Straight ahead!,TXT_SUB_LOG205,,,,Neloudej se. Jdi rovně!,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!,,Não pare. Siga adiante!,,Nu te lenevi. Drept în față!,, +You ever notice how these corridors look the same?,TXT_SUB_LOG206,,,,"Všimnul sis, jak všechny to chodby vypadají stejně?","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?,,Você já reparou como esses corredores parecem todos iguais?,,Nu observi cum coridoarele ăstea arată mereu la fel?,, +"Hey, sometimes I have to guess too!",TXT_SUB_LOG207,,,,"Hej, já taky musím někdy hádat!","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!",,"Ei, as vezes tenho que adivinhar também!",,"Hei, uneori și eu ghicesc!",, +"Oh, and watch out for the alarm.",TXT_SUB_LOG208,,,,"Oh, a dávej pozor na alarm.","Oh, und achte auf den Alarm.",,,"Oh, 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.",,"Ah, e cuidado com o alarme.",,"Oh, și ai grijă la alarmă!",, "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!","Oh je. Sieh nur, was du getan hast.",,,"Oh, cielos. ¡Mira lo que has hecho!",,"Voi hemmetti. Katso nyt, mitä olet tehnyt!","Oh, zut, regarde ce que tu as fait!","Jézusom, nézd mit műveltél!",,ああ、そうね。今貴方の仕出かした事を見直しなさい。,"맙소사, 무슨 짓을 저질렀는지 알기나 해?","Oh, jeez. Kijk nu wat je hebt gedaan!",,"Ai, caramba. Olha só o que você fez!",,"Oh, vai. Ia uite ce ai făcut.",, +Random comment when the player dies with Classic Mode turned off",,,"No sakra. Koukej, cos udělal!","Oh je. Sieh nur, was du getan hast.",,,"Oh, cielos. ¡Mira lo que has hecho!",,"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!",,"Ai, caramba. Olha só o que você fez!",,"Oh, vai. Ia uite ce ai făcut.","Ну блин. Только посмотри, что ты наделал!", 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!,"Mist, du hast es verbockt.",,,Mierda. ¡Ya la has liado!,,"Vittu, nyt meni ihan reisille!","Merde, t'as vraiment tout foutu en l'air!",Francba. Lebuktattál minket!,,クソが。アンタ今、台無しにしたぞ!,"제길, 다 망쳐 놓았네!",Shit. Nu heb je het verpest!,,Merda. Agora você ferrou tudo!,,Rahat. Acum ai distrus totul!,, -Come on! Let's get the hell out of here.,TXT_SUB_LOG211,STRIFE1.WAD: MAP15,,,No tak! Dostaňme se sakra odsud.,Komm schon! Lass uns auf der Stelle von hier verschwinden.,,,¡Venga! Larguémonos de aquí.,,Mennään! Häivytään täältä hittoon.,Allez! Sortons d'ici!,Gyerünk húzzunk innen a francba!,,頼むぞ!こっからとっとと失せろ!,빨리! 여길 어서 벗어나야 해!,Kom op! Laten we hier als de sodemieter weggaan.,,Vem! Vamos vazar daqui.,,"Haide, să ieșim de aici.",Ну же! Двигаем отсюда!, -Ooh. You don't mess around.,TXT_SUB_LOG212,,,,"Hmm, ty se nepáráš.",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. Je rotzooit niet.,,Oooh. Você não perde tempo mesmo.,,Ooh. Nu te joci.,, -You're going to mount them on the wall! Keep going!,TXT_SUB_LOG213,,,,Přišpendlíš je ke zdi! Jdi dál!,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!,,,저 녀석들을 모두 벽에 처박아놓자. 힘내! ,Je gaat ze aan de muur bevestigen! Ga door!,,Você vai montá-los na parede! Continua!,,O să le pună pe zid! Continuă să mergi!,, -Mm. You are a brute.,TXT_SUB_LOG214,,,,"Mhm, ty jsi ale surovec.",Hm. Du bist aber ein Rohling.,,,Mm. Eres un bruto.,,"Mm, olet julma peto.","Mm, tu est une brute.",Hm. Egy állat vagy.,,,"음, 넌 괴물이야.",Mm. Je bent een bruut.,,"Hmm, seu brutamontes.",,Mm. Ești o brută.,, -Got a nice rhythm going here.,TXT_SUB_LOG215,,,,Máme tu teď hezký rytmus.,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.,,,생각보다 박자가 잘 맞는데?,Ik heb hier een mooi ritme.,,Tá rolando um rítmo bom.,,Mișto ritm.,, -Ooh. Love that boom-boom stick.,TXT_SUB_LOG216,,,,"Oh, pěkná brokáda.",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. Ik hou van die boom-boom stok.,,"Oooh, adoro.",,Ooh. Îmi place arma aceea nimicitoare.,, -Mm. I like the way you carry yourself.,TXT_SUB_LOG217,,,,"Mhm, líbí se mi neseš.","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.,,,너 스스로 챙기는 모습이 정말 보기 좋아. ,Mm. Ik hou van de manier waarop je jezelf draagt.,,"Hmm, estou gostando de como você está indo.",,Ooh. Îmi place cum te descuri.,, -Blast away! They're not human!,TXT_SUB_LOG218,,,,Jen střílej! Nejsou to lidé!,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!,,,날려버려! 저놈들은 인간이 아니야! ,Blast away! Ze zijn niet menselijk!,,Arrebenta neles! Eles não são humanos!,,La naiba! Nu sunt umane!,, +Random comment when the player dies with Classic Mode turned off",,,Do prdele. Teď jsi to podělal!,"Mist, du hast es verbockt.",,,Mierda. ¡Ya la has liado!,,"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!,,Merda. Agora você ferrou tudo!,,Rahat. Acum ai distrus totul!,"Чёрт, ты всё испортил!", +Come on! Let's get the hell out of here.,TXT_SUB_LOG211,STRIFE1.WAD: MAP15,,,No tak! Dostaňme se sakra odsud.,Komm schon! Lass uns auf der Stelle von hier verschwinden.,,,¡Venga! Largué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.,,Vem! Vamos vazar daqui.,,"Haide, să ieșim de aici.",Ну же! Двигаем отсюда!, +Ooh. You don't mess around.,TXT_SUB_LOG212,,,,"Hmm, ty se nepáráš.",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.,,Oooh. Você não perde tempo mesmo.,,Ooh. Nu te joci.,, +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!,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!,,Você vai montá-los na parede! Continua!,,O să le pună pe zid! Continuă să mergi!,, +Mm. You are a brute.,TXT_SUB_LOG214,,,,"Mhm, ty jsi ale surovec.",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.,,"Hmm, seu brutamontes.",,Mm. Ești o brută.,, +Got a nice rhythm going here.,TXT_SUB_LOG215,,,,Máme tu teď hezký rytmus.,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.,,Tá rolando um rítmo bom.,,Mișto ritm.,, +Ooh. Love that boom-boom stick.,TXT_SUB_LOG216,,,,"Oh, pěkná brokáda.",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.,,"Oooh, adoro.",,Ooh. Îmi place arma aceea nimicitoare.,, +Mm. I like the way you carry yourself.,TXT_SUB_LOG217,,,,"Mhm, líbí se mi, jak se neseš.","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.,,"Hmm, estou gostando de como você está indo.",,Ooh. Îmi place cum te descuri.,, +Blast away! They're not human!,TXT_SUB_LOG218,,,,Jen střílej! Nejsou to lidé!,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!,,Arrebenta neles! Eles não são humanos!,,La naiba! Nu sunt umane!,, 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! 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! Zwarte acoliet! De nieuwe smaaksensatie....,,Uau! Acólito assado! Uma nova sensação de sabor...,,"Wow, Acolit Înegrit! Noua senzație...",, -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.,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.,,,이 걸 하다보면 네 눈이 좀 멀겠지만... 아찔하고 재밌는 것 같아.,Blijf dat doen en je wordt blind.... maar ik vind het leuk.,,Continua fazendo isso e você ficará cego... mas eu gosto.,,Continuă să faci asta și o să orbești... dar îmi place.,, -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!","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.,,,보답으로 저녁에 초대하지 않을 것 같아서 아쉽네! ,Ik denk dat ze ons niet meer zullen uitnodigen om terug te komen eten!,,Acho que não vão nos convidar para jantar!,,Cred că n-o să ne invite la cină!,, -We need to get to the top floor.,TXT_SUB_LOG222,,,,Musíme se dostat na vrchní podlaží.,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.,,,최상층으로 올라가야 해. ,We moeten naar de bovenste verdieping.,,Precisamos chegar até o último andar.,,Trebuie să ajungem la ultimul etaj.,, -Wait... This looks interesting. Check it out.,TXT_SUB_LOG223,,,,Počkej... Tohle vypadá zajímavě. Pojďme to omrknout.,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.,,,잠깐... 저거 뭔가 흥미로워. 확인해보자.,Wacht..... Dit ziet er interessant uit. Kijk maar eens.,,Peraí.... Isso parece interessante. Dá só uma olhada.,,"Stai, asta pare interesant. Ia uite.",, -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. 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. Die kerel geeft me de kriebels. Laten we wegblijven.,,Urgh. Esse cara me dá arrepios. Vamos passar longe.,,Ugh. Tipul ăla mă sperie.,, -"Left! Turn left!... Oh, other left!",TXT_SUB_LOG225,,,,"Doleva! Jdi doleva...! Aha, další doleva!",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!",,,"왼쪽! 왼쪽으로 이동해!... 잠깐, 다른 왼쪽!","Links! Sla linksaf!...... Oh, andere links!",,"Esquerda! Vira à esquerda!... Ai, a outra esquerda!",,"Stânga! Stânga!... Oh, cealaltă stânga!",, -Typical stubborn pig-headed male!... Unless you're a girl.,TXT_SUB_LOG226,,,,"Typický, tvrdohlavý, paličatý muž! ...Leda že bys byla holka.",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.,,,"뻔뻔한 고집불통 남충 놈!... 걱정 마, 너 말고.",Typisch koppig koppig mannetje!...... Tenzij je een meisje bent.,,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.,, -"Strong, brutal and silent. My kind of partner.",TXT_SUB_LOG227,,,,"Silný, tvrdý a tichý. Přesně můj typ.","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.",,,"크고, 아름답고, 과묵하네. 같이 있고 싶은 타입이야.","Sterk, wreed en stil. Mijn soort partner.",,"Forte, bruto e silencioso. Meu tipo de parceiro.",,"Puternic, brutal și silențios. Genul meu de partener.",, -Okay! I was wrong!,TXT_SUB_LOG228,,,,Dobře! Mýlila jsem se!,"Ok, ich habe mich geirrt.",,,¡OK! ¡Estaba equivocada!,,,"Ok, j'avais tort!",Jólvan na! Tévedtem!,,,아마도 아니었던 것 같네! ,Oké! Ik had het mis!,,Ok! Eu estava errada!,,Bine! Am greșit!,, +When obtaining the “Spontaneous Combustion” achievement",,,Wow! Zčernalý akolyta! Nové kulinářské šílenství...,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....,,Uau! Acólito assado! Uma nova sensação de sabor...,,"Wow, Acolit Înegrit! Noua senzație...","Ух ты, обугленный служитель! Совсем другое ощущение...", +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.,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.,,Continua fazendo isso e você ficará cego... mas eu gosto.,,Continuă să faci asta și o să orbești... dar îmi place.,, +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!","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!,,Acho que não vão nos convidar para jantar!,,Cred că n-o să ne invite la cină!,, +We need to get to the top floor.,TXT_SUB_LOG222,,,,Musíme se dostat na vrchní podlaží.,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.,,Precisamos chegar até o último andar.,,Trebuie să ajungem la ultimul etaj.,, +Wait... This looks interesting. Check it out.,TXT_SUB_LOG223,,,,Počkej... Tohle vypadá zajímavě. Pojďme to omrknout.,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.,,Peraí.... Isso parece interessante. Dá só uma olhada.,,"Stai, asta pare interesant. Ia uite.",, +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. 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.,,Urgh. Esse cara me dá arrepios. Vamos passar longe.,,Ugh. Tipul ăla mă sperie.,, +"Left! Turn left!... Oh, other left!",TXT_SUB_LOG225,,,,"Doleva! Jdi doleva...! Aha, další doleva!",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!",,"Esquerda! Vira à esquerda!... Ai, a outra esquerda!",,"Stânga! Stânga!... Oh, cealaltă stânga!",, +Typical stubborn pig-headed male!... Unless you're a girl.,TXT_SUB_LOG226,,,,"Typický, tvrdohlavý, paličatý muž! ...Leda že bys byla holka.",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.,,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.,, +"Strong, brutal and silent. My kind of partner.",TXT_SUB_LOG227,,,,"Silný, hrubý a tichý. Přesně můj typ.","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.",,"Forte, bruto e silencioso. Meu tipo de parceiro.",,"Puternic, brutal și silențios. Genul meu de partener.",, +Okay! I was wrong!,TXT_SUB_LOG228,,,,Dobře! Mýlila jsem se!,"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!,,Ok! Eu estava errada!,,Bine! Am greșit!,, 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ář.","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.",,私達はもう会えなくなったわ...面と向かって。,만나지 못한 게 유감스럽네... 가까이서. ,Jammer dat we elkaar nooit ontmoet hebben..... persoonlijk.,,Pena que nunca nos encontramos... cara a cara.,,Păcat că nu ne-am întâlnit... față în față.,, +Random comment when the player dies with Classic Mode turned off",,,"Škoda, že jsme se nikdy nepotkali... tváří v tvář.","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.,,Pena que nunca nos encontramos... cara a cara.,,Păcat că nu ne-am întâlnit... față în față.,"Жаль, мы раньше не встречались... лицом к лицу.", 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.,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.,,私は貴方に希望を抱いていた...クソ世知辛いわ。,너를 꿈꿔왔어... 꿈은 꿈이였나봐.,Ik had dromen voor je.... Moeilijke shit.,,Eu tinha uma grande expectativa sobre você... Que merda.,,Aveam visuri pentru tine... Rahatule...,, -"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ší kov 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.","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.",,,"잠깐, 시청으로 가지 마. 이미 발각되어서 이젠 안전하지 않아. 아마도 총알의 비가 내리는 유일한 이유일 거야. 최선을 다해서 저 커다란 친구들을 격파해봐. 저놈들은 ""크루세이더"" 라고 해. 이 일을 끝마치면, 마실이 있는 곳으로 안내해줄게. ","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.",,"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.",, -"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ř.","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.,,,"건투를 빌어, 친구! 안으로 들여보내 줄게. ","Goed werk, vriend! Het is tijd om je binnen te brengen.",,"Bom trabalho, amigo! Hora de trazê-lo pra dentro.",,"Bună treabă, prietene! E timpul să te aduc înăuntru!",, -"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ě.",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.",,,"크루세이더를 조심해. 저놈들은 커다랗고 강력한 기동 병기야. 난폭하기도 하지. 놈들의 무장이 뭔지 모르지만, 중요한 점은 넌 포위됐다는 거지. 조심해. ","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.",,"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ă.",, -"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.","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.",,,"잘 싸웠어. 내가 생각지도 못한 기발한 생각을 많이 하네. 이제, 모두가 너를 보지 않는 동안 오른쪽 문으로 들어가서 계단을 올라가고 남자를 만나.","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.",,"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.",, -"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.","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.",,,결국엔 사람들이 너를 보았네. 사적인 건 아니지만 넌 죽어줘야겠어. ,"Als je iemand je laat zien, hebben we je hoofd.",,"Se você deixar alguém te ver, a sua cabeça é nossa.",,Lași pe cineva să te vadă și-ți luăm capul.,, -"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!","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!,,,"이 어리석은, 멍청한, 짜리몽땅한 말미잘 얼간이! 우리 곁을 떠나다니!","Jij stomme, struikelende, knotsvoetige bochelende imbeciel! Je hebt ons weggegeven!",,Seu imbecil idiota estúpido duma figa! Você nos entregou!,,Imbecilule! Ne-ai dat de gol!,, -"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.","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.","Speravo di aspettarti da dietro la porta... ma sono dovuto stare nel sottosuolo. È 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.,,"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.",, +Random comment when the player dies with Classic Mode turned off",,,Snila jsem o tobě... Kurva.,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.,,Eu tinha uma grande expectativa sobre você... Que merda.,,Aveam visuri pentru tine... Rahatule...,Я так надеялся на тебя... Упрямый засранец., +"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.","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.",,"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.",, +"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ř.","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.",,"Bom trabalho, amigo! Hora de trazê-lo pra dentro.",,"Bună treabă, prietene! E timpul să te aduc înăuntru!",, +"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ě.",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.",,"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ă.",, +"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.","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.",,"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.",, +"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.","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.",,"Se você deixar alguém te ver, a sua cabeça é nossa.",,Lași pe cineva să te vadă și-ți luăm capul.,, +"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!","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!",,Seu imbecil idiota estúpido duma figa! Você nos entregou!,,Imbecilule! Ne-ai dat de gol!,, +"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.","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.,,"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.",, ,,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,,,,"Prohnilá svině. O téhle jakési spojce nic nevím, takže na to pojďme pomalu.",Aufgeblasener Mistkerl. Ich weiß nichts über diese sogenannte Anzapfung so lass uns vorsichtig sein.,,,"Cerdo hinchado. No sé nada sobre este tal 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 sul cosiddetto ""accoppiamento elettrico"", quindi andiamoci piano.","慢心してた。私はこの配電機と言われている物について何も知らない。 -まあゆっくりやろう。",배부른 돼지 같은 녀석. 난 이 추출기에 대해서 아무것도 몰라. 너무 급하게 하지 말자.,"Opgeblazen varken. Ik weet niets van deze zogenaamde stroomkoppeling, dus laten we langzaam gaan.",,"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.",Жирная свинья. Я ничего не знаю об этой «соединительной муфте». Давай не будем торопиться., +"Bloated pig. I know nothing about this so-called power coupling, so let's go slow.",TXT_BBSUB_SCRIPT02_D57608_IFIKN,,,,"Prohnilá svině. O téhle jakési spojce nic nevím, tak na to pojďme pomalu.",Aufgeblasener Mistkerl. Ich weiß nichts über diese sogenannte Anzapfung so lass uns vorsichtig sein.,,,"Cerdo hinchado. No sé nada sobre este tal 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.",,"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.",Жирная свинья. Я ничего не знаю об этой «соединительной муфте». Давай не будем торопиться., "Sounds like a dream job, doesn't it?",TXT_BBSUB_SCRIPT03_D4548_GOODB,,,,"To zní jako práce snů, ne?","Hört sich an wie ein Traumjob, nicht wahr?",,,"¿Suena como un trabajo ideal, verdad?",,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?",,"Parece ser o emprego dos sonhos, não é mesmo?",,"Sună ca un vis, nu?","Это же работа мечты, разве нет?", And I'll be right there with you.,TXT_BBSUB_SCRIPT03_D7580_TAKET,,,,A já tam budu s tebou.,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.,,E eu vou estar bem alí do seu lado.,,O să fie alături de tine.,А я буду рядом с тобой., 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 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 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.,,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.,"Уорнэр — шпион, которого мы завербовали на складе электростанции.", 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áš.","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.,,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.,Приготовься к главному бою в своей жизни. Не скупись. Потрать на подготовку всё золото., "Excuse me, I'm gonna be sick.",TXT_BBSUB_SCRIPT04_D21224_BUSIN,,,,"Omluv mě, budu zvracet.","Entschuldige, aber mir wird übel.",,,"Perdona, me voy a poner mala.",,"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.",,"Desculpa, estou passando mal.",,"Scuză-mă, o să mi se facă rău.","Прости, меня сейчас вырвет.", -Mmm. Sounds like weapons. We can always use more firepower.,TXT_BBSUB_SCRIPT04_D25772_TELLW,,,,"Mhmm, to zní jako zbraně. Palebná síla se nám vždycky hodí.",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 le armi. Possiamo sempre usare più potenza di fuoco.,フーム。聞く限り武器の様ね。いつも以上の火力を出せそうだ。,으음. 왠지 무기 같은데. 화력이야 더 많으면 좋지.,Mmm. Klinkt als wapens. We kunnen altijd meer vuurkracht gebruiken.,,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.,"М-м-м. Похоже, там оружие. Лишняя огневая мощь не помешает.", -"This sounds too easy, but let's give it a shot.",TXT_BBSUB_SCRIPT04_D31836_WHATD,,,,"To zní moc snadno, ale zkusme to.","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.",,"Tá parecendo fácil demais, mas vamos tentar.",,"Sună ușor, dar să încercăm.",Слишком уж заманчиво. Хотя давай попытаемся., +Mmm. Sounds like weapons. We can always use more firepower.,TXT_BBSUB_SCRIPT04_D25772_TELLW,,,,"Mhmm, to zní jako zbraně. Palebná síla se nám vždycky hodí.",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.,,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.,"М-м-м. Похоже, там оружие. Лишняя огневая мощь не помешает.", +"This sounds too easy, but let's give it a shot.",TXT_BBSUB_SCRIPT04_D31836_WHATD,,,,"To zní až moc snadně, ale zkusme to.","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.",,"Tá parecendo fácil demais, mas vamos tentar.",,"Sună ușor, dar să încercăm.",Слишком уж заманчиво. Хотя давай попытаемся., Who cares. Nobody listens to programmers anyway.,TXT_BBSUB_SCRIPT04_D40932_LETME,,,,"Koho to zajímá, programátory stejně nikdo neposlouchá.",Egal! Wer hört schon auf Programmierer.,,,A quien le importa. Nadie escucha a los programadores de todos modos.,,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.,,Quem liga? Ninguém dá bola pros programadores mesmo.,,Cui îi pasă. Nimeni nu ascultă de programatori oricum.,Какая разница? Программистов всё равно никто не слушает., -"Ooh. Glad I'm in hiding, if you know what I mean.",TXT_BBSUB_SCRIPT04_D54576_ITSAS,,,,"Oh, jsem ráda, že se schovávám, jestli víš, co tím myslím.","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.",,"Oooh. Ainda bem que estou escondida, se é que você me entende.",,"Ooh. Mă bucur că mă ascund, dacă știi ce zic.","Ой. Хорошо, что я в укрытии, если ты понимаешь, о чём я.", +"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.","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.",,"Oooh. Ainda bem que estou escondida, se é que você me entende.",,"Ooh. Mă bucur că mă ascund, dacă știi ce zic.","Ой. Хорошо, что я в укрытии, если ты понимаешь, о чём я.", What a grouch. I hope you get to kill him later.,TXT_BBSUB_SCRIPT05_D1516_OKBUT,,,,"Takový mrzout. Doufám, že ho pak zabijeme.",Was für ein Ekel. Hoffentlich kannst du ihn später mal erledigen.,,,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.,,Que rabugento! Espero que você mate ele depois.,,Ce dobitoc. Sper să îl omori mai târziu.,"Ну и зануда. Надеюсь, ты потом вернёшься и снесёшь ему башку.", -"""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.,„Zutritt verboten!“ Elendiger Wichtigtuer.,,,"""¡Esta área está fuera de limite!"" Que estirado.",,"""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 è off limits!"" Pomposo miserabile.",この区域は立入禁止!'そんなワザとらしい。,“이곳은 통행 금지야!” 웃기고 앉아있네.,Dit gebied is verboden terrein! Pompous zo-en-zo.,,"""Proibido entrar nessa área!"" Que miserável prepotente.",,"""Zona asta e interzisă!"" Pompos așa-și-așa.",«Здесь закрытая территория!» Надутый индюк., +"""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.,„Zutritt verboten!“ Elendiger Wichtigtuer.,,,"""¡Esta área está fuera de limite!"" Que estirado.",,"""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.,,"""Proibido entrar nessa área!"" Que miserável prepotente.",,"""Zona asta e interzisă!"" Pompos așa-și-așa.",«Здесь закрытая территория!» Надутый индюк., What an up guy.,TXT_BBSUB_SCRIPT05_D4548_THEOR,,,,Takový veselý chlapík!,Was für ein Blödmann.,,,Menudo idiota.,,Mikä höhlä.,Quel type honnête.,De egy hülye.,Che idiota.,あら、いい男。,아주 들떠있는 녀석이네.,Wat een geweldige kerel.,,Que imbecil.,,Ce tip.,Какой хороший мальчик!, "Maybe it's because you didn't say ""please"".",TXT_BBSUB_SCRIPT05_D7580_OVERM,,,,"Možná to je tím, žes neřekl „prosím“.",Vielleicht hättest du „Bitte“ sagen sollen.,,,"A lo mejor es 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.",,"Deve ser porque você não disse ""por favor"".",,"Poate pentru nu ai spus ""te rog"".","Наверное, ты забыл сказать «пожалуйста»?", "Everybody is so needy. ",TXT_BBSUB_SCRIPT06_D1516_DOMYF,,,,Každý toho tolik potřebuje.,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.,,Por que todo mundo é tão mimimizento?,,Toată lumea e așa neajutorată!,Тут все такие нуждающиеся!, Great. Now we're shopping for the Rat King.,TXT_BBSUB_SCRIPT06_D3032_BRING,,,,"Super, teď máme nakupovat pro Krysího krále.","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.,,Que beleza. Agora estamos fazendo comprinhas pro Rato-Rei.,,Grozav. Acum facem cumpărături pentru Regele Șobolanilor.,Классно. Мы идём за покупками для Крысиного короля., -"I bet this guy smells really bad, too.",TXT_BBSUB_SCRIPT06_D4548_OPENT,,,,"Hádám, že tenhle chlápek taky pěkně smrdí.","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 ragazzo ha pure un cattivo odore.,この男も酷い悪臭がすると賭けるわ。,얘도 분명 냄새 하나는 죽여줄 거야.,Ik durf te wedden dat deze kerel ook heel erg stinkt.,,Aposto que esse cara fede pra caramba também.,,Pun pariu că tipul ăsta mai și pute.,"Уверена, этот парень воняет особенно ужасно.", +"I bet this guy smells really bad, too.",TXT_BBSUB_SCRIPT06_D4548_OPENT,,,,"Hádám, že tenhle chlápek taky pěkně smrdí.","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.,,Aposto que esse cara fede pra caramba também.,,Pun pariu că tipul ăsta mai și pute.,"Уверена, этот парень воняет особенно ужасно.", 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.","Mehr Kanäle, toll... Ich frage mich, was da unten lebt.",,,Más alcantarillas... Genial. Me pregunto que 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.,,Mais esgotos... Que legal. O que será que vive lá embaixo?,,Mai multe canale... Grozav. Mă întreb ce-o mai trăi jos aici.,"Снова канализация... Замечательно. Интересно, кого мы там встретим?", Dead end here. We'd better keep looking.,TXT_BBSUB_SCRIPT07_D6064_PROGR,,,,Tudy cesta nevede. Měli bychom se podívat dál.,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.,,Sem saída aqui. Melhor seguirmos procurando.,,Capăt de linie. Mai bine ne mai uităm împrejur.,Тупик. Давай продолжать поиски., "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.",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 al sig. Brutto.",進み出よ、わがチャンピオン。ミスター生塵を捻りつぶしてやれ。,"어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.","Vooruit, mijn kampioen. Laten we Mr. Ugly aan het draaien en schreeuwen zetten.",,"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.","Вперёд, мой защитник. Заставим Г-на Урода сплясать и спеть.", +",TXT_BBSUB_SCRIPT10_D10612_YOUHA,,,,"Kupředu, můj šampióne. Pojďme pana Ošklivu hezky nakopat.",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.",,"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.","Вперёд, мой защитник. Заставим Г-на Урода сплясать и спеть.", "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.,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 brutto carattere.","生体工学'?どうやら奴等は軍隊を無限供給しているという訳だ! +",TXT_BBSUB_SCRIPT10_D12128_THERE,,,,Biomechanické? Tak to vysvětluje jejich zdánlivě nekonečné zásoby vojáků! A jejich špatnou náladu.,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? Nou, dat verklaart hun schijnbaar eindeloze voorraad aan troepen! En hun slechte houding.",,"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ă.,"Биомеханических? Что ж, теперь ясно, почему их солдаты не заканчиваются! И почему они так отвратительно себя ведут.", Sick fuck... Waste him!,TXT_BBSUB_SCRIPT10_D16676_IAMTH,,,,Podlý sráč... Zab ho!,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!,,Doente do caralho... Acaba com ele!,,Dobitoc bolnav... Nimicește-l!,Больной ублюдок... Мочи его!, -"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ě.","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 lui sia dalla nostra parte.",彼は醜いだろうが、我々に味方している。,"이 양반 못생기긴 했어도, 우리 편인 것 같네.","Hij is misschien lelijk, maar het lijkt erop dat hij aan onze kant staat.",,"Ele pode ser feio, mas parece que ele está no nosso lado.",,"O fi urât, dar pare să fie de partea noastră.","Пусть он и урод, но, похоже, он на нашей стороне.", -"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.","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 lo stealth sia da scartare.",最近の記録から判断すると、秘密は公になると私は思う。,"최근 상황을 보건대, 잠입 작전은 힘들 것 같아.","Te oordelen naar de recente geschiedenis, denk ik dat heimelijkheid uit is.",,"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.","Судя по недавним событиям, можно больше не прятаться.", +"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ě.","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.",,"Ele pode ser feio, mas parece que ele está no nosso lado.",,"O fi urât, dar pare să fie de partea noastră.","Пусть он и урод, но, похоже, он на нашей стороне.", +"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.","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.",,"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.","Судя по недавним событиям, можно больше не прятаться.", "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 kup, prosím!",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.","うーむ。慌てず、騒がず、ママの掃除も無し... +",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. 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. Geen gedoe, geen muss, niets voor mama om op te ruimen... Haal me er een, alsjeblieft.",,"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.","Хм-м. Ни шума, ни пыли, мама не заставит убираться... Достань мне одно такое, пожалуйста!", "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,,,,"Řekl bys, že by mě tohle zabíjení všech začalo unavovat, ale vím, že mi to bude chybět, až tohle všechno skončí.","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 stanchi di questa cosa di ""uccidere tutti"", ma io so già che mi mancherà quando tutto sarà finito.","貴方は全ての人々が殺害される事にうんざりしていると思うわ、 +",TXT_BBSUB_SCRIPT31_D0_OHNOI,,,,"Ř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 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.",,"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.","Ты думаешь, что я устану от всех этих убийств? Нет, на самом деле мне их будет не хватать.", \ No newline at end of file diff --git a/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt b/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt index 457ae8a00..6e9bb1336 100644 --- a/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt +++ b/wadsrc_lights/static/filter/doom.freedoom/gldefs.txt @@ -337,7 +337,7 @@ object ExplosiveBarrel // Floor lamp pointlight LAMP { - color 0.6 1.0 0.6 + color 1.0 1.0 0.6 size 84 offset 0 44 0 attenuate 1 @@ -367,9 +367,9 @@ object TechLamp2 // Tall tech lamp pulselight BIGLAMP { - color 1.0 1.0 0.7 - size 96 - secondarySize 99 + color 1.0 0.4 0.4 + size 100 + secondarySize 80 interval 0.4 offset 0 72 0 attenuate 1 @@ -479,7 +479,7 @@ object ShortBlueTorch // Burning barrel flickerlight2 FIREBARREL { - color 0.6 0.6 0.9 + color 1.0 0.9 0.4 size 72 secondarySize 81 interval 0.1 @@ -529,7 +529,7 @@ object Candlestick // Soul Sphere pulselight SOULSPHERE { - color 0.3 0.3 1.0 + color 1.0 1.0 0.3 size 60 secondarySize 63 interval 2.0 @@ -545,7 +545,7 @@ object SoulSphere // Soul Sphere pulselight MEGASPHERE { - color 0.4 1.0 0.4 + color 1.0 0.8 0.4 size 60 secondarySize 63 interval 2.0 @@ -561,7 +561,7 @@ object MegaSphere // Invulnerability Sphere pulselight INVULN { - color 1.0 0.6 1.0 + color 0.6 1.0 0.6 size 60 secondarySize 63 interval 2.0 @@ -577,62 +577,24 @@ object InvulnerabilitySphere // Blur Sphere pointlight BLURSPHERE1 { - color 1.0 0.0 0.0 + color 0.5 0.5 0.5 size 60 offset 0 16 0 attenuate 1 } -pointlight BLURSPHERE2 -{ - color 0.0 0.0 1.0 - size 48 - offset 0 16 0 - attenuate 1 -} - -pointlight BLURSPHERE3 -{ - color 0.0 0.0 1.0 - size 36 - offset 0 16 0 - attenuate 1 -} - -pointlight BLURSPHERE4 -{ - color 0.0 0.0 1.0 - size 24 - offset 0 16 0 - attenuate 1 -} - -pointlight BLURSPHERE5 -{ - color 0.0 0.0 1.0 - size 12 - offset 0 16 0 - attenuate 1 -} - object BlurSphere { frame PINS { light BLURSPHERE1 } - - frame PINSA { light BLURSPHERE2 } - frame PINSB { light BLURSPHERE3 } - frame PINSC { light BLURSPHERE4 } - frame PINSD { light BLURSPHERE5 } } -// Armour Helmet +// Armour Shield pulselight ARMORBONUS { color 0.3 0.1 0.1 size 16 secondarySize 20 interval 1.0 - dontlightself 1 attenuate 1 offset 0 10 0 } @@ -643,14 +605,23 @@ object ArmorBonus } // Blue Keys +pulselight BLUEKEY +{ + color 0.2 0.2 0.8 + size 15 + secondarySize 27 + interval 2.0 + attenuate 1 + offset 0 10 0 +} object BlueCard { - frame BKEY { light HEALTHPOTION } + frame BKEY { light BLUEKEY } } object BlueSkull { - frame BSKU { light HEALTHPOTION } + frame BSKU { light BLUEKEY } } // Yellow Keys @@ -695,6 +666,8 @@ object RedSkull frame RSKU { light REDKEY } } + +// Both armor pickups have a big red blinking light in the middle pointlight GREENARMOR2 { color 0.4 0.0 0.0 @@ -708,6 +681,11 @@ object GreenArmor frame ARM1B { light GREENARMOR2 } } +object BlueArmor +{ + frame ARM2B { light GREENARMOR2 } +} + // ------------------ // -- Doom Enemies -- @@ -749,7 +727,7 @@ object DoomPlayer // Doom Imp Fireball pointlight IMPBALL { - color 1.0 0.7 0.4 + color 0.8 0.7 0.4 size 96 attenuate 1 } @@ -757,7 +735,7 @@ pointlight IMPBALL // Doom imp fireball explosion flickerlight IMPBALL_X1 { - color 0.7 0.7 0.25 + color 0.9 0.7 0.25 size 120 secondarySize 132 chance 0.25 @@ -766,7 +744,7 @@ flickerlight IMPBALL_X1 flickerlight IMPBALL_X2 { - color 0.4 0.4 0.1 + color 0.5 0.4 0.1 size 144 secondarySize 156 chance 0.25 @@ -775,7 +753,7 @@ flickerlight IMPBALL_X2 flickerlight IMPBALL_X3 { - color 0.2 0.2 0.0 + color 0.3 0.2 0.0 size 168 secondarySize 180 chance 0.25 @@ -901,12 +879,20 @@ object BaronBall } // Lost Soul -flickerlight LOSTSOUL +pulselight LOSTSOUL { - color 1.0 0.6 0.3 + color 0.4 0.4 0.2 + size 64 + secondarysize 44 + interval 0.9 + attenuate 1 +} +flickerlight HATCHLING_ATK +{ + color 0.8 0.8 0.5 size 84 secondarysize 64 - chance 0.1 + chance 0.3 attenuate 1 } @@ -950,8 +936,8 @@ object LostSoul { frame SKULA { light LOSTSOUL } frame SKULB { light LOSTSOUL } - frame SKULC { light LOSTSOUL } - frame SKULD { light LOSTSOUL } + frame SKULC { light HATCHLING_ATK } + frame SKULD { light HATCHLING_ATK } frame SKULE { light LOSTSOUL } frame SKULF { light LOSTSOUL } frame SKULG { light LOSTSOUL } diff --git a/wadsrc_lights/static/filter/harmony/gldefs.txt b/wadsrc_lights/static/filter/harmony/gldefs.txt index 662bb3bc6..3907c4934 100644 --- a/wadsrc_lights/static/filter/harmony/gldefs.txt +++ b/wadsrc_lights/static/filter/harmony/gldefs.txt @@ -131,7 +131,7 @@ object Soldier frame CPOSF { light ZOMBIEATK } } -object Echida +object Echidna { frame SPIDG { light ZOMBIEATK } } diff --git a/wadsrc_lights/static/filter/strife/gldefs.txt b/wadsrc_lights/static/filter/strife/gldefs.txt index f33a930da..25fe78149 100644 --- a/wadsrc_lights/static/filter/strife/gldefs.txt +++ b/wadsrc_lights/static/filter/strife/gldefs.txt @@ -2410,14 +2410,6 @@ flickerlight POWCRYS_X5 chance 0.3 } -flickerlight POWCRYS_X6 -{ - color 1.0 0.65 0.24 - size 113 - secondarySize 115 - chance 0.3 -} - flickerlight POWCRYS_X6 { color 1.0 0.62 0.22 diff --git a/wadsrc_widepix/static/filter/chex.chex1/titlepic.lmp b/wadsrc_widepix/static/filter/chex.chex1/graphics/titlepic.lmp similarity index 100% rename from wadsrc_widepix/static/filter/chex.chex1/titlepic.lmp rename to wadsrc_widepix/static/filter/chex.chex1/graphics/titlepic.lmp diff --git a/wadsrc_widepix/static/filter/chex.chex1/wimap0.lmp b/wadsrc_widepix/static/filter/chex.chex1/graphics/wimap0.lmp similarity index 100% rename from wadsrc_widepix/static/filter/chex.chex1/wimap0.lmp rename to wadsrc_widepix/static/filter/chex.chex1/graphics/wimap0.lmp diff --git a/wadsrc_widepix/static/filter/doom.id/patches/SHT2E0.lmp b/wadsrc_widepix/static/filter/doom.id.doom2/sprites/SHT2E0.lmp similarity index 100% rename from wadsrc_widepix/static/filter/doom.id/patches/SHT2E0.lmp rename to wadsrc_widepix/static/filter/doom.id.doom2/sprites/SHT2E0.lmp diff --git a/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt b/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt deleted file mode 100644 index 4e2c7335f..000000000 --- a/wadsrc_widepix/static/filter/doom.id.doom2/textures.txt +++ /dev/null @@ -1,5 +0,0 @@ -sprite SHT2E0, 233, 63 -{ - offset 32, -105 - patch "/patches/SHT2E0.lmp", 0, 0 { } -} diff --git a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp new file mode 100644 index 000000000..b73a84fcb Binary files /dev/null and b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/sprites/SHT2E0.lmp differ diff --git a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt b/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt deleted file mode 100644 index 4e2c7335f..000000000 --- a/wadsrc_widepix/static/filter/doom.id.wadsmoosh/textures.txt +++ /dev/null @@ -1,5 +0,0 @@ -sprite SHT2E0, 233, 63 -{ - offset 32, -105 - patch "/patches/SHT2E0.lmp", 0, 0 { } -}